1/* libunwind - a platform-independent unwind library
2   Copyright (C) 2004 Hewlett-Packard Co
3	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5This file is part of libunwind.
6
7Permission is hereby granted, free of charge, to any person obtaining
8a copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be
16included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25
26#include "ucontext_i.h"
27
28#define GR(n)   (SC_GR + (n)*8)
29#define BR(n)   (SC_BR + (n)*8)
30#define FR(n)   (SC_FR + (n)*16)
31
32/* This should be compatible to the libc's getcontext(), except that
33   the sc->sc_mask field is always cleared and that the name is
34   prefixed with _Uia64_ so we don't step on the application's
35   name-space.  */
36
37	.align 32
38	.protected _Uia64_getcontext
39	.global _Uia64_getcontext
40	.proc _Uia64_getcontext
41_Uia64_getcontext:
42	.prologue
43	alloc rPFS = ar.pfs, 1, 0, 0, 0				// M2
44	mov rPR = pr						// I0, 2 cycles
45	add r2 = GR(1), in0					// I1
46	;;
47
48	.save ar.unat, rUNAT
49	mov.m rUNAT = ar.unat					// M2, 5 cycles
50	.body
51	st8.spill [r2] = r1, (SC_FLAGS - GR(1))			// M3
52	dep.z rFLAGS = -1, IA64_SC_FLAG_SYNCHRONOUS_BIT, 1	// I0, 1 cycle
53	;;
54
55	mov.m rRSC = ar.rsc					// M2, 12 cyc.
56	st8 [r2] = rFLAGS, (SC_PR  - SC_FLAGS)			// M3
57	add r3 = FR(2), in0
58	;;
59
60	mov.m rBSP = ar.bsp					// M2, 12 cyc.
61	st8 [r2] = rPR, (GR(12) - SC_PR)			// M3
62	add r8 = FR(16), in0
63	;;
64
65	mov.m rFPSR = ar.fpsr					// M2, 12 cyc.
66	st8.spill [r2] = r12, (GR(4) - GR(12))			// M3
67	add r9 = FR(24), in0
68	;;
69
70	stf.spill [r3] = f2					// M2
71	stf.spill [r8] = f16					// M3
72	add r3 = GR(7), in0
73	;;
74
75	flushrs							// M0
76	stf.spill [r9] = f24, (FR(31) - FR(24))			// M2
77	mov rB0 = b0						// I0, 2 cycles
78	;;
79
80	stf.spill [r9] = f31					// M2
81	st8.spill [r2] = r4, (GR(5) - GR(4))			// M3, bank 1
82	mov rB1 = b1						// I0, 2 cycles
83	;;
84
85.mem.offset 0,0; st8.spill [r2] = r5, (GR(6) - GR(5))		// M4, bank 0
86.mem.offset 8,0; st8.spill [r3] = r7, (BR(0) - GR(7))		// M3, bank 0
87	mov rB2 = b2						// I0, 2 cycles
88	;;
89
90	st8.spill [r2] = r6, (BR(1) - GR(6))			// M2, bank 1
91	st8 [r3] = rB0, (BR(4) - BR(0))				// M3, bank 1
92	mov rB4 = b4						// I0, 2 cycles
93	;;
94
95	mov.m rNAT = ar.unat					// M2, 5 cycles
96	st8 [r2] = rB1, (BR(2) - BR(1))				// M3, bank 0
97	mov rB3 = b3
98	;;
99
100	st8 [r2] = rB2, (BR(3) - BR(2))				// M2, bank 1
101	st8 [r3] = rB4, (SC_LC - BR(4))				// M3, bank 1
102	mov rB5 = b5						// I0, 2 cycles
103	;;
104
105	and rTMP = ~0x3, rRSC					// M0
106	add rPOS = GR(0), in0	// rPOS <- &sc_gr[0]		// M1
107	mov.i rLC = ar.lc					// I0, 2 cycles
108	;;
109
110	mov.m ar.rsc = rTMP	// put RSE into lazy mode	// M2, ? cycles
111	st8 [r2] = rB3, (BR(5) - BR(3))				// M3, bank 0
112	extr.u rPOS = rPOS, 3, 6 // get NaT bitnr for r0	// I0
113	;;
114
115	mov.m rRNAT = ar.rnat					// M2, 5 cycles
116	st8 [r2] = rB5, (SC_PFS - BR(5))			// M3, bank 0
117	sub rCPOS = 64, rPOS					// I0
118	;;
119
120	st8 [r2] = rPFS, (SC_UNAT - SC_PFS)			// M2
121	st8 [r3] = rLC, (SC_BSP - SC_LC)			// M3
122	shr.u rTMP = rNAT, rPOS					// I0, 3 cycles
123	;;
124
125	st8 [r2] = rUNAT, (SC_FPSR - SC_UNAT)			// M2
126	st8 [r3] = rBSP						// M3
127	add r8 = FR(3), in0
128	;;
129
130	st8 [r2] = rFPSR, (SC_RNAT - SC_FPSR)			// M2
131	stf.spill [r8] = f3, (FR(4) - FR(3))			// M3
132	add r9 = FR(5), in0
133	;;
134
135	stf.spill [r8] = f4, (FR(17) - FR(4))			// M2
136	stf.spill [r9] = f5, (FR(19) - FR(5))			// M3
137	shl rNAT = rNAT, rCPOS					// I0, 3 cycles
138	;;
139
140	st8 [r2] = rRNAT, (SC_NAT - SC_RNAT)			// M2
141	stf.spill [r8] = f17, (FR(18) - FR(17))			// M3
142	nop.i 0
143	;;
144
145	stf.spill [r8] = f18, (FR(20) - FR(18))			// M2
146	stf.spill [r9] = f19, (FR(21) - FR(19))			// M3
147	nop.i 0
148	;;
149
150	stf.spill [r8] = f20, (FR(22) - FR(20))			// M2
151	stf.spill [r9] = f21, (FR(23) - FR(21))			// M3
152	or rNAT = rNAT, rTMP					// I0
153	;;
154
155	st8 [r2] = rNAT						// M2
156	stf.spill [r8] = f22, (FR(25) - FR(22))			// M3
157	;;
158	stf.spill [r9] = f23, (FR(26) - FR(23))			// M2
159	stf.spill [r8] = f25, (FR(27) - FR(25))			// M3
160	;;
161	stf.spill [r9] = f26, (FR(28) - FR(26))			// M2
162	stf.spill [r8] = f27, (FR(29) - FR(27))			// M3
163	;;
164	mov.m ar.rsc = rRSC	// restore RSE mode		// M2
165	stf.spill [r9] = f28, (FR(30) - FR(28))			// M3
166	;;
167	mov.m ar.unat = rUNAT	// restore caller's UNaT	// M2
168	stf.spill [r8] = f29					// M3
169	;;
170	stf.spill [r9] = f30					// M2
171	mov r8 = 0
172	br.ret.sptk.many rp
173	.endp _Uia64_getcontext
174#ifdef __linux__
175	/* We do not need executable stack.  */
176	.section	.note.GNU-stack,"",@progbits
177#endif
178