Move shlib support to toplevel libgcc
[gcc.git] / libgcc / config / c6x / libunwind.S
1 .text
2 .macro do_call fn
3 #ifdef _TMS320C6400_PLUS
4 callp .s2 (\fn), B3
5 #elif defined(_TMS320C6400)
6 call .s2 (\fn)
7 addkpc .s2 9f, B3, 0
8 nop 4
9 9f:
10 #else
11 call .s2 (\fn)
12 mhkl .s2 9f, B3
13 mhkh .s2 9f, B3
14 nop 3
15 9f:
16 #endif
17 .endm
18 .align 2
19 .global restore_core_regs
20 .type restore_core_regs, STT_FUNC
21 restore_core_regs:
22 mv .s2x A4, B4
23 ldw .d1t1 *+A4[0], A0
24 || ldw .d2t2 *++B4[16], B0
25 ldw .d1t1 *+A4[1], A1
26 || ldw .d2t2 *+B4[1], B1
27 ldw .d1t1 *+A4[2], A2
28 || ldw .d2t2 *+B4[2], B2
29 ldw .d1t1 *+A4[3], A3
30 || ldw .d2t2 *+B4[3], B3
31 ;; Base registers are loaded later
32 ldw .d1t1 *+A4[5], A5
33 || ldw .d2t2 *+B4[5], B5
34 ldw .d1t1 *+A4[6], A6
35 || ldw .d2t2 *+B4[6], B6
36 ldw .d1t1 *+A4[7], A7
37 || ldw .d2t2 *+B4[7], B7
38 ldw .d1t1 *+A4[8], A8
39 || ldw .d2t2 *+B4[8], B8
40 ldw .d1t1 *+A4[9], A9
41 || ldw .d2t2 *+B4[9], B9
42 ;; load PC into B10 so that it is ready for the branch
43 ldw .d2t2 *+B4[16], B10
44 ldw .d1t1 *+A4[11], A11
45 || ldw .d2t2 *+B4[11], B11
46 ldw .d1t1 *+A4[12], A12
47 || ldw .d2t2 *+B4[12], B12
48 ldw .d1t1 *+A4[13], A13
49 || ldw .d2t2 *+B4[13], B13
50 ldw .d1t1 *+A4[14], A14
51 || ldw .d2t2 *+B4[14], B14
52 ;; Loads have 4 delay slots. Take advantage of this to restore the
53 ;; scratch registers and stack pointer before the base registers
54 ;; disappear. We also need to make sure no interrupts occur,
55 ;; so put the whole thing in the delay slots of a dummy branch
56 ;; We can not move the ret earlier as that would cause it to occur
57 ;; before the last load completes
58 b .s1 (1f)
59 ldw .d1t1 *+A4[4], A4
60 || ldw .d2t2 *+B4[4], B4
61 ldw .d1t1 *+A4[15], A15
62 || ldw .d2t2 *+B4[15], B15
63 ret .s2 B10
64 ldw .d1t1 *+A4[10], A10
65 || ldw .d2t2 *+B4[10], B10
66 nop 1
67 1:
68 nop 3
69 .size restore_core_regs, . - restore_core_regs
70
71 .macro UNWIND_WRAPPER name argreg argside
72 .global \name
73 .type \name, STT_FUNC
74 \name:
75 # Create saved register state: flags,A0-A15,B0-B15,PC = 136 bytes.
76 # Plus 4 (rounded to 8) for saving return.
77 addk .s2 -144, B15
78 stw .d2t1 A0, *+B15[2]
79 stw .d2t1 A1, *+B15[3]
80 stw .d2t1 A2, *+B15[4]
81 stw .d2t1 A3, *+B15[5]
82 stw .d2t1 A4, *+B15[6]
83 stw .d2t1 A5, *+B15[7]
84 stw .d2t1 A6, *+B15[8]
85 stw .d2t1 A7, *+B15[9]
86 stw .d2t1 A8, *+B15[10]
87 stw .d2t1 A9, *+B15[11]
88 stw .d2t1 A10, *+B15[12]
89 stw .d2t1 A11, *+B15[13]
90 stw .d2t1 A12, *+B15[14]
91 stw .d2t1 A13, *+B15[15]
92 stw .d2t1 A14, *+B15[16]
93 stw .d2t1 A15, *+B15[17]
94 mv .s1x B15, A0
95 addk .s1 144, A0
96 stw .d2t2 B0, *+B15[18]
97 stw .d2t2 B1, *+B15[19]
98 stw .d2t2 B2, *+B15[20]
99 stw .d2t2 B3, *+B15[21]
100 stw .d2t2 B4, *+B15[22]
101 stw .d2t2 B5, *+B15[23]
102 stw .d2t2 B6, *+B15[24]
103 stw .d2t2 B7, *+B15[25]
104 stw .d2t2 B8, *+B15[26]
105 stw .d2t2 B9, *+B15[27]
106 stw .d2t2 B10, *+B15[28]
107 stw .d2t2 B11, *+B15[29]
108 stw .d2t2 B12, *+B15[30]
109 stw .d2t2 B13, *+B15[31]
110 stw .d2t2 B14, *+B15[32]
111 stw .d2t1 A0, *+B15[33]
112 stw .d2t1 A0, *+B15[34]
113 # Zero demand saved flags
114 mvk .s1 0, A0
115 stw .d2t1 A0, *+B15[1]
116 # Save return address, setup additional argument and call fucntion
117 stw .d2t2 B3, *+B15[35]
118 add .d\argside B15, 4, \argreg
119 do_call __gnu\name
120 # Restore stack and return
121 ldw .d2t2 *+B15[35], B3
122 addk .s2 144, B15
123 nop 3
124 ret .s2 B3
125 nop 5
126 .size \name, . - \name
127 .endm
128
129 UNWIND_WRAPPER _Unwind_RaiseException B4 2
130 UNWIND_WRAPPER _Unwind_Resume B4 2
131 UNWIND_WRAPPER _Unwind_Resume_or_Rethrow B4 2
132 UNWIND_WRAPPER _Unwind_ForcedUnwind B6 2
133 UNWIND_WRAPPER _Unwind_Backtrace A6 1x