Imported Upstream version 1.1
[platform/upstream/libunwind.git] / src / ia64 / getcontext.S
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
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 #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