GNU Linux-libre 6.1.91-gnu
[releases.git] / arch / xtensa / lib / mulsi3.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */
2 #include <linux/linkage.h>
3 #include <asm/asmmacro.h>
4 #include <asm/core.h>
5
6         .macro  do_addx2 dst, as, at, tmp
7 #if XCHAL_HAVE_ADDX
8         addx2   \dst, \as, \at
9 #else
10         slli    \tmp, \as, 1
11         add     \dst, \tmp, \at
12 #endif
13         .endm
14
15         .macro  do_addx4 dst, as, at, tmp
16 #if XCHAL_HAVE_ADDX
17         addx4   \dst, \as, \at
18 #else
19         slli    \tmp, \as, 2
20         add     \dst, \tmp, \at
21 #endif
22         .endm
23
24         .macro  do_addx8 dst, as, at, tmp
25 #if XCHAL_HAVE_ADDX
26         addx8   \dst, \as, \at
27 #else
28         slli    \tmp, \as, 3
29         add     \dst, \tmp, \at
30 #endif
31         .endm
32
33 ENTRY(__mulsi3)
34
35         abi_entry_default
36
37 #if XCHAL_HAVE_MUL32
38         mull    a2, a2, a3
39
40 #elif XCHAL_HAVE_MUL16
41         or      a4, a2, a3
42         srai    a4, a4, 16
43         bnez    a4, .LMUL16
44         mul16u  a2, a2, a3
45         abi_ret_default
46 .LMUL16:
47         srai    a4, a2, 16
48         srai    a5, a3, 16
49         mul16u  a7, a4, a3
50         mul16u  a6, a5, a2
51         mul16u  a4, a2, a3
52         add     a7, a7, a6
53         slli    a7, a7, 16
54         add     a2, a7, a4
55
56 #elif XCHAL_HAVE_MAC16
57         mul.aa.hl a2, a3
58         mula.aa.lh a2, a3
59         rsr     a5, ACCLO
60         umul.aa.ll a2, a3
61         rsr     a4, ACCLO
62         slli    a5, a5, 16
63         add     a2, a4, a5
64
65 #else /* !MUL32 && !MUL16 && !MAC16 */
66
67         /* Multiply one bit at a time, but unroll the loop 4x to better
68            exploit the addx instructions and avoid overhead.
69            Peel the first iteration to save a cycle on init.  */
70
71         /* Avoid negative numbers.  */
72         xor     a5, a2, a3      /* Top bit is 1 if one input is negative.  */
73         do_abs  a3, a3, a6
74         do_abs  a2, a2, a6
75
76         /* Swap so the second argument is smaller.  */
77         sub     a7, a2, a3
78         mov     a4, a3
79         movgez  a4, a2, a7      /* a4 = max (a2, a3) */
80         movltz  a3, a2, a7      /* a3 = min (a2, a3) */
81
82         movi    a2, 0
83         extui   a6, a3, 0, 1
84         movnez  a2, a4, a6
85
86         do_addx2 a7, a4, a2, a7
87         extui   a6, a3, 1, 1
88         movnez  a2, a7, a6
89
90         do_addx4 a7, a4, a2, a7
91         extui   a6, a3, 2, 1
92         movnez  a2, a7, a6
93
94         do_addx8 a7, a4, a2, a7
95         extui   a6, a3, 3, 1
96         movnez  a2, a7, a6
97
98         bgeui   a3, 16, .Lmult_main_loop
99         neg     a3, a2
100         movltz  a2, a3, a5
101         abi_ret_default
102
103         .align  4
104 .Lmult_main_loop:
105         srli    a3, a3, 4
106         slli    a4, a4, 4
107
108         add     a7, a4, a2
109         extui   a6, a3, 0, 1
110         movnez  a2, a7, a6
111
112         do_addx2 a7, a4, a2, a7
113         extui   a6, a3, 1, 1
114         movnez  a2, a7, a6
115
116         do_addx4 a7, a4, a2, a7
117         extui   a6, a3, 2, 1
118         movnez  a2, a7, a6
119
120         do_addx8 a7, a4, a2, a7
121         extui   a6, a3, 3, 1
122         movnez  a2, a7, a6
123
124         bgeui   a3, 16, .Lmult_main_loop
125
126         neg     a3, a2
127         movltz  a2, a3, a5
128
129 #endif /* !MUL32 && !MUL16 && !MAC16 */
130
131         abi_ret_default
132
133 ENDPROC(__mulsi3)