2005-06-28 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / config / arm / lib1funcs.asm
blobebf31eb8cc5c8de9d3d53734dbcc7db3b93fce19
1 @ libgcc routines for ARM cpu.
2 @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
4 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
5 Free Software Foundation, Inc.
7 This file is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
19 executable.)
21 This file is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; see the file COPYING. If not, write to
28 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
30 /* ------------------------------------------------------------------------ */
32 /* We need to know what prefix to add to function names. */
34 #ifndef __USER_LABEL_PREFIX__
35 #error __USER_LABEL_PREFIX__ not defined
36 #endif
38 /* ANSI concatenation macros. */
40 #define CONCAT1(a, b) CONCAT2(a, b)
41 #define CONCAT2(a, b) a ## b
43 /* Use the right prefix for global labels. */
45 #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
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
56 #else
57 #define __PLT__
58 #define TYPE(x)
59 #define SIZE(x)
60 #define LSYM(x) x
61 #endif
63 /* Function end macros. Variants for interworking. */
65 @ This selects the minimum architecture level required.
66 #define __ARM_ARCH__ 3
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
76 #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
77 || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
78 || defined(__ARM_ARCH_5TEJ__)
79 # undef __ARM_ARCH__
80 # define __ARM_ARCH__ 5
81 #endif
83 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
84 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
85 || defined(__ARM_ARCH_6ZK__)
86 # undef __ARM_ARCH__
87 # define __ARM_ARCH__ 6
88 #endif
90 /* How to return from a function call depends on the architecture variant. */
92 #if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
94 # define RET bx lr
95 # define RETc(x) bx##x lr
97 /* Special precautions for interworking on armv4t. */
98 # if (__ARM_ARCH__ == 4)
100 /* Always use bx, not ldr pc. */
101 # if (defined(__thumb__) || defined(__THUMB_INTERWORK__))
102 # define __INTERWORKING__
103 # endif /* __THUMB__ || __THUMB_INTERWORK__ */
105 /* Include thumb stub before arm mode code. */
106 # if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
107 # define __INTERWORKING_STUBS__
108 # endif /* __thumb__ && !__THUMB_INTERWORK__ */
110 #endif /* __ARM_ARCH == 4 */
112 #else
114 # define RET mov pc, lr
115 # define RETc(x) mov##x pc, lr
117 #endif
119 .macro cfi_pop advance, reg, cfa_offset
120 #ifdef __ELF__
121 .pushsection .debug_frame
122 .byte 0x4 /* DW_CFA_advance_loc4 */
123 .4byte \advance
124 .byte (0xc0 | \reg) /* DW_CFA_restore */
125 .byte 0xe /* DW_CFA_def_cfa_offset */
126 .uleb128 \cfa_offset
127 .popsection
128 #endif
129 .endm
130 .macro cfi_push advance, reg, offset, cfa_offset
131 #ifdef __ELF__
132 .pushsection .debug_frame
133 .byte 0x4 /* DW_CFA_advance_loc4 */
134 .4byte \advance
135 .byte (0x80 | \reg) /* DW_CFA_offset */
136 .uleb128 (\offset / -4)
137 .byte 0xe /* DW_CFA_def_cfa_offset */
138 .uleb128 \cfa_offset
139 .popsection
140 #endif
141 .endm
142 .macro cfi_start start_label, end_label
143 #ifdef __ELF__
144 .pushsection .debug_frame
145 LSYM(Lstart_frame):
146 .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE
147 LSYM(Lstart_cie):
148 .4byte 0xffffffff @ CIE Identifier Tag
149 .byte 0x1 @ CIE Version
150 .ascii "\0" @ CIE Augmentation
151 .uleb128 0x1 @ CIE Code Alignment Factor
152 .sleb128 -4 @ CIE Data Alignment Factor
153 .byte 0xe @ CIE RA Column
154 .byte 0xc @ DW_CFA_def_cfa
155 .uleb128 0xd
156 .uleb128 0x0
158 .align 2
159 LSYM(Lend_cie):
160 .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length
161 LSYM(Lstart_fde):
162 .4byte LSYM(Lstart_frame) @ FDE CIE offset
163 .4byte \start_label @ FDE initial location
164 .4byte \end_label-\start_label @ FDE address range
165 .popsection
166 #endif
167 .endm
168 .macro cfi_end end_label
169 #ifdef __ELF__
170 .pushsection .debug_frame
171 .align 2
172 LSYM(Lend_fde):
173 .popsection
174 \end_label:
175 #endif
176 .endm
178 /* Don't pass dirn, it's there just to get token pasting right. */
180 .macro RETLDM regs=, cond=, unwind=, dirn=ia
181 #if defined (__INTERWORKING__)
182 .ifc "\regs",""
183 ldr\cond lr, [sp], #8
184 .else
185 ldm\cond\dirn sp!, {\regs, lr}
186 .endif
187 .ifnc "\unwind", ""
188 /* Mark LR as restored. */
189 97: cfi_pop 97b - \unwind, 0xe, 0x0
190 .endif
191 bx\cond lr
192 #else
193 .ifc "\regs",""
194 ldr\cond pc, [sp], #8
195 .else
196 ldm\cond\dirn sp!, {\regs, pc}
197 .endif
198 #endif
199 .endm
202 .macro ARM_LDIV0 name
203 str lr, [sp, #-8]!
204 98: cfi_push 98b - __\name, 0xe, -0x8, 0x8
205 bl SYM (__div0) __PLT__
206 mov r0, #0 @ About as wrong as it could be.
207 RETLDM unwind=98b
208 .endm
211 .macro THUMB_LDIV0 name
212 push { r1, lr }
213 98: cfi_push 98b - __\name, 0xe, -0x4, 0x8
214 bl SYM (__div0)
215 mov r0, #0 @ About as wrong as it could be.
216 #if defined (__INTERWORKING__)
217 pop { r1, r2 }
218 bx r2
219 #else
220 pop { r1, pc }
221 #endif
222 .endm
224 .macro FUNC_END name
225 SIZE (__\name)
226 .endm
228 .macro DIV_FUNC_END name
229 cfi_start __\name, LSYM(Lend_div0)
230 LSYM(Ldiv0):
231 #ifdef __thumb__
232 THUMB_LDIV0 \name
233 #else
234 ARM_LDIV0 \name
235 #endif
236 cfi_end LSYM(Lend_div0)
237 FUNC_END \name
238 .endm
240 .macro THUMB_FUNC_START name
241 .globl SYM (\name)
242 TYPE (\name)
243 .thumb_func
244 SYM (\name):
245 .endm
247 /* Function start macros. Variants for ARM and Thumb. */
249 #ifdef __thumb__
250 #define THUMB_FUNC .thumb_func
251 #define THUMB_CODE .force_thumb
252 #else
253 #define THUMB_FUNC
254 #define THUMB_CODE
255 #endif
257 .macro FUNC_START name
258 .text
259 .globl SYM (__\name)
260 TYPE (__\name)
261 .align 0
262 THUMB_CODE
263 THUMB_FUNC
264 SYM (__\name):
265 .endm
267 /* Special function that will always be coded in ARM assembly, even if
268 in Thumb-only compilation. */
270 #if defined(__INTERWORKING_STUBS__)
271 .macro ARM_FUNC_START name
272 FUNC_START \name
273 bx pc
275 .arm
276 /* A hook to tell gdb that we've switched to ARM mode. Also used to call
277 directly from other local arm routines. */
278 _L__\name:
279 .endm
280 #define EQUIV .thumb_set
281 /* Branch directly to a function declared with ARM_FUNC_START.
282 Must be called in arm mode. */
283 .macro ARM_CALL name
284 bl _L__\name
285 .endm
286 #else
287 .macro ARM_FUNC_START name
288 .text
289 .globl SYM (__\name)
290 TYPE (__\name)
291 .align 0
292 .arm
293 SYM (__\name):
294 .endm
295 #define EQUIV .set
296 .macro ARM_CALL name
297 bl __\name
298 .endm
299 #endif
301 .macro FUNC_ALIAS new old
302 .globl SYM (__\new)
303 #if defined (__thumb__)
304 .thumb_set SYM (__\new), SYM (__\old)
305 #else
306 .set SYM (__\new), SYM (__\old)
307 #endif
308 .endm
310 .macro ARM_FUNC_ALIAS new old
311 .globl SYM (__\new)
312 EQUIV SYM (__\new), SYM (__\old)
313 #if defined(__INTERWORKING_STUBS__)
314 .set SYM (_L__\new), SYM (_L__\old)
315 #endif
316 .endm
318 #ifdef __thumb__
319 /* Register aliases. */
321 work .req r4 @ XXXX is this safe ?
322 dividend .req r0
323 divisor .req r1
324 overdone .req r2
325 result .req r2
326 curbit .req r3
327 #endif
328 #if 0
329 ip .req r12
330 sp .req r13
331 lr .req r14
332 pc .req r15
333 #endif
335 /* ------------------------------------------------------------------------ */
336 /* Bodies of the division and modulo routines. */
337 /* ------------------------------------------------------------------------ */
338 .macro ARM_DIV_BODY dividend, divisor, result, curbit
340 #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
342 clz \curbit, \dividend
343 clz \result, \divisor
344 sub \curbit, \result, \curbit
345 rsbs \curbit, \curbit, #31
346 addne \curbit, \curbit, \curbit, lsl #1
347 mov \result, #0
348 addne pc, pc, \curbit, lsl #2
350 .set shift, 32
351 .rept 32
352 .set shift, shift - 1
353 cmp \dividend, \divisor, lsl #shift
354 adc \result, \result, \result
355 subcs \dividend, \dividend, \divisor, lsl #shift
356 .endr
358 #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
359 #if __ARM_ARCH__ >= 5
361 clz \curbit, \divisor
362 clz \result, \dividend
363 sub \result, \curbit, \result
364 mov \curbit, #1
365 mov \divisor, \divisor, lsl \result
366 mov \curbit, \curbit, lsl \result
367 mov \result, #0
369 #else /* __ARM_ARCH__ < 5 */
371 @ Initially shift the divisor left 3 bits if possible,
372 @ set curbit accordingly. This allows for curbit to be located
373 @ at the left end of each 4 bit nibbles in the division loop
374 @ to save one loop in most cases.
375 tst \divisor, #0xe0000000
376 moveq \divisor, \divisor, lsl #3
377 moveq \curbit, #8
378 movne \curbit, #1
380 @ Unless the divisor is very big, shift it up in multiples of
381 @ four bits, since this is the amount of unwinding in the main
382 @ division loop. Continue shifting until the divisor is
383 @ larger than the dividend.
384 1: cmp \divisor, #0x10000000
385 cmplo \divisor, \dividend
386 movlo \divisor, \divisor, lsl #4
387 movlo \curbit, \curbit, lsl #4
388 blo 1b
390 @ For very big divisors, we must shift it a bit at a time, or
391 @ we will be in danger of overflowing.
392 1: cmp \divisor, #0x80000000
393 cmplo \divisor, \dividend
394 movlo \divisor, \divisor, lsl #1
395 movlo \curbit, \curbit, lsl #1
396 blo 1b
398 mov \result, #0
400 #endif /* __ARM_ARCH__ < 5 */
402 @ Division loop
403 1: cmp \dividend, \divisor
404 subhs \dividend, \dividend, \divisor
405 orrhs \result, \result, \curbit
406 cmp \dividend, \divisor, lsr #1
407 subhs \dividend, \dividend, \divisor, lsr #1
408 orrhs \result, \result, \curbit, lsr #1
409 cmp \dividend, \divisor, lsr #2
410 subhs \dividend, \dividend, \divisor, lsr #2
411 orrhs \result, \result, \curbit, lsr #2
412 cmp \dividend, \divisor, lsr #3
413 subhs \dividend, \dividend, \divisor, lsr #3
414 orrhs \result, \result, \curbit, lsr #3
415 cmp \dividend, #0 @ Early termination?
416 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
417 movne \divisor, \divisor, lsr #4
418 bne 1b
420 #endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
422 .endm
423 /* ------------------------------------------------------------------------ */
424 .macro ARM_DIV2_ORDER divisor, order
426 #if __ARM_ARCH__ >= 5
428 clz \order, \divisor
429 rsb \order, \order, #31
431 #else
433 cmp \divisor, #(1 << 16)
434 movhs \divisor, \divisor, lsr #16
435 movhs \order, #16
436 movlo \order, #0
438 cmp \divisor, #(1 << 8)
439 movhs \divisor, \divisor, lsr #8
440 addhs \order, \order, #8
442 cmp \divisor, #(1 << 4)
443 movhs \divisor, \divisor, lsr #4
444 addhs \order, \order, #4
446 cmp \divisor, #(1 << 2)
447 addhi \order, \order, #3
448 addls \order, \order, \divisor, lsr #1
450 #endif
452 .endm
453 /* ------------------------------------------------------------------------ */
454 .macro ARM_MOD_BODY dividend, divisor, order, spare
456 #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
458 clz \order, \divisor
459 clz \spare, \dividend
460 sub \order, \order, \spare
461 rsbs \order, \order, #31
462 addne pc, pc, \order, lsl #3
464 .set shift, 32
465 .rept 32
466 .set shift, shift - 1
467 cmp \dividend, \divisor, lsl #shift
468 subcs \dividend, \dividend, \divisor, lsl #shift
469 .endr
471 #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
472 #if __ARM_ARCH__ >= 5
474 clz \order, \divisor
475 clz \spare, \dividend
476 sub \order, \order, \spare
477 mov \divisor, \divisor, lsl \order
479 #else /* __ARM_ARCH__ < 5 */
481 mov \order, #0
483 @ Unless the divisor is very big, shift it up in multiples of
484 @ four bits, since this is the amount of unwinding in the main
485 @ division loop. Continue shifting until the divisor is
486 @ larger than the dividend.
487 1: cmp \divisor, #0x10000000
488 cmplo \divisor, \dividend
489 movlo \divisor, \divisor, lsl #4
490 addlo \order, \order, #4
491 blo 1b
493 @ For very big divisors, we must shift it a bit at a time, or
494 @ we will be in danger of overflowing.
495 1: cmp \divisor, #0x80000000
496 cmplo \divisor, \dividend
497 movlo \divisor, \divisor, lsl #1
498 addlo \order, \order, #1
499 blo 1b
501 #endif /* __ARM_ARCH__ < 5 */
503 @ Perform all needed substractions to keep only the reminder.
504 @ Do comparisons in batch of 4 first.
505 subs \order, \order, #3 @ yes, 3 is intended here
506 blt 2f
508 1: cmp \dividend, \divisor
509 subhs \dividend, \dividend, \divisor
510 cmp \dividend, \divisor, lsr #1
511 subhs \dividend, \dividend, \divisor, lsr #1
512 cmp \dividend, \divisor, lsr #2
513 subhs \dividend, \dividend, \divisor, lsr #2
514 cmp \dividend, \divisor, lsr #3
515 subhs \dividend, \dividend, \divisor, lsr #3
516 cmp \dividend, #1
517 mov \divisor, \divisor, lsr #4
518 subges \order, \order, #4
519 bge 1b
521 tst \order, #3
522 teqne \dividend, #0
523 beq 5f
525 @ Either 1, 2 or 3 comparison/substractions are left.
526 2: cmn \order, #2
527 blt 4f
528 beq 3f
529 cmp \dividend, \divisor
530 subhs \dividend, \dividend, \divisor
531 mov \divisor, \divisor, lsr #1
532 3: cmp \dividend, \divisor
533 subhs \dividend, \dividend, \divisor
534 mov \divisor, \divisor, lsr #1
535 4: cmp \dividend, \divisor
536 subhs \dividend, \dividend, \divisor
539 #endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
541 .endm
542 /* ------------------------------------------------------------------------ */
543 .macro THUMB_DIV_MOD_BODY modulo
544 @ Load the constant 0x10000000 into our work register.
545 mov work, #1
546 lsl work, #28
547 LSYM(Loop1):
548 @ Unless the divisor is very big, shift it up in multiples of
549 @ four bits, since this is the amount of unwinding in the main
550 @ division loop. Continue shifting until the divisor is
551 @ larger than the dividend.
552 cmp divisor, work
553 bhs LSYM(Lbignum)
554 cmp divisor, dividend
555 bhs LSYM(Lbignum)
556 lsl divisor, #4
557 lsl curbit, #4
558 b LSYM(Loop1)
559 LSYM(Lbignum):
560 @ Set work to 0x80000000
561 lsl work, #3
562 LSYM(Loop2):
563 @ For very big divisors, we must shift it a bit at a time, or
564 @ we will be in danger of overflowing.
565 cmp divisor, work
566 bhs LSYM(Loop3)
567 cmp divisor, dividend
568 bhs LSYM(Loop3)
569 lsl divisor, #1
570 lsl curbit, #1
571 b LSYM(Loop2)
572 LSYM(Loop3):
573 @ Test for possible subtractions ...
574 .if \modulo
575 @ ... On the final pass, this may subtract too much from the dividend,
576 @ so keep track of which subtractions are done, we can fix them up
577 @ afterwards.
578 mov overdone, #0
579 cmp dividend, divisor
580 blo LSYM(Lover1)
581 sub dividend, dividend, divisor
582 LSYM(Lover1):
583 lsr work, divisor, #1
584 cmp dividend, work
585 blo LSYM(Lover2)
586 sub dividend, dividend, work
587 mov ip, curbit
588 mov work, #1
589 ror curbit, work
590 orr overdone, curbit
591 mov curbit, ip
592 LSYM(Lover2):
593 lsr work, divisor, #2
594 cmp dividend, work
595 blo LSYM(Lover3)
596 sub dividend, dividend, work
597 mov ip, curbit
598 mov work, #2
599 ror curbit, work
600 orr overdone, curbit
601 mov curbit, ip
602 LSYM(Lover3):
603 lsr work, divisor, #3
604 cmp dividend, work
605 blo LSYM(Lover4)
606 sub dividend, dividend, work
607 mov ip, curbit
608 mov work, #3
609 ror curbit, work
610 orr overdone, curbit
611 mov curbit, ip
612 LSYM(Lover4):
613 mov ip, curbit
614 .else
615 @ ... and note which bits are done in the result. On the final pass,
616 @ this may subtract too much from the dividend, but the result will be ok,
617 @ since the "bit" will have been shifted out at the bottom.
618 cmp dividend, divisor
619 blo LSYM(Lover1)
620 sub dividend, dividend, divisor
621 orr result, result, curbit
622 LSYM(Lover1):
623 lsr work, divisor, #1
624 cmp dividend, work
625 blo LSYM(Lover2)
626 sub dividend, dividend, work
627 lsr work, curbit, #1
628 orr result, work
629 LSYM(Lover2):
630 lsr work, divisor, #2
631 cmp dividend, work
632 blo LSYM(Lover3)
633 sub dividend, dividend, work
634 lsr work, curbit, #2
635 orr result, work
636 LSYM(Lover3):
637 lsr work, divisor, #3
638 cmp dividend, work
639 blo LSYM(Lover4)
640 sub dividend, dividend, work
641 lsr work, curbit, #3
642 orr result, work
643 LSYM(Lover4):
644 .endif
646 cmp dividend, #0 @ Early termination?
647 beq LSYM(Lover5)
648 lsr curbit, #4 @ No, any more bits to do?
649 beq LSYM(Lover5)
650 lsr divisor, #4
651 b LSYM(Loop3)
652 LSYM(Lover5):
653 .if \modulo
654 @ Any subtractions that we should not have done will be recorded in
655 @ the top three bits of "overdone". Exactly which were not needed
656 @ are governed by the position of the bit, stored in ip.
657 mov work, #0xe
658 lsl work, #28
659 and overdone, work
660 beq LSYM(Lgot_result)
662 @ If we terminated early, because dividend became zero, then the
663 @ bit in ip will not be in the bottom nibble, and we should not
664 @ perform the additions below. We must test for this though
665 @ (rather relying upon the TSTs to prevent the additions) since
666 @ the bit in ip could be in the top two bits which might then match
667 @ with one of the smaller RORs.
668 mov curbit, ip
669 mov work, #0x7
670 tst curbit, work
671 beq LSYM(Lgot_result)
673 mov curbit, ip
674 mov work, #3
675 ror curbit, work
676 tst overdone, curbit
677 beq LSYM(Lover6)
678 lsr work, divisor, #3
679 add dividend, work
680 LSYM(Lover6):
681 mov curbit, ip
682 mov work, #2
683 ror curbit, work
684 tst overdone, curbit
685 beq LSYM(Lover7)
686 lsr work, divisor, #2
687 add dividend, work
688 LSYM(Lover7):
689 mov curbit, ip
690 mov work, #1
691 ror curbit, work
692 tst overdone, curbit
693 beq LSYM(Lgot_result)
694 lsr work, divisor, #1
695 add dividend, work
696 .endif
697 LSYM(Lgot_result):
698 .endm
699 /* ------------------------------------------------------------------------ */
700 /* Start of the Real Functions */
701 /* ------------------------------------------------------------------------ */
702 #ifdef L_udivsi3
704 FUNC_START udivsi3
706 #ifdef __thumb__
708 cmp divisor, #0
709 beq LSYM(Ldiv0)
710 mov curbit, #1
711 mov result, #0
713 push { work }
714 cmp dividend, divisor
715 blo LSYM(Lgot_result)
717 THUMB_DIV_MOD_BODY 0
719 mov r0, result
720 pop { work }
723 #else /* ARM version. */
725 subs r2, r1, #1
726 RETc(eq)
727 bcc LSYM(Ldiv0)
728 cmp r0, r1
729 bls 11f
730 tst r1, r2
731 beq 12f
733 ARM_DIV_BODY r0, r1, r2, r3
735 mov r0, r2
736 RET
738 11: moveq r0, #1
739 movne r0, #0
742 12: ARM_DIV2_ORDER r1, r2
744 mov r0, r0, lsr r2
747 #endif /* ARM version */
749 DIV_FUNC_END udivsi3
751 FUNC_START aeabi_uidivmod
752 #ifdef __thumb__
753 push {r0, r1, lr}
754 bl SYM(__udivsi3)
755 POP {r1, r2, r3}
756 mul r2, r0
757 sub r1, r1, r2
758 bx r3
759 #else
760 stmfd sp!, { r0, r1, lr }
761 bl SYM(__udivsi3)
762 ldmfd sp!, { r1, r2, lr }
763 mul r3, r2, r0
764 sub r1, r1, r3
766 #endif
767 FUNC_END aeabi_uidivmod
769 #endif /* L_udivsi3 */
770 /* ------------------------------------------------------------------------ */
771 #ifdef L_umodsi3
773 FUNC_START umodsi3
775 #ifdef __thumb__
777 cmp divisor, #0
778 beq LSYM(Ldiv0)
779 mov curbit, #1
780 cmp dividend, divisor
781 bhs LSYM(Lover10)
782 RET
784 LSYM(Lover10):
785 push { work }
787 THUMB_DIV_MOD_BODY 1
789 pop { work }
792 #else /* ARM version. */
794 subs r2, r1, #1 @ compare divisor with 1
795 bcc LSYM(Ldiv0)
796 cmpne r0, r1 @ compare dividend with divisor
797 moveq r0, #0
798 tsthi r1, r2 @ see if divisor is power of 2
799 andeq r0, r0, r2
800 RETc(ls)
802 ARM_MOD_BODY r0, r1, r2, r3
804 RET
806 #endif /* ARM version. */
808 DIV_FUNC_END umodsi3
810 #endif /* L_umodsi3 */
811 /* ------------------------------------------------------------------------ */
812 #ifdef L_divsi3
814 FUNC_START divsi3
816 #ifdef __thumb__
817 cmp divisor, #0
818 beq LSYM(Ldiv0)
820 push { work }
821 mov work, dividend
822 eor work, divisor @ Save the sign of the result.
823 mov ip, work
824 mov curbit, #1
825 mov result, #0
826 cmp divisor, #0
827 bpl LSYM(Lover10)
828 neg divisor, divisor @ Loops below use unsigned.
829 LSYM(Lover10):
830 cmp dividend, #0
831 bpl LSYM(Lover11)
832 neg dividend, dividend
833 LSYM(Lover11):
834 cmp dividend, divisor
835 blo LSYM(Lgot_result)
837 THUMB_DIV_MOD_BODY 0
839 mov r0, result
840 mov work, ip
841 cmp work, #0
842 bpl LSYM(Lover12)
843 neg r0, r0
844 LSYM(Lover12):
845 pop { work }
848 #else /* ARM version. */
850 cmp r1, #0
851 eor ip, r0, r1 @ save the sign of the result.
852 beq LSYM(Ldiv0)
853 rsbmi r1, r1, #0 @ loops below use unsigned.
854 subs r2, r1, #1 @ division by 1 or -1 ?
855 beq 10f
856 movs r3, r0
857 rsbmi r3, r0, #0 @ positive dividend value
858 cmp r3, r1
859 bls 11f
860 tst r1, r2 @ divisor is power of 2 ?
861 beq 12f
863 ARM_DIV_BODY r3, r1, r0, r2
865 cmp ip, #0
866 rsbmi r0, r0, #0
867 RET
869 10: teq ip, r0 @ same sign ?
870 rsbmi r0, r0, #0
871 RET
873 11: movlo r0, #0
874 moveq r0, ip, asr #31
875 orreq r0, r0, #1
878 12: ARM_DIV2_ORDER r1, r2
880 cmp ip, #0
881 mov r0, r3, lsr r2
882 rsbmi r0, r0, #0
885 #endif /* ARM version */
887 DIV_FUNC_END divsi3
889 FUNC_START aeabi_idivmod
890 #ifdef __thumb__
891 push {r0, r1, lr}
892 bl SYM(__divsi3)
893 POP {r1, r2, r3}
894 mul r2, r0
895 sub r1, r1, r2
896 bx r3
897 #else
898 stmfd sp!, { r0, r1, lr }
899 bl SYM(__divsi3)
900 ldmfd sp!, { r1, r2, lr }
901 mul r3, r2, r0
902 sub r1, r1, r3
904 #endif
905 FUNC_END aeabi_idivmod
907 #endif /* L_divsi3 */
908 /* ------------------------------------------------------------------------ */
909 #ifdef L_modsi3
911 FUNC_START modsi3
913 #ifdef __thumb__
915 mov curbit, #1
916 cmp divisor, #0
917 beq LSYM(Ldiv0)
918 bpl LSYM(Lover10)
919 neg divisor, divisor @ Loops below use unsigned.
920 LSYM(Lover10):
921 push { work }
922 @ Need to save the sign of the dividend, unfortunately, we need
923 @ work later on. Must do this after saving the original value of
924 @ the work register, because we will pop this value off first.
925 push { dividend }
926 cmp dividend, #0
927 bpl LSYM(Lover11)
928 neg dividend, dividend
929 LSYM(Lover11):
930 cmp dividend, divisor
931 blo LSYM(Lgot_result)
933 THUMB_DIV_MOD_BODY 1
935 pop { work }
936 cmp work, #0
937 bpl LSYM(Lover12)
938 neg dividend, dividend
939 LSYM(Lover12):
940 pop { work }
941 RET
943 #else /* ARM version. */
945 cmp r1, #0
946 beq LSYM(Ldiv0)
947 rsbmi r1, r1, #0 @ loops below use unsigned.
948 movs ip, r0 @ preserve sign of dividend
949 rsbmi r0, r0, #0 @ if negative make positive
950 subs r2, r1, #1 @ compare divisor with 1
951 cmpne r0, r1 @ compare dividend with divisor
952 moveq r0, #0
953 tsthi r1, r2 @ see if divisor is power of 2
954 andeq r0, r0, r2
955 bls 10f
957 ARM_MOD_BODY r0, r1, r2, r3
959 10: cmp ip, #0
960 rsbmi r0, r0, #0
961 RET
963 #endif /* ARM version */
965 DIV_FUNC_END modsi3
967 #endif /* L_modsi3 */
968 /* ------------------------------------------------------------------------ */
969 #ifdef L_dvmd_tls
971 FUNC_START div0
972 FUNC_ALIAS aeabi_idiv0 div0
973 FUNC_ALIAS aeabi_ldiv0 div0
977 FUNC_END aeabi_ldiv0
978 FUNC_END aeabi_idiv0
979 FUNC_END div0
981 #endif /* L_divmodsi_tools */
982 /* ------------------------------------------------------------------------ */
983 #ifdef L_dvmd_lnx
984 @ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
986 /* Constants taken from <asm/unistd.h> and <asm/signal.h> */
987 #define SIGFPE 8
988 #define __NR_SYSCALL_BASE 0x900000
989 #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
990 #define __NR_kill (__NR_SYSCALL_BASE+ 37)
991 #define __NR_gettid (__NR_SYSCALL_BASE+ 224)
992 #define __NR_tkill (__NR_SYSCALL_BASE+ 238)
994 .code 32
995 FUNC_START div0
997 stmfd sp!, {r1, lr}
998 swi __NR_gettid
999 cmn r0, #1000
1000 swihs __NR_getpid
1001 cmnhs r0, #1000
1002 RETLDM r1 hs
1003 mov ip, r0
1004 mov r1, #SIGFPE
1005 swi __NR_tkill
1006 movs r0, r0
1007 movne r0, ip
1008 swine __NR_kill
1009 RETLDM r1
1011 FUNC_END div0
1013 #endif /* L_dvmd_lnx */
1014 /* ------------------------------------------------------------------------ */
1015 /* Dword shift operations. */
1016 /* All the following Dword shift variants rely on the fact that
1017 shft xxx, Reg
1018 is in fact done as
1019 shft xxx, (Reg & 255)
1020 so for Reg value in (32...63) and (-1...-31) we will get zero (in the
1021 case of logical shifts) or the sign (for asr). */
1023 #ifdef __ARMEB__
1024 #define al r1
1025 #define ah r0
1026 #else
1027 #define al r0
1028 #define ah r1
1029 #endif
1031 #ifdef L_lshrdi3
1033 FUNC_START lshrdi3
1034 FUNC_ALIAS aeabi_llsr lshrdi3
1036 #ifdef __thumb__
1037 lsr al, r2
1038 mov r3, ah
1039 lsr ah, r2
1040 mov ip, r3
1041 sub r2, #32
1042 lsr r3, r2
1043 orr al, r3
1044 neg r2, r2
1045 mov r3, ip
1046 lsl r3, r2
1047 orr al, r3
1049 #else
1050 subs r3, r2, #32
1051 rsb ip, r2, #32
1052 movmi al, al, lsr r2
1053 movpl al, ah, lsr r3
1054 orrmi al, al, ah, lsl ip
1055 mov ah, ah, lsr r2
1057 #endif
1058 FUNC_END aeabi_llsr
1059 FUNC_END lshrdi3
1061 #endif
1063 #ifdef L_ashrdi3
1065 FUNC_START ashrdi3
1066 FUNC_ALIAS aeabi_lasr ashrdi3
1068 #ifdef __thumb__
1069 lsr al, r2
1070 mov r3, ah
1071 asr ah, r2
1072 sub r2, #32
1073 @ If r2 is negative at this point the following step would OR
1074 @ the sign bit into all of AL. That's not what we want...
1075 bmi 1f
1076 mov ip, r3
1077 asr r3, r2
1078 orr al, r3
1079 mov r3, ip
1081 neg r2, r2
1082 lsl r3, r2
1083 orr al, r3
1085 #else
1086 subs r3, r2, #32
1087 rsb ip, r2, #32
1088 movmi al, al, lsr r2
1089 movpl al, ah, asr r3
1090 orrmi al, al, ah, lsl ip
1091 mov ah, ah, asr r2
1093 #endif
1095 FUNC_END aeabi_lasr
1096 FUNC_END ashrdi3
1098 #endif
1100 #ifdef L_ashldi3
1102 FUNC_START ashldi3
1103 FUNC_ALIAS aeabi_llsl ashldi3
1105 #ifdef __thumb__
1106 lsl ah, r2
1107 mov r3, al
1108 lsl al, r2
1109 mov ip, r3
1110 sub r2, #32
1111 lsl r3, r2
1112 orr ah, r3
1113 neg r2, r2
1114 mov r3, ip
1115 lsr r3, r2
1116 orr ah, r3
1118 #else
1119 subs r3, r2, #32
1120 rsb ip, r2, #32
1121 movmi ah, ah, lsl r2
1122 movpl ah, al, lsl r3
1123 orrmi ah, ah, al, lsr ip
1124 mov al, al, lsl r2
1126 #endif
1127 FUNC_END aeabi_llsl
1128 FUNC_END ashldi3
1130 #endif
1132 /* ------------------------------------------------------------------------ */
1133 /* These next two sections are here despite the fact that they contain Thumb
1134 assembler because their presence allows interworked code to be linked even
1135 when the GCC library is this one. */
1137 /* Do not build the interworking functions when the target architecture does
1138 not support Thumb instructions. (This can be a multilib option). */
1139 #if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
1140 || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
1141 || __ARM_ARCH__ >= 6
1143 #if defined L_call_via_rX
1145 /* These labels & instructions are used by the Arm/Thumb interworking code.
1146 The address of function to be called is loaded into a register and then
1147 one of these labels is called via a BL instruction. This puts the
1148 return address into the link register with the bottom bit set, and the
1149 code here switches to the correct mode before executing the function. */
1151 .text
1152 .align 0
1153 .force_thumb
1155 .macro call_via register
1156 THUMB_FUNC_START _call_via_\register
1158 bx \register
1161 SIZE (_call_via_\register)
1162 .endm
1164 call_via r0
1165 call_via r1
1166 call_via r2
1167 call_via r3
1168 call_via r4
1169 call_via r5
1170 call_via r6
1171 call_via r7
1172 call_via r8
1173 call_via r9
1174 call_via sl
1175 call_via fp
1176 call_via ip
1177 call_via sp
1178 call_via lr
1180 #endif /* L_call_via_rX */
1182 #if defined L_interwork_call_via_rX
1184 /* These labels & instructions are used by the Arm/Thumb interworking code,
1185 when the target address is in an unknown instruction set. The address
1186 of function to be called is loaded into a register and then one of these
1187 labels is called via a BL instruction. This puts the return address
1188 into the link register with the bottom bit set, and the code here
1189 switches to the correct mode before executing the function. Unfortunately
1190 the target code cannot be relied upon to return via a BX instruction, so
1191 instead we have to store the resturn address on the stack and allow the
1192 called function to return here instead. Upon return we recover the real
1193 return address and use a BX to get back to Thumb mode.
1195 There are three variations of this code. The first,
1196 _interwork_call_via_rN(), will push the return address onto the
1197 stack and pop it in _arm_return(). It should only be used if all
1198 arguments are passed in registers.
1200 The second, _interwork_r7_call_via_rN(), instead stores the return
1201 address at [r7, #-4]. It is the caller's responsibility to ensure
1202 that this address is valid and contains no useful data.
1204 The third, _interwork_r11_call_via_rN(), works in the same way but
1205 uses r11 instead of r7. It is useful if the caller does not really
1206 need a frame pointer. */
1208 .text
1209 .align 0
1211 .code 32
1212 .globl _arm_return
1213 LSYM(Lstart_arm_return):
1214 cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return)
1215 cfi_push 0, 0xe, -0x8, 0x8
1216 nop @ This nop is for the benefit of debuggers, so that
1217 @ backtraces will use the correct unwind information.
1218 _arm_return:
1219 RETLDM unwind=LSYM(Lstart_arm_return)
1220 cfi_end LSYM(Lend_arm_return)
1222 .globl _arm_return_r7
1223 _arm_return_r7:
1224 ldr lr, [r7, #-4]
1225 bx lr
1227 .globl _arm_return_r11
1228 _arm_return_r11:
1229 ldr lr, [r11, #-4]
1230 bx lr
1232 .macro interwork_with_frame frame, register, name, return
1233 .code 16
1235 THUMB_FUNC_START \name
1237 bx pc
1240 .code 32
1241 tst \register, #1
1242 streq lr, [\frame, #-4]
1243 adreq lr, _arm_return_\frame
1244 bx \register
1246 SIZE (\name)
1247 .endm
1249 .macro interwork register
1250 .code 16
1252 THUMB_FUNC_START _interwork_call_via_\register
1254 bx pc
1257 .code 32
1258 .globl LSYM(Lchange_\register)
1259 LSYM(Lchange_\register):
1260 tst \register, #1
1261 streq lr, [sp, #-8]!
1262 adreq lr, _arm_return
1263 bx \register
1265 SIZE (_interwork_call_via_\register)
1267 interwork_with_frame r7,\register,_interwork_r7_call_via_\register
1268 interwork_with_frame r11,\register,_interwork_r11_call_via_\register
1269 .endm
1271 interwork r0
1272 interwork r1
1273 interwork r2
1274 interwork r3
1275 interwork r4
1276 interwork r5
1277 interwork r6
1278 interwork r7
1279 interwork r8
1280 interwork r9
1281 interwork sl
1282 interwork fp
1283 interwork ip
1284 interwork sp
1286 /* The LR case has to be handled a little differently... */
1287 .code 16
1289 THUMB_FUNC_START _interwork_call_via_lr
1291 bx pc
1294 .code 32
1295 .globl .Lchange_lr
1296 .Lchange_lr:
1297 tst lr, #1
1298 stmeqdb r13!, {lr, pc}
1299 mov ip, lr
1300 adreq lr, _arm_return
1301 bx ip
1303 SIZE (_interwork_call_via_lr)
1305 #endif /* L_interwork_call_via_rX */
1306 #endif /* Arch supports thumb. */
1308 #ifndef __symbian__
1309 #include "ieee754-df.S"
1310 #include "ieee754-sf.S"
1311 #include "bpabi.S"
1312 #include "libunwind.S"
1313 #endif /* __symbian__ */