blob: 0e29970b0e8a3603d616f504a6ba9683501acb2d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001@ libgcc1 routines for ARM cpu.
2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
3
4/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
5
6This file is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
13compiled version of this file with other programs, and to distribute
14those programs without any restriction coming from the use of this
15file. (The General Public License restrictions do apply in other
16respects; for example, they cover modification of the file, and
17distribution when not linked into another program.)
18
19This file is distributed in the hope that it will be useful, but
20WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with this program; see the file COPYING. If not, write to
26the Free Software Foundation, 59 Temple Place - Suite 330,
27Boston, MA 02111-1307, USA. */
28
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.
35 */
36/* This code is derived from gcc 2.95.3 */
37/* I Molton 29/07/01 */
38
39#include <linux/linkage.h>
40#include <asm/assembler.h>
41#include <asm/hardware.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#define RET movs
44#define RETc(x) mov##x##s
45#define RETCOND ^
46
47dividend .req r0
48divisor .req r1
49result .req r2
50overdone .req r2
51curbit .req r3
52ip .req r12
53sp .req r13
54lr .req r14
55pc .req r15
56
57ENTRY(__udivsi3)
58 cmp divisor, #0
59 beq Ldiv0
60 mov curbit, #1
61 mov result, #0
62 cmp dividend, divisor
63 bcc Lgot_result_udivsi3
641:
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
73 bcc 1b
74
752:
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
82 bcc 2b
83
843:
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.
89 cmp dividend, divisor
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
104 bne 3b
105Lgot_result_udivsi3:
106 mov r0, result
107 RET pc, lr
108
109Ldiv0:
110 str lr, [sp, #-4]!
111 bl __div0
112 mov r0, #0 @ about as wrong as it could be
113 ldmia sp!, {pc}RETCOND
114
115/* __umodsi3 ----------------------- */
116
117ENTRY(__umodsi3)
118 cmp divisor, #0
119 beq Ldiv0
120 mov curbit, #1
121 cmp dividend, divisor
122 RETc(cc) pc, lr
1231:
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
132 bcc 1b
133
1342:
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
141 bcc 2b
142
1433:
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...
147 mov overdone, #0
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
159 mov ip, curbit
160 cmp dividend, #0 @ Early termination?
161 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
162 movne divisor, divisor, lsr #4
163 bne 3b
164
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
179 RET pc, lr
180
181ENTRY(__divsi3)
182 eor ip, dividend, divisor @ Save the sign of the result.
183 mov curbit, #1
184 mov result, #0
185 cmp divisor, #0
186 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
187 beq Ldiv0
188 cmp dividend, #0
189 rsbmi dividend, dividend, #0
190 cmp dividend, divisor
191 bcc Lgot_result_divsi3
192
1931:
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
202 bcc 1b
203
2042:
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
211 bcc 2b
212
2133:
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
233 bne 3b
234Lgot_result_divsi3:
235 mov r0, result
236 cmp ip, #0
237 rsbmi r0, r0, #0
238 RET pc, lr
239
240ENTRY(__modsi3)
241 mov curbit, #1
242 cmp divisor, #0
243 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
244 beq Ldiv0
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]!
248 cmp dividend, #0
249 rsbmi dividend, dividend, #0
250 cmp dividend, divisor
251 bcc Lgot_result_modsi3
252
2531:
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
262 bcc 1b
263
2642:
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
271 bcc 2b
272
2733:
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...
277 mov overdone, #0
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
289 mov ip, curbit
290 cmp dividend, #0 @ Early termination?
291 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
292 movne divisor, divisor, lsr #4
293 bne 3b
294
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
309Lgot_result_modsi3:
310 ldr ip, [sp], #4
311 cmp ip, #0
312 rsbmi dividend, dividend, #0
313 RET pc, lr