* Mainline merge as of 2006-02-16 (@111136).
[official-gcc.git] / gcc / config / pa / hpux-unwind.h
blobaa443bfba0b0652afd55fe255b3957371473bea9
1 /* DWARF2 EH unwinding support for PA HP-UX.
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file with other programs, and to distribute
14 those programs without any restriction coming from the use of this
15 file. (The General Public License restrictions do apply in other
16 respects; for example, they cover modification of the file, and
17 distribution when not linked into another program.)
19 GCC is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with GCC; see the file COPYING. If not, write to
26 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27 Boston, MA 02110-1301, USA. */
29 /* Do code reading to identify a signal frame, and set the frame
30 state data appropriately. See unwind-dw2.c for the structs. */
32 #include <signal.h>
33 #include <sys/ucontext.h>
34 #include <unistd.h>
36 /* FIXME: We currently ignore the high halves of general, space and
37 control registers on PA 2.0 machines for applications using the
38 32-bit runtime. We don't restore space registers or the floating
39 point status registers. */
41 #define MD_FALLBACK_FRAME_STATE_FOR pa_fallback_frame_state
43 /* HP-UX 10.X doesn't define GetSSReg. */
44 #ifndef GetSSReg
45 #define GetSSReg(ssp, ss_reg) \
46 ((UseWideRegs (ssp)) \
47 ? (ssp)->ss_wide.ss_32.ss_reg ## _lo \
48 : (ssp)->ss_narrow.ss_reg)
49 #endif
51 #if TARGET_64BIT
52 #define GetSSRegAddr(ssp, ss_reg) ((long) &((ssp)->ss_wide.ss_64.ss_reg))
53 #else
54 #define GetSSRegAddr(ssp, ss_reg) \
55 ((UseWideRegs (ssp)) \
56 ? (long) &((ssp)->ss_wide.ss_32.ss_reg ## _lo) \
57 : (long) &((ssp)->ss_narrow.ss_reg))
58 #endif
60 #define UPDATE_FS_FOR_SAR(FS, N) \
61 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
62 (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_cr11) - new_cfa
64 #define UPDATE_FS_FOR_GR(FS, GRN, N) \
65 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
66 (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_gr##GRN) - new_cfa
68 #define UPDATE_FS_FOR_FR(FS, FRN, N) \
69 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
70 (FS)->regs.reg[N].loc.offset = (long) &(mc->ss_fr##FRN) - new_cfa;
72 #define UPDATE_FS_FOR_PC(FS, N) \
73 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
74 (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_pcoq_head) - new_cfa
76 /* Extract bit field from word using HP's numbering (MSB = 0). */
77 #define GET_FIELD(X, FROM, TO) \
78 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
80 static inline int
81 sign_extend (int x, int len)
83 int signbit = (1 << (len - 1));
84 int mask = (signbit << 1) - 1;
85 return ((x & mask) ^ signbit) - signbit;
88 /* Extract a 17-bit signed constant from branch instructions. */
89 static inline int
90 extract_17 (unsigned word)
92 return sign_extend (GET_FIELD (word, 19, 28)
93 | GET_FIELD (word, 29, 29) << 10
94 | GET_FIELD (word, 11, 15) << 11
95 | (word & 0x1) << 16, 17);
98 /* Extract a 22-bit signed constant from branch instructions. */
99 static inline int
100 extract_22 (unsigned word)
102 return sign_extend (GET_FIELD (word, 19, 28)
103 | GET_FIELD (word, 29, 29) << 10
104 | GET_FIELD (word, 11, 15) << 11
105 | GET_FIELD (word, 6, 10) << 16
106 | (word & 0x1) << 21, 22);
109 static _Unwind_Reason_Code
110 pa_fallback_frame_state (struct _Unwind_Context *context,
111 _Unwind_FrameState *fs)
113 static long cpu;
114 unsigned int *pc = (unsigned int *) context->ra;
116 if (pc == 0)
117 return _URC_END_OF_STACK;
119 /* Check if the return address points to an export stub (PA 1.1 or 2.0). */
120 if ((!TARGET_64BIT
121 && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */
122 && *(pc + 1) == 0x004010a1 /* ldsid (rp),r1 */
123 && *(pc + 2) == 0x00011820 /* mtsp r1,sr0 */
124 && *(pc + 3) == 0xe0400002) /* be,n 0(sr0,rp) */
126 (!TARGET_64BIT
127 && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */
128 && *(pc + 1) == 0xe840d002)) /* bve,n (rp) */
130 fs->cfa_how = CFA_REG_OFFSET;
131 fs->cfa_reg = 30;
132 fs->cfa_offset = 0;
134 fs->retaddr_column = 0;
135 fs->regs.reg[0].how = REG_SAVED_OFFSET;
136 fs->regs.reg[0].loc.offset = -24;
138 return _URC_NO_REASON;
141 /* Check if the return address is an export stub as signal handlers
142 may return via an export stub. */
143 if (!TARGET_64BIT
144 && (*pc & 0xffe0e002) == 0xe8400000 /* bl x,r2 */
145 && *(pc + 1) == 0x08000240 /* nop */
146 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
147 && *(pc + 3) == 0x004010a1 /* ldsid (rp),r1 */
148 && *(pc + 4) == 0x00011820 /* mtsp r1,sr0 */
149 && *(pc + 5) == 0xe0400002) /* be,n 0(sr0,rp) */
150 /* Extract target address from PA 1.x 17-bit branch. */
151 pc += extract_17 (*pc) + 2;
152 else if (!TARGET_64BIT
153 && (*pc & 0xfc00e002) == 0xe800a000 /* b,l x,r2 */
154 && *(pc + 1) == 0x08000240 /* nop */
155 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
156 && *(pc + 3) == 0xe840d002) /* bve,n (rp) */
157 /* Extract target address from PA 2.0 22-bit branch. */
158 pc += extract_22 (*pc) + 2;
160 /* Now check if the return address is one of the signal handler
161 returns, _sigreturn or _sigsetreturn. */
162 if ((TARGET_64BIT
163 && *(pc + 0) == 0x53db3f51 /* ldd -58(sp),dp */
164 && *(pc + 8) == 0x34160116 /* ldi 8b,r22 */
165 && *(pc + 9) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
166 && *(pc + 10) == 0x0c2010c1 /* ldd 0(r1),r1 */
167 && *(pc + 11) == 0xe4202000) /* be,l 0(sr4,r1) */
169 (TARGET_64BIT
170 && *(pc + 0) == 0x36dc0000 /* ldo 0(r22),ret0 */
171 && *(pc + 6) == 0x341601c0 /* ldi e0,r22 */
172 && *(pc + 7) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
173 && *(pc + 8) == 0x0c2010c1 /* ldd 0(r1),r1 */
174 && *(pc + 9) == 0xe4202000) /* be,l 0(sr4,r1) */
176 (!TARGET_64BIT
177 && *(pc + 0) == 0x379a0000 /* ldo 0(ret0),r26 */
178 && *(pc + 1) == 0x6bd33fc9 /* stw r19,-1c(sp) */
179 && *(pc + 2) == 0x20200801 /* ldil L%-40000000,r1 */
180 && *(pc + 3) == 0xe420e008 /* be,l 4(sr7,r1) */
181 && *(pc + 4) == 0x34160116) /* ldi 8b,r22 */
183 (!TARGET_64BIT
184 && *(pc + 0) == 0x6bd33fc9 /* stw r19,-1c(sp) */
185 && *(pc + 1) == 0x20200801 /* ldil L%-40000000,r1 */
186 && *(pc + 2) == 0xe420e008 /* be,l 4(sr7,r1) */
187 && *(pc + 3) == 0x341601c0)) /* ldi e0,r22 */
189 /* The previous stack pointer is saved at (long *)SP - 1. The
190 ucontext structure is offset from the start of the previous
191 frame by the siglocal_misc structure. */
192 struct siglocalx *sl = (struct siglocalx *)
193 (*((long *) context->cfa - 1));
194 mcontext_t *mc = &(sl->sl_uc.uc_mcontext);
196 long new_cfa = GetSSReg (mc, ss_sp);
198 fs->cfa_how = CFA_REG_OFFSET;
199 fs->cfa_reg = 30;
200 fs->cfa_offset = new_cfa - (long) context->cfa;
202 UPDATE_FS_FOR_GR (fs, 1, 1);
203 UPDATE_FS_FOR_GR (fs, 2, 2);
204 UPDATE_FS_FOR_GR (fs, 3, 3);
205 UPDATE_FS_FOR_GR (fs, 4, 4);
206 UPDATE_FS_FOR_GR (fs, 5, 5);
207 UPDATE_FS_FOR_GR (fs, 6, 6);
208 UPDATE_FS_FOR_GR (fs, 7, 7);
209 UPDATE_FS_FOR_GR (fs, 8, 8);
210 UPDATE_FS_FOR_GR (fs, 9, 9);
211 UPDATE_FS_FOR_GR (fs, 10, 10);
212 UPDATE_FS_FOR_GR (fs, 11, 11);
213 UPDATE_FS_FOR_GR (fs, 12, 12);
214 UPDATE_FS_FOR_GR (fs, 13, 13);
215 UPDATE_FS_FOR_GR (fs, 14, 14);
216 UPDATE_FS_FOR_GR (fs, 15, 15);
217 UPDATE_FS_FOR_GR (fs, 16, 16);
218 UPDATE_FS_FOR_GR (fs, 17, 17);
219 UPDATE_FS_FOR_GR (fs, 18, 18);
220 UPDATE_FS_FOR_GR (fs, 19, 19);
221 UPDATE_FS_FOR_GR (fs, 20, 20);
222 UPDATE_FS_FOR_GR (fs, 21, 21);
223 UPDATE_FS_FOR_GR (fs, 22, 22);
224 UPDATE_FS_FOR_GR (fs, 23, 23);
225 UPDATE_FS_FOR_GR (fs, 24, 24);
226 UPDATE_FS_FOR_GR (fs, 25, 25);
227 UPDATE_FS_FOR_GR (fs, 26, 26);
228 UPDATE_FS_FOR_GR (fs, 27, 27);
229 UPDATE_FS_FOR_GR (fs, 28, 28);
230 UPDATE_FS_FOR_GR (fs, 29, 29);
231 UPDATE_FS_FOR_GR (fs, 30, 30);
232 UPDATE_FS_FOR_GR (fs, 31, 31);
234 if (TARGET_64BIT)
236 UPDATE_FS_FOR_FR (fs, 4, 32);
237 UPDATE_FS_FOR_FR (fs, 5, 33);
238 UPDATE_FS_FOR_FR (fs, 6, 34);
239 UPDATE_FS_FOR_FR (fs, 7, 35);
240 UPDATE_FS_FOR_FR (fs, 8, 36);
241 UPDATE_FS_FOR_FR (fs, 9, 37);
242 UPDATE_FS_FOR_FR (fs, 10, 38);
243 UPDATE_FS_FOR_FR (fs, 11, 39);
244 UPDATE_FS_FOR_FR (fs, 12, 40);
245 UPDATE_FS_FOR_FR (fs, 13, 41);
246 UPDATE_FS_FOR_FR (fs, 14, 42);
247 UPDATE_FS_FOR_FR (fs, 15, 43);
248 UPDATE_FS_FOR_FR (fs, 16, 44);
249 UPDATE_FS_FOR_FR (fs, 17, 45);
250 UPDATE_FS_FOR_FR (fs, 18, 46);
251 UPDATE_FS_FOR_FR (fs, 19, 47);
252 UPDATE_FS_FOR_FR (fs, 20, 48);
253 UPDATE_FS_FOR_FR (fs, 21, 49);
254 UPDATE_FS_FOR_FR (fs, 22, 50);
255 UPDATE_FS_FOR_FR (fs, 23, 51);
256 UPDATE_FS_FOR_FR (fs, 24, 52);
257 UPDATE_FS_FOR_FR (fs, 25, 53);
258 UPDATE_FS_FOR_FR (fs, 26, 54);
259 UPDATE_FS_FOR_FR (fs, 27, 55);
260 UPDATE_FS_FOR_FR (fs, 28, 56);
261 UPDATE_FS_FOR_FR (fs, 29, 57);
262 UPDATE_FS_FOR_FR (fs, 30, 58);
263 UPDATE_FS_FOR_FR (fs, 31, 59);
265 UPDATE_FS_FOR_SAR (fs, 60);
267 else
269 UPDATE_FS_FOR_FR (fs, 4, 32);
270 UPDATE_FS_FOR_FR (fs, 5, 34);
271 UPDATE_FS_FOR_FR (fs, 6, 36);
272 UPDATE_FS_FOR_FR (fs, 7, 38);
273 UPDATE_FS_FOR_FR (fs, 8, 40);
274 UPDATE_FS_FOR_FR (fs, 9, 44);
275 UPDATE_FS_FOR_FR (fs, 10, 44);
276 UPDATE_FS_FOR_FR (fs, 11, 46);
277 UPDATE_FS_FOR_FR (fs, 12, 48);
278 UPDATE_FS_FOR_FR (fs, 13, 50);
279 UPDATE_FS_FOR_FR (fs, 14, 52);
280 UPDATE_FS_FOR_FR (fs, 15, 54);
282 if (!cpu)
283 cpu = sysconf (_SC_CPU_VERSION);
285 /* PA-RISC 1.0 only has 16 floating point registers. */
286 if (cpu != CPU_PA_RISC1_0)
288 UPDATE_FS_FOR_FR (fs, 16, 56);
289 UPDATE_FS_FOR_FR (fs, 17, 58);
290 UPDATE_FS_FOR_FR (fs, 18, 60);
291 UPDATE_FS_FOR_FR (fs, 19, 62);
292 UPDATE_FS_FOR_FR (fs, 20, 64);
293 UPDATE_FS_FOR_FR (fs, 21, 66);
294 UPDATE_FS_FOR_FR (fs, 22, 68);
295 UPDATE_FS_FOR_FR (fs, 23, 70);
296 UPDATE_FS_FOR_FR (fs, 24, 72);
297 UPDATE_FS_FOR_FR (fs, 25, 74);
298 UPDATE_FS_FOR_FR (fs, 26, 76);
299 UPDATE_FS_FOR_FR (fs, 27, 78);
300 UPDATE_FS_FOR_FR (fs, 28, 80);
301 UPDATE_FS_FOR_FR (fs, 29, 82);
302 UPDATE_FS_FOR_FR (fs, 30, 84);
303 UPDATE_FS_FOR_FR (fs, 31, 86);
306 UPDATE_FS_FOR_SAR (fs, 88);
309 fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
310 UPDATE_FS_FOR_PC (fs, DWARF_ALT_FRAME_RETURN_COLUMN);
312 return _URC_NO_REASON;
315 return _URC_END_OF_STACK;