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->cfa_how = CFA_REG_OFFSET;
154 fs->retaddr_column = 0;
155 fs->regs.reg[0].how = REG_SAVED_OFFSET;
156 fs->regs.reg[0].loc.offset = -24;
158 return _URC_NO_REASON;
160 /* Check if the return address points to a relocation stub. */
161 else if (!TARGET_64BIT
162 && *(pc + 0) == 0x0fd11082 /* ldw -8(sp),rp */
163 && (*(pc + 1) == 0xe840c002 /* bv,n r0(rp) */
164 || *(pc + 1) == 0xe840d002)) /* bve,n (rp) */
166 fs->cfa_how = CFA_REG_OFFSET;
170 fs->retaddr_column = 0;
171 fs->regs.reg[0].how = REG_SAVED_OFFSET;
172 fs->regs.reg[0].loc.offset = -8;
174 return _URC_NO_REASON;
177 /* Check if the return address is an export stub as signal handlers
178 may return via an export stub. */
180 && (*pc & 0xffe0e002) == 0xe8400000 /* bl x,r2 */
181 && *(pc + 1) == 0x08000240 /* nop */
182 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
183 && *(pc + 3) == 0x004010a1 /* ldsid (rp),r1 */
184 && *(pc + 4) == 0x00011820 /* mtsp r1,sr0 */
185 && *(pc + 5) == 0xe0400002) /* be,n 0(sr0,rp) */
186 /* Extract target address from PA 1.x 17-bit branch. */
187 pc += extract_17 (*pc) + 2;
188 else if (!TARGET_64BIT
189 && (*pc & 0xfc00e002) == 0xe800a000 /* b,l x,r2 */
190 && *(pc + 1) == 0x08000240 /* nop */
191 && *(pc + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
192 && *(pc + 3) == 0xe840d002) /* bve,n (rp) */
193 /* Extract target address from PA 2.0 22-bit branch. */
194 pc += extract_22 (*pc) + 2;
196 /* Now check if the return address is one of the signal handler
197 returns, _sigreturn or _sigsetreturn. */
199 && *(pc + 0) == 0x53db3f51 /* ldd -58(sp),dp */
200 && *(pc + 8) == 0x34160116 /* ldi 8b,r22 */
201 && *(pc + 9) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
202 && *(pc + 10) == 0x0c2010c1 /* ldd 0(r1),r1 */
203 && *(pc + 11) == 0xe4202000) /* be,l 0(sr4,r1) */
206 && *(pc + 0) == 0x36dc0000 /* ldo 0(r22),ret0 */
207 && *(pc + 6) == 0x341601c0 /* ldi e0,r22 */
208 && *(pc + 7) == 0x08360ac1 /* shladd,l r22,3,r1,r1 */
209 && *(pc + 8) == 0x0c2010c1 /* ldd 0(r1),r1 */
210 && *(pc + 9) == 0xe4202000) /* be,l 0(sr4,r1) */
213 && *(pc + 0) == 0x379a0000 /* ldo 0(ret0),r26 */
214 && *(pc + 1) == 0x6bd33fc9 /* stw r19,-1c(sp) */
215 && *(pc + 2) == 0x20200801 /* ldil L%-40000000,r1 */
216 && *(pc + 3) == 0xe420e008 /* be,l 4(sr7,r1) */
217 && *(pc + 4) == 0x34160116) /* ldi 8b,r22 */
220 && *(pc + 0) == 0x6bd33fc9 /* stw r19,-1c(sp) */
221 && *(pc + 1) == 0x20200801 /* ldil L%-40000000,r1 */
222 && *(pc + 2) == 0xe420e008 /* be,l 4(sr7,r1) */
223 && *(pc + 3) == 0x341601c0)) /* ldi e0,r22 */
225 /* The previous stack pointer is saved at (long *)SP - 1. The
226 ucontext structure is offset from the start of the previous
227 frame by the siglocal_misc structure. */
228 struct siglocalx *sl = (struct siglocalx *)
229 (*((long *) context->cfa - 1));
230 mcontext_t *mc = &(sl->sl_uc.uc_mcontext);
232 long new_cfa = GetSSReg (mc, ss_sp);
234 fs->cfa_how = CFA_REG_OFFSET;
236 fs->cfa_offset = new_cfa - (long) context->cfa;
238 UPDATE_FS_FOR_GR (fs, 1, 1);
239 UPDATE_FS_FOR_GR (fs, 2, 2);
240 UPDATE_FS_FOR_GR (fs, 3, 3);
241 UPDATE_FS_FOR_GR (fs, 4, 4);
242 UPDATE_FS_FOR_GR (fs, 5, 5);
243 UPDATE_FS_FOR_GR (fs, 6, 6);
244 UPDATE_FS_FOR_GR (fs, 7, 7);
245 UPDATE_FS_FOR_GR (fs, 8, 8);
246 UPDATE_FS_FOR_GR (fs, 9, 9);
247 UPDATE_FS_FOR_GR (fs, 10, 10);
248 UPDATE_FS_FOR_GR (fs, 11, 11);
249 UPDATE_FS_FOR_GR (fs, 12, 12);
250 UPDATE_FS_FOR_GR (fs, 13, 13);
251 UPDATE_FS_FOR_GR (fs, 14, 14);
252 UPDATE_FS_FOR_GR (fs, 15, 15);
253 UPDATE_FS_FOR_GR (fs, 16, 16);
254 UPDATE_FS_FOR_GR (fs, 17, 17);
255 UPDATE_FS_FOR_GR (fs, 18, 18);
256 UPDATE_FS_FOR_GR (fs, 19, 19);
257 UPDATE_FS_FOR_GR (fs, 20, 20);
258 UPDATE_FS_FOR_GR (fs, 21, 21);
259 UPDATE_FS_FOR_GR (fs, 22, 22);
260 UPDATE_FS_FOR_GR (fs, 23, 23);
261 UPDATE_FS_FOR_GR (fs, 24, 24);
262 UPDATE_FS_FOR_GR (fs, 25, 25);
263 UPDATE_FS_FOR_GR (fs, 26, 26);
264 UPDATE_FS_FOR_GR (fs, 27, 27);
265 UPDATE_FS_FOR_GR (fs, 28, 28);
266 UPDATE_FS_FOR_GR (fs, 29, 29);
267 UPDATE_FS_FOR_GR (fs, 30, 30);
268 UPDATE_FS_FOR_GR (fs, 31, 31);
272 UPDATE_FS_FOR_FR (fs, 4, 32);
273 UPDATE_FS_FOR_FR (fs, 5, 33);
274 UPDATE_FS_FOR_FR (fs, 6, 34);
275 UPDATE_FS_FOR_FR (fs, 7, 35);
276 UPDATE_FS_FOR_FR (fs, 8, 36);
277 UPDATE_FS_FOR_FR (fs, 9, 37);
278 UPDATE_FS_FOR_FR (fs, 10, 38);
279 UPDATE_FS_FOR_FR (fs, 11, 39);
280 UPDATE_FS_FOR_FR (fs, 12, 40);
281 UPDATE_FS_FOR_FR (fs, 13, 41);
282 UPDATE_FS_FOR_FR (fs, 14, 42);
283 UPDATE_FS_FOR_FR (fs, 15, 43);
284 UPDATE_FS_FOR_FR (fs, 16, 44);
285 UPDATE_FS_FOR_FR (fs, 17, 45);
286 UPDATE_FS_FOR_FR (fs, 18, 46);
287 UPDATE_FS_FOR_FR (fs, 19, 47);
288 UPDATE_FS_FOR_FR (fs, 20, 48);
289 UPDATE_FS_FOR_FR (fs, 21, 49);
290 UPDATE_FS_FOR_FR (fs, 22, 50);
291 UPDATE_FS_FOR_FR (fs, 23, 51);
292 UPDATE_FS_FOR_FR (fs, 24, 52);
293 UPDATE_FS_FOR_FR (fs, 25, 53);
294 UPDATE_FS_FOR_FR (fs, 26, 54);
295 UPDATE_FS_FOR_FR (fs, 27, 55);
296 UPDATE_FS_FOR_FR (fs, 28, 56);
297 UPDATE_FS_FOR_FR (fs, 29, 57);
298 UPDATE_FS_FOR_FR (fs, 30, 58);
299 UPDATE_FS_FOR_FR (fs, 31, 59);
301 UPDATE_FS_FOR_SAR (fs, 60);
305 UPDATE_FS_FOR_FR (fs, 4, 32);
306 UPDATE_FS_FOR_FR (fs, 5, 34);
307 UPDATE_FS_FOR_FR (fs, 6, 36);
308 UPDATE_FS_FOR_FR (fs, 7, 38);
309 UPDATE_FS_FOR_FR (fs, 8, 40);
310 UPDATE_FS_FOR_FR (fs, 9, 44);
311 UPDATE_FS_FOR_FR (fs, 10, 44);
312 UPDATE_FS_FOR_FR (fs, 11, 46);
313 UPDATE_FS_FOR_FR (fs, 12, 48);
314 UPDATE_FS_FOR_FR (fs, 13, 50);
315 UPDATE_FS_FOR_FR (fs, 14, 52);
316 UPDATE_FS_FOR_FR (fs, 15, 54);
319 cpu = sysconf (_SC_CPU_VERSION);
321 /* PA-RISC 1.0 only has 16 floating point registers. */
322 if (cpu != CPU_PA_RISC1_0)
324 UPDATE_FS_FOR_FR (fs, 16, 56);
325 UPDATE_FS_FOR_FR (fs, 17, 58);
326 UPDATE_FS_FOR_FR (fs, 18, 60);
327 UPDATE_FS_FOR_FR (fs, 19, 62);
328 UPDATE_FS_FOR_FR (fs, 20, 64);
329 UPDATE_FS_FOR_FR (fs, 21, 66);
330 UPDATE_FS_FOR_FR (fs, 22, 68);
331 UPDATE_FS_FOR_FR (fs, 23, 70);
332 UPDATE_FS_FOR_FR (fs, 24, 72);
333 UPDATE_FS_FOR_FR (fs, 25, 74);
334 UPDATE_FS_FOR_FR (fs, 26, 76);
335 UPDATE_FS_FOR_FR (fs, 27, 78);
336 UPDATE_FS_FOR_FR (fs, 28, 80);
337 UPDATE_FS_FOR_FR (fs, 29, 82);
338 UPDATE_FS_FOR_FR (fs, 30, 84);
339 UPDATE_FS_FOR_FR (fs, 31, 86);
342 UPDATE_FS_FOR_SAR (fs, 88);
345 fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
346 UPDATE_FS_FOR_PC (fs, DWARF_ALT_FRAME_RETURN_COLUMN);
348 return _URC_NO_REASON;
351 return _URC_END_OF_STACK;