Deleted Added
full compact
lib1funcs.asm (90075) lib1funcs.asm (132718)
1@ libgcc routines for ARM cpu.
2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
3
1@ libgcc routines for ARM cpu.
2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
3
4/* Copyright 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc.
4/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004
5 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

--- 33 unchanged lines hidden (view full) ---

46#ifdef __ELF__
47#ifdef __thumb__
48#define __PLT__ /* Not supported in Thumb assembler (for now). */
49#else
50#define __PLT__ (PLT)
51#endif
52#define TYPE(x) .type SYM(x),function
53#define SIZE(x) .size SYM(x), . - SYM(x)
6
7This file is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 2, or (at your option) any
10later version.
11
12In addition to the permissions in the GNU General Public License, the
13Free Software Foundation gives you unlimited permission to link the

--- 33 unchanged lines hidden (view full) ---

47#ifdef __ELF__
48#ifdef __thumb__
49#define __PLT__ /* Not supported in Thumb assembler (for now). */
50#else
51#define __PLT__ (PLT)
52#endif
53#define TYPE(x) .type SYM(x),function
54#define SIZE(x) .size SYM(x), . - SYM(x)
55#define LSYM(x) .x
54#else
55#define __PLT__
56#define TYPE(x)
57#define SIZE(x)
56#else
57#define __PLT__
58#define TYPE(x)
59#define SIZE(x)
60#define LSYM(x) x
58#endif
59
60/* Function end macros. Variants for 26 bit APCS and interworking. */
61
61#endif
62
63/* Function end macros. Variants for 26 bit APCS and interworking. */
64
65@ This selects the minimum architecture level required.
66#define __ARM_ARCH__ 3
67
68#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
69 || defined(__ARM_ARCH_4T__)
70/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
71 long multiply instructions. That includes v3M. */
72# undef __ARM_ARCH__
73# define __ARM_ARCH__ 4
74#endif
75
76#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
77 || defined(__ARM_ARCH_5TE__)
78# undef __ARM_ARCH__
79# define __ARM_ARCH__ 5
80#endif
81
82/* How to return from a function call depends on the architecture variant. */
83
62#ifdef __APCS_26__
84#ifdef __APCS_26__
85
63# define RET movs pc, lr
64# define RETc(x) mov##x##s pc, lr
86# define RET movs pc, lr
87# define RETc(x) mov##x##s pc, lr
65# define RETCOND ^
88
89#elif (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
90
91# define RET bx lr
92# define RETc(x) bx##x lr
93
94# if (__ARM_ARCH__ == 4) \
95 && (defined(__thumb__) || defined(__THUMB_INTERWORK__))
96# define __INTERWORKING__
97# endif
98
99#else
100
101# define RET mov pc, lr
102# define RETc(x) mov##x pc, lr
103
104#endif
105
106/* Don't pass dirn, it's there just to get token pasting right. */
107
108.macro RETLDM regs=, cond=, dirn=ia
109#ifdef __APCS_26__
110 .ifc "\regs",""
111 ldm\cond\dirn sp!, {pc}^
112 .else
113 ldm\cond\dirn sp!, {\regs, pc}^
114 .endif
115#elif defined (__INTERWORKING__)
116 .ifc "\regs",""
117 ldr\cond lr, [sp], #4
118 .else
119 ldm\cond\dirn sp!, {\regs, lr}
120 .endif
121 bx\cond lr
122#else
123 .ifc "\regs",""
124 ldr\cond pc, [sp], #4
125 .else
126 ldm\cond\dirn sp!, {\regs, pc}
127 .endif
128#endif
129.endm
130
131
66.macro ARM_LDIV0
132.macro ARM_LDIV0
67Ldiv0:
133LSYM(Ldiv0):
68 str lr, [sp, #-4]!
69 bl SYM (__div0) __PLT__
70 mov r0, #0 @ About as wrong as it could be.
134 str lr, [sp, #-4]!
135 bl SYM (__div0) __PLT__
136 mov r0, #0 @ About as wrong as it could be.
71 ldmia sp!, {pc}^
137 RETLDM
72.endm
138.endm
73#else
74# ifdef __THUMB_INTERWORK__
75# define RET bx lr
76# define RETc(x) bx##x lr
139
140
77.macro THUMB_LDIV0
141.macro THUMB_LDIV0
78Ldiv0:
142LSYM(Ldiv0):
79 push { lr }
80 bl SYM (__div0)
81 mov r0, #0 @ About as wrong as it could be.
143 push { lr }
144 bl SYM (__div0)
145 mov r0, #0 @ About as wrong as it could be.
146#if defined (__INTERWORKING__)
82 pop { r1 }
83 bx r1
147 pop { r1 }
148 bx r1
84.endm
85.macro ARM_LDIV0
86Ldiv0:
87 str lr, [sp, #-4]!
88 bl SYM (__div0) __PLT__
89 mov r0, #0 @ About as wrong as it could be.
90 ldr lr, [sp], #4
91 bx lr
92.endm
93# else
94# define RET mov pc, lr
95# define RETc(x) mov##x pc, lr
96.macro THUMB_LDIV0
97Ldiv0:
98 push { lr }
99 bl SYM (__div0)
100 mov r0, #0 @ About as wrong as it could be.
149#else
101 pop { pc }
150 pop { pc }
102.endm
103.macro ARM_LDIV0
104Ldiv0:
105 str lr, [sp, #-4]!
106 bl SYM (__div0) __PLT__
107 mov r0, #0 @ About as wrong as it could be.
108 ldmia sp!, {pc}
109.endm
110# endif
111# define RETCOND
112#endif
151#endif
152.endm
113
114.macro FUNC_END name
153
154.macro FUNC_END name
115Ldiv0:
155 SIZE (__\name)
156.endm
157
158.macro DIV_FUNC_END name
159LSYM(Ldiv0):
116#ifdef __thumb__
117 THUMB_LDIV0
118#else
119 ARM_LDIV0
120#endif
160#ifdef __thumb__
161 THUMB_LDIV0
162#else
163 ARM_LDIV0
164#endif
121 SIZE (__\name)
165 FUNC_END \name
122.endm
123
124.macro THUMB_FUNC_START name
125 .globl SYM (\name)
126 TYPE (\name)
127 .thumb_func
128SYM (\name):
129.endm

--- 12 unchanged lines hidden (view full) ---

142 .text
143 .globl SYM (__\name)
144 TYPE (__\name)
145 .align 0
146 THUMB_CODE
147 THUMB_FUNC
148SYM (__\name):
149.endm
166.endm
167
168.macro THUMB_FUNC_START name
169 .globl SYM (\name)
170 TYPE (\name)
171 .thumb_func
172SYM (\name):
173.endm

--- 12 unchanged lines hidden (view full) ---

186 .text
187 .globl SYM (__\name)
188 TYPE (__\name)
189 .align 0
190 THUMB_CODE
191 THUMB_FUNC
192SYM (__\name):
193.endm
150
194
195/* Special function that will always be coded in ARM assembly, even if
196 in Thumb-only compilation. */
197
198#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
199.macro ARM_FUNC_START name
200 FUNC_START \name
201 bx pc
202 nop
203 .arm
204_L__\name: /* A hook to tell gdb that we've switched to ARM */
205.endm
206#define EQUIV .thumb_set
207#else
208.macro ARM_FUNC_START name
209 .text
210 .globl SYM (__\name)
211 TYPE (__\name)
212 .align 0
213 .arm
214SYM (__\name):
215.endm
216#define EQUIV .set
217#endif
218
219.macro ARM_FUNC_ALIAS new old
220 .globl SYM (__\new)
221 EQUIV SYM (__\new), SYM (__\old)
222.endm
223
224#ifdef __thumb__
151/* Register aliases. */
152
153work .req r4 @ XXXX is this safe ?
154dividend .req r0
155divisor .req r1
156overdone .req r2
157result .req r2
158curbit .req r3
225/* Register aliases. */
226
227work .req r4 @ XXXX is this safe ?
228dividend .req r0
229divisor .req r1
230overdone .req r2
231result .req r2
232curbit .req r3
233#endif
234#if 0
159ip .req r12
160sp .req r13
161lr .req r14
162pc .req r15
235ip .req r12
236sp .req r13
237lr .req r14
238pc .req r15
239#endif
163
164/* ------------------------------------------------------------------------ */
240
241/* ------------------------------------------------------------------------ */
165/* Bodies of the divsion and modulo routines. */
242/* Bodies of the division and modulo routines. */
166/* ------------------------------------------------------------------------ */
243/* ------------------------------------------------------------------------ */
167.macro ARM_DIV_MOD_BODY modulo
168Loop1:
244.macro ARM_DIV_BODY dividend, divisor, result, curbit
245
246#if __ARM_ARCH__ >= 5
247
248 clz \curbit, \divisor
249 clz \result, \dividend
250 sub \result, \curbit, \result
251 mov \curbit, #1
252 mov \divisor, \divisor, lsl \result
253 mov \curbit, \curbit, lsl \result
254 mov \result, #0
255
256#else
257
258 @ Initially shift the divisor left 3 bits if possible,
259 @ set curbit accordingly. This allows for curbit to be located
260 @ at the left end of each 4 bit nibbles in the division loop
261 @ to save one loop in most cases.
262 tst \divisor, #0xe0000000
263 moveq \divisor, \divisor, lsl #3
264 moveq \curbit, #8
265 movne \curbit, #1
266
169 @ Unless the divisor is very big, shift it up in multiples of
170 @ four bits, since this is the amount of unwinding in the main
171 @ division loop. Continue shifting until the divisor is
172 @ larger than the dividend.
267 @ Unless the divisor is very big, shift it up in multiples of
268 @ four bits, since this is the amount of unwinding in the main
269 @ division loop. Continue shifting until the divisor is
270 @ larger than the dividend.
173 cmp divisor, #0x10000000
174 cmplo divisor, dividend
175 movlo divisor, divisor, lsl #4
176 movlo curbit, curbit, lsl #4
177 blo Loop1
2711: cmp \divisor, #0x10000000
272 cmplo \divisor, \dividend
273 movlo \divisor, \divisor, lsl #4
274 movlo \curbit, \curbit, lsl #4
275 blo 1b
178
276
179Lbignum:
180 @ For very big divisors, we must shift it a bit at a time, or
181 @ we will be in danger of overflowing.
277 @ For very big divisors, we must shift it a bit at a time, or
278 @ we will be in danger of overflowing.
182 cmp divisor, #0x80000000
183 cmplo divisor, dividend
184 movlo divisor, divisor, lsl #1
185 movlo curbit, curbit, lsl #1
186 blo Lbignum
2791: cmp \divisor, #0x80000000
280 cmplo \divisor, \dividend
281 movlo \divisor, \divisor, lsl #1
282 movlo \curbit, \curbit, lsl #1
283 blo 1b
187
284
188Loop3:
189 @ Test for possible subtractions. On the final pass, this may
190 @ subtract too much from the dividend ...
285 mov \result, #0
286
287#endif
288
289 @ Division loop
2901: cmp \dividend, \divisor
291 subhs \dividend, \dividend, \divisor
292 orrhs \result, \result, \curbit
293 cmp \dividend, \divisor, lsr #1
294 subhs \dividend, \dividend, \divisor, lsr #1
295 orrhs \result, \result, \curbit, lsr #1
296 cmp \dividend, \divisor, lsr #2
297 subhs \dividend, \dividend, \divisor, lsr #2
298 orrhs \result, \result, \curbit, lsr #2
299 cmp \dividend, \divisor, lsr #3
300 subhs \dividend, \dividend, \divisor, lsr #3
301 orrhs \result, \result, \curbit, lsr #3
302 cmp \dividend, #0 @ Early termination?
303 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
304 movne \divisor, \divisor, lsr #4
305 bne 1b
306
307.endm
308/* ------------------------------------------------------------------------ */
309.macro ARM_DIV2_ORDER divisor, order
310
311#if __ARM_ARCH__ >= 5
312
313 clz \order, \divisor
314 rsb \order, \order, #31
315
316#else
317
318 cmp \divisor, #(1 << 16)
319 movhs \divisor, \divisor, lsr #16
320 movhs \order, #16
321 movlo \order, #0
322
323 cmp \divisor, #(1 << 8)
324 movhs \divisor, \divisor, lsr #8
325 addhs \order, \order, #8
326
327 cmp \divisor, #(1 << 4)
328 movhs \divisor, \divisor, lsr #4
329 addhs \order, \order, #4
330
331 cmp \divisor, #(1 << 2)
332 addhi \order, \order, #3
333 addls \order, \order, \divisor, lsr #1
334
335#endif
336
337.endm
338/* ------------------------------------------------------------------------ */
339.macro ARM_MOD_BODY dividend, divisor, order, spare
340
341#if __ARM_ARCH__ >= 5
342
343 clz \order, \divisor
344 clz \spare, \dividend
345 sub \order, \order, \spare
346 mov \divisor, \divisor, lsl \order
191
347
192 .if \modulo
193 @ ... so keep track of which subtractions are done in OVERDONE.
194 @ We can fix them up afterwards.
195 mov overdone, #0
196 cmp dividend, divisor
197 subhs dividend, dividend, divisor
198 cmp dividend, divisor, lsr #1
199 subhs dividend, dividend, divisor, lsr #1
200 orrhs overdone, overdone, curbit, ror #1
201 cmp dividend, divisor, lsr #2
202 subhs dividend, dividend, divisor, lsr #2
203 orrhs overdone, overdone, curbit, ror #2
204 cmp dividend, divisor, lsr #3
205 subhs dividend, dividend, divisor, lsr #3
206 orrhs overdone, overdone, curbit, ror #3
207 mov ip, curbit
208 .else
209 @ ... so keep track of which subtractions are done in RESULT.
210 @ The result will be ok, since the "bit" will have been
211 @ shifted out at the bottom.
212 cmp dividend, divisor
213 subhs dividend, dividend, divisor
214 orrhs result, result, curbit
215 cmp dividend, divisor, lsr #1
216 subhs dividend, dividend, divisor, lsr #1
217 orrhs result, result, curbit, lsr #1
218 cmp dividend, divisor, lsr #2
219 subhs dividend, dividend, divisor, lsr #2
220 orrhs result, result, curbit, lsr #2
221 cmp dividend, divisor, lsr #3
222 subhs dividend, dividend, divisor, lsr #3
223 orrhs result, result, curbit, lsr #3
224 .endif
348#else
225
349
226 cmp dividend, #0 @ Early termination?
227 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
228 movne divisor, divisor, lsr #4
229 bne Loop3
350 mov \order, #0
230
351
231 .if \modulo
232Lfixup_dividend:
233 @ Any subtractions that we should not have done will be recorded in
234 @ the top three bits of OVERDONE. Exactly which were not needed
235 @ are governed by the position of the bit, stored in IP.
236 ands overdone, overdone, #0xe0000000
237 @ If we terminated early, because dividend became zero, then the
238 @ bit in ip will not be in the bottom nibble, and we should not
239 @ perform the additions below. We must test for this though
240 @ (rather relying upon the TSTs to prevent the additions) since
241 @ the bit in ip could be in the top two bits which might then match
242 @ with one of the smaller RORs.
243 tstne ip, #0x7
244 beq Lgot_result
245 tst overdone, ip, ror #3
246 addne dividend, dividend, divisor, lsr #3
247 tst overdone, ip, ror #2
248 addne dividend, dividend, divisor, lsr #2
249 tst overdone, ip, ror #1
250 addne dividend, dividend, divisor, lsr #1
251 .endif
352 @ Unless the divisor is very big, shift it up in multiples of
353 @ four bits, since this is the amount of unwinding in the main
354 @ division loop. Continue shifting until the divisor is
355 @ larger than the dividend.
3561: cmp \divisor, #0x10000000
357 cmplo \divisor, \dividend
358 movlo \divisor, \divisor, lsl #4
359 addlo \order, \order, #4
360 blo 1b
252
361
253Lgot_result:
362 @ For very big divisors, we must shift it a bit at a time, or
363 @ we will be in danger of overflowing.
3641: cmp \divisor, #0x80000000
365 cmplo \divisor, \dividend
366 movlo \divisor, \divisor, lsl #1
367 addlo \order, \order, #1
368 blo 1b
369
370#endif
371
372 @ Perform all needed substractions to keep only the reminder.
373 @ Do comparisons in batch of 4 first.
374 subs \order, \order, #3 @ yes, 3 is intended here
375 blt 2f
376
3771: cmp \dividend, \divisor
378 subhs \dividend, \dividend, \divisor
379 cmp \dividend, \divisor, lsr #1
380 subhs \dividend, \dividend, \divisor, lsr #1
381 cmp \dividend, \divisor, lsr #2
382 subhs \dividend, \dividend, \divisor, lsr #2
383 cmp \dividend, \divisor, lsr #3
384 subhs \dividend, \dividend, \divisor, lsr #3
385 cmp \dividend, #1
386 mov \divisor, \divisor, lsr #4
387 subges \order, \order, #4
388 bge 1b
389
390 tst \order, #3
391 teqne \dividend, #0
392 beq 5f
393
394 @ Either 1, 2 or 3 comparison/substractions are left.
3952: cmn \order, #2
396 blt 4f
397 beq 3f
398 cmp \dividend, \divisor
399 subhs \dividend, \dividend, \divisor
400 mov \divisor, \divisor, lsr #1
4013: cmp \dividend, \divisor
402 subhs \dividend, \dividend, \divisor
403 mov \divisor, \divisor, lsr #1
4044: cmp \dividend, \divisor
405 subhs \dividend, \dividend, \divisor
4065:
254.endm
255/* ------------------------------------------------------------------------ */
256.macro THUMB_DIV_MOD_BODY modulo
257 @ Load the constant 0x10000000 into our work register.
258 mov work, #1
259 lsl work, #28
407.endm
408/* ------------------------------------------------------------------------ */
409.macro THUMB_DIV_MOD_BODY modulo
410 @ Load the constant 0x10000000 into our work register.
411 mov work, #1
412 lsl work, #28
260Loop1:
413LSYM(Loop1):
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, work
414 @ Unless the divisor is very big, shift it up in multiples of
415 @ four bits, since this is the amount of unwinding in the main
416 @ division loop. Continue shifting until the divisor is
417 @ larger than the dividend.
418 cmp divisor, work
266 bhs Lbignum
419 bhs LSYM(Lbignum)
267 cmp divisor, dividend
420 cmp divisor, dividend
268 bhs Lbignum
421 bhs LSYM(Lbignum)
269 lsl divisor, #4
270 lsl curbit, #4
422 lsl divisor, #4
423 lsl curbit, #4
271 b Loop1
272Lbignum:
424 b LSYM(Loop1)
425LSYM(Lbignum):
273 @ Set work to 0x80000000
274 lsl work, #3
426 @ Set work to 0x80000000
427 lsl work, #3
275Loop2:
428LSYM(Loop2):
276 @ For very big divisors, we must shift it a bit at a time, or
277 @ we will be in danger of overflowing.
278 cmp divisor, work
429 @ For very big divisors, we must shift it a bit at a time, or
430 @ we will be in danger of overflowing.
431 cmp divisor, work
279 bhs Loop3
432 bhs LSYM(Loop3)
280 cmp divisor, dividend
433 cmp divisor, dividend
281 bhs Loop3
434 bhs LSYM(Loop3)
282 lsl divisor, #1
283 lsl curbit, #1
435 lsl divisor, #1
436 lsl curbit, #1
284 b Loop2
285Loop3:
437 b LSYM(Loop2)
438LSYM(Loop3):
286 @ Test for possible subtractions ...
287 .if \modulo
288 @ ... On the final pass, this may subtract too much from the dividend,
289 @ so keep track of which subtractions are done, we can fix them up
290 @ afterwards.
291 mov overdone, #0
292 cmp dividend, divisor
439 @ Test for possible subtractions ...
440 .if \modulo
441 @ ... On the final pass, this may subtract too much from the dividend,
442 @ so keep track of which subtractions are done, we can fix them up
443 @ afterwards.
444 mov overdone, #0
445 cmp dividend, divisor
293 blo Lover1
446 blo LSYM(Lover1)
294 sub dividend, dividend, divisor
447 sub dividend, dividend, divisor
295Lover1:
448LSYM(Lover1):
296 lsr work, divisor, #1
297 cmp dividend, work
449 lsr work, divisor, #1
450 cmp dividend, work
298 blo Lover2
451 blo LSYM(Lover2)
299 sub dividend, dividend, work
300 mov ip, curbit
301 mov work, #1
302 ror curbit, work
303 orr overdone, curbit
304 mov curbit, ip
452 sub dividend, dividend, work
453 mov ip, curbit
454 mov work, #1
455 ror curbit, work
456 orr overdone, curbit
457 mov curbit, ip
305Lover2:
458LSYM(Lover2):
306 lsr work, divisor, #2
307 cmp dividend, work
459 lsr work, divisor, #2
460 cmp dividend, work
308 blo Lover3
461 blo LSYM(Lover3)
309 sub dividend, dividend, work
310 mov ip, curbit
311 mov work, #2
312 ror curbit, work
313 orr overdone, curbit
314 mov curbit, ip
462 sub dividend, dividend, work
463 mov ip, curbit
464 mov work, #2
465 ror curbit, work
466 orr overdone, curbit
467 mov curbit, ip
315Lover3:
468LSYM(Lover3):
316 lsr work, divisor, #3
317 cmp dividend, work
469 lsr work, divisor, #3
470 cmp dividend, work
318 blo Lover4
471 blo LSYM(Lover4)
319 sub dividend, dividend, work
320 mov ip, curbit
321 mov work, #3
322 ror curbit, work
323 orr overdone, curbit
324 mov curbit, ip
472 sub dividend, dividend, work
473 mov ip, curbit
474 mov work, #3
475 ror curbit, work
476 orr overdone, curbit
477 mov curbit, ip
325Lover4:
478LSYM(Lover4):
326 mov ip, curbit
327 .else
328 @ ... and note which bits are done in the result. On the final pass,
329 @ this may subtract too much from the dividend, but the result will be ok,
330 @ since the "bit" will have been shifted out at the bottom.
331 cmp dividend, divisor
479 mov ip, curbit
480 .else
481 @ ... and note which bits are done in the result. On the final pass,
482 @ this may subtract too much from the dividend, but the result will be ok,
483 @ since the "bit" will have been shifted out at the bottom.
484 cmp dividend, divisor
332 blo Lover1
485 blo LSYM(Lover1)
333 sub dividend, dividend, divisor
334 orr result, result, curbit
486 sub dividend, dividend, divisor
487 orr result, result, curbit
335Lover1:
488LSYM(Lover1):
336 lsr work, divisor, #1
337 cmp dividend, work
489 lsr work, divisor, #1
490 cmp dividend, work
338 blo Lover2
491 blo LSYM(Lover2)
339 sub dividend, dividend, work
340 lsr work, curbit, #1
341 orr result, work
492 sub dividend, dividend, work
493 lsr work, curbit, #1
494 orr result, work
342Lover2:
495LSYM(Lover2):
343 lsr work, divisor, #2
344 cmp dividend, work
496 lsr work, divisor, #2
497 cmp dividend, work
345 blo Lover3
498 blo LSYM(Lover3)
346 sub dividend, dividend, work
347 lsr work, curbit, #2
348 orr result, work
499 sub dividend, dividend, work
500 lsr work, curbit, #2
501 orr result, work
349Lover3:
502LSYM(Lover3):
350 lsr work, divisor, #3
351 cmp dividend, work
503 lsr work, divisor, #3
504 cmp dividend, work
352 blo Lover4
505 blo LSYM(Lover4)
353 sub dividend, dividend, work
354 lsr work, curbit, #3
355 orr result, work
506 sub dividend, dividend, work
507 lsr work, curbit, #3
508 orr result, work
356Lover4:
509LSYM(Lover4):
357 .endif
358
359 cmp dividend, #0 @ Early termination?
510 .endif
511
512 cmp dividend, #0 @ Early termination?
360 beq Lover5
513 beq LSYM(Lover5)
361 lsr curbit, #4 @ No, any more bits to do?
514 lsr curbit, #4 @ No, any more bits to do?
362 beq Lover5
515 beq LSYM(Lover5)
363 lsr divisor, #4
516 lsr divisor, #4
364 b Loop3
365Lover5:
517 b LSYM(Loop3)
518LSYM(Lover5):
366 .if \modulo
367 @ Any subtractions that we should not have done will be recorded in
368 @ the top three bits of "overdone". Exactly which were not needed
369 @ are governed by the position of the bit, stored in ip.
370 mov work, #0xe
371 lsl work, #28
372 and overdone, work
519 .if \modulo
520 @ Any subtractions that we should not have done will be recorded in
521 @ the top three bits of "overdone". Exactly which were not needed
522 @ are governed by the position of the bit, stored in ip.
523 mov work, #0xe
524 lsl work, #28
525 and overdone, work
373 beq Lgot_result
526 beq LSYM(Lgot_result)
374
375 @ If we terminated early, because dividend became zero, then the
376 @ bit in ip will not be in the bottom nibble, and we should not
377 @ perform the additions below. We must test for this though
378 @ (rather relying upon the TSTs to prevent the additions) since
379 @ the bit in ip could be in the top two bits which might then match
380 @ with one of the smaller RORs.
381 mov curbit, ip
382 mov work, #0x7
383 tst curbit, work
527
528 @ If we terminated early, because dividend became zero, then the
529 @ bit in ip will not be in the bottom nibble, and we should not
530 @ perform the additions below. We must test for this though
531 @ (rather relying upon the TSTs to prevent the additions) since
532 @ the bit in ip could be in the top two bits which might then match
533 @ with one of the smaller RORs.
534 mov curbit, ip
535 mov work, #0x7
536 tst curbit, work
384 beq Lgot_result
537 beq LSYM(Lgot_result)
385
386 mov curbit, ip
387 mov work, #3
388 ror curbit, work
389 tst overdone, curbit
538
539 mov curbit, ip
540 mov work, #3
541 ror curbit, work
542 tst overdone, curbit
390 beq Lover6
543 beq LSYM(Lover6)
391 lsr work, divisor, #3
392 add dividend, work
544 lsr work, divisor, #3
545 add dividend, work
393Lover6:
546LSYM(Lover6):
394 mov curbit, ip
395 mov work, #2
396 ror curbit, work
397 tst overdone, curbit
547 mov curbit, ip
548 mov work, #2
549 ror curbit, work
550 tst overdone, curbit
398 beq Lover7
551 beq LSYM(Lover7)
399 lsr work, divisor, #2
400 add dividend, work
552 lsr work, divisor, #2
553 add dividend, work
401Lover7:
554LSYM(Lover7):
402 mov curbit, ip
403 mov work, #1
404 ror curbit, work
405 tst overdone, curbit
555 mov curbit, ip
556 mov work, #1
557 ror curbit, work
558 tst overdone, curbit
406 beq Lgot_result
559 beq LSYM(Lgot_result)
407 lsr work, divisor, #1
408 add dividend, work
409 .endif
560 lsr work, divisor, #1
561 add dividend, work
562 .endif
410Lgot_result:
563LSYM(Lgot_result):
411.endm
412/* ------------------------------------------------------------------------ */
413/* Start of the Real Functions */
414/* ------------------------------------------------------------------------ */
415#ifdef L_udivsi3
416
417 FUNC_START udivsi3
418
419#ifdef __thumb__
420
421 cmp divisor, #0
564.endm
565/* ------------------------------------------------------------------------ */
566/* Start of the Real Functions */
567/* ------------------------------------------------------------------------ */
568#ifdef L_udivsi3
569
570 FUNC_START udivsi3
571
572#ifdef __thumb__
573
574 cmp divisor, #0
422 beq Ldiv0
575 beq LSYM(Ldiv0)
423 mov curbit, #1
424 mov result, #0
425
426 push { work }
427 cmp dividend, divisor
576 mov curbit, #1
577 mov result, #0
578
579 push { work }
580 cmp dividend, divisor
428 blo Lgot_result
581 blo LSYM(Lgot_result)
429
430 THUMB_DIV_MOD_BODY 0
431
432 mov r0, result
433 pop { work }
434 RET
435
436#else /* ARM version. */
582
583 THUMB_DIV_MOD_BODY 0
584
585 mov r0, result
586 pop { work }
587 RET
588
589#else /* ARM version. */
590
591 subs r2, r1, #1
592 RETc(eq)
593 bcc LSYM(Ldiv0)
594 cmp r0, r1
595 bls 11f
596 tst r1, r2
597 beq 12f
437
598
438 cmp divisor, #0
439 beq Ldiv0
440 mov curbit, #1
441 mov result, #0
442 cmp dividend, divisor
443 blo Lgot_result
599 ARM_DIV_BODY r0, r1, r2, r3
444
600
445 ARM_DIV_MOD_BODY 0
446
447 mov r0, result
601 mov r0, r2
448 RET
449
602 RET
603
60411: moveq r0, #1
605 movne r0, #0
606 RET
607
60812: ARM_DIV2_ORDER r1, r2
609
610 mov r0, r0, lsr r2
611 RET
612
450#endif /* ARM version */
451
613#endif /* ARM version */
614
452 FUNC_END udivsi3
615 DIV_FUNC_END udivsi3
453
454#endif /* L_udivsi3 */
455/* ------------------------------------------------------------------------ */
456#ifdef L_umodsi3
457
458 FUNC_START umodsi3
459
460#ifdef __thumb__
461
462 cmp divisor, #0
616
617#endif /* L_udivsi3 */
618/* ------------------------------------------------------------------------ */
619#ifdef L_umodsi3
620
621 FUNC_START umodsi3
622
623#ifdef __thumb__
624
625 cmp divisor, #0
463 beq Ldiv0
626 beq LSYM(Ldiv0)
464 mov curbit, #1
465 cmp dividend, divisor
627 mov curbit, #1
628 cmp dividend, divisor
466 bhs Lover10
629 bhs LSYM(Lover10)
467 RET
468
630 RET
631
469Lover10:
632LSYM(Lover10):
470 push { work }
471
472 THUMB_DIV_MOD_BODY 1
473
474 pop { work }
475 RET
476
477#else /* ARM version. */
478
633 push { work }
634
635 THUMB_DIV_MOD_BODY 1
636
637 pop { work }
638 RET
639
640#else /* ARM version. */
641
479 cmp divisor, #0
480 beq Ldiv0
481 cmp divisor, #1
482 cmpne dividend, divisor
483 moveq dividend, #0
484 RETc(lo)
485 mov curbit, #1
642 subs r2, r1, #1 @ compare divisor with 1
643 bcc LSYM(Ldiv0)
644 cmpne r0, r1 @ compare dividend with divisor
645 moveq r0, #0
646 tsthi r1, r2 @ see if divisor is power of 2
647 andeq r0, r0, r2
648 RETc(ls)
486
649
487 ARM_DIV_MOD_BODY 1
650 ARM_MOD_BODY r0, r1, r2, r3
488
489 RET
490
491#endif /* ARM version. */
492
651
652 RET
653
654#endif /* ARM version. */
655
493 FUNC_END umodsi3
656 DIV_FUNC_END umodsi3
494
495#endif /* L_umodsi3 */
496/* ------------------------------------------------------------------------ */
497#ifdef L_divsi3
498
499 FUNC_START divsi3
500
501#ifdef __thumb__
502 cmp divisor, #0
657
658#endif /* L_umodsi3 */
659/* ------------------------------------------------------------------------ */
660#ifdef L_divsi3
661
662 FUNC_START divsi3
663
664#ifdef __thumb__
665 cmp divisor, #0
503 beq Ldiv0
666 beq LSYM(Ldiv0)
504
505 push { work }
506 mov work, dividend
507 eor work, divisor @ Save the sign of the result.
508 mov ip, work
509 mov curbit, #1
510 mov result, #0
511 cmp divisor, #0
667
668 push { work }
669 mov work, dividend
670 eor work, divisor @ Save the sign of the result.
671 mov ip, work
672 mov curbit, #1
673 mov result, #0
674 cmp divisor, #0
512 bpl Lover10
675 bpl LSYM(Lover10)
513 neg divisor, divisor @ Loops below use unsigned.
676 neg divisor, divisor @ Loops below use unsigned.
514Lover10:
677LSYM(Lover10):
515 cmp dividend, #0
678 cmp dividend, #0
516 bpl Lover11
679 bpl LSYM(Lover11)
517 neg dividend, dividend
680 neg dividend, dividend
518Lover11:
681LSYM(Lover11):
519 cmp dividend, divisor
682 cmp dividend, divisor
520 blo Lgot_result
683 blo LSYM(Lgot_result)
521
522 THUMB_DIV_MOD_BODY 0
523
524 mov r0, result
525 mov work, ip
526 cmp work, #0
684
685 THUMB_DIV_MOD_BODY 0
686
687 mov r0, result
688 mov work, ip
689 cmp work, #0
527 bpl Lover12
690 bpl LSYM(Lover12)
528 neg r0, r0
691 neg r0, r0
529Lover12:
692LSYM(Lover12):
530 pop { work }
531 RET
532
533#else /* ARM version. */
534
693 pop { work }
694 RET
695
696#else /* ARM version. */
697
535 eor ip, dividend, divisor @ Save the sign of the result.
536 mov curbit, #1
537 mov result, #0
538 cmp divisor, #0
539 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
540 beq Ldiv0
541 cmp dividend, #0
542 rsbmi dividend, dividend, #0
543 cmp dividend, divisor
544 blo Lgot_result
698 cmp r1, #0
699 eor ip, r0, r1 @ save the sign of the result.
700 beq LSYM(Ldiv0)
701 rsbmi r1, r1, #0 @ loops below use unsigned.
702 subs r2, r1, #1 @ division by 1 or -1 ?
703 beq 10f
704 movs r3, r0
705 rsbmi r3, r0, #0 @ positive dividend value
706 cmp r3, r1
707 bls 11f
708 tst r1, r2 @ divisor is power of 2 ?
709 beq 12f
545
710
546 ARM_DIV_MOD_BODY 0
711 ARM_DIV_BODY r3, r1, r0, r2
547
712
548 mov r0, result
549 cmp ip, #0
550 rsbmi r0, r0, #0
551 RET
552
713 cmp ip, #0
714 rsbmi r0, r0, #0
715 RET
716
71710: teq ip, r0 @ same sign ?
718 rsbmi r0, r0, #0
719 RET
720
72111: movlo r0, #0
722 moveq r0, ip, asr #31
723 orreq r0, r0, #1
724 RET
725
72612: ARM_DIV2_ORDER r1, r2
727
728 cmp ip, #0
729 mov r0, r3, lsr r2
730 rsbmi r0, r0, #0
731 RET
732
553#endif /* ARM version */
554
733#endif /* ARM version */
734
555 FUNC_END divsi3
735 DIV_FUNC_END divsi3
556
557#endif /* L_divsi3 */
558/* ------------------------------------------------------------------------ */
559#ifdef L_modsi3
560
561 FUNC_START modsi3
562
563#ifdef __thumb__
564
565 mov curbit, #1
566 cmp divisor, #0
736
737#endif /* L_divsi3 */
738/* ------------------------------------------------------------------------ */
739#ifdef L_modsi3
740
741 FUNC_START modsi3
742
743#ifdef __thumb__
744
745 mov curbit, #1
746 cmp divisor, #0
567 beq Ldiv0
568 bpl Lover10
747 beq LSYM(Ldiv0)
748 bpl LSYM(Lover10)
569 neg divisor, divisor @ Loops below use unsigned.
749 neg divisor, divisor @ Loops below use unsigned.
570Lover10:
750LSYM(Lover10):
571 push { work }
572 @ Need to save the sign of the dividend, unfortunately, we need
573 @ work later on. Must do this after saving the original value of
574 @ the work register, because we will pop this value off first.
575 push { dividend }
576 cmp dividend, #0
751 push { work }
752 @ Need to save the sign of the dividend, unfortunately, we need
753 @ work later on. Must do this after saving the original value of
754 @ the work register, because we will pop this value off first.
755 push { dividend }
756 cmp dividend, #0
577 bpl Lover11
757 bpl LSYM(Lover11)
578 neg dividend, dividend
758 neg dividend, dividend
579Lover11:
759LSYM(Lover11):
580 cmp dividend, divisor
760 cmp dividend, divisor
581 blo Lgot_result
761 blo LSYM(Lgot_result)
582
583 THUMB_DIV_MOD_BODY 1
584
585 pop { work }
586 cmp work, #0
762
763 THUMB_DIV_MOD_BODY 1
764
765 pop { work }
766 cmp work, #0
587 bpl Lover12
767 bpl LSYM(Lover12)
588 neg dividend, dividend
768 neg dividend, dividend
589Lover12:
769LSYM(Lover12):
590 pop { work }
591 RET
592
593#else /* ARM version. */
594
770 pop { work }
771 RET
772
773#else /* ARM version. */
774
595 cmp divisor, #0
596 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
597 beq Ldiv0
598 @ Need to save the sign of the dividend, unfortunately, we need
599 @ ip later on; this is faster than pushing lr and using that.
600 str dividend, [sp, #-4]!
601 cmp dividend, #0 @ Test dividend against zero
602 rsbmi dividend, dividend, #0 @ If negative make positive
603 cmp dividend, divisor @ else if zero return zero
604 blo Lgot_result @ if smaller return dividend
605 mov curbit, #1
775 cmp r1, #0
776 beq LSYM(Ldiv0)
777 rsbmi r1, r1, #0 @ loops below use unsigned.
778 movs ip, r0 @ preserve sign of dividend
779 rsbmi r0, r0, #0 @ if negative make positive
780 subs r2, r1, #1 @ compare divisor with 1
781 cmpne r0, r1 @ compare dividend with divisor
782 moveq r0, #0
783 tsthi r1, r2 @ see if divisor is power of 2
784 andeq r0, r0, r2
785 bls 10f
606
786
607 ARM_DIV_MOD_BODY 1
787 ARM_MOD_BODY r0, r1, r2, r3
608
788
609 ldr ip, [sp], #4
610 cmp ip, #0
611 rsbmi dividend, dividend, #0
78910: cmp ip, #0
790 rsbmi r0, r0, #0
612 RET
613
614#endif /* ARM version */
615
791 RET
792
793#endif /* ARM version */
794
616 FUNC_END modsi3
795 DIV_FUNC_END modsi3
617
618#endif /* L_modsi3 */
619/* ------------------------------------------------------------------------ */
620#ifdef L_dvmd_tls
621
622 FUNC_START div0
623
624 RET
625
796
797#endif /* L_modsi3 */
798/* ------------------------------------------------------------------------ */
799#ifdef L_dvmd_tls
800
801 FUNC_START div0
802
803 RET
804
626 SIZE (__div0)
805 FUNC_END div0
627
628#endif /* L_divmodsi_tools */
629/* ------------------------------------------------------------------------ */
630#ifdef L_dvmd_lnx
631@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
632
633/* Constants taken from <asm/unistd.h> and <asm/signal.h> */
634#define SIGFPE 8
635#define __NR_SYSCALL_BASE 0x900000
636#define __NR_getpid (__NR_SYSCALL_BASE+ 20)
637#define __NR_kill (__NR_SYSCALL_BASE+ 37)
638
806
807#endif /* L_divmodsi_tools */
808/* ------------------------------------------------------------------------ */
809#ifdef L_dvmd_lnx
810@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
811
812/* Constants taken from <asm/unistd.h> and <asm/signal.h> */
813#define SIGFPE 8
814#define __NR_SYSCALL_BASE 0x900000
815#define __NR_getpid (__NR_SYSCALL_BASE+ 20)
816#define __NR_kill (__NR_SYSCALL_BASE+ 37)
817
818 .code 32
639 FUNC_START div0
640
641 stmfd sp!, {r1, lr}
642 swi __NR_getpid
643 cmn r0, #1000
819 FUNC_START div0
820
821 stmfd sp!, {r1, lr}
822 swi __NR_getpid
823 cmn r0, #1000
644 ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
824 RETLDM r1 hs
645 mov r1, #SIGFPE
646 swi __NR_kill
825 mov r1, #SIGFPE
826 swi __NR_kill
647#ifdef __THUMB_INTERWORK__
648 ldmfd sp!, {r1, lr}
649 bx lr
650#else
651 ldmfd sp!, {r1, pc}RETCOND
652#endif
827 RETLDM r1
653
828
654 SIZE (__div0)
829 FUNC_END div0
655
656#endif /* L_dvmd_lnx */
657/* ------------------------------------------------------------------------ */
658/* These next two sections are here despite the fact that they contain Thumb
659 assembler because their presence allows interworked code to be linked even
660 when the GCC library is this one. */
661
662/* Do not build the interworking functions when the target architecture does

--- 52 unchanged lines hidden (view full) ---

715 called function to return here instead. Upon return we recover the real
716 return address and use a BX to get back to Thumb mode. */
717
718 .text
719 .align 0
720
721 .code 32
722 .globl _arm_return
830
831#endif /* L_dvmd_lnx */
832/* ------------------------------------------------------------------------ */
833/* These next two sections are here despite the fact that they contain Thumb
834 assembler because their presence allows interworked code to be linked even
835 when the GCC library is this one. */
836
837/* Do not build the interworking functions when the target architecture does

--- 52 unchanged lines hidden (view full) ---

890 called function to return here instead. Upon return we recover the real
891 return address and use a BX to get back to Thumb mode. */
892
893 .text
894 .align 0
895
896 .code 32
897 .globl _arm_return
723_arm_return:
724 ldmia r13!, {r12}
725 bx r12
898_arm_return:
899 RETLDM
726 .code 16
727
900 .code 16
901
728.macro interwork register
729 .code 16
902.macro interwork register
903 .code 16
730
731 THUMB_FUNC_START _interwork_call_via_\register
732
904
905 THUMB_FUNC_START _interwork_call_via_\register
906
733 bx pc
907 bx pc
734 nop
908 nop
735
736 .code 32
737 .globl .Lchange_\register
738.Lchange_\register:
909
910 .code 32
911 .globl LSYM(Lchange_\register)
912LSYM(Lchange_\register):
739 tst \register, #1
913 tst \register, #1
740 stmeqdb r13!, {lr}
914 streq lr, [sp, #-4]!
741 adreq lr, _arm_return
742 bx \register
743
744 SIZE (_interwork_call_via_\register)
745.endm
746
747 interwork r0
748 interwork r1

--- 25 unchanged lines hidden (view full) ---

774 stmeqdb r13!, {lr}
775 mov ip, lr
776 adreq lr, _arm_return
777 bx ip
778
779 SIZE (_interwork_call_via_lr)
780
781#endif /* L_interwork_call_via_rX */
915 adreq lr, _arm_return
916 bx \register
917
918 SIZE (_interwork_call_via_\register)
919.endm
920
921 interwork r0
922 interwork r1

--- 25 unchanged lines hidden (view full) ---

948 stmeqdb r13!, {lr}
949 mov ip, lr
950 adreq lr, _arm_return
951 bx ip
952
953 SIZE (_interwork_call_via_lr)
954
955#endif /* L_interwork_call_via_rX */
956
957#include "ieee754-df.S"
958#include "ieee754-sf.S"
959