1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
13 .macro ARM_DIV_BODY dividend, divisor, result, curbit
15 #if __COREBOOT_ARM_ARCH__ >= 5
18 clz \result, \dividend
19 sub \result, \curbit, \result
21 mov \divisor, \divisor, lsl \result
22 mov \curbit, \curbit, lsl \result
27 @ Initially shift the divisor left 3 bits if possible,
28 @ set curbit accordingly. This allows for curbit to be located
29 @ at the left end of each 4 bit nibbles in the division loop
30 @ to save one loop in most cases.
31 tst \divisor, #0xe0000000
32 moveq \divisor, \divisor, lsl #3
36 @ Unless the divisor is very big, shift it up in multiples of
37 @ four bits, since this is the amount of unwinding in the main
38 @ division loop. Continue shifting until the divisor is
39 @ larger than the dividend.
40 1: cmp \divisor, #0x10000000
41 cmplo \divisor, \dividend
42 movlo \divisor, \divisor, lsl #4
43 movlo \curbit, \curbit, lsl #4
46 @ For very big divisors, we must shift it a bit at a time, or
47 @ we will be in danger of overflowing.
48 1: cmp \divisor, #0x80000000
49 cmplo \divisor, \dividend
50 movlo \divisor, \divisor, lsl #1
51 movlo \curbit, \curbit, lsl #1
59 1: cmp \dividend, \divisor
60 subhs \dividend, \dividend, \divisor
61 orrhs \result, \result, \curbit
62 cmp \dividend, \divisor, lsr #1
63 subhs \dividend, \dividend, \divisor, lsr #1
64 orrhs \result, \result, \curbit, lsr #1
65 cmp \dividend, \divisor, lsr #2
66 subhs \dividend, \dividend, \divisor, lsr #2
67 orrhs \result, \result, \curbit, lsr #2
68 cmp \dividend, \divisor, lsr #3
69 subhs \dividend, \dividend, \divisor, lsr #3
70 orrhs \result, \result, \curbit, lsr #3
71 cmp \dividend, #0 @ Early termination?
72 movsne \curbit, \curbit, lsr #4 @ No, any more bits to do?
73 movne \divisor, \divisor, lsr #4
79 .macro ARM_DIV2_ORDER divisor, order
81 #if __COREBOOT_ARM_ARCH__ >= 5
84 rsb \order, \order, #31
88 cmp \divisor, #(1 << 16)
89 movhs \divisor, \divisor, lsr #16
93 cmp \divisor, #(1 << 8)
94 movhs \divisor, \divisor, lsr #8
95 addhs \order, \order, #8
97 cmp \divisor, #(1 << 4)
98 movhs \divisor, \divisor, lsr #4
99 addhs \order, \order, #4
101 cmp \divisor, #(1 << 2)
102 addhi \order, \order, #3
103 addls \order, \order, \divisor, lsr #1
110 .macro ARM_MOD_BODY dividend, divisor, order, spare
112 #if __COREBOOT_ARM_ARCH__ >= 5
115 clz \spare, \dividend
116 sub \order, \order, \spare
117 mov \divisor, \divisor, lsl \order
123 @ Unless the divisor is very big, shift it up in multiples of
124 @ four bits, since this is the amount of unwinding in the main
125 @ division loop. Continue shifting until the divisor is
126 @ larger than the dividend.
127 1: cmp \divisor, #0x10000000
128 cmplo \divisor, \dividend
129 movlo \divisor, \divisor, lsl #4
130 addlo \order, \order, #4
133 @ For very big divisors, we must shift it a bit at a time, or
134 @ we will be in danger of overflowing.
135 1: cmp \divisor, #0x80000000
136 cmplo \divisor, \dividend
137 movlo \divisor, \divisor, lsl #1
138 addlo \order, \order, #1
143 @ Perform all needed substractions to keep only the reminder.
144 @ Do comparisons in batch of 4 first.
145 subs \order, \order, #3 @ yes, 3 is intended here
148 1: cmp \dividend, \divisor
149 subhs \dividend, \dividend, \divisor
150 cmp \dividend, \divisor, lsr #1
151 subhs \dividend, \dividend, \divisor, lsr #1
152 cmp \dividend, \divisor, lsr #2
153 subhs \dividend, \dividend, \divisor, lsr #2
154 cmp \dividend, \divisor, lsr #3
155 subhs \dividend, \dividend, \divisor, lsr #3
157 mov \divisor, \divisor, lsr #4
158 subsge \order, \order, #4
165 @ Either 1, 2 or 3 comparison/substractions are left.
169 cmp \dividend, \divisor
170 subhs \dividend, \dividend, \divisor
171 mov \divisor, \divisor, lsr #1
172 3: cmp \dividend, \divisor
173 subhs \dividend, \dividend, \divisor
174 mov \divisor, \divisor, lsr #1
175 4: cmp \dividend, \divisor
176 subhs \dividend, \dividend, \divisor
182 .global __aeabi_uidiv
193 ARM_DIV_BODY r0, r1, r2, r3
202 12: ARM_DIV2_ORDER r1, r2
207 .type __aeabi_uidiv, %function
208 .size __aeabi_uidiv, .-__aeabi_uidiv
213 subs r2, r1, #1 @ compare divisor with 1
215 cmpne r0, r1 @ compare dividend with divisor
217 tsthi r1, r2 @ see if divisor is power of 2
221 ARM_MOD_BODY r0, r1, r2, r3
232 eor ip, r0, r1 @ save the sign of the result.
234 rsbmi r1, r1, #0 @ loops below use unsigned.
235 subs r2, r1, #1 @ division by 1 or -1 ?
238 rsbmi r3, r0, #0 @ positive dividend value
241 tst r1, r2 @ divisor is power of 2 ?
244 ARM_DIV_BODY r3, r1, r0, r2
250 10: teq ip, r0 @ same sign ?
255 moveq r0, ip, asr #31
259 12: ARM_DIV2_ORDER r1, r2
266 .type __aeabi_idiv, %function
267 .size __aeabi_idiv, .-__aeabi_idiv
274 rsbmi r1, r1, #0 @ loops below use unsigned.
275 movs ip, r0 @ preserve sign of dividend
276 rsbmi r0, r0, #0 @ if negative make positive
277 subs r2, r1, #1 @ compare divisor with 1
278 cmpne r0, r1 @ compare dividend with divisor
280 tsthi r1, r2 @ see if divisor is power of 2
284 ARM_MOD_BODY r0, r1, r2, r3
292 ENTRY(__aeabi_uidivmod)
294 stmfd sp!, {r0, r1, ip, lr}
296 ldmfd sp!, {r1, r2, ip, lr}
301 ENDPROC(__aeabi_uidivmod)
303 ENTRY(__aeabi_idivmod)
304 stmfd sp!, {r0, r1, ip, lr}
306 ldmfd sp!, {r1, r2, ip, lr}
311 ENDPROC(__aeabi_idivmod)
317 mov r0, #0 @ About as wrong as it could be.