1 /* SPDX-License-Identifier: GPL-2.0+ */
3 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
5 * Author: Nicolas Pitre <nico@fluxnic.net>
6 * - contributed to gcc-3.4 on Sep 30, 2003
7 * - adapted for the Linux kernel on Oct 2, 2003
10 * Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
13 #include <linux/linkage.h>
14 #include <asm/assembler.h>
17 * U-Boot compatibility bit, define empty UNWIND() macro as, since we
18 * do not support stack unwinding and define CONFIG_AEABI to make all
19 * of the functions available without diverging from Linux code.
26 .macro ARM_DIV_BODY dividend, divisor, result, curbit
28 #if __LINUX_ARM_ARCH__ >= 5
31 clz \result, \dividend
32 sub \result, \curbit, \result
34 mov \divisor, \divisor, lsl \result
35 mov \curbit, \curbit, lsl \result
40 @ Initially shift the divisor left 3 bits if possible,
41 @ set curbit accordingly. This allows for curbit to be located
42 @ at the left end of each 4 bit nibbles in the division loop
43 @ to save one loop in most cases.
44 tst \divisor, #0xe0000000
45 moveq \divisor, \divisor, lsl #3
49 @ Unless the divisor is very big, shift it up in multiples of
50 @ four bits, since this is the amount of unwinding in the main
51 @ division loop. Continue shifting until the divisor is
52 @ larger than the dividend.
53 1: cmp \divisor, #0x10000000
54 cmplo \divisor, \dividend
55 movlo \divisor, \divisor, lsl #4
56 movlo \curbit, \curbit, lsl #4
59 @ For very big divisors, we must shift it a bit at a time, or
60 @ we will be in danger of overflowing.
61 1: cmp \divisor, #0x80000000
62 cmplo \divisor, \dividend
63 movlo \divisor, \divisor, lsl #1
64 movlo \curbit, \curbit, lsl #1
72 1: cmp \dividend, \divisor
73 subhs \dividend, \dividend, \divisor
74 orrhs \result, \result, \curbit
75 cmp \dividend, \divisor, lsr #1
76 subhs \dividend, \dividend, \divisor, lsr #1
77 orrhs \result, \result, \curbit, lsr #1
78 cmp \dividend, \divisor, lsr #2
79 subhs \dividend, \dividend, \divisor, lsr #2
80 orrhs \result, \result, \curbit, lsr #2
81 cmp \dividend, \divisor, lsr #3
82 subhs \dividend, \dividend, \divisor, lsr #3
83 orrhs \result, \result, \curbit, lsr #3
84 cmp \dividend, #0 @ Early termination?
85 movsne \curbit, \curbit, lsr #4 @ No, any more bits to do?
86 movne \divisor, \divisor, lsr #4
92 .macro ARM_DIV2_ORDER divisor, order
94 #if __LINUX_ARM_ARCH__ >= 5
97 rsb \order, \order, #31
101 cmp \divisor, #(1 << 16)
102 movhs \divisor, \divisor, lsr #16
106 cmp \divisor, #(1 << 8)
107 movhs \divisor, \divisor, lsr #8
108 addhs \order, \order, #8
110 cmp \divisor, #(1 << 4)
111 movhs \divisor, \divisor, lsr #4
112 addhs \order, \order, #4
114 cmp \divisor, #(1 << 2)
115 addhi \order, \order, #3
116 addls \order, \order, \divisor, lsr #1
123 .macro ARM_MOD_BODY dividend, divisor, order, spare
125 #if __LINUX_ARM_ARCH__ >= 5
128 clz \spare, \dividend
129 sub \order, \order, \spare
130 mov \divisor, \divisor, lsl \order
136 @ Unless the divisor is very big, shift it up in multiples of
137 @ four bits, since this is the amount of unwinding in the main
138 @ division loop. Continue shifting until the divisor is
139 @ larger than the dividend.
140 1: cmp \divisor, #0x10000000
141 cmplo \divisor, \dividend
142 movlo \divisor, \divisor, lsl #4
143 addlo \order, \order, #4
146 @ For very big divisors, we must shift it a bit at a time, or
147 @ we will be in danger of overflowing.
148 1: cmp \divisor, #0x80000000
149 cmplo \divisor, \dividend
150 movlo \divisor, \divisor, lsl #1
151 addlo \order, \order, #1
156 @ Perform all needed subtractions to keep only the reminder.
157 @ Do comparisons in batch of 4 first.
158 subs \order, \order, #3 @ yes, 3 is intended here
161 1: cmp \dividend, \divisor
162 subhs \dividend, \dividend, \divisor
163 cmp \dividend, \divisor, lsr #1
164 subhs \dividend, \dividend, \divisor, lsr #1
165 cmp \dividend, \divisor, lsr #2
166 subhs \dividend, \dividend, \divisor, lsr #2
167 cmp \dividend, \divisor, lsr #3
168 subhs \dividend, \dividend, \divisor, lsr #3
170 mov \divisor, \divisor, lsr #4
171 subsge \order, \order, #4
178 @ Either 1, 2 or 3 comparison/subtractions are left.
182 cmp \dividend, \divisor
183 subhs \dividend, \dividend, \divisor
184 mov \divisor, \divisor, lsr #1
185 3: cmp \dividend, \divisor
186 subhs \dividend, \dividend, \divisor
187 mov \divisor, \divisor, lsr #1
188 4: cmp \dividend, \divisor
189 subhs \dividend, \dividend, \divisor
194 .pushsection .text.__udivsi3, "ax"
207 ARM_DIV_BODY r0, r1, r2, r3
216 12: ARM_DIV2_ORDER r1, r2
223 ENDPROC(__aeabi_uidiv)
226 .pushsection .text.__umodsi3, "ax"
230 subs r2, r1, #1 @ compare divisor with 1
232 cmpne r0, r1 @ compare dividend with divisor
234 tsthi r1, r2 @ see if divisor is power of 2
238 ARM_MOD_BODY r0, r1, r2, r3
246 .pushsection .text.__divsi3, "ax"
252 eor ip, r0, r1 @ save the sign of the result.
254 rsbmi r1, r1, #0 @ loops below use unsigned.
255 subs r2, r1, #1 @ division by 1 or -1 ?
258 rsbmi r3, r0, #0 @ positive dividend value
261 tst r1, r2 @ divisor is power of 2 ?
264 ARM_DIV_BODY r3, r1, r0, r2
270 10: teq ip, r0 @ same sign ?
275 moveq r0, ip, asr #31
279 12: ARM_DIV2_ORDER r1, r2
288 ENDPROC(__aeabi_idiv)
291 .pushsection .text.__modsi3, "ax"
297 rsbmi r1, r1, #0 @ loops below use unsigned.
298 movs ip, r0 @ preserve sign of dividend
299 rsbmi r0, r0, #0 @ if negative make positive
300 subs r2, r1, #1 @ compare divisor with 1
301 cmpne r0, r1 @ compare dividend with divisor
303 tsthi r1, r2 @ see if divisor is power of 2
307 ARM_MOD_BODY r0, r1, r2, r3
319 .pushsection .text.__aeabi_uidivmod, "ax"
320 ENTRY(__aeabi_uidivmod)
322 UNWIND(.save {r0, r1, ip, lr} )
324 stmfd sp!, {r0, r1, ip, lr}
326 ldmfd sp!, {r1, r2, ip, lr}
332 ENDPROC(__aeabi_uidivmod)
335 .pushsection .text.__aeabi_uidivmod, "ax"
336 ENTRY(__aeabi_idivmod)
338 UNWIND(.save {r0, r1, ip, lr} )
340 stmfd sp!, {r0, r1, ip, lr}
342 ldmfd sp!, {r1, r2, ip, lr}
348 ENDPROC(__aeabi_idivmod)
353 .pushsection .text.Ldiv0, "ax"
361 mov r0, #0 @ About as wrong as it could be.
368 /* Thumb-1 specialities */
369 #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) && !defined(CONFIG_HAS_THUMB2)
370 .pushsection .text.__gnu_thumb1_case_sqi, "ax"
371 ENTRY(__gnu_thumb1_case_sqi)
381 ENDPROC(__gnu_thumb1_case_sqi)
384 .pushsection .text.__gnu_thumb1_case_uqi, "ax"
385 ENTRY(__gnu_thumb1_case_uqi)
395 ENDPROC(__gnu_thumb1_case_uqi)
398 .pushsection .text.__gnu_thumb1_case_shi, "ax"
399 ENTRY(__gnu_thumb1_case_shi)
410 ENDPROC(__gnu_thumb1_case_shi)
413 .pushsection .text.__gnu_thumb1_case_uhi, "ax"
414 ENTRY(__gnu_thumb1_case_uhi)
425 ENDPROC(__gnu_thumb1_case_uhi)