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)
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. */
33 #include <sys/ucontext.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. */
45 #define GetSSReg(ssp, ss_reg) \
46 ((UseWideRegs (ssp)) \
47 ? (ssp)->ss_wide.ss_32.ss_reg ## _lo \
48 : (ssp)->ss_narrow.ss_reg)
52 #define GetSSRegAddr(ssp, ss_reg) ((long) &((ssp)->ss_wide.ss_64.ss_reg))
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))
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))
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. */
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. */
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)
114 unsigned int *pc = (unsigned int *) context->ra;
117 return _URC_END_OF_STACK;
119 /* Check for relocation of the return value. */
121 && *(pc + 0) == 0x2fd01224 /* fstd,ma fr4,8(sp) */
122 && *(pc + 1) == 0x0fd9109d /* ldw -4(sp),ret1 */
123 && *(pc + 2) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */
125 else if (!TARGET_64BIT
126 && *(pc + 0) == 0x27d01224 /* fstw,ma fr4,8(sp) */
127 && *(pc + 1) == 0x0fd130bc) /* ldw,mb -8(sp),ret0 */
129 else if (!TARGET_64BIT
130 && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */
131 && *(pc + 1) == 0x0fdd1299 /* stw ret1,-4(sp) */
132 && *(pc + 2) == 0x2fd13024) /* fldd,mb -8(sp),fr4 */
134 else if (!TARGET_64BIT
135 && *(pc + 0) == 0x0fdc12b0 /* stw,ma ret0,8(sp) */
136 && *(pc + 1) == 0x27d13024) /* fldw,mb -8(sp),fr4 */
139 /* Check if the return address points to an export stub (PA 1.1 or 2.0). */
141 && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */
142 && *(pc + 1) == 0x004010a1 /* ldsid (rp),r1 */
143 && *(pc + 2) == 0x00011820 /* mtsp r1,sr0 */
144 && *(pc + 3) == 0xe0400002) /* be,n 0(sr0,rp) */
147 && *(pc + 0) == 0x4bc23fd1 /* ldw -18(sp),rp */
148 && *(pc + 1) == 0xe840d002)) /* bve,n (rp) */
150 fs->regs.cfa_how = CFA_REG_OFFSET;
151 fs->regs.cfa_reg = 30;
152 fs->regs.cfa_offset = 0;
154 fs->retaddr_column = 0;
155 fs->regs.reg[0].how = REG_SAVED_OFFSET;
156 fs->regs.reg[0].loc.offset = -24;
158 /* Update context to describe the stub frame. */
159 uw_update_context (context, fs);
161 /* Set up fs to describe the FDE for the caller of this stub. */
162 return uw_frame_state_for (context, fs);
164 /* Check if the return address points to a relocation stub. */
165 else if (!TARGET_64BIT
166 && *(pc + 0) == 0x0fd11082 /* ldw -8(sp),rp */
167 && (*(pc + 1) == 0xe840c002 /* bv,n r0(rp) */
168 || *(pc + 1) == 0xe840d002)) /* bve,n (rp) */
170 fs->regs.cfa_how = CFA_REG_OFFSET;
171 fs->regs.cfa_reg = 30;
172 fs->regs.cfa_offset = 0;
174 fs->retaddr_column = 0;
175 fs->regs.reg[0].how = REG_SAVED_OFFSET;
176 fs->regs.reg[0].loc.offset = -8;
178 /* Update context to describe the stub frame. */
179 uw_update_context (context, fs);
181 /* Set up fs to describe the FDE for the caller of this stub. */
182 return uw_frame_state_for (context, fs);
185 /* Check if the return address is an export stub as signal handlers
186 may return via an export stub. */
188 && (*pc & 0xffe0e002) == 0xe8400000 /* bl x,r2 */
189 && *(pc + 1) == 0x08000240 /* nop */
190 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
191 && *(pc + 3) == 0x004010a1 /* ldsid (rp),r1 */
192 && *(pc + 4) == 0x00011820 /* mtsp r1,sr0 */
193 && *(pc + 5) == 0xe0400002) /* be,n 0(sr0,rp) */
194 /* Extract target address from PA 1.x 17-bit branch. */
195 pc += extract_17 (*pc) + 2;
196 else if (!TARGET_64BIT
197 && (*pc & 0xfc00e002) == 0xe800a000 /* b,l x,r2 */
198 && *(pc + 1) == 0x08000240 /* nop */
199 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
200 && *(pc + 3) == 0xe840d002) /* bve,n (rp) */
201 /* Extract target address from PA 2.0 22-bit branch. */
202 pc += extract_22 (*pc) + 2;
204 /* Now check if the return address is one of the signal handler
205 returns, _sigreturn or _sigsetreturn. */
207 && *(pc + 0) == 0x53db3f51 /* ldd -58(sp),dp */
208 && *(pc + 8) == 0x34160116 /* ldi 8b,r22 */
209 && *(pc + 9) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
210 && *(pc + 10) == 0x0c2010c1 /* ldd 0(r1),r1 */
211 && *(pc + 11) == 0xe4202000) /* be,l 0(sr4,r1) */
214 && *(pc + 0) == 0x36dc0000 /* ldo 0(r22),ret0 */
215 && *(pc + 6) == 0x341601c0 /* ldi e0,r22 */
216 && *(pc + 7) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
217 && *(pc + 8) == 0x0c2010c1 /* ldd 0(r1),r1 */
218 && *(pc + 9) == 0xe4202000) /* be,l 0(sr4,r1) */
221 && *(pc + 0) == 0x379a0000 /* ldo 0(ret0),r26 */
222 && *(pc + 1) == 0x6bd33fc9 /* stw r19,-1c(sp) */
223 && *(pc + 2) == 0x20200801 /* ldil L%-40000000,r1 */
224 && *(pc + 3) == 0xe420e008 /* be,l 4(sr7,r1) */
225 && *(pc + 4) == 0x34160116) /* ldi 8b,r22 */
228 && *(pc + 0) == 0x6bd33fc9 /* stw r19,-1c(sp) */
229 && *(pc + 1) == 0x20200801 /* ldil L%-40000000,r1 */
230 && *(pc + 2) == 0xe420e008 /* be,l 4(sr7,r1) */
231 && *(pc + 3) == 0x341601c0)) /* ldi e0,r22 */
233 /* The previous stack pointer is saved at (long *)SP - 1. The
234 ucontext structure is offset from the start of the previous
235 frame by the siglocal_misc structure. */
236 struct siglocalx *sl = (struct siglocalx *)
237 (*((long *) context->cfa - 1));
238 mcontext_t *mc = &(sl->sl_uc.uc_mcontext);
240 long new_cfa = GetSSReg (mc, ss_sp);
242 fs->regs.cfa_how = CFA_REG_OFFSET;
243 fs->regs.cfa_reg = 30;
244 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
246 UPDATE_FS_FOR_GR (fs, 1, 1);
247 UPDATE_FS_FOR_GR (fs, 2, 2);
248 UPDATE_FS_FOR_GR (fs, 3, 3);
249 UPDATE_FS_FOR_GR (fs, 4, 4);
250 UPDATE_FS_FOR_GR (fs, 5, 5);
251 UPDATE_FS_FOR_GR (fs, 6, 6);
252 UPDATE_FS_FOR_GR (fs, 7, 7);
253 UPDATE_FS_FOR_GR (fs, 8, 8);
254 UPDATE_FS_FOR_GR (fs, 9, 9);
255 UPDATE_FS_FOR_GR (fs, 10, 10);
256 UPDATE_FS_FOR_GR (fs, 11, 11);
257 UPDATE_FS_FOR_GR (fs, 12, 12);
258 UPDATE_FS_FOR_GR (fs, 13, 13);
259 UPDATE_FS_FOR_GR (fs, 14, 14);
260 UPDATE_FS_FOR_GR (fs, 15, 15);
261 UPDATE_FS_FOR_GR (fs, 16, 16);
262 UPDATE_FS_FOR_GR (fs, 17, 17);
263 UPDATE_FS_FOR_GR (fs, 18, 18);
264 UPDATE_FS_FOR_GR (fs, 19, 19);
265 UPDATE_FS_FOR_GR (fs, 20, 20);
266 UPDATE_FS_FOR_GR (fs, 21, 21);
267 UPDATE_FS_FOR_GR (fs, 22, 22);
268 UPDATE_FS_FOR_GR (fs, 23, 23);
269 UPDATE_FS_FOR_GR (fs, 24, 24);
270 UPDATE_FS_FOR_GR (fs, 25, 25);
271 UPDATE_FS_FOR_GR (fs, 26, 26);
272 UPDATE_FS_FOR_GR (fs, 27, 27);
273 UPDATE_FS_FOR_GR (fs, 28, 28);
274 UPDATE_FS_FOR_GR (fs, 29, 29);
275 UPDATE_FS_FOR_GR (fs, 30, 30);
276 UPDATE_FS_FOR_GR (fs, 31, 31);
280 UPDATE_FS_FOR_FR (fs, 4, 32);
281 UPDATE_FS_FOR_FR (fs, 5, 33);
282 UPDATE_FS_FOR_FR (fs, 6, 34);
283 UPDATE_FS_FOR_FR (fs, 7, 35);
284 UPDATE_FS_FOR_FR (fs, 8, 36);
285 UPDATE_FS_FOR_FR (fs, 9, 37);
286 UPDATE_FS_FOR_FR (fs, 10, 38);
287 UPDATE_FS_FOR_FR (fs, 11, 39);
288 UPDATE_FS_FOR_FR (fs, 12, 40);
289 UPDATE_FS_FOR_FR (fs, 13, 41);
290 UPDATE_FS_FOR_FR (fs, 14, 42);
291 UPDATE_FS_FOR_FR (fs, 15, 43);
292 UPDATE_FS_FOR_FR (fs, 16, 44);
293 UPDATE_FS_FOR_FR (fs, 17, 45);
294 UPDATE_FS_FOR_FR (fs, 18, 46);
295 UPDATE_FS_FOR_FR (fs, 19, 47);
296 UPDATE_FS_FOR_FR (fs, 20, 48);
297 UPDATE_FS_FOR_FR (fs, 21, 49);
298 UPDATE_FS_FOR_FR (fs, 22, 50);
299 UPDATE_FS_FOR_FR (fs, 23, 51);
300 UPDATE_FS_FOR_FR (fs, 24, 52);
301 UPDATE_FS_FOR_FR (fs, 25, 53);
302 UPDATE_FS_FOR_FR (fs, 26, 54);
303 UPDATE_FS_FOR_FR (fs, 27, 55);
304 UPDATE_FS_FOR_FR (fs, 28, 56);
305 UPDATE_FS_FOR_FR (fs, 29, 57);
306 UPDATE_FS_FOR_FR (fs, 30, 58);
307 UPDATE_FS_FOR_FR (fs, 31, 59);
309 UPDATE_FS_FOR_SAR (fs, 60);
313 UPDATE_FS_FOR_FR (fs, 4, 32);
314 UPDATE_FS_FOR_FR (fs, 5, 34);
315 UPDATE_FS_FOR_FR (fs, 6, 36);
316 UPDATE_FS_FOR_FR (fs, 7, 38);
317 UPDATE_FS_FOR_FR (fs, 8, 40);
318 UPDATE_FS_FOR_FR (fs, 9, 44);
319 UPDATE_FS_FOR_FR (fs, 10, 44);
320 UPDATE_FS_FOR_FR (fs, 11, 46);
321 UPDATE_FS_FOR_FR (fs, 12, 48);
322 UPDATE_FS_FOR_FR (fs, 13, 50);
323 UPDATE_FS_FOR_FR (fs, 14, 52);
324 UPDATE_FS_FOR_FR (fs, 15, 54);
327 cpu = sysconf (_SC_CPU_VERSION);
329 /* PA-RISC 1.0 only has 16 floating point registers. */
330 if (cpu != CPU_PA_RISC1_0)
332 UPDATE_FS_FOR_FR (fs, 16, 56);
333 UPDATE_FS_FOR_FR (fs, 17, 58);
334 UPDATE_FS_FOR_FR (fs, 18, 60);
335 UPDATE_FS_FOR_FR (fs, 19, 62);
336 UPDATE_FS_FOR_FR (fs, 20, 64);
337 UPDATE_FS_FOR_FR (fs, 21, 66);
338 UPDATE_FS_FOR_FR (fs, 22, 68);
339 UPDATE_FS_FOR_FR (fs, 23, 70);
340 UPDATE_FS_FOR_FR (fs, 24, 72);
341 UPDATE_FS_FOR_FR (fs, 25, 74);
342 UPDATE_FS_FOR_FR (fs, 26, 76);
343 UPDATE_FS_FOR_FR (fs, 27, 78);
344 UPDATE_FS_FOR_FR (fs, 28, 80);
345 UPDATE_FS_FOR_FR (fs, 29, 82);
346 UPDATE_FS_FOR_FR (fs, 30, 84);
347 UPDATE_FS_FOR_FR (fs, 31, 86);
350 UPDATE_FS_FOR_SAR (fs, 88);
353 fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
354 UPDATE_FS_FOR_PC (fs, DWARF_ALT_FRAME_RETURN_COLUMN);
356 return _URC_NO_REASON;
359 return _URC_END_OF_STACK;