OSDN Git Service

* i960.c (i960_output_function_prologue, i960_print_operand,
[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 Free Software Foundation, Inc.
5
6 This file is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file.  (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
18 executable.)
19
20 This file is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; see the file COPYING.  If not, write to
27 the Free Software Foundation, 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.  */
29 /* ------------------------------------------------------------------------ */
30
31 /* We need to know what prefix to add to function names.  */
32
33 #ifndef __USER_LABEL_PREFIX__
34 #error  __USER_LABEL_PREFIX__ not defined
35 #endif
36
37 /* ANSI concatenation macros.  */
38
39 #define CONCAT1(a, b) CONCAT2(a, b)
40 #define CONCAT2(a, b) a ## b
41
42 /* Use the right prefix for global labels.  */
43
44 #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
45
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)
54 #define LSYM(x) .x
55 #else
56 #define __PLT__
57 #define TYPE(x)
58 #define SIZE(x)
59 #define LSYM(x) x
60 #endif
61
62 /* Function end macros.  Variants for 26 bit APCS and interworking.  */
63
64 #ifdef __APCS_26__
65 # define RET            movs    pc, lr
66 # define RETc(x)        mov##x##s       pc, lr
67 # define RETCOND        ^
68 .macro ARM_LDIV0
69 LSYM(Ldiv0):
70         str     lr, [sp, #-4]!
71         bl      SYM (__div0) __PLT__
72         mov     r0, #0                  @ About as wrong as it could be.
73         ldmia   sp!, {pc}^
74 .endm
75 #else
76 # ifdef __THUMB_INTERWORK__
77 #  define RET           bx      lr
78 #  define RETc(x)       bx##x   lr
79 .macro THUMB_LDIV0
80 LSYM(Ldiv0):
81         push    { lr }
82         bl      SYM (__div0)
83         mov     r0, #0                  @ About as wrong as it could be.
84         pop     { r1 }
85         bx      r1
86 .endm
87 .macro ARM_LDIV0
88 LSYM(Ldiv0):
89         str     lr, [sp, #-4]!
90         bl      SYM (__div0) __PLT__
91         mov     r0, #0                  @ About as wrong as it could be.
92         ldr     lr, [sp], #4
93         bx      lr
94 .endm   
95 # else
96 #  define RET           mov     pc, lr
97 #  define RETc(x)       mov##x  pc, lr
98 .macro THUMB_LDIV0
99 LSYM(Ldiv0):
100         push    { lr }
101         bl      SYM (__div0)
102         mov     r0, #0                  @ About as wrong as it could be.
103         pop     { pc }
104 .endm
105 .macro ARM_LDIV0
106 LSYM(Ldiv0):
107         str     lr, [sp, #-4]!
108         bl      SYM (__div0) __PLT__
109         mov     r0, #0                  @ About as wrong as it could be.
110         ldmia   sp!, {pc}
111 .endm   
112 # endif
113 # define RETCOND
114 #endif
115
116 .macro FUNC_END name
117 LSYM(Ldiv0):
118 #ifdef __thumb__
119         THUMB_LDIV0
120 #else
121         ARM_LDIV0
122 #endif
123         SIZE (__\name)  
124 .endm
125
126 .macro THUMB_FUNC_START name
127         .globl  SYM (\name)
128         TYPE    (\name)
129         .thumb_func
130 SYM (\name):
131 .endm
132
133 /* Function start macros.  Variants for ARM and Thumb.  */
134
135 #ifdef __thumb__
136 #define THUMB_FUNC .thumb_func
137 #define THUMB_CODE .force_thumb
138 #else
139 #define THUMB_FUNC
140 #define THUMB_CODE
141 #endif
142         
143 .macro FUNC_START name
144         .text
145         .globl SYM (__\name)
146         TYPE (__\name)
147         .align 0
148         THUMB_CODE
149         THUMB_FUNC
150 SYM (__\name):
151 .endm
152                 
153 /* Register aliases.  */
154
155 work            .req    r4      @ XXXX is this safe ?
156 dividend        .req    r0
157 divisor         .req    r1
158 overdone        .req    r2
159 result          .req    r2
160 curbit          .req    r3
161 ip              .req    r12
162 sp              .req    r13
163 lr              .req    r14
164 pc              .req    r15
165
166 /* ------------------------------------------------------------------------ */
167 /*              Bodies of the divsion and modulo routines.                  */
168 /* ------------------------------------------------------------------------ */  
169 .macro ARM_DIV_MOD_BODY modulo
170 LSYM(Loop1):
171         @ Unless the divisor is very big, shift it up in multiples of
172         @ four bits, since this is the amount of unwinding in the main
173         @ division loop.  Continue shifting until the divisor is 
174         @ larger than the dividend.
175         cmp     divisor, #0x10000000
176         cmplo   divisor, dividend
177         movlo   divisor, divisor, lsl #4
178         movlo   curbit,  curbit,  lsl #4
179         blo     LSYM(Loop1)
180
181 LSYM(Lbignum):
182         @ For very big divisors, we must shift it a bit at a time, or
183         @ we will be in danger of overflowing.
184         cmp     divisor, #0x80000000
185         cmplo   divisor, dividend
186         movlo   divisor, divisor, lsl #1
187         movlo   curbit,  curbit,  lsl #1
188         blo     LSYM(Lbignum)
189
190 LSYM(Loop3):
191         @ Test for possible subtractions.  On the final pass, this may 
192         @ subtract too much from the dividend ...
193         
194   .if \modulo
195         @ ... so keep track of which subtractions are done in OVERDONE.
196         @ We can fix them up afterwards.
197         mov     overdone, #0
198         cmp     dividend, divisor
199         subhs   dividend, dividend, divisor
200         cmp     dividend, divisor,  lsr #1
201         subhs   dividend, dividend, divisor, lsr #1
202         orrhs   overdone, overdone, curbit,  ror #1
203         cmp     dividend, divisor,  lsr #2
204         subhs   dividend, dividend, divisor, lsr #2
205         orrhs   overdone, overdone, curbit,  ror #2
206         cmp     dividend, divisor,  lsr #3
207         subhs   dividend, dividend, divisor, lsr #3
208         orrhs   overdone, overdone, curbit,  ror #3
209         mov     ip,       curbit
210   .else
211         @ ... so keep track of which subtractions are done in RESULT.
212         @ The result will be ok, since the "bit" will have been 
213         @ shifted out at the bottom.
214         cmp     dividend, divisor
215         subhs   dividend, dividend, divisor
216         orrhs   result,   result,   curbit
217         cmp     dividend, divisor,  lsr #1
218         subhs   dividend, dividend, divisor, lsr #1
219         orrhs   result,   result,   curbit,  lsr #1
220         cmp     dividend, divisor,  lsr #2
221         subhs   dividend, dividend, divisor, lsr #2
222         orrhs   result,   result,   curbit,  lsr #2
223         cmp     dividend, divisor,  lsr #3
224         subhs   dividend, dividend, divisor, lsr #3
225         orrhs   result,   result,   curbit,  lsr #3
226   .endif
227
228         cmp     dividend, #0                    @ Early termination?
229         movnes  curbit,   curbit,  lsr #4       @ No, any more bits to do?
230         movne   divisor,  divisor, lsr #4
231         bne     LSYM(Loop3)
232
233   .if \modulo
234 LSYM(Lfixup_dividend):  
235         @ Any subtractions that we should not have done will be recorded in
236         @ the top three bits of OVERDONE.  Exactly which were not needed
237         @ are governed by the position of the bit, stored in IP.
238         ands    overdone, overdone, #0xe0000000
239         @ If we terminated early, because dividend became zero, then the 
240         @ bit in ip will not be in the bottom nibble, and we should not
241         @ perform the additions below.  We must test for this though
242         @ (rather relying upon the TSTs to prevent the additions) since
243         @ the bit in ip could be in the top two bits which might then match
244         @ with one of the smaller RORs.
245         tstne   ip, #0x7
246         beq     LSYM(Lgot_result)
247         tst     overdone, ip, ror #3
248         addne   dividend, dividend, divisor, lsr #3
249         tst     overdone, ip, ror #2
250         addne   dividend, dividend, divisor, lsr #2
251         tst     overdone, ip, ror #1
252         addne   dividend, dividend, divisor, lsr #1
253   .endif
254
255 LSYM(Lgot_result):
256 .endm
257 /* ------------------------------------------------------------------------ */
258 .macro THUMB_DIV_MOD_BODY modulo
259         @ Load the constant 0x10000000 into our work register.
260         mov     work, #1
261         lsl     work, #28
262 LSYM(Loop1):
263         @ Unless the divisor is very big, shift it up in multiples of
264         @ four bits, since this is the amount of unwinding in the main
265         @ division loop.  Continue shifting until the divisor is 
266         @ larger than the dividend.
267         cmp     divisor, work
268         bhs     LSYM(Lbignum)
269         cmp     divisor, dividend
270         bhs     LSYM(Lbignum)
271         lsl     divisor, #4
272         lsl     curbit,  #4
273         b       LSYM(Loop1)
274 LSYM(Lbignum):
275         @ Set work to 0x80000000
276         lsl     work, #3
277 LSYM(Loop2):
278         @ For very big divisors, we must shift it a bit at a time, or
279         @ we will be in danger of overflowing.
280         cmp     divisor, work
281         bhs     LSYM(Loop3)
282         cmp     divisor, dividend
283         bhs     LSYM(Loop3)
284         lsl     divisor, #1
285         lsl     curbit,  #1
286         b       LSYM(Loop2)
287 LSYM(Loop3):
288         @ Test for possible subtractions ...
289   .if \modulo
290         @ ... On the final pass, this may subtract too much from the dividend, 
291         @ so keep track of which subtractions are done, we can fix them up 
292         @ afterwards.
293         mov     overdone, #0
294         cmp     dividend, divisor
295         blo     LSYM(Lover1)
296         sub     dividend, dividend, divisor
297 LSYM(Lover1):
298         lsr     work, divisor, #1
299         cmp     dividend, work
300         blo     LSYM(Lover2)
301         sub     dividend, dividend, work
302         mov     ip, curbit
303         mov     work, #1
304         ror     curbit, work
305         orr     overdone, curbit
306         mov     curbit, ip
307 LSYM(Lover2):
308         lsr     work, divisor, #2
309         cmp     dividend, work
310         blo     LSYM(Lover3)
311         sub     dividend, dividend, work
312         mov     ip, curbit
313         mov     work, #2
314         ror     curbit, work
315         orr     overdone, curbit
316         mov     curbit, ip
317 LSYM(Lover3):
318         lsr     work, divisor, #3
319         cmp     dividend, work
320         blo     LSYM(Lover4)
321         sub     dividend, dividend, work
322         mov     ip, curbit
323         mov     work, #3
324         ror     curbit, work
325         orr     overdone, curbit
326         mov     curbit, ip
327 LSYM(Lover4):
328         mov     ip, curbit
329   .else
330         @ ... and note which bits are done in the result.  On the final pass,
331         @ this may subtract too much from the dividend, but the result will be ok,
332         @ since the "bit" will have been shifted out at the bottom.
333         cmp     dividend, divisor
334         blo     LSYM(Lover1)
335         sub     dividend, dividend, divisor
336         orr     result, result, curbit
337 LSYM(Lover1):
338         lsr     work, divisor, #1
339         cmp     dividend, work
340         blo     LSYM(Lover2)
341         sub     dividend, dividend, work
342         lsr     work, curbit, #1
343         orr     result, work
344 LSYM(Lover2):
345         lsr     work, divisor, #2
346         cmp     dividend, work
347         blo     LSYM(Lover3)
348         sub     dividend, dividend, work
349         lsr     work, curbit, #2
350         orr     result, work
351 LSYM(Lover3):
352         lsr     work, divisor, #3
353         cmp     dividend, work
354         blo     LSYM(Lover4)
355         sub     dividend, dividend, work
356         lsr     work, curbit, #3
357         orr     result, work
358 LSYM(Lover4):
359   .endif
360         
361         cmp     dividend, #0                    @ Early termination?
362         beq     LSYM(Lover5)
363         lsr     curbit,  #4                     @ No, any more bits to do?
364         beq     LSYM(Lover5)
365         lsr     divisor, #4
366         b       LSYM(Loop3)
367 LSYM(Lover5):
368   .if \modulo
369         @ Any subtractions that we should not have done will be recorded in
370         @ the top three bits of "overdone".  Exactly which were not needed
371         @ are governed by the position of the bit, stored in ip.
372         mov     work, #0xe
373         lsl     work, #28
374         and     overdone, work
375         beq     LSYM(Lgot_result)
376         
377         @ If we terminated early, because dividend became zero, then the 
378         @ bit in ip will not be in the bottom nibble, and we should not
379         @ perform the additions below.  We must test for this though
380         @ (rather relying upon the TSTs to prevent the additions) since
381         @ the bit in ip could be in the top two bits which might then match
382         @ with one of the smaller RORs.
383         mov     curbit, ip
384         mov     work, #0x7
385         tst     curbit, work
386         beq     LSYM(Lgot_result)
387         
388         mov     curbit, ip
389         mov     work, #3
390         ror     curbit, work
391         tst     overdone, curbit
392         beq     LSYM(Lover6)
393         lsr     work, divisor, #3
394         add     dividend, work
395 LSYM(Lover6):
396         mov     curbit, ip
397         mov     work, #2
398         ror     curbit, work
399         tst     overdone, curbit
400         beq     LSYM(Lover7)
401         lsr     work, divisor, #2
402         add     dividend, work
403 LSYM(Lover7):
404         mov     curbit, ip
405         mov     work, #1
406         ror     curbit, work
407         tst     overdone, curbit
408         beq     LSYM(Lgot_result)
409         lsr     work, divisor, #1
410         add     dividend, work
411   .endif
412 LSYM(Lgot_result):
413 .endm   
414 /* ------------------------------------------------------------------------ */
415 /*              Start of the Real Functions                                 */
416 /* ------------------------------------------------------------------------ */
417 #ifdef L_udivsi3
418
419         FUNC_START udivsi3
420
421 #ifdef __thumb__
422
423         cmp     divisor, #0
424         beq     LSYM(Ldiv0)
425         mov     curbit, #1
426         mov     result, #0
427         
428         push    { work }
429         cmp     dividend, divisor
430         blo     LSYM(Lgot_result)
431
432         THUMB_DIV_MOD_BODY 0
433         
434         mov     r0, result
435         pop     { work }
436         RET
437
438 #else /* ARM version.  */
439         
440         cmp     divisor, #0
441         beq     LSYM(Ldiv0)
442         mov     curbit, #1
443         mov     result, #0
444         cmp     dividend, divisor
445         blo     LSYM(Lgot_result)
446         
447         ARM_DIV_MOD_BODY 0
448         
449         mov     r0, result
450         RET     
451
452 #endif /* ARM version */
453
454         FUNC_END udivsi3
455
456 #endif /* L_udivsi3 */
457 /* ------------------------------------------------------------------------ */
458 #ifdef L_umodsi3
459
460         FUNC_START umodsi3
461
462 #ifdef __thumb__
463
464         cmp     divisor, #0
465         beq     LSYM(Ldiv0)
466         mov     curbit, #1
467         cmp     dividend, divisor
468         bhs     LSYM(Lover10)
469         RET     
470
471 LSYM(Lover10):
472         push    { work }
473
474         THUMB_DIV_MOD_BODY 1
475         
476         pop     { work }
477         RET
478         
479 #else  /* ARM version.  */
480         
481         cmp     divisor, #0
482         beq     LSYM(Ldiv0)
483         cmp     divisor, #1
484         cmpne   dividend, divisor
485         moveq   dividend, #0
486         RETc(lo)
487         mov     curbit, #1
488
489         ARM_DIV_MOD_BODY 1
490         
491         RET     
492
493 #endif /* ARM version.  */
494         
495         FUNC_END umodsi3
496
497 #endif /* L_umodsi3 */
498 /* ------------------------------------------------------------------------ */
499 #ifdef L_divsi3
500
501         FUNC_START divsi3       
502
503 #ifdef __thumb__
504         cmp     divisor, #0
505         beq     LSYM(Ldiv0)
506         
507         push    { work }
508         mov     work, dividend
509         eor     work, divisor           @ Save the sign of the result.
510         mov     ip, work
511         mov     curbit, #1
512         mov     result, #0
513         cmp     divisor, #0
514         bpl     LSYM(Lover10)
515         neg     divisor, divisor        @ Loops below use unsigned.
516 LSYM(Lover10):
517         cmp     dividend, #0
518         bpl     LSYM(Lover11)
519         neg     dividend, dividend
520 LSYM(Lover11):
521         cmp     dividend, divisor
522         blo     LSYM(Lgot_result)
523
524         THUMB_DIV_MOD_BODY 0
525         
526         mov     r0, result
527         mov     work, ip
528         cmp     work, #0
529         bpl     LSYM(Lover12)
530         neg     r0, r0
531 LSYM(Lover12):
532         pop     { work }
533         RET
534
535 #else /* ARM version.  */
536         
537         eor     ip, dividend, divisor           @ Save the sign of the result.
538         mov     curbit, #1
539         mov     result, #0
540         cmp     divisor, #0
541         rsbmi   divisor, divisor, #0            @ Loops below use unsigned.
542         beq     LSYM(Ldiv0)
543         cmp     dividend, #0
544         rsbmi   dividend, dividend, #0
545         cmp     dividend, divisor
546         blo     LSYM(Lgot_result)
547
548         ARM_DIV_MOD_BODY 0
549         
550         mov     r0, result
551         cmp     ip, #0
552         rsbmi   r0, r0, #0
553         RET     
554
555 #endif /* ARM version */
556         
557         FUNC_END divsi3
558
559 #endif /* L_divsi3 */
560 /* ------------------------------------------------------------------------ */
561 #ifdef L_modsi3
562
563         FUNC_START modsi3
564
565 #ifdef __thumb__
566
567         mov     curbit, #1
568         cmp     divisor, #0
569         beq     LSYM(Ldiv0)
570         bpl     LSYM(Lover10)
571         neg     divisor, divisor                @ Loops below use unsigned.
572 LSYM(Lover10):
573         push    { work }
574         @ Need to save the sign of the dividend, unfortunately, we need
575         @ work later on.  Must do this after saving the original value of
576         @ the work register, because we will pop this value off first.
577         push    { dividend }
578         cmp     dividend, #0
579         bpl     LSYM(Lover11)
580         neg     dividend, dividend
581 LSYM(Lover11):
582         cmp     dividend, divisor
583         blo     LSYM(Lgot_result)
584
585         THUMB_DIV_MOD_BODY 1
586                 
587         pop     { work }
588         cmp     work, #0
589         bpl     LSYM(Lover12)
590         neg     dividend, dividend
591 LSYM(Lover12):
592         pop     { work }
593         RET     
594
595 #else /* ARM version.  */
596         
597         cmp     divisor, #0
598         rsbmi   divisor, divisor, #0            @ Loops below use unsigned.
599         beq     LSYM(Ldiv0)
600         @ Need to save the sign of the dividend, unfortunately, we need
601         @ ip later on; this is faster than pushing lr and using that.
602         str     dividend, [sp, #-4]!
603         cmp     dividend, #0                    @ Test dividend against zero
604         rsbmi   dividend, dividend, #0          @ If negative make positive
605         cmp     dividend, divisor               @ else if zero return zero
606         blo     LSYM(Lgot_result)               @ if smaller return dividend
607         mov     curbit, #1
608
609         ARM_DIV_MOD_BODY 1
610
611         ldr     ip, [sp], #4
612         cmp     ip, #0
613         rsbmi   dividend, dividend, #0
614         RET     
615
616 #endif /* ARM version */
617         
618         FUNC_END modsi3
619
620 #endif /* L_modsi3 */
621 /* ------------------------------------------------------------------------ */
622 #ifdef L_dvmd_tls
623
624         FUNC_START div0
625
626         RET
627
628         SIZE    (__div0)
629         
630 #endif /* L_divmodsi_tools */
631 /* ------------------------------------------------------------------------ */
632 #ifdef L_dvmd_lnx
633 @ GNU/Linux division-by zero handler.  Used in place of L_dvmd_tls
634
635 /* Constants taken from <asm/unistd.h> and <asm/signal.h> */
636 #define SIGFPE  8
637 #define __NR_SYSCALL_BASE       0x900000
638 #define __NR_getpid                     (__NR_SYSCALL_BASE+ 20)
639 #define __NR_kill                       (__NR_SYSCALL_BASE+ 37)
640
641         FUNC_START div0
642
643         stmfd   sp!, {r1, lr}
644         swi     __NR_getpid
645         cmn     r0, #1000
646         ldmhsfd sp!, {r1, pc}RETCOND    @ not much we can do
647         mov     r1, #SIGFPE
648         swi     __NR_kill
649 #ifdef __THUMB_INTERWORK__
650         ldmfd   sp!, {r1, lr}
651         bx      lr
652 #else
653         ldmfd   sp!, {r1, pc}RETCOND
654 #endif
655
656         SIZE    (__div0)
657         
658 #endif /* L_dvmd_lnx */
659 /* ------------------------------------------------------------------------ */
660 /* These next two sections are here despite the fact that they contain Thumb 
661    assembler because their presence allows interworked code to be linked even
662    when the GCC library is this one.  */
663                 
664 /* Do not build the interworking functions when the target architecture does 
665    not support Thumb instructions.  (This can be a multilib option).  */
666 #if defined L_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
667
668 /* These labels & instructions are used by the Arm/Thumb interworking code. 
669    The address of function to be called is loaded into a register and then 
670    one of these labels is called via a BL instruction.  This puts the 
671    return address into the link register with the bottom bit set, and the 
672    code here switches to the correct mode before executing the function.  */
673         
674         .text
675         .align 0
676         .force_thumb
677
678 .macro call_via register
679         THUMB_FUNC_START _call_via_\register
680
681         bx      \register
682         nop
683
684         SIZE    (_call_via_\register)
685 .endm
686
687         call_via r0
688         call_via r1
689         call_via r2
690         call_via r3
691         call_via r4
692         call_via r5
693         call_via r6
694         call_via r7
695         call_via r8
696         call_via r9
697         call_via sl
698         call_via fp
699         call_via ip
700         call_via sp
701         call_via lr
702
703 #endif /* L_call_via_rX */
704 /* ------------------------------------------------------------------------ */
705 /* Do not build the interworking functions when the target architecture does 
706    not support Thumb instructions.  (This can be a multilib option).  */
707 #if defined L_interwork_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
708
709 /* These labels & instructions are used by the Arm/Thumb interworking code,
710    when the target address is in an unknown instruction set.  The address 
711    of function to be called is loaded into a register and then one of these
712    labels is called via a BL instruction.  This puts the return address 
713    into the link register with the bottom bit set, and the code here 
714    switches to the correct mode before executing the function.  Unfortunately
715    the target code cannot be relied upon to return via a BX instruction, so
716    instead we have to store the resturn address on the stack and allow the
717    called function to return here instead.  Upon return we recover the real
718    return address and use a BX to get back to Thumb mode.  */
719         
720         .text
721         .align 0
722
723         .code   32
724         .globl _arm_return
725 _arm_return:            
726         ldmia   r13!, {r12}
727         bx      r12
728         .code   16
729
730 .macro interwork register                                       
731         .code   16
732
733         THUMB_FUNC_START _interwork_call_via_\register
734
735         bx      pc
736         nop
737         
738         .code   32
739         .globl .Lchange_\register
740 .Lchange_\register:
741         tst     \register, #1
742         stmeqdb r13!, {lr}
743         adreq   lr, _arm_return
744         bx      \register
745
746         SIZE    (_interwork_call_via_\register)
747 .endm
748         
749         interwork r0
750         interwork r1
751         interwork r2
752         interwork r3
753         interwork r4
754         interwork r5
755         interwork r6
756         interwork r7
757         interwork r8
758         interwork r9
759         interwork sl
760         interwork fp
761         interwork ip
762         interwork sp
763         
764         /* The LR case has to be handled a little differently...  */
765         .code 16
766
767         THUMB_FUNC_START _interwork_call_via_lr
768
769         bx      pc
770         nop
771         
772         .code 32
773         .globl .Lchange_lr
774 .Lchange_lr:
775         tst     lr, #1
776         stmeqdb r13!, {lr}
777         mov     ip, lr
778         adreq   lr, _arm_return
779         bx      ip
780         
781         SIZE    (_interwork_call_via_lr)
782         
783 #endif /* L_interwork_call_via_rX */