OSDN Git Service

aa443bfba0b0652afd55fe255b3957371473bea9
[pf3gnuchains/gcc-fork.git] / gcc / config / pa / hpux-unwind.h
1 /* DWARF2 EH unwinding support for PA HP-UX.
2    Copyright (C) 2005 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.)
18
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.
23
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.  */
28
29 /* Do code reading to identify a signal frame, and set the frame
30    state data appropriately.  See unwind-dw2.c for the structs.  */
31
32 #include <signal.h>
33 #include <sys/ucontext.h>
34 #include <unistd.h>
35
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.  */
40
41 #define MD_FALLBACK_FRAME_STATE_FOR pa_fallback_frame_state
42
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
50
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
59
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
63
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
67
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;
71
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
75
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))
79
80 static inline int
81 sign_extend (int x, int len)
82 {
83   int signbit = (1 << (len - 1));
84   int mask = (signbit << 1) - 1;
85   return ((x & mask) ^ signbit) - signbit;
86 }
87
88 /* Extract a 17-bit signed constant from branch instructions.  */
89 static inline int
90 extract_17 (unsigned word)
91 {
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);
96 }
97
98 /* Extract a 22-bit signed constant from branch instructions.  */
99 static inline int
100 extract_22 (unsigned word)
101 {
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);
107 }
108
109 static _Unwind_Reason_Code
110 pa_fallback_frame_state (struct _Unwind_Context *context,
111                          _Unwind_FrameState *fs)
112 {
113   static long cpu;
114   unsigned int *pc = (unsigned int *) context->ra;
115
116   if (pc == 0)
117     return _URC_END_OF_STACK;
118
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) */
125       ||
126       (!TARGET_64BIT
127        && *(pc + 0) == 0x4bc23fd1               /* ldw -18(sp),rp */
128        && *(pc + 1) == 0xe840d002))             /* bve,n (rp) */
129     {
130       fs->cfa_how    = CFA_REG_OFFSET;
131       fs->cfa_reg    = 30;
132       fs->cfa_offset = 0;
133
134       fs->retaddr_column = 0;
135       fs->regs.reg[0].how = REG_SAVED_OFFSET;
136       fs->regs.reg[0].loc.offset = -24;
137
138       return _URC_NO_REASON;
139     }
140
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;
159
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) */
168       ||
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) */
175       ||
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 */
182       ||
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 */
188     {
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);
195
196       long new_cfa = GetSSReg (mc, ss_sp);
197
198       fs->cfa_how = CFA_REG_OFFSET;
199       fs->cfa_reg = 30;
200       fs->cfa_offset = new_cfa - (long) context->cfa;
201
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);
233
234       if (TARGET_64BIT)
235         {
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);
264
265           UPDATE_FS_FOR_SAR (fs, 60);
266         }
267       else
268         {
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);
281
282           if (!cpu)
283             cpu = sysconf (_SC_CPU_VERSION);
284
285           /* PA-RISC 1.0 only has 16 floating point registers.  */
286           if (cpu != CPU_PA_RISC1_0)
287             {
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);
304             }
305
306           UPDATE_FS_FOR_SAR (fs, 88);
307         }
308
309       fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN;
310       UPDATE_FS_FOR_PC (fs, DWARF_ALT_FRAME_RETURN_COLUMN);
311
312       return _URC_NO_REASON;
313     }
314
315   return _URC_END_OF_STACK;
316 }