.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