1 @ libgcc1 routines for ARM cpu.
2 @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
4 /* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
6 This file is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file with other programs, and to distribute
14 those programs without any restriction coming from the use of this
15 file. (The General Public License restrictions do apply in other
16 respects; for example, they cover modification of the file, and
17 distribution when not linked into another program.)
19 This file is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA. */
29 /* As a special exception, if you link this library with other files,
30 some of which are compiled with GCC, to produce an executable,
31 this library does not by itself cause the resulting executable
32 to be covered by the GNU General Public License.
33 This exception does not however invalidate any other reasons why
34 the executable file might be covered by the GNU General Public License.
36 /* This code is derived from gcc 2.95.3 */
37 /* I Molton 29/07/01 */
39 #include <linux/linkage.h>
40 #include <asm/assembler.h>
41 #include <asm/hardware.h>
44 #define RETc(x) mov##x##s
63 bcc Lgot_result_udivsi3
65 @ Unless the divisor is very big, shift it up in multiples of
66 @ four bits, since this is the amount of unwinding in the main
67 @ division loop. Continue shifting until the divisor is
68 @ larger than the dividend.
69 cmp divisor, #0x10000000
70 cmpcc divisor, dividend
71 movcc divisor, divisor, lsl #4
72 movcc curbit, curbit, lsl #4
76 @ For very big divisors, we must shift it a bit at a time, or
77 @ we will be in danger of overflowing.
78 cmp divisor, #0x80000000
79 cmpcc divisor, dividend
80 movcc divisor, divisor, lsl #1
81 movcc curbit, curbit, lsl #1
85 @ Test for possible subtractions, and note which bits
86 @ are done in the result. On the final pass, this may subtract
87 @ too much from the dividend, but the result will be ok, since the
88 @ "bit" will have been shifted out at the bottom.
90 subcs dividend, dividend, divisor
91 orrcs result, result, curbit
92 cmp dividend, divisor, lsr #1
93 subcs dividend, dividend, divisor, lsr #1
94 orrcs result, result, curbit, lsr #1
95 cmp dividend, divisor, lsr #2
96 subcs dividend, dividend, divisor, lsr #2
97 orrcs result, result, curbit, lsr #2
98 cmp dividend, divisor, lsr #3
99 subcs dividend, dividend, divisor, lsr #3
100 orrcs result, result, curbit, lsr #3
101 cmp dividend, #0 @ Early termination?
102 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
103 movne divisor, divisor, lsr #4
112 mov r0, #0 @ about as wrong as it could be
113 ldmia sp!, {pc}RETCOND
115 /* __umodsi3 ----------------------- */
121 cmp dividend, divisor
124 @ Unless the divisor is very big, shift it up in multiples of
125 @ four bits, since this is the amount of unwinding in the main
126 @ division loop. Continue shifting until the divisor is
127 @ larger than the dividend.
128 cmp divisor, #0x10000000
129 cmpcc divisor, dividend
130 movcc divisor, divisor, lsl #4
131 movcc curbit, curbit, lsl #4
135 @ For very big divisors, we must shift it a bit at a time, or
136 @ we will be in danger of overflowing.
137 cmp divisor, #0x80000000
138 cmpcc divisor, dividend
139 movcc divisor, divisor, lsl #1
140 movcc curbit, curbit, lsl #1
144 @ Test for possible subtractions. On the final pass, this may
145 @ subtract too much from the dividend, so keep track of which
146 @ subtractions are done, we can fix them up afterwards...
148 cmp dividend, divisor
149 subcs dividend, dividend, divisor
150 cmp dividend, divisor, lsr #1
151 subcs dividend, dividend, divisor, lsr #1
152 orrcs overdone, overdone, curbit, ror #1
153 cmp dividend, divisor, lsr #2
154 subcs dividend, dividend, divisor, lsr #2
155 orrcs overdone, overdone, curbit, ror #2
156 cmp dividend, divisor, lsr #3
157 subcs dividend, dividend, divisor, lsr #3
158 orrcs overdone, overdone, curbit, ror #3
160 cmp dividend, #0 @ Early termination?
161 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
162 movne divisor, divisor, lsr #4
165 @ Any subtractions that we should not have done will be recorded in
166 @ the top three bits of "overdone". Exactly which were not needed
167 @ are governed by the position of the bit, stored in ip.
168 @ If we terminated early, because dividend became zero,
169 @ then none of the below will match, since the bit in ip will not be
170 @ in the bottom nibble.
171 ands overdone, overdone, #0xe0000000
172 RETc(eq) pc, lr @ No fixups needed
173 tst overdone, ip, ror #3
174 addne dividend, dividend, divisor, lsr #3
175 tst overdone, ip, ror #2
176 addne dividend, dividend, divisor, lsr #2
177 tst overdone, ip, ror #1
178 addne dividend, dividend, divisor, lsr #1
182 eor ip, dividend, divisor @ Save the sign of the result.
186 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
189 rsbmi dividend, dividend, #0
190 cmp dividend, divisor
191 bcc Lgot_result_divsi3
194 @ Unless the divisor is very big, shift it up in multiples of
195 @ four bits, since this is the amount of unwinding in the main
196 @ division loop. Continue shifting until the divisor is
197 @ larger than the dividend.
198 cmp divisor, #0x10000000
199 cmpcc divisor, dividend
200 movcc divisor, divisor, lsl #4
201 movcc curbit, curbit, lsl #4
205 @ For very big divisors, we must shift it a bit at a time, or
206 @ we will be in danger of overflowing.
207 cmp divisor, #0x80000000
208 cmpcc divisor, dividend
209 movcc divisor, divisor, lsl #1
210 movcc curbit, curbit, lsl #1
214 @ Test for possible subtractions, and note which bits
215 @ are done in the result. On the final pass, this may subtract
216 @ too much from the dividend, but the result will be ok, since the
217 @ "bit" will have been shifted out at the bottom.
218 cmp dividend, divisor
219 subcs dividend, dividend, divisor
220 orrcs result, result, curbit
221 cmp dividend, divisor, lsr #1
222 subcs dividend, dividend, divisor, lsr #1
223 orrcs result, result, curbit, lsr #1
224 cmp dividend, divisor, lsr #2
225 subcs dividend, dividend, divisor, lsr #2
226 orrcs result, result, curbit, lsr #2
227 cmp dividend, divisor, lsr #3
228 subcs dividend, dividend, divisor, lsr #3
229 orrcs result, result, curbit, lsr #3
230 cmp dividend, #0 @ Early termination?
231 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
232 movne divisor, divisor, lsr #4
243 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
245 @ Need to save the sign of the dividend, unfortunately, we need
246 @ ip later on; this is faster than pushing lr and using that.
247 str dividend, [sp, #-4]!
249 rsbmi dividend, dividend, #0
250 cmp dividend, divisor
251 bcc Lgot_result_modsi3
254 @ Unless the divisor is very big, shift it up in multiples of
255 @ four bits, since this is the amount of unwinding in the main
256 @ division loop. Continue shifting until the divisor is
257 @ larger than the dividend.
258 cmp divisor, #0x10000000
259 cmpcc divisor, dividend
260 movcc divisor, divisor, lsl #4
261 movcc curbit, curbit, lsl #4
265 @ For very big divisors, we must shift it a bit at a time, or
266 @ we will be in danger of overflowing.
267 cmp divisor, #0x80000000
268 cmpcc divisor, dividend
269 movcc divisor, divisor, lsl #1
270 movcc curbit, curbit, lsl #1
274 @ Test for possible subtractions. On the final pass, this may
275 @ subtract too much from the dividend, so keep track of which
276 @ subtractions are done, we can fix them up afterwards...
278 cmp dividend, divisor
279 subcs dividend, dividend, divisor
280 cmp dividend, divisor, lsr #1
281 subcs dividend, dividend, divisor, lsr #1
282 orrcs overdone, overdone, curbit, ror #1
283 cmp dividend, divisor, lsr #2
284 subcs dividend, dividend, divisor, lsr #2
285 orrcs overdone, overdone, curbit, ror #2
286 cmp dividend, divisor, lsr #3
287 subcs dividend, dividend, divisor, lsr #3
288 orrcs overdone, overdone, curbit, ror #3
290 cmp dividend, #0 @ Early termination?
291 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
292 movne divisor, divisor, lsr #4
295 @ Any subtractions that we should not have done will be recorded in
296 @ the top three bits of "overdone". Exactly which were not needed
297 @ are governed by the position of the bit, stored in ip.
298 @ If we terminated early, because dividend became zero,
299 @ then none of the below will match, since the bit in ip will not be
300 @ in the bottom nibble.
301 ands overdone, overdone, #0xe0000000
302 beq Lgot_result_modsi3
303 tst overdone, ip, ror #3
304 addne dividend, dividend, divisor, lsr #3
305 tst overdone, ip, ror #2
306 addne dividend, dividend, divisor, lsr #2
307 tst overdone, ip, ror #1
308 addne dividend, dividend, divisor, lsr #1
312 rsbmi dividend, dividend, #0