OSDN Git Service

More MIPS vector cleanup work.
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / lib1funcs.asm
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, 2003, 2004
5    Free Software Foundation, Inc.
6
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.
11
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.)
20
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.
25
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, 59 Temple Place - Suite 330,
29 Boston, MA 02111-1307, USA.  */
30 /* ------------------------------------------------------------------------ */
31
32 /* We need to know what prefix to add to function names.  */
33
34 #ifndef __USER_LABEL_PREFIX__
35 #error  __USER_LABEL_PREFIX__ not defined
36 #endif
37
38 /* ANSI concatenation macros.  */
39
40 #define CONCAT1(a, b) CONCAT2(a, b)
41 #define CONCAT2(a, b) a ## b
42
43 /* Use the right prefix for global labels.  */
44
45 #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
46
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
62
63 /* Function end macros.  Variants for 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_5E__) || defined(__ARM_ARCH_5TE__) \
78         || defined(__ARM_ARCH_5TEJ__)
79 # undef __ARM_ARCH__
80 # define __ARM_ARCH__ 5
81 #endif
82
83 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__)
84 # undef __ARM_ARCH__
85 # define __ARM_ARCH__ 6
86 #endif
87
88 /* How to return from a function call depends on the architecture variant.  */
89
90 #if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
91
92 # define RET            bx      lr
93 # define RETc(x)        bx##x   lr
94
95 # if (__ARM_ARCH__ == 4) \
96         && (defined(__thumb__) || defined(__THUMB_INTERWORK__))
97 #  define __INTERWORKING__
98 # endif
99
100 #else
101
102 # define RET            mov     pc, lr
103 # define RETc(x)        mov##x  pc, lr
104
105 #endif
106
107 /* Don't pass dirn, it's there just to get token pasting right.  */
108
109 .macro  RETLDM  regs=, cond=, dirn=ia
110 #if defined (__INTERWORKING__)
111         .ifc "\regs",""
112         ldr\cond        lr, [sp], #4
113         .else
114         ldm\cond\dirn   sp!, {\regs, lr}
115         .endif
116         bx\cond lr
117 #else
118         .ifc "\regs",""
119         ldr\cond        pc, [sp], #4
120         .else
121         ldm\cond\dirn   sp!, {\regs, pc}
122         .endif
123 #endif
124 .endm
125
126
127 .macro ARM_LDIV0
128 LSYM(Ldiv0):
129         str     lr, [sp, #-4]!
130         bl      SYM (__div0) __PLT__
131         mov     r0, #0                  @ About as wrong as it could be.
132         RETLDM
133 .endm
134
135
136 .macro THUMB_LDIV0
137 LSYM(Ldiv0):
138         push    { lr }
139         bl      SYM (__div0)
140         mov     r0, #0                  @ About as wrong as it could be.
141 #if defined (__INTERWORKING__)
142         pop     { r1 }
143         bx      r1
144 #else
145         pop     { pc }
146 #endif
147 .endm
148
149 .macro FUNC_END name
150         SIZE (__\name)
151 .endm
152
153 .macro DIV_FUNC_END name
154 LSYM(Ldiv0):
155 #ifdef __thumb__
156         THUMB_LDIV0
157 #else
158         ARM_LDIV0
159 #endif
160         FUNC_END \name
161 .endm
162
163 .macro THUMB_FUNC_START name
164         .globl  SYM (\name)
165         TYPE    (\name)
166         .thumb_func
167 SYM (\name):
168 .endm
169
170 /* Function start macros.  Variants for ARM and Thumb.  */
171
172 #ifdef __thumb__
173 #define THUMB_FUNC .thumb_func
174 #define THUMB_CODE .force_thumb
175 #else
176 #define THUMB_FUNC
177 #define THUMB_CODE
178 #endif
179         
180 .macro FUNC_START name
181         .text
182         .globl SYM (__\name)
183         TYPE (__\name)
184         .align 0
185         THUMB_CODE
186         THUMB_FUNC
187 SYM (__\name):
188 .endm
189
190 /* Special function that will always be coded in ARM assembly, even if
191    in Thumb-only compilation.  */
192
193 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
194 .macro  ARM_FUNC_START name
195         FUNC_START \name
196         bx      pc
197         nop
198         .arm
199 /* A hook to tell gdb that we've switched to ARM mode.  Also used to call
200    directly from other local arm routines.  */
201 _L__\name:              
202 .endm
203 #define EQUIV .thumb_set
204 /* Branch directly to a function declared with ARM_FUNC_START.
205    Must be called in arm mode.  */
206 .macro  ARM_CALL name
207         bl      _L__\name
208 .endm
209 #else
210 .macro  ARM_FUNC_START name
211         .text
212         .globl SYM (__\name)
213         TYPE (__\name)
214         .align 0
215         .arm
216 SYM (__\name):
217 .endm
218 #define EQUIV .set
219 .macro  ARM_CALL name
220         bl      __\name
221 .endm
222 #endif
223
224 .macro  ARM_FUNC_ALIAS new old
225         .globl  SYM (__\new)
226         EQUIV   SYM (__\new), SYM (__\old)
227 #ifdef __thumb__
228         .set    SYM (_L__\new), SYM (_L__\old)
229 #endif
230 .endm
231
232 #ifdef __thumb__
233 /* Register aliases.  */
234
235 work            .req    r4      @ XXXX is this safe ?
236 dividend        .req    r0
237 divisor         .req    r1
238 overdone        .req    r2
239 result          .req    r2
240 curbit          .req    r3
241 #endif
242 #if 0
243 ip              .req    r12
244 sp              .req    r13
245 lr              .req    r14
246 pc              .req    r15
247 #endif
248
249 /* ------------------------------------------------------------------------ */
250 /*              Bodies of the division and modulo routines.                 */
251 /* ------------------------------------------------------------------------ */  
252 .macro ARM_DIV_BODY dividend, divisor, result, curbit
253
254 #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
255
256         clz     \curbit, \dividend
257         clz     \result, \divisor
258         sub     \curbit, \result, \curbit
259         rsbs    \curbit, \curbit, #31
260         addne   \curbit, \curbit, \curbit, lsl #1
261         mov     \result, #0
262         addne   pc, pc, \curbit, lsl #2
263         nop
264         .set    shift, 32
265         .rept   32
266         .set    shift, shift - 1
267         cmp     \dividend, \divisor, lsl #shift
268         adc     \result, \result, \result
269         subcs   \dividend, \dividend, \divisor, lsl #shift
270         .endr
271
272 #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
273 #if __ARM_ARCH__ >= 5
274
275         clz     \curbit, \divisor
276         clz     \result, \dividend
277         sub     \result, \curbit, \result
278         mov     \curbit, #1
279         mov     \divisor, \divisor, lsl \result
280         mov     \curbit, \curbit, lsl \result
281         mov     \result, #0
282         
283 #else /* __ARM_ARCH__ < 5 */
284
285         @ Initially shift the divisor left 3 bits if possible,
286         @ set curbit accordingly.  This allows for curbit to be located
287         @ at the left end of each 4 bit nibbles in the division loop
288         @ to save one loop in most cases.
289         tst     \divisor, #0xe0000000
290         moveq   \divisor, \divisor, lsl #3
291         moveq   \curbit, #8
292         movne   \curbit, #1
293
294         @ Unless the divisor is very big, shift it up in multiples of
295         @ four bits, since this is the amount of unwinding in the main
296         @ division loop.  Continue shifting until the divisor is 
297         @ larger than the dividend.
298 1:      cmp     \divisor, #0x10000000
299         cmplo   \divisor, \dividend
300         movlo   \divisor, \divisor, lsl #4
301         movlo   \curbit, \curbit, lsl #4
302         blo     1b
303
304         @ For very big divisors, we must shift it a bit at a time, or
305         @ we will be in danger of overflowing.
306 1:      cmp     \divisor, #0x80000000
307         cmplo   \divisor, \dividend
308         movlo   \divisor, \divisor, lsl #1
309         movlo   \curbit, \curbit, lsl #1
310         blo     1b
311
312         mov     \result, #0
313
314 #endif /* __ARM_ARCH__ < 5 */
315
316         @ Division loop
317 1:      cmp     \dividend, \divisor
318         subhs   \dividend, \dividend, \divisor
319         orrhs   \result,   \result,   \curbit
320         cmp     \dividend, \divisor,  lsr #1
321         subhs   \dividend, \dividend, \divisor, lsr #1
322         orrhs   \result,   \result,   \curbit,  lsr #1
323         cmp     \dividend, \divisor,  lsr #2
324         subhs   \dividend, \dividend, \divisor, lsr #2
325         orrhs   \result,   \result,   \curbit,  lsr #2
326         cmp     \dividend, \divisor,  lsr #3
327         subhs   \dividend, \dividend, \divisor, lsr #3
328         orrhs   \result,   \result,   \curbit,  lsr #3
329         cmp     \dividend, #0                   @ Early termination?
330         movnes  \curbit,   \curbit,  lsr #4     @ No, any more bits to do?
331         movne   \divisor,  \divisor, lsr #4
332         bne     1b
333
334 #endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
335
336 .endm
337 /* ------------------------------------------------------------------------ */  
338 .macro ARM_DIV2_ORDER divisor, order
339
340 #if __ARM_ARCH__ >= 5
341
342         clz     \order, \divisor
343         rsb     \order, \order, #31
344
345 #else
346
347         cmp     \divisor, #(1 << 16)
348         movhs   \divisor, \divisor, lsr #16
349         movhs   \order, #16
350         movlo   \order, #0
351
352         cmp     \divisor, #(1 << 8)
353         movhs   \divisor, \divisor, lsr #8
354         addhs   \order, \order, #8
355
356         cmp     \divisor, #(1 << 4)
357         movhs   \divisor, \divisor, lsr #4
358         addhs   \order, \order, #4
359
360         cmp     \divisor, #(1 << 2)
361         addhi   \order, \order, #3
362         addls   \order, \order, \divisor, lsr #1
363
364 #endif
365
366 .endm
367 /* ------------------------------------------------------------------------ */
368 .macro ARM_MOD_BODY dividend, divisor, order, spare
369
370 #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
371
372         clz     \order, \divisor
373         clz     \spare, \dividend
374         sub     \order, \order, \spare
375         rsbs    \order, \order, #31
376         addne   pc, pc, \order, lsl #3
377         nop
378         .set    shift, 32
379         .rept   32
380         .set    shift, shift - 1
381         cmp     \dividend, \divisor, lsl #shift
382         subcs   \dividend, \dividend, \divisor, lsl #shift
383         .endr
384
385 #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
386 #if __ARM_ARCH__ >= 5
387
388         clz     \order, \divisor
389         clz     \spare, \dividend
390         sub     \order, \order, \spare
391         mov     \divisor, \divisor, lsl \order
392         
393 #else /* __ARM_ARCH__ < 5 */
394
395         mov     \order, #0
396
397         @ Unless the divisor is very big, shift it up in multiples of
398         @ four bits, since this is the amount of unwinding in the main
399         @ division loop.  Continue shifting until the divisor is 
400         @ larger than the dividend.
401 1:      cmp     \divisor, #0x10000000
402         cmplo   \divisor, \dividend
403         movlo   \divisor, \divisor, lsl #4
404         addlo   \order, \order, #4
405         blo     1b
406
407         @ For very big divisors, we must shift it a bit at a time, or
408         @ we will be in danger of overflowing.
409 1:      cmp     \divisor, #0x80000000
410         cmplo   \divisor, \dividend
411         movlo   \divisor, \divisor, lsl #1
412         addlo   \order, \order, #1
413         blo     1b
414
415 #endif /* __ARM_ARCH__ < 5 */
416
417         @ Perform all needed substractions to keep only the reminder.
418         @ Do comparisons in batch of 4 first.
419         subs    \order, \order, #3              @ yes, 3 is intended here
420         blt     2f
421
422 1:      cmp     \dividend, \divisor
423         subhs   \dividend, \dividend, \divisor
424         cmp     \dividend, \divisor,  lsr #1
425         subhs   \dividend, \dividend, \divisor, lsr #1
426         cmp     \dividend, \divisor,  lsr #2
427         subhs   \dividend, \dividend, \divisor, lsr #2
428         cmp     \dividend, \divisor,  lsr #3
429         subhs   \dividend, \dividend, \divisor, lsr #3
430         cmp     \dividend, #1
431         mov     \divisor, \divisor, lsr #4
432         subges  \order, \order, #4
433         bge     1b
434
435         tst     \order, #3
436         teqne   \dividend, #0
437         beq     5f
438
439         @ Either 1, 2 or 3 comparison/substractions are left.
440 2:      cmn     \order, #2
441         blt     4f
442         beq     3f
443         cmp     \dividend, \divisor
444         subhs   \dividend, \dividend, \divisor
445         mov     \divisor,  \divisor,  lsr #1
446 3:      cmp     \dividend, \divisor
447         subhs   \dividend, \dividend, \divisor
448         mov     \divisor,  \divisor,  lsr #1
449 4:      cmp     \dividend, \divisor
450         subhs   \dividend, \dividend, \divisor
451 5:
452
453 #endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
454
455 .endm
456 /* ------------------------------------------------------------------------ */
457 .macro THUMB_DIV_MOD_BODY modulo
458         @ Load the constant 0x10000000 into our work register.
459         mov     work, #1
460         lsl     work, #28
461 LSYM(Loop1):
462         @ Unless the divisor is very big, shift it up in multiples of
463         @ four bits, since this is the amount of unwinding in the main
464         @ division loop.  Continue shifting until the divisor is 
465         @ larger than the dividend.
466         cmp     divisor, work
467         bhs     LSYM(Lbignum)
468         cmp     divisor, dividend
469         bhs     LSYM(Lbignum)
470         lsl     divisor, #4
471         lsl     curbit,  #4
472         b       LSYM(Loop1)
473 LSYM(Lbignum):
474         @ Set work to 0x80000000
475         lsl     work, #3
476 LSYM(Loop2):
477         @ For very big divisors, we must shift it a bit at a time, or
478         @ we will be in danger of overflowing.
479         cmp     divisor, work
480         bhs     LSYM(Loop3)
481         cmp     divisor, dividend
482         bhs     LSYM(Loop3)
483         lsl     divisor, #1
484         lsl     curbit,  #1
485         b       LSYM(Loop2)
486 LSYM(Loop3):
487         @ Test for possible subtractions ...
488   .if \modulo
489         @ ... On the final pass, this may subtract too much from the dividend, 
490         @ so keep track of which subtractions are done, we can fix them up 
491         @ afterwards.
492         mov     overdone, #0
493         cmp     dividend, divisor
494         blo     LSYM(Lover1)
495         sub     dividend, dividend, divisor
496 LSYM(Lover1):
497         lsr     work, divisor, #1
498         cmp     dividend, work
499         blo     LSYM(Lover2)
500         sub     dividend, dividend, work
501         mov     ip, curbit
502         mov     work, #1
503         ror     curbit, work
504         orr     overdone, curbit
505         mov     curbit, ip
506 LSYM(Lover2):
507         lsr     work, divisor, #2
508         cmp     dividend, work
509         blo     LSYM(Lover3)
510         sub     dividend, dividend, work
511         mov     ip, curbit
512         mov     work, #2
513         ror     curbit, work
514         orr     overdone, curbit
515         mov     curbit, ip
516 LSYM(Lover3):
517         lsr     work, divisor, #3
518         cmp     dividend, work
519         blo     LSYM(Lover4)
520         sub     dividend, dividend, work
521         mov     ip, curbit
522         mov     work, #3
523         ror     curbit, work
524         orr     overdone, curbit
525         mov     curbit, ip
526 LSYM(Lover4):
527         mov     ip, curbit
528   .else
529         @ ... and note which bits are done in the result.  On the final pass,
530         @ this may subtract too much from the dividend, but the result will be ok,
531         @ since the "bit" will have been shifted out at the bottom.
532         cmp     dividend, divisor
533         blo     LSYM(Lover1)
534         sub     dividend, dividend, divisor
535         orr     result, result, curbit
536 LSYM(Lover1):
537         lsr     work, divisor, #1
538         cmp     dividend, work
539         blo     LSYM(Lover2)
540         sub     dividend, dividend, work
541         lsr     work, curbit, #1
542         orr     result, work
543 LSYM(Lover2):
544         lsr     work, divisor, #2
545         cmp     dividend, work
546         blo     LSYM(Lover3)
547         sub     dividend, dividend, work
548         lsr     work, curbit, #2
549         orr     result, work
550 LSYM(Lover3):
551         lsr     work, divisor, #3
552         cmp     dividend, work
553         blo     LSYM(Lover4)
554         sub     dividend, dividend, work
555         lsr     work, curbit, #3
556         orr     result, work
557 LSYM(Lover4):
558   .endif
559         
560         cmp     dividend, #0                    @ Early termination?
561         beq     LSYM(Lover5)
562         lsr     curbit,  #4                     @ No, any more bits to do?
563         beq     LSYM(Lover5)
564         lsr     divisor, #4
565         b       LSYM(Loop3)
566 LSYM(Lover5):
567   .if \modulo
568         @ Any subtractions that we should not have done will be recorded in
569         @ the top three bits of "overdone".  Exactly which were not needed
570         @ are governed by the position of the bit, stored in ip.
571         mov     work, #0xe
572         lsl     work, #28
573         and     overdone, work
574         beq     LSYM(Lgot_result)
575         
576         @ If we terminated early, because dividend became zero, then the 
577         @ bit in ip will not be in the bottom nibble, and we should not
578         @ perform the additions below.  We must test for this though
579         @ (rather relying upon the TSTs to prevent the additions) since
580         @ the bit in ip could be in the top two bits which might then match
581         @ with one of the smaller RORs.
582         mov     curbit, ip
583         mov     work, #0x7
584         tst     curbit, work
585         beq     LSYM(Lgot_result)
586         
587         mov     curbit, ip
588         mov     work, #3
589         ror     curbit, work
590         tst     overdone, curbit
591         beq     LSYM(Lover6)
592         lsr     work, divisor, #3
593         add     dividend, work
594 LSYM(Lover6):
595         mov     curbit, ip
596         mov     work, #2
597         ror     curbit, work
598         tst     overdone, curbit
599         beq     LSYM(Lover7)
600         lsr     work, divisor, #2
601         add     dividend, work
602 LSYM(Lover7):
603         mov     curbit, ip
604         mov     work, #1
605         ror     curbit, work
606         tst     overdone, curbit
607         beq     LSYM(Lgot_result)
608         lsr     work, divisor, #1
609         add     dividend, work
610   .endif
611 LSYM(Lgot_result):
612 .endm   
613 /* ------------------------------------------------------------------------ */
614 /*              Start of the Real Functions                                 */
615 /* ------------------------------------------------------------------------ */
616 #ifdef L_udivsi3
617
618         FUNC_START udivsi3
619
620 #ifdef __thumb__
621
622         cmp     divisor, #0
623         beq     LSYM(Ldiv0)
624         mov     curbit, #1
625         mov     result, #0
626         
627         push    { work }
628         cmp     dividend, divisor
629         blo     LSYM(Lgot_result)
630
631         THUMB_DIV_MOD_BODY 0
632         
633         mov     r0, result
634         pop     { work }
635         RET
636
637 #else /* ARM version.  */
638
639         subs    r2, r1, #1
640         RETc(eq)
641         bcc     LSYM(Ldiv0)
642         cmp     r0, r1
643         bls     11f
644         tst     r1, r2
645         beq     12f
646         
647         ARM_DIV_BODY r0, r1, r2, r3
648         
649         mov     r0, r2
650         RET     
651
652 11:     moveq   r0, #1
653         movne   r0, #0
654         RET
655
656 12:     ARM_DIV2_ORDER r1, r2
657
658         mov     r0, r0, lsr r2
659         RET
660
661 #endif /* ARM version */
662
663         DIV_FUNC_END udivsi3
664
665 FUNC_START aeabi_uidivmod
666 #ifdef __thumb__
667         push    {r0, r1, lr}
668         bl      SYM(__udivsi3)
669         POP     {r1, r2, r3}
670         mul     r2, r0
671         sub     r1, r1, r2
672         bx      r3
673 #else
674         stmfd   sp!, { r0, r1, lr }
675         bl      SYM(__udivsi3)
676         ldmfd   sp!, { r1, r2, lr }
677         mul     r3, r2, r0
678         sub     r1, r1, r3
679         RET
680 #endif
681         FUNC_END aeabi_uidivmod
682         
683 #endif /* L_udivsi3 */
684 /* ------------------------------------------------------------------------ */
685 #ifdef L_umodsi3
686
687         FUNC_START umodsi3
688
689 #ifdef __thumb__
690
691         cmp     divisor, #0
692         beq     LSYM(Ldiv0)
693         mov     curbit, #1
694         cmp     dividend, divisor
695         bhs     LSYM(Lover10)
696         RET     
697
698 LSYM(Lover10):
699         push    { work }
700
701         THUMB_DIV_MOD_BODY 1
702         
703         pop     { work }
704         RET
705         
706 #else  /* ARM version.  */
707         
708         subs    r2, r1, #1                      @ compare divisor with 1
709         bcc     LSYM(Ldiv0)
710         cmpne   r0, r1                          @ compare dividend with divisor
711         moveq   r0, #0
712         tsthi   r1, r2                          @ see if divisor is power of 2
713         andeq   r0, r0, r2
714         RETc(ls)
715
716         ARM_MOD_BODY r0, r1, r2, r3
717         
718         RET     
719
720 #endif /* ARM version.  */
721         
722         DIV_FUNC_END umodsi3
723
724 #endif /* L_umodsi3 */
725 /* ------------------------------------------------------------------------ */
726 #ifdef L_divsi3
727
728         FUNC_START divsi3       
729
730 #ifdef __thumb__
731         cmp     divisor, #0
732         beq     LSYM(Ldiv0)
733         
734         push    { work }
735         mov     work, dividend
736         eor     work, divisor           @ Save the sign of the result.
737         mov     ip, work
738         mov     curbit, #1
739         mov     result, #0
740         cmp     divisor, #0
741         bpl     LSYM(Lover10)
742         neg     divisor, divisor        @ Loops below use unsigned.
743 LSYM(Lover10):
744         cmp     dividend, #0
745         bpl     LSYM(Lover11)
746         neg     dividend, dividend
747 LSYM(Lover11):
748         cmp     dividend, divisor
749         blo     LSYM(Lgot_result)
750
751         THUMB_DIV_MOD_BODY 0
752         
753         mov     r0, result
754         mov     work, ip
755         cmp     work, #0
756         bpl     LSYM(Lover12)
757         neg     r0, r0
758 LSYM(Lover12):
759         pop     { work }
760         RET
761
762 #else /* ARM version.  */
763         
764         cmp     r1, #0
765         eor     ip, r0, r1                      @ save the sign of the result.
766         beq     LSYM(Ldiv0)
767         rsbmi   r1, r1, #0                      @ loops below use unsigned.
768         subs    r2, r1, #1                      @ division by 1 or -1 ?
769         beq     10f
770         movs    r3, r0
771         rsbmi   r3, r0, #0                      @ positive dividend value
772         cmp     r3, r1
773         bls     11f
774         tst     r1, r2                          @ divisor is power of 2 ?
775         beq     12f
776
777         ARM_DIV_BODY r3, r1, r0, r2
778         
779         cmp     ip, #0
780         rsbmi   r0, r0, #0
781         RET     
782
783 10:     teq     ip, r0                          @ same sign ?
784         rsbmi   r0, r0, #0
785         RET     
786
787 11:     movlo   r0, #0
788         moveq   r0, ip, asr #31
789         orreq   r0, r0, #1
790         RET
791
792 12:     ARM_DIV2_ORDER r1, r2
793
794         cmp     ip, #0
795         mov     r0, r3, lsr r2
796         rsbmi   r0, r0, #0
797         RET
798
799 #endif /* ARM version */
800         
801         DIV_FUNC_END divsi3
802
803 FUNC_START aeabi_idivmod
804 #ifdef __thumb__
805         push    {r0, r1, lr}
806         bl      SYM(__divsi3)
807         POP     {r1, r2, r3}
808         mul     r2, r0
809         sub     r1, r1, r2
810         bx      r3
811 #else
812         stmfd   sp!, { r0, r1, lr }
813         bl      SYM(__divsi3)
814         ldmfd   sp!, { r1, r2, lr }
815         mul     r3, r2, r0
816         sub     r1, r1, r3
817         RET
818 #endif
819         FUNC_END aeabi_idivmod
820         
821 #endif /* L_divsi3 */
822 /* ------------------------------------------------------------------------ */
823 #ifdef L_modsi3
824
825         FUNC_START modsi3
826
827 #ifdef __thumb__
828
829         mov     curbit, #1
830         cmp     divisor, #0
831         beq     LSYM(Ldiv0)
832         bpl     LSYM(Lover10)
833         neg     divisor, divisor                @ Loops below use unsigned.
834 LSYM(Lover10):
835         push    { work }
836         @ Need to save the sign of the dividend, unfortunately, we need
837         @ work later on.  Must do this after saving the original value of
838         @ the work register, because we will pop this value off first.
839         push    { dividend }
840         cmp     dividend, #0
841         bpl     LSYM(Lover11)
842         neg     dividend, dividend
843 LSYM(Lover11):
844         cmp     dividend, divisor
845         blo     LSYM(Lgot_result)
846
847         THUMB_DIV_MOD_BODY 1
848                 
849         pop     { work }
850         cmp     work, #0
851         bpl     LSYM(Lover12)
852         neg     dividend, dividend
853 LSYM(Lover12):
854         pop     { work }
855         RET     
856
857 #else /* ARM version.  */
858         
859         cmp     r1, #0
860         beq     LSYM(Ldiv0)
861         rsbmi   r1, r1, #0                      @ loops below use unsigned.
862         movs    ip, r0                          @ preserve sign of dividend
863         rsbmi   r0, r0, #0                      @ if negative make positive
864         subs    r2, r1, #1                      @ compare divisor with 1
865         cmpne   r0, r1                          @ compare dividend with divisor
866         moveq   r0, #0
867         tsthi   r1, r2                          @ see if divisor is power of 2
868         andeq   r0, r0, r2
869         bls     10f
870
871         ARM_MOD_BODY r0, r1, r2, r3
872
873 10:     cmp     ip, #0
874         rsbmi   r0, r0, #0
875         RET     
876
877 #endif /* ARM version */
878         
879         DIV_FUNC_END modsi3
880
881 #endif /* L_modsi3 */
882 /* ------------------------------------------------------------------------ */
883 #ifdef L_dvmd_tls
884
885         FUNC_START div0
886         ARM_FUNC_ALIAS aeabi_idiv0 div0
887         ARM_FUNC_ALIAS aeabi_ldiv0 div0
888
889         RET
890
891         FUNC_END aeabi_ldiv0
892         FUNC_END aeabi_idiv0
893         FUNC_END div0
894         
895 #endif /* L_divmodsi_tools */
896 /* ------------------------------------------------------------------------ */
897 #ifdef L_dvmd_lnx
898 @ GNU/Linux division-by zero handler.  Used in place of L_dvmd_tls
899
900 /* Constants taken from <asm/unistd.h> and <asm/signal.h> */
901 #define SIGFPE  8
902 #define __NR_SYSCALL_BASE       0x900000
903 #define __NR_getpid                     (__NR_SYSCALL_BASE+ 20)
904 #define __NR_kill                       (__NR_SYSCALL_BASE+ 37)
905
906         .code   32
907         FUNC_START div0
908
909         stmfd   sp!, {r1, lr}
910         swi     __NR_getpid
911         cmn     r0, #1000
912         RETLDM  r1 hs
913         mov     r1, #SIGFPE
914         swi     __NR_kill
915         RETLDM  r1
916
917         FUNC_END div0
918         
919 #endif /* L_dvmd_lnx */
920 /* ------------------------------------------------------------------------ */
921 /* Dword shift operations.  */
922 /* All the following Dword shift variants rely on the fact that
923         shft xxx, Reg
924    is in fact done as
925         shft xxx, (Reg & 255)
926    so for Reg value in (32...63) and (-1...-31) we will get zero (in the
927    case of logical shifts) or the sign (for asr).  */
928
929 #ifdef __ARMEB__
930 #define al      r1
931 #define ah      r0
932 #else
933 #define al      r0
934 #define ah      r1
935 #endif
936
937 #ifdef L_lshrdi3
938
939         FUNC_START lshrdi3
940         ARM_FUNC_ALIAS aeabi_llsr lshrdi3
941         
942 #ifdef __thumb__
943         lsr     al, r2
944         mov     r3, ah
945         lsr     ah, r2
946         mov     ip, r3
947         sub     r2, #32
948         lsr     r3, r2
949         orr     al, r3
950         neg     r2, r2
951         mov     r3, ip
952         lsl     r3, r2
953         orr     al, r3
954         RET
955 #else
956         subs    r3, r2, #32
957         rsb     ip, r2, #32
958         movmi   al, al, lsr r2
959         movpl   al, ah, lsr r3
960         orrmi   al, al, ah, lsl ip
961         mov     ah, ah, lsr r2
962         RET
963 #endif
964         FUNC_END aeabi_llsr
965         FUNC_END lshrdi3
966
967 #endif
968         
969 #ifdef L_ashrdi3
970         
971         FUNC_START ashrdi3
972         ARM_FUNC_ALIAS aeabi_lasr ashrdi3
973         
974 #ifdef __thumb__
975         lsr     al, r2
976         mov     r3, ah
977         asr     ah, r2
978         sub     r2, #32
979         @ If r2 is negative at this point the following step would OR
980         @ the sign bit into all of AL.  That's not what we want...
981         bmi     1f
982         mov     ip, r3
983         asr     r3, r2
984         orr     al, r3
985         mov     r3, ip
986 1:
987         neg     r2, r2
988         lsl     r3, r2
989         orr     al, r3
990         RET
991 #else
992         subs    r3, r2, #32
993         rsb     ip, r2, #32
994         movmi   al, al, lsr r2
995         movpl   al, ah, asr r3
996         orrmi   al, al, ah, lsl ip
997         mov     ah, ah, asr r2
998         RET
999 #endif
1000
1001         FUNC_END aeabi_lasr
1002         FUNC_END ashrdi3
1003
1004 #endif
1005
1006 #ifdef L_ashldi3
1007
1008         FUNC_START ashldi3
1009         ARM_FUNC_ALIAS aeabi_llsl ashldi3
1010         
1011 #ifdef __thumb__
1012         lsl     ah, r2
1013         mov     r3, al
1014         lsl     al, r2
1015         mov     ip, r3
1016         sub     r2, #32
1017         lsl     r3, r2
1018         orr     ah, r3
1019         neg     r2, r2
1020         mov     r3, ip
1021         lsr     r3, r2
1022         orr     ah, r3
1023         RET
1024 #else
1025         subs    r3, r2, #32
1026         rsb     ip, r2, #32
1027         movmi   ah, ah, lsl r2
1028         movpl   ah, al, lsl r3
1029         orrmi   ah, ah, al, lsr ip
1030         mov     al, al, lsl r2
1031         RET
1032 #endif
1033         FUNC_END aeabi_llsl
1034         FUNC_END ashldi3
1035
1036 #endif
1037
1038 /* ------------------------------------------------------------------------ */
1039 /* These next two sections are here despite the fact that they contain Thumb 
1040    assembler because their presence allows interworked code to be linked even
1041    when the GCC library is this one.  */
1042                 
1043 /* Do not build the interworking functions when the target architecture does 
1044    not support Thumb instructions.  (This can be a multilib option).  */
1045 #if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
1046       || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
1047       || __ARM_ARCH__ >= 6
1048
1049 #if defined L_call_via_rX
1050
1051 /* These labels & instructions are used by the Arm/Thumb interworking code. 
1052    The address of function to be called is loaded into a register and then 
1053    one of these labels is called via a BL instruction.  This puts the 
1054    return address into the link register with the bottom bit set, and the 
1055    code here switches to the correct mode before executing the function.  */
1056         
1057         .text
1058         .align 0
1059         .force_thumb
1060
1061 .macro call_via register
1062         THUMB_FUNC_START _call_via_\register
1063
1064         bx      \register
1065         nop
1066
1067         SIZE    (_call_via_\register)
1068 .endm
1069
1070         call_via r0
1071         call_via r1
1072         call_via r2
1073         call_via r3
1074         call_via r4
1075         call_via r5
1076         call_via r6
1077         call_via r7
1078         call_via r8
1079         call_via r9
1080         call_via sl
1081         call_via fp
1082         call_via ip
1083         call_via sp
1084         call_via lr
1085
1086 #endif /* L_call_via_rX */
1087
1088 #if defined L_interwork_call_via_rX
1089
1090 /* These labels & instructions are used by the Arm/Thumb interworking code,
1091    when the target address is in an unknown instruction set.  The address 
1092    of function to be called is loaded into a register and then one of these
1093    labels is called via a BL instruction.  This puts the return address 
1094    into the link register with the bottom bit set, and the code here 
1095    switches to the correct mode before executing the function.  Unfortunately
1096    the target code cannot be relied upon to return via a BX instruction, so
1097    instead we have to store the resturn address on the stack and allow the
1098    called function to return here instead.  Upon return we recover the real
1099    return address and use a BX to get back to Thumb mode.  */
1100         
1101         .text
1102         .align 0
1103
1104         .code   32
1105         .globl _arm_return
1106 _arm_return:
1107         RETLDM
1108         .code   16
1109
1110 .macro interwork register
1111         .code   16
1112
1113         THUMB_FUNC_START _interwork_call_via_\register
1114
1115         bx      pc
1116         nop
1117
1118         .code   32
1119         .globl LSYM(Lchange_\register)
1120 LSYM(Lchange_\register):
1121         tst     \register, #1
1122         streq   lr, [sp, #-4]!
1123         adreq   lr, _arm_return
1124         bx      \register
1125
1126         SIZE    (_interwork_call_via_\register)
1127 .endm
1128         
1129         interwork r0
1130         interwork r1
1131         interwork r2
1132         interwork r3
1133         interwork r4
1134         interwork r5
1135         interwork r6
1136         interwork r7
1137         interwork r8
1138         interwork r9
1139         interwork sl
1140         interwork fp
1141         interwork ip
1142         interwork sp
1143         
1144         /* The LR case has to be handled a little differently...  */
1145         .code 16
1146
1147         THUMB_FUNC_START _interwork_call_via_lr
1148
1149         bx      pc
1150         nop
1151         
1152         .code 32
1153         .globl .Lchange_lr
1154 .Lchange_lr:
1155         tst     lr, #1
1156         stmeqdb r13!, {lr}
1157         mov     ip, lr
1158         adreq   lr, _arm_return
1159         bx      ip
1160         
1161         SIZE    (_interwork_call_via_lr)
1162         
1163 #endif /* L_interwork_call_via_rX */
1164 #endif /* Arch supports thumb.  */
1165
1166 #ifndef __symbian__
1167 #include "ieee754-df.S"
1168 #include "ieee754-sf.S"
1169 #include "bpabi.S"
1170 #endif /* __symbian__ */