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)
134 EXPORT_SYMBOL(__mulsi3)
135