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>
42 #include <linux/config.h>
46 #define RETc(x) mov##x##s
50 #define RETc(x) mov##x
70 bcc Lgot_result_udivsi3
72 @ Unless the divisor is very big, shift it up in multiples of
73 @ four bits, since this is the amount of unwinding in the main
74 @ division loop. Continue shifting until the divisor is
75 @ larger than the dividend.
76 cmp divisor, #0x10000000
77 cmpcc divisor, dividend
78 movcc divisor, divisor, lsl #4
79 movcc curbit, curbit, lsl #4
83 @ For very big divisors, we must shift it a bit at a time, or
84 @ we will be in danger of overflowing.
85 cmp divisor, #0x80000000
86 cmpcc divisor, dividend
87 movcc divisor, divisor, lsl #1
88 movcc curbit, curbit, lsl #1
92 @ Test for possible subtractions, and note which bits
93 @ are done in the result. On the final pass, this may subtract
94 @ too much from the dividend, but the result will be ok, since the
95 @ "bit" will have been shifted out at the bottom.
97 subcs dividend, dividend, divisor
98 orrcs result, result, curbit
99 cmp dividend, divisor, lsr #1
100 subcs dividend, dividend, divisor, lsr #1
101 orrcs result, result, curbit, lsr #1
102 cmp dividend, divisor, lsr #2
103 subcs dividend, dividend, divisor, lsr #2
104 orrcs result, result, curbit, lsr #2
105 cmp dividend, divisor, lsr #3
106 subcs dividend, dividend, divisor, lsr #3
107 orrcs result, result, curbit, lsr #3
108 cmp dividend, #0 @ Early termination?
109 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
110 movne divisor, divisor, lsr #4
119 mov r0, #0 @ about as wrong as it could be
120 ldmia sp!, {pc}RETCOND
122 /* __umodsi3 ----------------------- */
128 cmp dividend, divisor
131 @ Unless the divisor is very big, shift it up in multiples of
132 @ four bits, since this is the amount of unwinding in the main
133 @ division loop. Continue shifting until the divisor is
134 @ larger than the dividend.
135 cmp divisor, #0x10000000
136 cmpcc divisor, dividend
137 movcc divisor, divisor, lsl #4
138 movcc curbit, curbit, lsl #4
142 @ For very big divisors, we must shift it a bit at a time, or
143 @ we will be in danger of overflowing.
144 cmp divisor, #0x80000000
145 cmpcc divisor, dividend
146 movcc divisor, divisor, lsl #1
147 movcc curbit, curbit, lsl #1
151 @ Test for possible subtractions. On the final pass, this may
152 @ subtract too much from the dividend, so keep track of which
153 @ subtractions are done, we can fix them up afterwards...
155 cmp dividend, divisor
156 subcs dividend, dividend, divisor
157 cmp dividend, divisor, lsr #1
158 subcs dividend, dividend, divisor, lsr #1
159 orrcs overdone, overdone, curbit, ror #1
160 cmp dividend, divisor, lsr #2
161 subcs dividend, dividend, divisor, lsr #2
162 orrcs overdone, overdone, curbit, ror #2
163 cmp dividend, divisor, lsr #3
164 subcs dividend, dividend, divisor, lsr #3
165 orrcs overdone, overdone, curbit, ror #3
167 cmp dividend, #0 @ Early termination?
168 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
169 movne divisor, divisor, lsr #4
172 @ Any subtractions that we should not have done will be recorded in
173 @ the top three bits of "overdone". Exactly which were not needed
174 @ are governed by the position of the bit, stored in ip.
175 @ If we terminated early, because dividend became zero,
176 @ then none of the below will match, since the bit in ip will not be
177 @ in the bottom nibble.
178 ands overdone, overdone, #0xe0000000
179 RETc(eq) pc, lr @ No fixups needed
180 tst overdone, ip, ror #3
181 addne dividend, dividend, divisor, lsr #3
182 tst overdone, ip, ror #2
183 addne dividend, dividend, divisor, lsr #2
184 tst overdone, ip, ror #1
185 addne dividend, dividend, divisor, lsr #1
189 eor ip, dividend, divisor @ Save the sign of the result.
193 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
196 rsbmi dividend, dividend, #0
197 cmp dividend, divisor
198 bcc Lgot_result_divsi3
201 @ Unless the divisor is very big, shift it up in multiples of
202 @ four bits, since this is the amount of unwinding in the main
203 @ division loop. Continue shifting until the divisor is
204 @ larger than the dividend.
205 cmp divisor, #0x10000000
206 cmpcc divisor, dividend
207 movcc divisor, divisor, lsl #4
208 movcc curbit, curbit, lsl #4
212 @ For very big divisors, we must shift it a bit at a time, or
213 @ we will be in danger of overflowing.
214 cmp divisor, #0x80000000
215 cmpcc divisor, dividend
216 movcc divisor, divisor, lsl #1
217 movcc curbit, curbit, lsl #1
221 @ Test for possible subtractions, and note which bits
222 @ are done in the result. On the final pass, this may subtract
223 @ too much from the dividend, but the result will be ok, since the
224 @ "bit" will have been shifted out at the bottom.
225 cmp dividend, divisor
226 subcs dividend, dividend, divisor
227 orrcs result, result, curbit
228 cmp dividend, divisor, lsr #1
229 subcs dividend, dividend, divisor, lsr #1
230 orrcs result, result, curbit, lsr #1
231 cmp dividend, divisor, lsr #2
232 subcs dividend, dividend, divisor, lsr #2
233 orrcs result, result, curbit, lsr #2
234 cmp dividend, divisor, lsr #3
235 subcs dividend, dividend, divisor, lsr #3
236 orrcs result, result, curbit, lsr #3
237 cmp dividend, #0 @ Early termination?
238 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
239 movne divisor, divisor, lsr #4
250 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
252 @ Need to save the sign of the dividend, unfortunately, we need
253 @ ip later on; this is faster than pushing lr and using that.
254 str dividend, [sp, #-4]!
256 rsbmi dividend, dividend, #0
257 cmp dividend, divisor
258 bcc Lgot_result_modsi3
261 @ Unless the divisor is very big, shift it up in multiples of
262 @ four bits, since this is the amount of unwinding in the main
263 @ division loop. Continue shifting until the divisor is
264 @ larger than the dividend.
265 cmp divisor, #0x10000000
266 cmpcc divisor, dividend
267 movcc divisor, divisor, lsl #4
268 movcc curbit, curbit, lsl #4
272 @ For very big divisors, we must shift it a bit at a time, or
273 @ we will be in danger of overflowing.
274 cmp divisor, #0x80000000
275 cmpcc divisor, dividend
276 movcc divisor, divisor, lsl #1
277 movcc curbit, curbit, lsl #1
281 @ Test for possible subtractions. On the final pass, this may
282 @ subtract too much from the dividend, so keep track of which
283 @ subtractions are done, we can fix them up afterwards...
285 cmp dividend, divisor
286 subcs dividend, dividend, divisor
287 cmp dividend, divisor, lsr #1
288 subcs dividend, dividend, divisor, lsr #1
289 orrcs overdone, overdone, curbit, ror #1
290 cmp dividend, divisor, lsr #2
291 subcs dividend, dividend, divisor, lsr #2
292 orrcs overdone, overdone, curbit, ror #2
293 cmp dividend, divisor, lsr #3
294 subcs dividend, dividend, divisor, lsr #3
295 orrcs overdone, overdone, curbit, ror #3
297 cmp dividend, #0 @ Early termination?
298 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
299 movne divisor, divisor, lsr #4
302 @ Any subtractions that we should not have done will be recorded in
303 @ the top three bits of "overdone". Exactly which were not needed
304 @ are governed by the position of the bit, stored in ip.
305 @ If we terminated early, because dividend became zero,
306 @ then none of the below will match, since the bit in ip will not be
307 @ in the bottom nibble.
308 ands overdone, overdone, #0xe0000000
309 beq Lgot_result_modsi3
310 tst overdone, ip, ror #3
311 addne dividend, dividend, divisor, lsr #3
312 tst overdone, ip, ror #2
313 addne dividend, dividend, divisor, lsr #2
314 tst overdone, ip, ror #1
315 addne dividend, dividend, divisor, lsr #1
319 rsbmi dividend, dividend, #0