Retro68/gcc/libgcc/config/c6x/libunwind.S
2014-09-21 19:33:12 +02:00

134 lines
3.3 KiB
ArmAsm

.text
.macro do_call fn
#ifdef _TMS320C6400_PLUS
callp .s2 (\fn), B3
#elif defined(_TMS320C6400)
call .s2 (\fn)
addkpc .s2 9f, B3, 0
nop 4
9f:
#else
call .s2 (\fn)
mhkl .s2 9f, B3
mhkh .s2 9f, B3
nop 3
9f:
#endif
.endm
.align 2
.global restore_core_regs
.type restore_core_regs, STT_FUNC
restore_core_regs:
mv .s2x A4, B4
ldw .d1t1 *+A4[0], A0
|| ldw .d2t2 *++B4[16], B0
ldw .d1t1 *+A4[1], A1
|| ldw .d2t2 *+B4[1], B1
ldw .d1t1 *+A4[2], A2
|| ldw .d2t2 *+B4[2], B2
ldw .d1t1 *+A4[3], A3
|| ldw .d2t2 *+B4[3], B3
;; Base registers are loaded later
ldw .d1t1 *+A4[5], A5
|| ldw .d2t2 *+B4[5], B5
ldw .d1t1 *+A4[6], A6
|| ldw .d2t2 *+B4[6], B6
ldw .d1t1 *+A4[7], A7
|| ldw .d2t2 *+B4[7], B7
ldw .d1t1 *+A4[8], A8
|| ldw .d2t2 *+B4[8], B8
ldw .d1t1 *+A4[9], A9
|| ldw .d2t2 *+B4[9], B9
;; load PC into B10 so that it is ready for the branch
ldw .d2t2 *+B4[16], B10
ldw .d1t1 *+A4[11], A11
|| ldw .d2t2 *+B4[11], B11
ldw .d1t1 *+A4[12], A12
|| ldw .d2t2 *+B4[12], B12
ldw .d1t1 *+A4[13], A13
|| ldw .d2t2 *+B4[13], B13
ldw .d1t1 *+A4[14], A14
|| ldw .d2t2 *+B4[14], B14
;; Loads have 4 delay slots. Take advantage of this to restore the
;; scratch registers and stack pointer before the base registers
;; disappear. We also need to make sure no interrupts occur,
;; so put the whole thing in the delay slots of a dummy branch
;; We can not move the ret earlier as that would cause it to occur
;; before the last load completes
b .s1 (1f)
ldw .d1t1 *+A4[4], A4
|| ldw .d2t2 *+B4[4], B4
ldw .d1t1 *+A4[15], A15
|| ldw .d2t2 *+B4[15], B15
ret .s2 B10
ldw .d1t1 *+A4[10], A10
|| ldw .d2t2 *+B4[10], B10
nop 1
1:
nop 3
.size restore_core_regs, . - restore_core_regs
.macro UNWIND_WRAPPER name argreg argside
.global \name
.type \name, STT_FUNC
\name:
# Create saved register state: flags,A0-A15,B0-B15,PC = 136 bytes.
# Plus 4 (rounded to 8) for saving return.
addk .s2 -144, B15
stw .d2t1 A0, *+B15[2]
stw .d2t1 A1, *+B15[3]
stw .d2t1 A2, *+B15[4]
stw .d2t1 A3, *+B15[5]
stw .d2t1 A4, *+B15[6]
stw .d2t1 A5, *+B15[7]
stw .d2t1 A6, *+B15[8]
stw .d2t1 A7, *+B15[9]
stw .d2t1 A8, *+B15[10]
stw .d2t1 A9, *+B15[11]
stw .d2t1 A10, *+B15[12]
stw .d2t1 A11, *+B15[13]
stw .d2t1 A12, *+B15[14]
stw .d2t1 A13, *+B15[15]
stw .d2t1 A14, *+B15[16]
stw .d2t1 A15, *+B15[17]
mv .s1x B15, A0
addk .s1 144, A0
stw .d2t2 B0, *+B15[18]
stw .d2t2 B1, *+B15[19]
stw .d2t2 B2, *+B15[20]
stw .d2t2 B3, *+B15[21]
stw .d2t2 B4, *+B15[22]
stw .d2t2 B5, *+B15[23]
stw .d2t2 B6, *+B15[24]
stw .d2t2 B7, *+B15[25]
stw .d2t2 B8, *+B15[26]
stw .d2t2 B9, *+B15[27]
stw .d2t2 B10, *+B15[28]
stw .d2t2 B11, *+B15[29]
stw .d2t2 B12, *+B15[30]
stw .d2t2 B13, *+B15[31]
stw .d2t2 B14, *+B15[32]
stw .d2t1 A0, *+B15[33]
stw .d2t1 A0, *+B15[34]
# Zero demand saved flags
mvk .s1 0, A0
stw .d2t1 A0, *+B15[1]
# Save return address, setup additional argument and call function
stw .d2t2 B3, *+B15[35]
add .d\argside B15, 4, \argreg
do_call __gnu\name
# Restore stack and return
ldw .d2t2 *+B15[35], B3
addk .s2 144, B15
nop 3
ret .s2 B3
nop 5
.size \name, . - \name
.endm
UNWIND_WRAPPER _Unwind_RaiseException B4 2
UNWIND_WRAPPER _Unwind_Resume B4 2
UNWIND_WRAPPER _Unwind_Resume_or_Rethrow B4 2
UNWIND_WRAPPER _Unwind_ForcedUnwind B6 2
UNWIND_WRAPPER _Unwind_Backtrace A6 1x