diff options
Diffstat (limited to 'gcc/config/arm/lib1thumb.asm')
-rw-r--r-- | gcc/config/arm/lib1thumb.asm | 159 |
1 files changed, 76 insertions, 83 deletions
diff --git a/gcc/config/arm/lib1thumb.asm b/gcc/config/arm/lib1thumb.asm index 8df1ae79e7d..d50d35d15f1 100644 --- a/gcc/config/arm/lib1thumb.asm +++ b/gcc/config/arm/lib1thumb.asm @@ -605,98 +605,91 @@ SYM (__div0): one of these labels is called via a BL instruction. This puts the return address into the link register with the bottom bit set, and the code here switches to the correct mode before executing the function. */ - + .text .align 0 - - .globl SYM (_call_via_r0) - .thumb_func -SYM (_call_via_r0): - bx r0 - nop - - .globl SYM (_call_via_r1) - .thumb_func -SYM (_call_via_r1): - bx r1 - nop - - .globl SYM (_call_via_r2) - .thumb_func -SYM (_call_via_r2): - bx r2 - nop - - .globl SYM (_call_via_r3) - .thumb_func -SYM (_call_via_r3): - bx r3 - nop - - .globl SYM (_call_via_r4) - .thumb_func -SYM (_call_via_r4): - bx r4 - nop - - .globl SYM (_call_via_r5) - .thumb_func -SYM (_call_via_r5): - bx r5 - nop - - .globl SYM (_call_via_r6) - .thumb_func -SYM (_call_via_r6): - bx r6 - nop - .globl SYM (_call_via_r7) +.macro call_via register + .globl SYM (_call_via_\register) .thumb_func -SYM (_call_via_r7): - bx r7 +SYM (_call_via_\register): + bx \register nop +.endm + + call_via r0 + call_via r1 + call_via r2 + call_via r3 + call_via r4 + call_via r5 + call_via r6 + call_via r7 + call_via r8 + call_via r9 + call_via sl + call_via fp + call_via ip + call_via sp + call_via lr - .globl SYM (_call_via_r8) - .thumb_func -SYM (_call_via_r8): - bx r8 - nop - - .globl SYM (_call_via_r9) - .thumb_func -SYM (_call_via_r9): - bx r9 - nop - - .globl SYM (_call_via_sl) - .thumb_func -SYM (_call_via_sl): - bx sl - nop - - .globl SYM (_call_via_fp) - .thumb_func -SYM (_call_via_fp): - bx fp - nop +#endif /* L_call_via_rX */ - .globl SYM (_call_via_ip) - .thumb_func -SYM (_call_via_ip): - bx ip - nop +#ifdef L_interwork_call_via_rX + +/* These labels & instructions are used by the Arm/Thumb interworking code, + when the target address is in an unknown instruction set. The address + of function to be called is loaded into a register and then one of these + labels is called via a BL instruction. This puts the return address + into the link register with the bottom bit set, and the code here + switches to the correct mode before executing the function. Unfortunately + the target code cannot be relied upon to return via a BX instruction, so + instead we have to store the resturn address on the stack and allow the + called function to return here instead. Upon return we recover the real + return address and use a BX to get back to Thumb mode. */ + + .text + .align 0 - .globl SYM (_call_via_sp) - .thumb_func -SYM (_call_via_sp): - bx sp - nop + .code 32 +_arm_return: + ldmia r13!, {r12} + bx r12 + .code 16 - .globl SYM (_call_via_lr) +.macro interwork register + .globl SYM (_interwork_call_via_\register) .thumb_func -SYM (_call_via_lr): - bx lr +SYM (_interwork_call_via_\register): + bx pc nop + + .code 32 + .globl .Lchange_\register +.Lchange_\register: + tst \register, #1 + stmeqdb r13!, {lr} + adreq lr, _arm_return + bx \register + .code 16 +.endm + + interwork r0 + interwork r1 + interwork r2 + interwork r3 + interwork r4 + interwork r5 + interwork r6 + interwork r7 + interwork r8 + interwork r9 + interwork sl + interwork fp + interwork ip + interwork sp + interwork lr + +#endif /* L_interwork_call_via_rX */ -#endif /* L_call_via_rX */ + |