Merge with gcc-4_3-branch up to revision 175516.
[official-gcc.git] / gcc / config / pa / hpux-unwind.h
blob464a31b6c30e21caca29071a675744045d7cd349
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 /* Don't use this if inhibit_libc is set.
33 The build for this target will fail trying to include missing headers. */
34 #ifndef inhibit_libc
35 #include <signal.h>
36 #include <sys/ucontext.h>
37 #include <unistd.h>
39 /* FIXME: We currently ignore the high halves of general, space and
40 control registers on PA 2.0 machines for applications using the
41 32-bit runtime. We don't restore space registers or the floating
42 point status registers. */
44 #define MD_FALLBACK_FRAME_STATE_FOR pa_fallback_frame_state
46 /* HP-UX 10.X doesn't define GetSSReg. */
47 #ifndef GetSSReg
48 #define GetSSReg(ssp, ss_reg) \
49 ((UseWideRegs (ssp)) \
50 ? (ssp)->ss_wide.ss_32.ss_reg ## _lo \
51 : (ssp)->ss_narrow.ss_reg)
52 #endif
54 #if TARGET_64BIT
55 #define GetSSRegAddr(ssp, ss_reg) ((long) &((ssp)->ss_wide.ss_64.ss_reg))
56 #else
57 #define GetSSRegAddr(ssp, ss_reg) \
58 ((UseWideRegs (ssp)) \
59 ? (long) &((ssp)->ss_wide.ss_32.ss_reg ## _lo) \
60 : (long) &((ssp)->ss_narrow.ss_reg))
61 #endif
63 #define UPDATE_FS_FOR_SAR(FS, N) \
64 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
65 (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_cr11) - new_cfa
67 #define UPDATE_FS_FOR_GR(FS, GRN, N) \
68 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
69 (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_gr##GRN) - new_cfa
71 #define UPDATE_FS_FOR_FR(FS, FRN, N) \
72 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
73 (FS)->regs.reg[N].loc.offset = (long) &(mc->ss_fr##FRN) - new_cfa;
75 #define UPDATE_FS_FOR_PC(FS, N) \
76 (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \
77 (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_pcoq_head) - new_cfa
79 /* Extract bit field from word using HP's numbering (MSB = 0). */
80 #define GET_FIELD(X, FROM, TO) \
81 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
83 static inline int
84 sign_extend (int x, int len)
86 int signbit = (1 << (len - 1));
87 int mask = (signbit << 1) - 1;
88 return ((x & mask) ^ signbit) - signbit;
91 /* Extract a 17-bit signed constant from branch instructions. */
92 static inline int
93 extract_17 (unsigned word)
95 return sign_extend (GET_FIELD (word, 19, 28)
96 | GET_FIELD (word, 29, 29) << 10
97 | GET_FIELD (word, 11, 15) << 11
98 | (word & 0x1) << 16, 17);
101 /* Extract a 22-bit signed constant from branch instructions. */
102 static inline int
103 extract_22 (unsigned word)
105 return sign_extend (GET_FIELD (word, 19, 28)
106 | GET_FIELD (word, 29, 29) << 10
107 | GET_FIELD (word, 11, 15) << 11
108 | GET_FIELD (word, 6, 10) << 16
109 | (word & 0x1) << 21, 22);
112 static _Unwind_Reason_Code
113 pa_fallback_frame_state (struct _Unwind_Context *context,
114 _Unwind_FrameState *fs)
116 static long cpu;
117 unsigned int *pc = (unsigned int *) context->ra;
119 if (pc == 0)
120 return _URC_END_OF_STACK;
122 /* Check for relocation of the return value. */
123 if (!TARGET_64BIT
124 && *(pc + 0) == 0x2fd01224 /* fstd,ma fr4,8(sp) */
125 && *(pc + 1) == 0x0fd9109d /* ldw -4(sp),ret1 */
126 && *(pc + 2) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */
127 pc += 3;
128 else if (!TARGET_64BIT
129 && *(pc + 0) == 0x27d01224 /* fstw,ma fr4,8(sp) */
130 && *(pc + 1) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */
131 pc += 2;
132 else if (!TARGET_64BIT
133 && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */
134 && *(pc + 1) == 0x0fdd1299 /* stw ret1,-4(sp) */
135 && *(pc + 2) == 0x2fd13024) /* fldd,mb -8(sp),fr4 */
136 pc += 3;
137 else if (!TARGET_64BIT
138 && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */
139 && *(pc + 1) == 0x27d13024) /* fldw,mb -8(sp),fr4 */
140 pc += 2;
142 /* Check if the return address points to an export stub (PA 1.1 or 2.0). */
143 if ((!TARGET_64BIT
144 && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */
145 && *(pc + 1) == 0x004010a1 /* ldsid (rp),r1 */
146 && *(pc + 2) == 0x00011820 /* mtsp r1,sr0 */
147 && *(pc + 3) == 0xe0400002) /* be,n 0(sr0,rp) */
149 (!TARGET_64BIT
150 && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */
151 && *(pc + 1) == 0xe840d002)) /* bve,n (rp) */
153 fs->regs.cfa_how = CFA_REG_OFFSET;
154 fs->regs.cfa_reg = 30;
155 fs->regs.cfa_offset = 0;
157 fs->retaddr_column = 0;
158 fs->regs.reg[0].how = REG_SAVED_OFFSET;
159 fs->regs.reg[0].loc.offset = -24;
161 /* Update context to describe the stub frame. */
162 uw_update_context (context, fs);
164 /* Set up fs to describe the FDE for the caller of this stub. */
165 return uw_frame_state_for (context, fs);
167 /* Check if the return address points to a relocation stub. */
168 else if (!TARGET_64BIT
169 && *(pc + 0) == 0x0fd11082 /* ldw -8(sp),rp */
170 && (*(pc + 1) == 0xe840c002 /* bv,n r0(rp) */
171 || *(pc + 1) == 0xe840d002)) /* bve,n (rp) */
173 fs->regs.cfa_how = CFA_REG_OFFSET;
174 fs->regs.cfa_reg = 30;
175 fs->regs.cfa_offset = 0;
177 fs->retaddr_column = 0;
178 fs->regs.reg[0].how = REG_SAVED_OFFSET;
179 fs->regs.reg[0].loc.offset = -8;
181 /* Update context to describe the stub frame. */
182 uw_update_context (context, fs);
184 /* Set up fs to describe the FDE for the caller of this stub. */
185 return uw_frame_state_for (context, fs);
188 /* Check if the return address is an export stub as signal handlers
189 may return via an export stub. */
190 if (!TARGET_64BIT
191 && (*pc & 0xffe0e002) == 0xe8400000 /* bl x,r2 */
192 && *(pc + 1) == 0x08000240 /* nop */
193 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
194 && *(pc + 3) == 0x004010a1 /* ldsid (rp),r1 */
195 && *(pc + 4) == 0x00011820 /* mtsp r1,sr0 */
196 && *(pc + 5) == 0xe0400002) /* be,n 0(sr0,rp) */
197 /* Extract target address from PA 1.x 17-bit branch. */
198 pc += extract_17 (*pc) + 2;
199 else if (!TARGET_64BIT
200 && (*pc & 0xfc00e002) == 0xe800a000 /* b,l x,r2 */
201 && *(pc + 1) == 0x08000240 /* nop */
202 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
203 && *(pc + 3) == 0xe840d002) /* bve,n (rp) */
204 /* Extract target address from PA 2.0 22-bit branch. */
205 pc += extract_22 (*pc) + 2;
207 /* Now check if the return address is one of the signal handler
208 returns, _sigreturn or _sigsetreturn. */
209 if ((TARGET_64BIT
210 && *(pc + 0) == 0x53db3f51 /* ldd -58(sp),dp */
211 && *(pc + 8) == 0x34160116 /* ldi 8b,r22 */
212 && *(pc + 9) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
213 && *(pc + 10) == 0x0c2010c1 /* ldd 0(r1),r1 */
214 && *(pc + 11) == 0xe4202000) /* be,l 0(sr4,r1) */
216 (TARGET_64BIT
217 && *(pc + 0) == 0x36dc0000 /* ldo 0(r22),ret0 */
218 && *(pc + 6) == 0x341601c0 /* ldi e0,r22 */
219 && *(pc + 7) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
220 && *(pc + 8) == 0x0c2010c1 /* ldd 0(r1),r1 */
221 && *(pc + 9) == 0xe4202000) /* be,l 0(sr4,r1) */
223 (!TARGET_64BIT
224 && *(pc + 0) == 0x379a0000 /* ldo 0(ret0),r26 */
225 && *(pc + 1) == 0x6bd33fc9 /* stw r19,-1c(sp) */
226 && *(pc + 2) == 0x20200801 /* ldil L%-40000000,r1 */
227 && *(pc + 3) == 0xe420e008 /* be,l 4(sr7,r1) */
228 && *(pc + 4) == 0x34160116) /* ldi 8b,r22 */
230 (!TARGET_64BIT
231 && *(pc + 0) == 0x6bd33fc9 /* stw r19,-1c(sp) */
232 && *(pc + 1) == 0x20200801 /* ldil L%-40000000,r1 */
233 && *(pc + 2) == 0xe420e008 /* be,l 4(sr7,r1) */
234 && *(pc + 3) == 0x341601c0)) /* ldi e0,r22 */
236 /* The previous stack pointer is saved at (long *)SP - 1. The
237 ucontext structure is offset from the start of the previous
238 frame by the siglocal_misc structure. */
239 struct siglocalx *sl = (struct siglocalx *)
240 (*((long *) context->cfa - 1));
241 mcontext_t *mc = &(sl->sl_uc.uc_mcontext);
243 long new_cfa = GetSSReg (mc, ss_sp);
245 fs->regs.cfa_how = CFA_REG_OFFSET;
246 fs->regs.cfa_reg = 30;
247 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
249 UPDATE_FS_FOR_GR (fs, 1, 1);
250 UPDATE_FS_FOR_GR (fs, 2, 2);
251 UPDATE_FS_FOR_GR (fs, 3, 3);
252 UPDATE_FS_FOR_GR (fs, 4, 4);
253 UPDATE_FS_FOR_GR (fs, 5, 5);
254 UPDATE_FS_FOR_GR (fs, 6, 6);
255 UPDATE_FS_FOR_GR (fs, 7, 7);
256 UPDATE_FS_FOR_GR (fs, 8, 8);
257 UPDATE_FS_FOR_GR (fs, 9, 9);
258 UPDATE_FS_FOR_GR (fs, 10, 10);
259 UPDATE_FS_FOR_GR (fs, 11, 11);
260 UPDATE_FS_FOR_GR (fs, 12, 12);
261 UPDATE_FS_FOR_GR (fs, 13, 13);
262 UPDATE_FS_FOR_GR (fs, 14, 14);
263 UPDATE_FS_FOR_GR (fs, 15, 15);
264 UPDATE_FS_FOR_GR (fs, 16, 16);
265 UPDATE_FS_FOR_GR (fs, 17, 17);
266 UPDATE_FS_FOR_GR (fs, 18, 18);
267 UPDATE_FS_FOR_GR (fs, 19, 19);
268 UPDATE_FS_FOR_GR (fs, 20, 20);
269 UPDATE_FS_FOR_GR (fs, 21, 21);
270 UPDATE_FS_FOR_GR (fs, 22, 22);
271 UPDATE_FS_FOR_GR (fs, 23, 23);
272 UPDATE_FS_FOR_GR (fs, 24, 24);
273 UPDATE_FS_FOR_GR (fs, 25, 25);
274 UPDATE_FS_FOR_GR (fs, 26, 26);
275 UPDATE_FS_FOR_GR (fs, 27, 27);
276 UPDATE_FS_FOR_GR (fs, 28, 28);
277 UPDATE_FS_FOR_GR (fs, 29, 29);
278 UPDATE_FS_FOR_GR (fs, 30, 30);
279 UPDATE_FS_FOR_GR (fs, 31, 31);
281 if (TARGET_64BIT)
283 UPDATE_FS_FOR_FR (fs, 4, 32);
284 UPDATE_FS_FOR_FR (fs, 5, 33);
285 UPDATE_FS_FOR_FR (fs, 6, 34);
286 UPDATE_FS_FOR_FR (fs, 7, 35);
287 UPDATE_FS_FOR_FR (fs, 8, 36);
288 UPDATE_FS_FOR_FR (fs, 9, 37);
289 UPDATE_FS_FOR_FR (fs, 10, 38);
290 UPDATE_FS_FOR_FR (fs, 11, 39);
291 UPDATE_FS_FOR_FR (fs, 12, 40);
292 UPDATE_FS_FOR_FR (fs, 13, 41);
293 UPDATE_FS_FOR_FR (fs, 14, 42);
294 UPDATE_FS_FOR_FR (fs, 15, 43);
295 UPDATE_FS_FOR_FR (fs, 16, 44);
296 UPDATE_FS_FOR_FR (fs, 17, 45);
297 UPDATE_FS_FOR_FR (fs, 18, 46);
298 UPDATE_FS_FOR_FR (fs, 19, 47);
299 UPDATE_FS_FOR_FR (fs, 20, 48);
300 UPDATE_FS_FOR_FR (fs, 21, 49);
301 UPDATE_FS_FOR_FR (fs, 22, 50);
302 UPDATE_FS_FOR_FR (fs, 23, 51);
303 UPDATE_FS_FOR_FR (fs, 24, 52);
304 UPDATE_FS_FOR_FR (fs, 25, 53);
305 UPDATE_FS_FOR_FR (fs, 26, 54);
306 UPDATE_FS_FOR_FR (fs, 27, 55);
307 UPDATE_FS_FOR_FR (fs, 28, 56);
308 UPDATE_FS_FOR_FR (fs, 29, 57);
309 UPDATE_FS_FOR_FR (fs, 30, 58);
310 UPDATE_FS_FOR_FR (fs, 31, 59);
312 UPDATE_FS_FOR_SAR (fs, 60);
314 else
316 UPDATE_FS_FOR_FR (fs, 4, 32);
317 UPDATE_FS_FOR_FR (fs, 5, 34);
318 UPDATE_FS_FOR_FR (fs, 6, 36);
319 UPDATE_FS_FOR_FR (fs, 7, 38);
320 UPDATE_FS_FOR_FR (fs, 8, 40);
321 UPDATE_FS_FOR_FR (fs, 9, 44);
322 UPDATE_FS_FOR_FR (fs, 10, 44);
323 UPDATE_FS_FOR_FR (fs, 11, 46);
324 UPDATE_FS_FOR_FR (fs, 12, 48);
325 UPDATE_FS_FOR_FR (fs, 13, 50);
326 UPDATE_FS_FOR_FR (fs, 14, 52);
327 UPDATE_FS_FOR_FR (fs, 15, 54);
329 if (!cpu)
330 cpu = sysconf (_SC_CPU_VERSION);
332 /* PA-RISC 1.0 only has 16 floating point registers. */
333 if (cpu != CPU_PA_RISC1_0)
335 UPDATE_FS_FOR_FR (fs, 16, 56);
336 UPDATE_FS_FOR_FR (fs, 17, 58);
337 UPDATE_FS_FOR_FR (fs, 18, 60);
338 UPDATE_FS_FOR_FR (fs, 19, 62);
339 UPDATE_FS_FOR_FR (fs, 20, 64);
340 UPDATE_FS_FOR_FR (fs, 21, 66);
341 UPDATE_FS_FOR_FR (fs, 22, 68);
342 UPDATE_FS_FOR_FR (fs, 23, 70);
343 UPDATE_FS_FOR_FR (fs, 24, 72);
344 UPDATE_FS_FOR_FR (fs, 25, 74);
345 UPDATE_FS_FOR_FR (fs, 26, 76);
346 UPDATE_FS_FOR_FR (fs, 27, 78);
347 UPDATE_FS_FOR_FR (fs, 28, 80);
348 UPDATE_FS_FOR_FR (fs, 29, 82);
349 UPDATE_FS_FOR_FR (fs, 30, 84);
350 UPDATE_FS_FOR_FR (fs, 31, 86);
353 UPDATE_FS_FOR_SAR (fs, 88);
356 fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
357 UPDATE_FS_FOR_PC (fs, DWARF_ALT_FRAME_RETURN_COLUMN);
358 fs->signal_frame = 1;
360 return _URC_NO_REASON;
363 return _URC_END_OF_STACK;
365 #endif /* inhibit_libc */