aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc/config/c6x/libunwind.S
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgcc/config/c6x/libunwind.S')
-rw-r--r--gcc-4.9/libgcc/config/c6x/libunwind.S133
1 files changed, 133 insertions, 0 deletions
diff --git a/gcc-4.9/libgcc/config/c6x/libunwind.S b/gcc-4.9/libgcc/config/c6x/libunwind.S
new file mode 100644
index 000000000..7e6498378
--- /dev/null
+++ b/gcc-4.9/libgcc/config/c6x/libunwind.S
@@ -0,0 +1,133 @@
+.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