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
99f:
10#else
11	call	.s2	(\fn)
12	mhkl	.s2	9f, B3
13	mhkh	.s2	9f, B3
14	nop		3
159f:
16#endif
17.endm
18.align 2
19.global restore_core_regs
20.type restore_core_regs, STT_FUNC
21restore_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
671:
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 function
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
129UNWIND_WRAPPER _Unwind_RaiseException B4 2
130UNWIND_WRAPPER _Unwind_Resume B4 2
131UNWIND_WRAPPER _Unwind_Resume_or_Rethrow B4 2
132UNWIND_WRAPPER _Unwind_ForcedUnwind B6 2
133UNWIND_WRAPPER _Unwind_Backtrace A6 1x
134