2 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
4 * Author: Nicolas Pitre <nico@cam.org>
5 * - contributed to gcc-3.4 on Sep 30, 2003
6 * - adapted for the Linux kernel on Oct 2, 2003
9 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
11 This file is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 In addition to the permissions in the GNU General Public License, the
17 Free Software Foundation gives you unlimited permission to link the
18 compiled version of this file into combinations with other programs,
19 and to distribute those combinations without any restriction coming
20 from the use of this file. (The General Public License restrictions
21 do apply in other respects; for example, they cover modification of
22 the file, and distribution when not linked into a combine
25 This file is distributed in the hope that it will be useful, but
26 WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with this program; see the file COPYING. If not, write to
32 the Free Software Foundation, 59 Temple Place - Suite 330,
33 Boston, MA 02111-1307, USA. */
38 .macro ARM_DIV_BODY dividend, divisor, result, curbit
40 #if TI_CONFIG_ARM_VERSION >= 5
43 clz \result, \dividend
44 sub \result, \curbit, \result
46 mov \divisor, \divisor, lsl \result
47 mov \curbit, \curbit, lsl \result
52 @ Initially shift the divisor left 3 bits if possible,
53 @ set curbit accordingly. This allows for curbit to be located
54 @ at the left end of each 4 bit nibbles in the division loop
55 @ to save one loop in most cases.
56 tst \divisor, #0xe0000000
57 moveq \divisor, \divisor, lsl #3
61 @ Unless the divisor is very big, shift it up in multiples of
62 @ four bits, since this is the amount of unwinding in the main
63 @ division loop. Continue shifting until the divisor is
64 @ larger than the dividend.
65 1: cmp \divisor, #0x10000000
66 cmplo \divisor, \dividend
67 movlo \divisor, \divisor, lsl #4
68 movlo \curbit, \curbit, lsl #4
71 @ For very big divisors, we must shift it a bit at a time, or
72 @ we will be in danger of overflowing.
73 1: cmp \divisor, #0x80000000
74 cmplo \divisor, \dividend
75 movlo \divisor, \divisor, lsl #1
76 movlo \curbit, \curbit, lsl #1
84 1: cmp \dividend, \divisor
85 subhs \dividend, \dividend, \divisor
86 orrhs \result, \result, \curbit
87 cmp \dividend, \divisor, lsr #1
88 subhs \dividend, \dividend, \divisor, lsr #1
89 orrhs \result, \result, \curbit, lsr #1
90 cmp \dividend, \divisor, lsr #2
91 subhs \dividend, \dividend, \divisor, lsr #2
92 orrhs \result, \result, \curbit, lsr #2
93 cmp \dividend, \divisor, lsr #3
94 subhs \dividend, \dividend, \divisor, lsr #3
95 orrhs \result, \result, \curbit, lsr #3
96 cmp \dividend, #0 @ Early termination?
97 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
98 movne \divisor, \divisor, lsr #4
104 .macro ARM_DIV2_ORDER divisor, order
106 #if TI_CONFIG_ARM_VERSION >= 5
109 rsb \order, \order, #31
113 cmp \divisor, #(1 << 16)
114 movhs \divisor, \divisor, lsr #16
118 cmp \divisor, #(1 << 8)
119 movhs \divisor, \divisor, lsr #8
120 addhs \order, \order, #8
122 cmp \divisor, #(1 << 4)
123 movhs \divisor, \divisor, lsr #4
124 addhs \order, \order, #4
126 cmp \divisor, #(1 << 2)
127 addhi \order, \order, #3
128 addls \order, \order, \divisor, lsr #1
135 .macro ARM_MOD_BODY dividend, divisor, order, spare
137 #if TI_CONFIG_ARM_VERSION >= 5
140 clz \spare, \dividend
141 sub \order, \order, \spare
142 mov \divisor, \divisor, lsl \order
148 @ Unless the divisor is very big, shift it up in multiples of
149 @ four bits, since this is the amount of unwinding in the main
150 @ division loop. Continue shifting until the divisor is
151 @ larger than the dividend.
152 1: cmp \divisor, #0x10000000
153 cmplo \divisor, \dividend
154 movlo \divisor, \divisor, lsl #4
155 addlo \order, \order, #4
158 @ For very big divisors, we must shift it a bit at a time, or
159 @ we will be in danger of overflowing.
160 1: cmp \divisor, #0x80000000
161 cmplo \divisor, \dividend
162 movlo \divisor, \divisor, lsl #1
163 addlo \order, \order, #1
168 @ Perform all needed substractions to keep only the reminder.
169 @ Do comparisons in batch of 4 first.
170 subs \order, \order, #3 @ yes, 3 is intended here
173 1: cmp \dividend, \divisor
174 subhs \dividend, \dividend, \divisor
175 cmp \dividend, \divisor, lsr #1
176 subhs \dividend, \dividend, \divisor, lsr #1
177 cmp \dividend, \divisor, lsr #2
178 subhs \dividend, \dividend, \divisor, lsr #2
179 cmp \dividend, \divisor, lsr #3
180 subhs \dividend, \dividend, \divisor, lsr #3
182 mov \divisor, \divisor, lsr #4
183 subges \order, \order, #4
190 @ Either 1, 2 or 3 comparison/substractions are left.
194 cmp \dividend, \divisor
195 subhs \dividend, \dividend, \divisor
196 mov \divisor, \divisor, lsr #1
197 3: cmp \dividend, \divisor
198 subhs \dividend, \dividend, \divisor
199 mov \divisor, \divisor, lsr #1
200 4: cmp \dividend, \divisor
201 subhs \dividend, \dividend, \divisor
206 TI_ASM_EXPORT(__udivsi3)
207 TI_ASM_EXPORT(__aeabi_uidiv)
217 ARM_DIV_BODY r0, r1, r2, r3
226 12: ARM_DIV2_ORDER r1, r2
232 TI_ASM_EXPORT(__umodsi3)
234 subs r2, r1, #1 @ compare divisor with 1
236 cmpne r0, r1 @ compare dividend with divisor
238 tsthi r1, r2 @ see if divisor is power of 2
242 ARM_MOD_BODY r0, r1, r2, r3
246 TI_ASM_EXPORT(__divsi3)
247 TI_ASM_EXPORT(__aeabi_idiv)
250 eor ip, r0, r1 @ save the sign of the result.
252 rsbmi r1, r1, #0 @ loops below use unsigned.
253 subs r2, r1, #1 @ division by 1 or -1 ?
256 rsbmi r3, r0, #0 @ positive dividend value
259 tst r1, r2 @ divisor is power of 2 ?
262 ARM_DIV_BODY r3, r1, r0, r2
268 10: teq ip, r0 @ same sign ?
273 moveq r0, ip, asr #31
277 12: ARM_DIV2_ORDER r1, r2
285 TI_ASM_EXPORT(__modsi3)
289 rsbmi r1, r1, #0 @ loops below use unsigned.
290 movs ip, r0 @ preserve sign of dividend
291 rsbmi r0, r0, #0 @ if negative make positive
292 subs r2, r1, #1 @ compare divisor with 1
293 cmpne r0, r1 @ compare dividend with divisor
295 tsthi r1, r2 @ see if divisor is power of 2
299 ARM_MOD_BODY r0, r1, r2, r3
306 #ifdef TI_CONFIG_AEABI
308 TI_ASM_EXPORT(__aeabi_uidivmod)
310 stmfd sp!, {r0, r1, ip, lr}
312 ldmfd sp!, {r1, r2, ip, lr}
318 TI_ASM_EXPORT(__aeabi_idivmod)
320 stmfd sp!, {r0, r1, ip, lr}
322 ldmfd sp!, {r1, r2, ip, lr}
334 mov r0, #0 @ About as wrong as it could be.