Initial import
[external/libunwind.git] / src / ia64 / Ginstall_cursor.S
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2001-2003 Hewlett-Packard Co
3         Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5 This file is part of libunwind.
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25
26 #include "ucontext_i.h"
27
28 #ifdef UNW_LOCAL_ONLY
29 # include "Lcursor_i.h"
30 # define ia64_install_cursor    _ULia64_install_cursor
31 #else
32 # include "Gcursor_i.h"
33 # define ia64_install_cursor    _Uia64_install_cursor
34 #endif
35
36 #define SYS_sigreturn   1181
37
38 #ifndef UNW_REMOTE_ONLY
39
40 /*  ia64_install_cursor (const cursor *c, long pri_unat, long *extra,
41                          long bspstore, long dirty_size, long *dirty_partition,
42                          long dirty_rnat)
43
44   Restores the machine-state represented by C and thereby resumes execution
45   in that frame.  If the frame or one of its descendants was interrupted
46   by a signal, all registers are restored (including the signal mask).
47   Otherwise, only the preserved registers, the global-pointer (r1), and
48   the exception-arguments (r15-r18) are restored.  */
49
50 #define pRet    p6
51 #define pSig    p7
52
53         .align 32
54         .hidden ia64_install_cursor
55         .global ia64_install_cursor
56         .proc ia64_install_cursor
57 ia64_install_cursor:
58         alloc r3 = ar.pfs, 7, 0, 0, 0
59         invala
60         add r2 = FR_LOC_OFF, in0
61         ;;
62
63         ld8 r16 = [r2], LOC_SIZE        // r16 = loc[IA64_REG_FR16]
64         mov.m r10 = ar.rsc              // (ar.rsc: ~ 12 cycle latency)
65         add r3 = FR_LOC_OFF + 16, in0
66         ;;
67
68         ld8 r17 = [r2], 2*LOC_SIZE      // r17 = loc[IA64_REG_FR17]
69         ld8 r18 = [r3], 2*LOC_SIZE      // r18 = loc[IA64_REG_FR18]
70         and r16 = -4, r16
71         ;;
72
73         ld8 r19 = [r2], 2*LOC_SIZE      // r19 = loc[IA64_REG_FR19]
74         ld8 r20 = [r3], 2*LOC_SIZE      // r20 = loc[IA64_REG_FR20]
75         and r17 = -4, r17
76         ;;
77
78         ldf.fill f16 = [r16]            // f16 restored (don't touch no more)
79         ldf.fill f17 = [r17]            // f17 restored (don't touch no more)
80         and r18 = -4, r18
81
82         ld8 r21 = [r2], 2*LOC_SIZE      // r21 = loc[IA64_REG_FR21]
83         ld8 r22 = [r3], 2*LOC_SIZE      // r22 = loc[IA64_REG_FR22]
84         and r19 = -4, r19
85         ;;
86
87         ldf.fill f18 = [r18]            // f18 restored (don't touch no more)
88         ldf.fill f19 = [r19]            // f19 restored (don't touch no more)
89         and r20 = -4, r20
90
91         ld8 r23 = [r2], 2*LOC_SIZE      // r23 = loc[IA64_REG_FR23]
92         ld8 r24 = [r3], 2*LOC_SIZE      // r24 = loc[IA64_REG_FR24]
93         and r21 = -4, r21
94         ;;
95
96         ldf.fill f20 = [r20]            // f20 restored (don't touch no more)
97         ldf.fill f21 = [r21]            // f21 restored (don't touch no more)
98         and r22 = -4, r22
99
100         ld8 r25 = [r2], 2*LOC_SIZE      // r25 = loc[IA64_REG_FR25]
101         ld8 r26 = [r3], 2*LOC_SIZE      // r26 = loc[IA64_REG_FR26]
102         and r23 = -4, r23
103         ;;
104
105         ldf.fill f22 = [r22]            // f22 restored (don't touch no more)
106         ldf.fill f23 = [r23]            // f23 restored (don't touch no more)
107         and r24 = -4, r24
108
109         ld8 r27 = [r2], 2*LOC_SIZE      // r27 = loc[IA64_REG_FR27]
110         ld8 r28 = [r3], 2*LOC_SIZE      // r28 = loc[IA64_REG_FR28]
111         and r25 = -4, r25
112         ;;
113
114         ldf.fill f24 = [r24]            // f24 restored (don't touch no more)
115         ldf.fill f25 = [r25]            // f25 restored (don't touch no more)
116         and r26 = -4, r26
117
118         ld8 r29 = [r2], 2*LOC_SIZE      // r29 = loc[IA64_REG_FR29]
119         ld8 r30 = [r3], 2*LOC_SIZE      // r30 = loc[IA64_REG_FR30]
120         and r27 = -4, r27
121         ;;
122
123         ldf.fill f26 = [r26]            // f26 restored (don't touch no more)
124         ldf.fill f27 = [r27]            // f27 restored (don't touch no more)
125         and r28 = -4, r28
126
127         ld8 r31 = [r2]                  // r31 = loc[IA64_REG_FR31]
128         mov.m ar.unat = in1
129         and r29 = -4, r29
130         ;;
131
132         ldf.fill f28 = [r28]            // f28 restored (don't touch no more)
133         ldf.fill f29 = [r29]            // f29 restored (don't touch no more)
134         and r30 = -4, r30
135
136         ld8 r1 = [in2], 8               // gp restored (don't touch no more)
137         add r8 = SIGCONTEXT_ADDR_OFF, in0
138         and r31 = -4, r31
139         ;;
140
141         ld8 r8 = [r8]                   // r8 = sigcontext_addr
142         and r11 = 0x1c, r10             // clear all but rsc.be and rsc.pl
143         add r2 = PFS_LOC_OFF, in0
144
145         ldf.fill f30 = [r30]            // f30 restored (don't touch no more)
146         ldf.fill f31 = [r31]            // f31 restored (don't touch no more)
147         add r3 = 8, in2
148         ;;
149
150         ld8.fill r4 = [in2], 16         // r4 restored (don't touch no more)
151         ld8.fill r5 = [r3], 16          // r5 restored (don't touch no more)
152         cmp.eq pRet, pSig = r0, r8      // sigcontext_addr == NULL?
153         ;;
154         ld8.fill r6 = [in2], 16         // r6 restored (don't touch no more)
155         ld8.fill r7 = [r3]              // r7 restored (don't touch no more)
156         add r3 = IP_OFF, in0
157         ;;
158
159         ld8 r14 = [r2], (B1_LOC_OFF - PFS_LOC_OFF)      // r14 = pfs_loc
160         ld8 r15 = [r3]                  // r15 = ip
161         add r3 = (B2_LOC_OFF - IP_OFF), r3
162         ;;
163
164         ld8 r16 = [r2], (B3_LOC_OFF - B1_LOC_OFF)       // r16 = b1_loc
165         ld8 r17= [r3], (B4_LOC_OFF - B2_LOC_OFF)        // r17 = b2_loc
166         and r14 = -4, r14
167         ;;
168
169         ld8 r18 = [r2], (B5_LOC_OFF - B3_LOC_OFF)       // r18 = b3_loc
170         ld8 r19 = [r3], (F2_LOC_OFF - B4_LOC_OFF)       // r19 = b4_loc
171         and r16 = -4, r16
172         ;;
173
174         ld8 r20 = [r2], (F3_LOC_OFF - B5_LOC_OFF)       // r20 = b5_loc
175         ld8 r21 = [r3], (F4_LOC_OFF - F2_LOC_OFF)       // r21 = f2_loc
176         and r17 = -4, r17
177         ;;
178
179         ld8 r16 = [r16]                 // r16 = *b1_loc
180         ld8 r17 = [r17]                 // r17 = *b2_loc
181         and r18 = -4, r18
182
183         ld8 r22 = [r2], (F5_LOC_OFF - F3_LOC_OFF)       // r21 = f3_loc
184         ld8 r23 = [r3], (UNAT_LOC_OFF - F4_LOC_OFF)     // r22 = f4_loc
185         and r19 = -4, r19
186         ;;
187
188         ld8 r18 = [r18]                 // r18 = *b3_loc
189         ld8 r19 = [r19]                 // r19 = *b4_loc
190         and r20 = -4, r20
191
192         ld8 r24 = [r2], (LC_LOC_OFF - F5_LOC_OFF)       // r24 = f5_loc
193         ld8 r25 = [r3], (FPSR_LOC_OFF - UNAT_LOC_OFF)   // r25 = unat_loc
194         and r21 = -4, r21
195         ;;
196
197         and r22 = -4, r22
198         and r23 = -4, r23
199         and r24 = -4, r24
200
201         ld8 r20 = [r20]                 // r20 = *b5_loc
202         ldf.fill f2 = [r21]             // f2 restored (don't touch no more)
203         mov b1 = r16                    // b1 restored (don't touch no more)
204         ;;
205
206         ldf.fill f3 = [r22]             // f3 restored (don't touch no more)
207         ldf.fill f4 = [r23]             // f4 restored (don't touch no more)
208         mov b2 = r17                    // b2 restored (don't touch no more)
209
210         ld8 r26 = [r2], (RNAT_LOC_OFF - LC_LOC_OFF)     // r26 = lc_loc
211         ld8 r27 = [r3]                  // r27 = fpsr_loc
212         and r25 = -4, r25
213
214         add r3 = (PSP_OFF - FPSR_LOC_OFF), r3
215         nop 0
216         nop 0
217         ;;
218
219         ldf.fill f5 = [r24]             // f5 restored (don't touch no more)
220 (pRet)  ld8 r25 = [r25]                 // r25 = *unat_loc
221         mov b3 = r18                    // b3 restored (don't touch no more)
222
223         ld8 r28 = [r2], (BSP_OFF - RNAT_LOC_OFF)        // r28 = rnat_loc
224         ld8 r29 = [r3], (PR_OFF - PSP_OFF)              // r29 = sp
225         mov b4 = r19                    // b4 restored (don't touch no more)
226
227         and r26 = -4, r26
228         and r27 = -4, r27
229         mov b5 = r20                    // b5 restored (don't touch no more)
230         ;;
231
232         ld8 r26 = [r26]                 // r26 = *lc_loc
233         ld8 r27 = [r27]                 // r27 = *fpsr_loc
234         and r28 = -4, r28
235
236         mov r30 = in3                   // make backup-copy of new bsp
237         ld8 r31 = [r3]                  // r31 = pr
238         mov rp = r15
239         ;;
240
241         ld8 r28 = [r28]                 // r28 = rnat
242         mov.m ar.rsc = r11              // put RSE into enforced lazy mode
243         mov.i ar.lc = r26               // lc restored (don't touch no more)
244         ;;
245
246         loadrs                          // drop dirty partition
247         mov r9 = in2                    // make backup-copy of &extra[r16]
248         cmp.eq p8, p0 = in4, r0         // dirty-size == 0?
249 (p8)    br.cond.dpnt.many .skip_load_dirty
250
251         mov r2 = in4                    // make backup-copy of dirty_size
252         mov r15 = in5                   // make backup-copy of dirty_partition
253         mov r16 = in6                   // make backup-copy of dirty_rnat
254         ;;
255
256         alloc r3 = ar.pfs, 0, 0, 0, 0   // drop register frame
257         dep r11 = r2, r11, 16, 16
258         ;;
259         mov.m ar.bspstore = r15
260         ;;
261         mov.m ar.rnat = r16
262         mov.m ar.rsc = r11              // 14 cycles latency to loadrs
263         ;;
264         loadrs                          // loadup new dirty partition
265         ;;
266
267 .skip_load_dirty:
268         mov.m ar.bspstore = r30         // restore register backing-store
269         add r3 = 8, r9                  // r3 = &extra[r16]
270         ;;
271
272 (pRet)  mov.m ar.fpsr = r27             // fpsr restored (don't touch no more)
273         mov.m ar.rnat = r28
274 (pSig)  br.cond.dpnt.many .next
275
276 /****** Return via br.ret: */
277
278         ld8 r14 = [r14]                 // r14 = *pfs_loc
279         ld8 r15 = [r9], 16              // r15 restored (don't touch no more)
280         mov pr = r31, -1                // pr restored (don't touch no more)
281         ;;
282
283         ld8 r16 = [r3], 16              // r16 restored (don't touch no more)
284         ld8 r17 = [r9]                  // r17 restored (don't touch no more)
285         nop.i 0
286         ;;
287
288         ld8 r18 = [r3]                  // r18 restored (don't touch no more)
289         mov.m ar.rsc = r10              // restore original ar.rsc
290         mov sp = r29
291
292         mov.m ar.unat = r25             // unat restored (don't touch no more)
293         mov.i ar.pfs = r14
294         br.ret.sptk.many rp
295         ;;
296
297 /****** Return via sigreturn(): */
298
299 .next:  mov.m ar.rsc = r10              // restore original ar.rsc
300         add r2 = (SC_FR + 6*16), r8
301         add r3 = (SC_FR + 7*16), r8
302         ;;
303
304         ldf.fill f6 = [r2], 32
305         ldf.fill f7 = [r3], 32
306         nop 0
307         ;;
308
309         ldf.fill f8 = [r2], 32
310         ldf.fill f9 = [r3], 32
311         nop 0
312         ;;
313
314         ldf.fill f10 = [r2], 32
315         ldf.fill f11 = [r3], 32
316         nop 0
317         ;;
318
319         ldf.fill f12 = [r2], 32
320         ldf.fill f13 = [r3], 32
321         nop 0
322         ;;
323
324         ldf.fill f14 = [r2], 32
325         ldf.fill f15 = [r3], 32
326         mov sp = r29
327         ;;
328
329 #if NEW_SYSCALL
330         add r2 = 8, tp;;
331         ld8 r2 = [r2]
332         mov r15 = SYS_sigreturn
333         mov b7 = r2
334         br.call.sptk.many b6 = b7
335         ;;
336 #else
337         mov r15 = SYS_sigreturn
338         break 0x100000
339 #endif
340         break 0                         // bug out if sigreturn() returns
341
342         .endp ia64_install_cursor
343
344 #endif /* !UNW_REMOTE_ONLY */
345 #ifdef __linux__
346         /* We do not need executable stack.  */
347         .section        .note.GNU-stack,"",@progbits
348 #endif