annotate libgcc/config/ia64/unwind-ia64.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Subroutines needed for unwinding IA-64 standard format stack frame
kono
parents:
diff changeset
2 info for exception handling.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3 Copyright (C) 1997-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
4 Contributed by Andrew MacLeod <amacleod@cygnus.com>
kono
parents:
diff changeset
5 Andrew Haley <aph@cygnus.com>
kono
parents:
diff changeset
6 David Mosberger-Tang <davidm@hpl.hp.com>
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 This file is part of GCC.
kono
parents:
diff changeset
9
kono
parents:
diff changeset
10 GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
11 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
12 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
13 any later version.
kono
parents:
diff changeset
14
kono
parents:
diff changeset
15 GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
18 GNU General Public License for more details.
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
21 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
22 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
23
kono
parents:
diff changeset
24 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
25 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
26 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
27 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29 #include "tconfig.h"
kono
parents:
diff changeset
30 #include "tsystem.h"
kono
parents:
diff changeset
31 #include "coretypes.h"
kono
parents:
diff changeset
32 #include "tm.h"
kono
parents:
diff changeset
33 #include "libgcc_tm.h"
kono
parents:
diff changeset
34 #include "unwind.h"
kono
parents:
diff changeset
35 #include "unwind-ia64.h"
kono
parents:
diff changeset
36 #include "unwind-compat.h"
kono
parents:
diff changeset
37 #include "ia64intrin.h"
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 /* This isn't thread safe, but nice for occasional tests. */
kono
parents:
diff changeset
40 #undef ENABLE_MALLOC_CHECKING
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 #ifndef __USING_SJLJ_EXCEPTIONS__
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 enum unw_application_register
kono
parents:
diff changeset
45 {
kono
parents:
diff changeset
46 UNW_AR_BSP,
kono
parents:
diff changeset
47 UNW_AR_BSPSTORE,
kono
parents:
diff changeset
48 UNW_AR_PFS,
kono
parents:
diff changeset
49 UNW_AR_RNAT,
kono
parents:
diff changeset
50 UNW_AR_UNAT,
kono
parents:
diff changeset
51 UNW_AR_LC,
kono
parents:
diff changeset
52 UNW_AR_EC,
kono
parents:
diff changeset
53 UNW_AR_FPSR,
kono
parents:
diff changeset
54 UNW_AR_RSC,
kono
parents:
diff changeset
55 UNW_AR_CCV
kono
parents:
diff changeset
56 };
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 enum unw_register_index
kono
parents:
diff changeset
59 {
kono
parents:
diff changeset
60 /* Primary UNAT. */
kono
parents:
diff changeset
61 UNW_REG_PRI_UNAT_GR,
kono
parents:
diff changeset
62 UNW_REG_PRI_UNAT_MEM,
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 /* Memory Stack. */
kono
parents:
diff changeset
65 UNW_REG_PSP, /* previous memory stack pointer */
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 /* Register Stack. */
kono
parents:
diff changeset
68 UNW_REG_BSP, /* register stack pointer */
kono
parents:
diff changeset
69 UNW_REG_BSPSTORE,
kono
parents:
diff changeset
70 UNW_REG_PFS, /* previous function state */
kono
parents:
diff changeset
71 UNW_REG_RNAT,
kono
parents:
diff changeset
72 /* Return Pointer. */
kono
parents:
diff changeset
73 UNW_REG_RP,
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 /* Special preserved registers. */
kono
parents:
diff changeset
76 UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 /* Non-stacked general registers. */
kono
parents:
diff changeset
79 UNW_REG_R2,
kono
parents:
diff changeset
80 UNW_REG_R4 = UNW_REG_R2 + 2,
kono
parents:
diff changeset
81 UNW_REG_R7 = UNW_REG_R2 + 5,
kono
parents:
diff changeset
82 UNW_REG_R31 = UNW_REG_R2 + 29,
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 /* Non-stacked floating point registers. */
kono
parents:
diff changeset
85 UNW_REG_F2,
kono
parents:
diff changeset
86 UNW_REG_F5 = UNW_REG_F2 + 3,
kono
parents:
diff changeset
87 UNW_REG_F16 = UNW_REG_F2 + 14,
kono
parents:
diff changeset
88 UNW_REG_F31 = UNW_REG_F2 + 29,
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 /* Branch registers. */
kono
parents:
diff changeset
91 UNW_REG_B0, UNW_REG_B1,
kono
parents:
diff changeset
92 UNW_REG_B5 = UNW_REG_B1 + 4,
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 UNW_NUM_REGS
kono
parents:
diff changeset
95 };
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 enum unw_where
kono
parents:
diff changeset
98 {
kono
parents:
diff changeset
99 UNW_WHERE_NONE, /* register isn't saved at all */
kono
parents:
diff changeset
100 UNW_WHERE_GR, /* register is saved in a general register */
kono
parents:
diff changeset
101 UNW_WHERE_FR, /* register is saved in a floating-point register */
kono
parents:
diff changeset
102 UNW_WHERE_BR, /* register is saved in a branch register */
kono
parents:
diff changeset
103 UNW_WHERE_SPREL, /* register is saved on memstack (sp-relative) */
kono
parents:
diff changeset
104 UNW_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 /* At the end of each prologue these locations get resolved to
kono
parents:
diff changeset
107 UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively. */
kono
parents:
diff changeset
108 UNW_WHERE_SPILL_HOME, /* register is saved in its spill home */
kono
parents:
diff changeset
109 UNW_WHERE_GR_SAVE /* register is saved in next general register */
kono
parents:
diff changeset
110 };
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 #define UNW_WHEN_NEVER 0x7fffffff
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 struct unw_reg_info
kono
parents:
diff changeset
115 {
kono
parents:
diff changeset
116 unw_word val; /* save location: register number or offset */
kono
parents:
diff changeset
117 enum unw_where where; /* where the register gets saved */
kono
parents:
diff changeset
118 int when; /* when the register gets saved */
kono
parents:
diff changeset
119 };
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 struct unw_reg_state {
kono
parents:
diff changeset
122 struct unw_reg_state *next; /* next (outer) element on state stack */
kono
parents:
diff changeset
123 struct unw_reg_info reg[UNW_NUM_REGS]; /* register save locations */
kono
parents:
diff changeset
124 };
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 struct unw_labeled_state {
kono
parents:
diff changeset
127 struct unw_labeled_state *next; /* next labeled state (or NULL) */
kono
parents:
diff changeset
128 unw_word label; /* label for this state */
kono
parents:
diff changeset
129 struct unw_reg_state saved_state;
kono
parents:
diff changeset
130 };
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 typedef struct unw_state_record
kono
parents:
diff changeset
133 {
kono
parents:
diff changeset
134 unsigned int first_region : 1; /* is this the first region? */
kono
parents:
diff changeset
135 unsigned int done : 1; /* are we done scanning descriptors? */
kono
parents:
diff changeset
136 unsigned int any_spills : 1; /* got any register spills? */
kono
parents:
diff changeset
137 unsigned int in_body : 1; /* are we inside a body? */
kono
parents:
diff changeset
138 unsigned int no_reg_stack_frame : 1; /* Don't adjust bsp for i&l regs */
kono
parents:
diff changeset
139 unsigned char *imask; /* imask of spill_mask record or NULL */
kono
parents:
diff changeset
140 unw_word pr_val; /* predicate values */
kono
parents:
diff changeset
141 unw_word pr_mask; /* predicate mask */
kono
parents:
diff changeset
142 unw_sword spill_offset; /* psp-relative offset for spill base */
kono
parents:
diff changeset
143 int region_start;
kono
parents:
diff changeset
144 int region_len;
kono
parents:
diff changeset
145 int epilogue_start;
kono
parents:
diff changeset
146 int epilogue_count;
kono
parents:
diff changeset
147 int when_target;
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 unsigned char gr_save_loc; /* next general register to use for saving */
kono
parents:
diff changeset
150 unsigned char return_link_reg; /* branch register for return link */
kono
parents:
diff changeset
151 unsigned short unwabi;
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 struct unw_labeled_state *labeled_states; /* list of all labeled states */
kono
parents:
diff changeset
154 struct unw_reg_state curr; /* current state */
kono
parents:
diff changeset
155
kono
parents:
diff changeset
156 _Unwind_Personality_Fn personality;
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 } _Unwind_FrameState;
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 enum unw_nat_type
kono
parents:
diff changeset
161 {
kono
parents:
diff changeset
162 UNW_NAT_NONE, /* NaT not represented */
kono
parents:
diff changeset
163 UNW_NAT_VAL, /* NaT represented by NaT value (fp reg) */
kono
parents:
diff changeset
164 UNW_NAT_MEMSTK, /* NaT value is in unat word at offset OFF */
kono
parents:
diff changeset
165 UNW_NAT_REGSTK /* NaT is in rnat */
kono
parents:
diff changeset
166 };
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 struct unw_stack
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 unw_word limit;
kono
parents:
diff changeset
171 unw_word top;
kono
parents:
diff changeset
172 };
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 struct _Unwind_Context
kono
parents:
diff changeset
175 {
kono
parents:
diff changeset
176 /* Initial frame info. */
kono
parents:
diff changeset
177 unw_word rnat; /* rse nat collection */
kono
parents:
diff changeset
178 unw_word regstk_top; /* lowest address of rbs stored register
kono
parents:
diff changeset
179 which uses context->rnat collection */
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 /* Current frame info. */
kono
parents:
diff changeset
182 unw_word bsp; /* backing store pointer value
kono
parents:
diff changeset
183 corresponding to psp. */
kono
parents:
diff changeset
184 unw_word sp; /* stack pointer value */
kono
parents:
diff changeset
185 unw_word psp; /* previous sp value */
kono
parents:
diff changeset
186 unw_word rp; /* return pointer */
kono
parents:
diff changeset
187 unw_word pr; /* predicate collection */
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189 unw_word region_start;/* start of unwind region */
kono
parents:
diff changeset
190 unw_word gp; /* global pointer value */
kono
parents:
diff changeset
191 void *lsda; /* language specific data area */
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 /* Preserved state. */
kono
parents:
diff changeset
194 unw_word *bsp_loc; /* previous bsp save location
kono
parents:
diff changeset
195 Appears to be write-only? */
kono
parents:
diff changeset
196 unw_word *bspstore_loc;
kono
parents:
diff changeset
197 unw_word *pfs_loc; /* Save location for pfs in current
kono
parents:
diff changeset
198 (corr. to sp) frame. Target
kono
parents:
diff changeset
199 contains cfm for caller. */
kono
parents:
diff changeset
200 unw_word *signal_pfs_loc;/* Save location for pfs in current
kono
parents:
diff changeset
201 signal frame. Target contains
kono
parents:
diff changeset
202 pfs for caller. */
kono
parents:
diff changeset
203 unw_word *pri_unat_loc;
kono
parents:
diff changeset
204 unw_word *unat_loc;
kono
parents:
diff changeset
205 unw_word *lc_loc;
kono
parents:
diff changeset
206 unw_word *fpsr_loc;
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 unw_word eh_data[4];
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 struct unw_ireg
kono
parents:
diff changeset
211 {
kono
parents:
diff changeset
212 unw_word *loc;
kono
parents:
diff changeset
213 struct unw_ireg_nat
kono
parents:
diff changeset
214 {
kono
parents:
diff changeset
215 enum unw_nat_type type : 3;
kono
parents:
diff changeset
216 unw_sword off : 61; /* NaT word is at loc+nat.off */
kono
parents:
diff changeset
217 } nat;
kono
parents:
diff changeset
218 } ireg[32 - 2]; /* Indexed by <register number> - 2 */
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 unw_word *br_loc[8];
kono
parents:
diff changeset
221 void *fr_loc[32 - 2];
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 /* ??? We initially point pri_unat_loc here. The entire NAT bit
kono
parents:
diff changeset
224 logic needs work. */
kono
parents:
diff changeset
225 unw_word initial_unat;
kono
parents:
diff changeset
226 };
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 /* Implicit register save order. See section 11.4.2.3 Rules for Using
kono
parents:
diff changeset
229 Unwind Descriptors, rule 3. */
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 static unsigned char const save_order[] =
kono
parents:
diff changeset
232 {
kono
parents:
diff changeset
233 UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
kono
parents:
diff changeset
234 UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
kono
parents:
diff changeset
235 };
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 /* MASK is a bitmap describing the allocation state of emergency buffers,
kono
parents:
diff changeset
241 with bit set indicating free. Return >= 0 if allocation is successful;
kono
parents:
diff changeset
242 < 0 if failure. */
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 static inline int
kono
parents:
diff changeset
245 atomic_alloc (unsigned int *mask)
kono
parents:
diff changeset
246 {
kono
parents:
diff changeset
247 unsigned int old = *mask, ret, new;
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 while (1)
kono
parents:
diff changeset
250 {
kono
parents:
diff changeset
251 if (old == 0)
kono
parents:
diff changeset
252 return -1;
kono
parents:
diff changeset
253 ret = old & -old;
kono
parents:
diff changeset
254 new = old & ~ret;
kono
parents:
diff changeset
255 new = __sync_val_compare_and_swap (mask, old, new);
kono
parents:
diff changeset
256 if (old == new)
kono
parents:
diff changeset
257 break;
kono
parents:
diff changeset
258 old = new;
kono
parents:
diff changeset
259 }
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 return __builtin_ffs (ret) - 1;
kono
parents:
diff changeset
262 }
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 /* Similarly, free an emergency buffer. */
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 static inline void
kono
parents:
diff changeset
267 atomic_free (unsigned int *mask, int bit)
kono
parents:
diff changeset
268 {
kono
parents:
diff changeset
269 __sync_xor_and_fetch (mask, 1 << bit);
kono
parents:
diff changeset
270 }
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 #define SIZE(X) (sizeof(X) / sizeof(*(X)))
kono
parents:
diff changeset
274 #define MASK_FOR(X) ((2U << (SIZE (X) - 1)) - 1)
kono
parents:
diff changeset
275 #define PTR_IN(X, P) ((P) >= (X) && (P) < (X) + SIZE (X))
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 static struct unw_reg_state emergency_reg_state[32];
kono
parents:
diff changeset
278 static unsigned int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 static struct unw_labeled_state emergency_labeled_state[8];
kono
parents:
diff changeset
281 static unsigned int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
kono
parents:
diff changeset
282
kono
parents:
diff changeset
283 #ifdef ENABLE_MALLOC_CHECKING
kono
parents:
diff changeset
284 static int reg_state_alloced;
kono
parents:
diff changeset
285 static int labeled_state_alloced;
kono
parents:
diff changeset
286 #endif
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 /* Allocation and deallocation of structures. */
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 static struct unw_reg_state *
kono
parents:
diff changeset
291 alloc_reg_state (void)
kono
parents:
diff changeset
292 {
kono
parents:
diff changeset
293 struct unw_reg_state *rs;
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 #ifdef ENABLE_MALLOC_CHECKING
kono
parents:
diff changeset
296 reg_state_alloced++;
kono
parents:
diff changeset
297 #endif
kono
parents:
diff changeset
298
kono
parents:
diff changeset
299 rs = malloc (sizeof (struct unw_reg_state));
kono
parents:
diff changeset
300 if (!rs)
kono
parents:
diff changeset
301 {
kono
parents:
diff changeset
302 int n = atomic_alloc (&emergency_reg_state_free);
kono
parents:
diff changeset
303 if (n >= 0)
kono
parents:
diff changeset
304 rs = &emergency_reg_state[n];
kono
parents:
diff changeset
305 }
kono
parents:
diff changeset
306
kono
parents:
diff changeset
307 return rs;
kono
parents:
diff changeset
308 }
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310 static void
kono
parents:
diff changeset
311 free_reg_state (struct unw_reg_state *rs)
kono
parents:
diff changeset
312 {
kono
parents:
diff changeset
313 #ifdef ENABLE_MALLOC_CHECKING
kono
parents:
diff changeset
314 reg_state_alloced--;
kono
parents:
diff changeset
315 #endif
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 if (PTR_IN (emergency_reg_state, rs))
kono
parents:
diff changeset
318 atomic_free (&emergency_reg_state_free, rs - emergency_reg_state);
kono
parents:
diff changeset
319 else
kono
parents:
diff changeset
320 free (rs);
kono
parents:
diff changeset
321 }
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 static struct unw_labeled_state *
kono
parents:
diff changeset
324 alloc_label_state (void)
kono
parents:
diff changeset
325 {
kono
parents:
diff changeset
326 struct unw_labeled_state *ls;
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 #ifdef ENABLE_MALLOC_CHECKING
kono
parents:
diff changeset
329 labeled_state_alloced++;
kono
parents:
diff changeset
330 #endif
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 ls = malloc(sizeof(struct unw_labeled_state));
kono
parents:
diff changeset
333 if (!ls)
kono
parents:
diff changeset
334 {
kono
parents:
diff changeset
335 int n = atomic_alloc (&emergency_labeled_state_free);
kono
parents:
diff changeset
336 if (n >= 0)
kono
parents:
diff changeset
337 ls = &emergency_labeled_state[n];
kono
parents:
diff changeset
338 }
kono
parents:
diff changeset
339
kono
parents:
diff changeset
340 return ls;
kono
parents:
diff changeset
341 }
kono
parents:
diff changeset
342
kono
parents:
diff changeset
343 static void
kono
parents:
diff changeset
344 free_label_state (struct unw_labeled_state *ls)
kono
parents:
diff changeset
345 {
kono
parents:
diff changeset
346 #ifdef ENABLE_MALLOC_CHECKING
kono
parents:
diff changeset
347 labeled_state_alloced--;
kono
parents:
diff changeset
348 #endif
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 if (PTR_IN (emergency_labeled_state, ls))
kono
parents:
diff changeset
351 atomic_free (&emergency_labeled_state_free, emergency_labeled_state - ls);
kono
parents:
diff changeset
352 else
kono
parents:
diff changeset
353 free (ls);
kono
parents:
diff changeset
354 }
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 /* Routines to manipulate the state stack. */
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 static void
kono
parents:
diff changeset
359 push (struct unw_state_record *sr)
kono
parents:
diff changeset
360 {
kono
parents:
diff changeset
361 struct unw_reg_state *rs = alloc_reg_state ();
kono
parents:
diff changeset
362 memcpy (rs, &sr->curr, sizeof (*rs));
kono
parents:
diff changeset
363 sr->curr.next = rs;
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 static void
kono
parents:
diff changeset
367 pop (struct unw_state_record *sr)
kono
parents:
diff changeset
368 {
kono
parents:
diff changeset
369 struct unw_reg_state *rs = sr->curr.next;
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 if (!rs)
kono
parents:
diff changeset
372 abort ();
kono
parents:
diff changeset
373 memcpy (&sr->curr, rs, sizeof(*rs));
kono
parents:
diff changeset
374 free_reg_state (rs);
kono
parents:
diff changeset
375 }
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 /* Make a copy of the state stack. Non-recursive to avoid stack overflows. */
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379 static struct unw_reg_state *
kono
parents:
diff changeset
380 dup_state_stack (struct unw_reg_state *rs)
kono
parents:
diff changeset
381 {
kono
parents:
diff changeset
382 struct unw_reg_state *copy, *prev = NULL, *first = NULL;
kono
parents:
diff changeset
383
kono
parents:
diff changeset
384 while (rs)
kono
parents:
diff changeset
385 {
kono
parents:
diff changeset
386 copy = alloc_reg_state ();
kono
parents:
diff changeset
387 memcpy (copy, rs, sizeof(*copy));
kono
parents:
diff changeset
388 if (first)
kono
parents:
diff changeset
389 prev->next = copy;
kono
parents:
diff changeset
390 else
kono
parents:
diff changeset
391 first = copy;
kono
parents:
diff changeset
392 rs = rs->next;
kono
parents:
diff changeset
393 prev = copy;
kono
parents:
diff changeset
394 }
kono
parents:
diff changeset
395
kono
parents:
diff changeset
396 return first;
kono
parents:
diff changeset
397 }
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 /* Free all stacked register states (but not RS itself). */
kono
parents:
diff changeset
400 static void
kono
parents:
diff changeset
401 free_state_stack (struct unw_reg_state *rs)
kono
parents:
diff changeset
402 {
kono
parents:
diff changeset
403 struct unw_reg_state *p, *next;
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 for (p = rs->next; p != NULL; p = next)
kono
parents:
diff changeset
406 {
kono
parents:
diff changeset
407 next = p->next;
kono
parents:
diff changeset
408 free_reg_state (p);
kono
parents:
diff changeset
409 }
kono
parents:
diff changeset
410 rs->next = NULL;
kono
parents:
diff changeset
411 }
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 /* Free all labeled states. */
kono
parents:
diff changeset
414
kono
parents:
diff changeset
415 static void
kono
parents:
diff changeset
416 free_label_states (struct unw_labeled_state *ls)
kono
parents:
diff changeset
417 {
kono
parents:
diff changeset
418 struct unw_labeled_state *next;
kono
parents:
diff changeset
419
kono
parents:
diff changeset
420 for (; ls ; ls = next)
kono
parents:
diff changeset
421 {
kono
parents:
diff changeset
422 next = ls->next;
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 free_state_stack (&ls->saved_state);
kono
parents:
diff changeset
425 free_label_state (ls);
kono
parents:
diff changeset
426 }
kono
parents:
diff changeset
427 }
kono
parents:
diff changeset
428
kono
parents:
diff changeset
429 /* Unwind decoder routines */
kono
parents:
diff changeset
430
kono
parents:
diff changeset
431 static enum unw_register_index __attribute__((const))
kono
parents:
diff changeset
432 decode_abreg (unsigned char abreg, int memory)
kono
parents:
diff changeset
433 {
kono
parents:
diff changeset
434 switch (abreg)
kono
parents:
diff changeset
435 {
kono
parents:
diff changeset
436 #if TARGET_ABI_OPEN_VMS
kono
parents:
diff changeset
437 /* OpenVMS Calling Standard specifies R3 - R31. */
kono
parents:
diff changeset
438 case 0x03 ... 0x1f: return UNW_REG_R2 + (abreg - 0x02);
kono
parents:
diff changeset
439 #else
kono
parents:
diff changeset
440 /* Standard Intel ABI specifies GR 4 - 7. */
kono
parents:
diff changeset
441 case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
kono
parents:
diff changeset
442 #endif
kono
parents:
diff changeset
443 case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
kono
parents:
diff changeset
444 case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
kono
parents:
diff changeset
445 case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
kono
parents:
diff changeset
446 case 0x60: return UNW_REG_PR;
kono
parents:
diff changeset
447 case 0x61: return UNW_REG_PSP;
kono
parents:
diff changeset
448 case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
kono
parents:
diff changeset
449 case 0x63: return UNW_REG_RP;
kono
parents:
diff changeset
450 case 0x64: return UNW_REG_BSP;
kono
parents:
diff changeset
451 case 0x65: return UNW_REG_BSPSTORE;
kono
parents:
diff changeset
452 case 0x66: return UNW_REG_RNAT;
kono
parents:
diff changeset
453 case 0x67: return UNW_REG_UNAT;
kono
parents:
diff changeset
454 case 0x68: return UNW_REG_FPSR;
kono
parents:
diff changeset
455 case 0x69: return UNW_REG_PFS;
kono
parents:
diff changeset
456 case 0x6a: return UNW_REG_LC;
kono
parents:
diff changeset
457 default:
kono
parents:
diff changeset
458 abort ();
kono
parents:
diff changeset
459 }
kono
parents:
diff changeset
460 }
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 static void
kono
parents:
diff changeset
463 set_reg (struct unw_reg_info *reg, enum unw_where where,
kono
parents:
diff changeset
464 int when, unw_word val)
kono
parents:
diff changeset
465 {
kono
parents:
diff changeset
466 reg->val = val;
kono
parents:
diff changeset
467 reg->where = where;
kono
parents:
diff changeset
468 if (reg->when == UNW_WHEN_NEVER)
kono
parents:
diff changeset
469 reg->when = when;
kono
parents:
diff changeset
470 }
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 static void
kono
parents:
diff changeset
473 alloc_spill_area (unw_word *offp, unw_word regsize,
kono
parents:
diff changeset
474 struct unw_reg_info *lo, struct unw_reg_info *hi)
kono
parents:
diff changeset
475 {
kono
parents:
diff changeset
476 struct unw_reg_info *reg;
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 for (reg = hi; reg >= lo; --reg)
kono
parents:
diff changeset
479 {
kono
parents:
diff changeset
480 if (reg->where == UNW_WHERE_SPILL_HOME)
kono
parents:
diff changeset
481 {
kono
parents:
diff changeset
482 reg->where = UNW_WHERE_PSPREL;
kono
parents:
diff changeset
483 *offp -= regsize;
kono
parents:
diff changeset
484 reg->val = *offp;
kono
parents:
diff changeset
485 }
kono
parents:
diff changeset
486 }
kono
parents:
diff changeset
487 }
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 static inline void
kono
parents:
diff changeset
490 spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim,
kono
parents:
diff changeset
491 unw_word t)
kono
parents:
diff changeset
492 {
kono
parents:
diff changeset
493 struct unw_reg_info *reg;
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 for (reg = *regp; reg <= lim; ++reg)
kono
parents:
diff changeset
496 {
kono
parents:
diff changeset
497 if (reg->where == UNW_WHERE_SPILL_HOME)
kono
parents:
diff changeset
498 {
kono
parents:
diff changeset
499 reg->when = t;
kono
parents:
diff changeset
500 *regp = reg + 1;
kono
parents:
diff changeset
501 return;
kono
parents:
diff changeset
502 }
kono
parents:
diff changeset
503 }
kono
parents:
diff changeset
504 /* Excess spill. */
kono
parents:
diff changeset
505 abort ();
kono
parents:
diff changeset
506 }
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 static void
kono
parents:
diff changeset
509 finish_prologue (struct unw_state_record *sr)
kono
parents:
diff changeset
510 {
kono
parents:
diff changeset
511 struct unw_reg_info *reg;
kono
parents:
diff changeset
512 unw_word off;
kono
parents:
diff changeset
513 int i;
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 /* First, resolve implicit register save locations
kono
parents:
diff changeset
516 (see Section "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 for (i = 0; i < (int) sizeof (save_order); ++i)
kono
parents:
diff changeset
519 {
kono
parents:
diff changeset
520 reg = sr->curr.reg + save_order[i];
kono
parents:
diff changeset
521 if (reg->where == UNW_WHERE_GR_SAVE)
kono
parents:
diff changeset
522 {
kono
parents:
diff changeset
523 reg->where = UNW_WHERE_GR;
kono
parents:
diff changeset
524 reg->val = sr->gr_save_loc++;
kono
parents:
diff changeset
525 }
kono
parents:
diff changeset
526 }
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 /* Next, compute when the fp, general, and branch registers get saved.
kono
parents:
diff changeset
529 This must come before alloc_spill_area() because we need to know
kono
parents:
diff changeset
530 which registers are spilled to their home locations. */
kono
parents:
diff changeset
531 if (sr->imask)
kono
parents:
diff changeset
532 {
kono
parents:
diff changeset
533 static unsigned char const limit[3] = {
kono
parents:
diff changeset
534 UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
kono
parents:
diff changeset
535 };
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 unsigned char kind, mask = 0, *cp = sr->imask;
kono
parents:
diff changeset
538 int t;
kono
parents:
diff changeset
539 struct unw_reg_info *(regs[3]);
kono
parents:
diff changeset
540
kono
parents:
diff changeset
541 regs[0] = sr->curr.reg + UNW_REG_F2;
kono
parents:
diff changeset
542 regs[1] = sr->curr.reg + UNW_REG_R4;
kono
parents:
diff changeset
543 regs[2] = sr->curr.reg + UNW_REG_B1;
kono
parents:
diff changeset
544
kono
parents:
diff changeset
545 for (t = 0; t < sr->region_len; ++t)
kono
parents:
diff changeset
546 {
kono
parents:
diff changeset
547 if ((t & 3) == 0)
kono
parents:
diff changeset
548 mask = *cp++;
kono
parents:
diff changeset
549 kind = (mask >> 2*(3-(t & 3))) & 3;
kono
parents:
diff changeset
550 if (kind > 0)
kono
parents:
diff changeset
551 spill_next_when (&regs[kind - 1], sr->curr.reg + limit[kind - 1],
kono
parents:
diff changeset
552 sr->region_start + t);
kono
parents:
diff changeset
553 }
kono
parents:
diff changeset
554 }
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 /* Next, lay out the memory stack spill area. */
kono
parents:
diff changeset
557 if (sr->any_spills)
kono
parents:
diff changeset
558 {
kono
parents:
diff changeset
559 off = sr->spill_offset;
kono
parents:
diff changeset
560 alloc_spill_area (&off, 16, sr->curr.reg + UNW_REG_F2,
kono
parents:
diff changeset
561 sr->curr.reg + UNW_REG_F31);
kono
parents:
diff changeset
562 alloc_spill_area (&off, 8, sr->curr.reg + UNW_REG_B1,
kono
parents:
diff changeset
563 sr->curr.reg + UNW_REG_B5);
kono
parents:
diff changeset
564 alloc_spill_area (&off, 8, sr->curr.reg + UNW_REG_R4,
kono
parents:
diff changeset
565 sr->curr.reg + UNW_REG_R7);
kono
parents:
diff changeset
566 }
kono
parents:
diff changeset
567 }
kono
parents:
diff changeset
568
kono
parents:
diff changeset
569 /*
kono
parents:
diff changeset
570 * Region header descriptors.
kono
parents:
diff changeset
571 */
kono
parents:
diff changeset
572
kono
parents:
diff changeset
573 static void
kono
parents:
diff changeset
574 desc_prologue (int body, unw_word rlen, unsigned char mask,
kono
parents:
diff changeset
575 unsigned char grsave, struct unw_state_record *sr)
kono
parents:
diff changeset
576 {
kono
parents:
diff changeset
577 int i;
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 if (!(sr->in_body || sr->first_region))
kono
parents:
diff changeset
580 finish_prologue (sr);
kono
parents:
diff changeset
581 sr->first_region = 0;
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 /* Check if we're done. */
kono
parents:
diff changeset
584 if (sr->when_target < sr->region_start + sr->region_len)
kono
parents:
diff changeset
585 {
kono
parents:
diff changeset
586 sr->done = 1;
kono
parents:
diff changeset
587 return;
kono
parents:
diff changeset
588 }
kono
parents:
diff changeset
589
kono
parents:
diff changeset
590 for (i = 0; i < sr->epilogue_count; ++i)
kono
parents:
diff changeset
591 pop (sr);
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 sr->epilogue_count = 0;
kono
parents:
diff changeset
594 sr->epilogue_start = UNW_WHEN_NEVER;
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 if (!body)
kono
parents:
diff changeset
597 push (sr);
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 sr->region_start += sr->region_len;
kono
parents:
diff changeset
600 sr->region_len = rlen;
kono
parents:
diff changeset
601 sr->in_body = body;
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 if (!body)
kono
parents:
diff changeset
604 {
kono
parents:
diff changeset
605 for (i = 0; i < 4; ++i)
kono
parents:
diff changeset
606 {
kono
parents:
diff changeset
607 if (mask & 0x8)
kono
parents:
diff changeset
608 set_reg (sr->curr.reg + save_order[i], UNW_WHERE_GR,
kono
parents:
diff changeset
609 sr->region_start + sr->region_len - 1, grsave++);
kono
parents:
diff changeset
610 mask <<= 1;
kono
parents:
diff changeset
611 }
kono
parents:
diff changeset
612 sr->gr_save_loc = grsave;
kono
parents:
diff changeset
613 sr->any_spills = 0;
kono
parents:
diff changeset
614 sr->imask = 0;
kono
parents:
diff changeset
615 sr->spill_offset = 0x10; /* default to psp+16 */
kono
parents:
diff changeset
616 }
kono
parents:
diff changeset
617 }
kono
parents:
diff changeset
618
kono
parents:
diff changeset
619 /*
kono
parents:
diff changeset
620 * Prologue descriptors.
kono
parents:
diff changeset
621 */
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 static inline void
kono
parents:
diff changeset
624 desc_abi (unsigned char abi,
kono
parents:
diff changeset
625 unsigned char context,
kono
parents:
diff changeset
626 struct unw_state_record *sr)
kono
parents:
diff changeset
627 {
kono
parents:
diff changeset
628 sr->unwabi = (abi << 8) | context;
kono
parents:
diff changeset
629 }
kono
parents:
diff changeset
630
kono
parents:
diff changeset
631 static inline void
kono
parents:
diff changeset
632 desc_br_gr (unsigned char brmask, unsigned char gr,
kono
parents:
diff changeset
633 struct unw_state_record *sr)
kono
parents:
diff changeset
634 {
kono
parents:
diff changeset
635 int i;
kono
parents:
diff changeset
636
kono
parents:
diff changeset
637 for (i = 0; i < 5; ++i)
kono
parents:
diff changeset
638 {
kono
parents:
diff changeset
639 if (brmask & 1)
kono
parents:
diff changeset
640 set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
kono
parents:
diff changeset
641 sr->region_start + sr->region_len - 1, gr++);
kono
parents:
diff changeset
642 brmask >>= 1;
kono
parents:
diff changeset
643 }
kono
parents:
diff changeset
644 }
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 static inline void
kono
parents:
diff changeset
647 desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
kono
parents:
diff changeset
648 {
kono
parents:
diff changeset
649 int i;
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 for (i = 0; i < 5; ++i)
kono
parents:
diff changeset
652 {
kono
parents:
diff changeset
653 if (brmask & 1)
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
kono
parents:
diff changeset
656 sr->region_start + sr->region_len - 1, 0);
kono
parents:
diff changeset
657 sr->any_spills = 1;
kono
parents:
diff changeset
658 }
kono
parents:
diff changeset
659 brmask >>= 1;
kono
parents:
diff changeset
660 }
kono
parents:
diff changeset
661 }
kono
parents:
diff changeset
662
kono
parents:
diff changeset
663 static inline void
kono
parents:
diff changeset
664 desc_frgr_mem (unsigned char grmask, unw_word frmask,
kono
parents:
diff changeset
665 struct unw_state_record *sr)
kono
parents:
diff changeset
666 {
kono
parents:
diff changeset
667 int i;
kono
parents:
diff changeset
668
kono
parents:
diff changeset
669 for (i = 0; i < 4; ++i)
kono
parents:
diff changeset
670 {
kono
parents:
diff changeset
671 if ((grmask & 1) != 0)
kono
parents:
diff changeset
672 {
kono
parents:
diff changeset
673 set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
kono
parents:
diff changeset
674 sr->region_start + sr->region_len - 1, 0);
kono
parents:
diff changeset
675 sr->any_spills = 1;
kono
parents:
diff changeset
676 }
kono
parents:
diff changeset
677 grmask >>= 1;
kono
parents:
diff changeset
678 }
kono
parents:
diff changeset
679 for (i = 0; i < 20; ++i)
kono
parents:
diff changeset
680 {
kono
parents:
diff changeset
681 if ((frmask & 1) != 0)
kono
parents:
diff changeset
682 {
kono
parents:
diff changeset
683 enum unw_register_index base = i < 4 ? UNW_REG_F2 : UNW_REG_F16 - 4;
kono
parents:
diff changeset
684 set_reg (sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
kono
parents:
diff changeset
685 sr->region_start + sr->region_len - 1, 0);
kono
parents:
diff changeset
686 sr->any_spills = 1;
kono
parents:
diff changeset
687 }
kono
parents:
diff changeset
688 frmask >>= 1;
kono
parents:
diff changeset
689 }
kono
parents:
diff changeset
690 }
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 static inline void
kono
parents:
diff changeset
693 desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
kono
parents:
diff changeset
694 {
kono
parents:
diff changeset
695 int i;
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 for (i = 0; i < 4; ++i)
kono
parents:
diff changeset
698 {
kono
parents:
diff changeset
699 if ((frmask & 1) != 0)
kono
parents:
diff changeset
700 {
kono
parents:
diff changeset
701 set_reg (sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
kono
parents:
diff changeset
702 sr->region_start + sr->region_len - 1, 0);
kono
parents:
diff changeset
703 sr->any_spills = 1;
kono
parents:
diff changeset
704 }
kono
parents:
diff changeset
705 frmask >>= 1;
kono
parents:
diff changeset
706 }
kono
parents:
diff changeset
707 }
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 static inline void
kono
parents:
diff changeset
710 desc_gr_gr (unsigned char grmask, unsigned char gr,
kono
parents:
diff changeset
711 struct unw_state_record *sr)
kono
parents:
diff changeset
712 {
kono
parents:
diff changeset
713 int i;
kono
parents:
diff changeset
714
kono
parents:
diff changeset
715 for (i = 0; i < 4; ++i)
kono
parents:
diff changeset
716 {
kono
parents:
diff changeset
717 if ((grmask & 1) != 0)
kono
parents:
diff changeset
718 set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
kono
parents:
diff changeset
719 sr->region_start + sr->region_len - 1, gr++);
kono
parents:
diff changeset
720 grmask >>= 1;
kono
parents:
diff changeset
721 }
kono
parents:
diff changeset
722 }
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 static inline void
kono
parents:
diff changeset
725 desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
kono
parents:
diff changeset
726 {
kono
parents:
diff changeset
727 int i;
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 for (i = 0; i < 4; ++i)
kono
parents:
diff changeset
730 {
kono
parents:
diff changeset
731 if ((grmask & 1) != 0)
kono
parents:
diff changeset
732 {
kono
parents:
diff changeset
733 set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
kono
parents:
diff changeset
734 sr->region_start + sr->region_len - 1, 0);
kono
parents:
diff changeset
735 sr->any_spills = 1;
kono
parents:
diff changeset
736 }
kono
parents:
diff changeset
737 grmask >>= 1;
kono
parents:
diff changeset
738 }
kono
parents:
diff changeset
739 }
kono
parents:
diff changeset
740
kono
parents:
diff changeset
741 static inline void
kono
parents:
diff changeset
742 desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
kono
parents:
diff changeset
743 {
kono
parents:
diff changeset
744 set_reg (sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
kono
parents:
diff changeset
745 sr->region_start + MIN ((int)t, sr->region_len - 1), 16*size);
kono
parents:
diff changeset
746 }
kono
parents:
diff changeset
747
kono
parents:
diff changeset
748 static inline void
kono
parents:
diff changeset
749 desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
kono
parents:
diff changeset
750 {
kono
parents:
diff changeset
751 sr->curr.reg[UNW_REG_PSP].when
kono
parents:
diff changeset
752 = sr->region_start + MIN ((int)t, sr->region_len - 1);
kono
parents:
diff changeset
753 }
kono
parents:
diff changeset
754
kono
parents:
diff changeset
755 static inline void
kono
parents:
diff changeset
756 desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
kono
parents:
diff changeset
757 {
kono
parents:
diff changeset
758 set_reg (sr->curr.reg + reg, UNW_WHERE_GR,
kono
parents:
diff changeset
759 sr->region_start + sr->region_len - 1, dst);
kono
parents:
diff changeset
760 }
kono
parents:
diff changeset
761
kono
parents:
diff changeset
762 static inline void
kono
parents:
diff changeset
763 desc_reg_psprel (unsigned char reg, unw_word pspoff,
kono
parents:
diff changeset
764 struct unw_state_record *sr)
kono
parents:
diff changeset
765 {
kono
parents:
diff changeset
766 set_reg (sr->curr.reg + reg, UNW_WHERE_PSPREL,
kono
parents:
diff changeset
767 sr->region_start + sr->region_len - 1,
kono
parents:
diff changeset
768 0x10 - 4*pspoff);
kono
parents:
diff changeset
769 }
kono
parents:
diff changeset
770
kono
parents:
diff changeset
771 static inline void
kono
parents:
diff changeset
772 desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
kono
parents:
diff changeset
773 {
kono
parents:
diff changeset
774 set_reg (sr->curr.reg + reg, UNW_WHERE_SPREL,
kono
parents:
diff changeset
775 sr->region_start + sr->region_len - 1,
kono
parents:
diff changeset
776 4*spoff);
kono
parents:
diff changeset
777 }
kono
parents:
diff changeset
778
kono
parents:
diff changeset
779 static inline void
kono
parents:
diff changeset
780 desc_rp_br (unsigned char dst, struct unw_state_record *sr)
kono
parents:
diff changeset
781 {
kono
parents:
diff changeset
782 sr->return_link_reg = dst;
kono
parents:
diff changeset
783 }
kono
parents:
diff changeset
784
kono
parents:
diff changeset
785 static inline void
kono
parents:
diff changeset
786 desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
kono
parents:
diff changeset
787 {
kono
parents:
diff changeset
788 struct unw_reg_info *reg = sr->curr.reg + regnum;
kono
parents:
diff changeset
789
kono
parents:
diff changeset
790 if (reg->where == UNW_WHERE_NONE)
kono
parents:
diff changeset
791 reg->where = UNW_WHERE_GR_SAVE;
kono
parents:
diff changeset
792 reg->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
kono
parents:
diff changeset
793 }
kono
parents:
diff changeset
794
kono
parents:
diff changeset
795 static inline void
kono
parents:
diff changeset
796 desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
kono
parents:
diff changeset
797 {
kono
parents:
diff changeset
798 sr->spill_offset = 0x10 - 4*pspoff;
kono
parents:
diff changeset
799 }
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 static inline unsigned char *
kono
parents:
diff changeset
802 desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
kono
parents:
diff changeset
803 {
kono
parents:
diff changeset
804 sr->imask = imaskp;
kono
parents:
diff changeset
805 return imaskp + (2*sr->region_len + 7)/8;
kono
parents:
diff changeset
806 }
kono
parents:
diff changeset
807
kono
parents:
diff changeset
808 /*
kono
parents:
diff changeset
809 * Body descriptors.
kono
parents:
diff changeset
810 */
kono
parents:
diff changeset
811 static inline void
kono
parents:
diff changeset
812 desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
kono
parents:
diff changeset
813 {
kono
parents:
diff changeset
814 sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
kono
parents:
diff changeset
815 sr->epilogue_count = ecount + 1;
kono
parents:
diff changeset
816 }
kono
parents:
diff changeset
817
kono
parents:
diff changeset
818 static inline void
kono
parents:
diff changeset
819 desc_copy_state (unw_word label, struct unw_state_record *sr)
kono
parents:
diff changeset
820 {
kono
parents:
diff changeset
821 struct unw_labeled_state *ls;
kono
parents:
diff changeset
822
kono
parents:
diff changeset
823 for (ls = sr->labeled_states; ls; ls = ls->next)
kono
parents:
diff changeset
824 {
kono
parents:
diff changeset
825 if (ls->label == label)
kono
parents:
diff changeset
826 {
kono
parents:
diff changeset
827 free_state_stack (&sr->curr);
kono
parents:
diff changeset
828 memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
kono
parents:
diff changeset
829 sr->curr.next = dup_state_stack (ls->saved_state.next);
kono
parents:
diff changeset
830 return;
kono
parents:
diff changeset
831 }
kono
parents:
diff changeset
832 }
kono
parents:
diff changeset
833 abort ();
kono
parents:
diff changeset
834 }
kono
parents:
diff changeset
835
kono
parents:
diff changeset
836 static inline void
kono
parents:
diff changeset
837 desc_label_state (unw_word label, struct unw_state_record *sr)
kono
parents:
diff changeset
838 {
kono
parents:
diff changeset
839 struct unw_labeled_state *ls = alloc_label_state ();
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 ls->label = label;
kono
parents:
diff changeset
842 memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
kono
parents:
diff changeset
843 ls->saved_state.next = dup_state_stack (sr->curr.next);
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 /* Insert into list of labeled states. */
kono
parents:
diff changeset
846 ls->next = sr->labeled_states;
kono
parents:
diff changeset
847 sr->labeled_states = ls;
kono
parents:
diff changeset
848 }
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 /*
kono
parents:
diff changeset
851 * General descriptors.
kono
parents:
diff changeset
852 */
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 static inline int
kono
parents:
diff changeset
855 desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
kono
parents:
diff changeset
856 {
kono
parents:
diff changeset
857 if (sr->when_target <= sr->region_start + MIN ((int)t, sr->region_len - 1))
kono
parents:
diff changeset
858 return 0;
kono
parents:
diff changeset
859 if (qp > 0)
kono
parents:
diff changeset
860 {
kono
parents:
diff changeset
861 if ((sr->pr_val & (1UL << qp)) == 0)
kono
parents:
diff changeset
862 return 0;
kono
parents:
diff changeset
863 sr->pr_mask |= (1UL << qp);
kono
parents:
diff changeset
864 }
kono
parents:
diff changeset
865 return 1;
kono
parents:
diff changeset
866 }
kono
parents:
diff changeset
867
kono
parents:
diff changeset
868 static inline void
kono
parents:
diff changeset
869 desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
kono
parents:
diff changeset
870 struct unw_state_record *sr)
kono
parents:
diff changeset
871 {
kono
parents:
diff changeset
872 struct unw_reg_info *r;
kono
parents:
diff changeset
873
kono
parents:
diff changeset
874 if (! desc_is_active (qp, t, sr))
kono
parents:
diff changeset
875 return;
kono
parents:
diff changeset
876
kono
parents:
diff changeset
877 r = sr->curr.reg + decode_abreg (abreg, 0);
kono
parents:
diff changeset
878 r->where = UNW_WHERE_NONE;
kono
parents:
diff changeset
879 r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
kono
parents:
diff changeset
880 r->val = 0;
kono
parents:
diff changeset
881 }
kono
parents:
diff changeset
882
kono
parents:
diff changeset
883 static inline void
kono
parents:
diff changeset
884 desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
kono
parents:
diff changeset
885 unsigned char x, unsigned char ytreg,
kono
parents:
diff changeset
886 struct unw_state_record *sr)
kono
parents:
diff changeset
887 {
kono
parents:
diff changeset
888 enum unw_where where = UNW_WHERE_GR;
kono
parents:
diff changeset
889 struct unw_reg_info *r;
kono
parents:
diff changeset
890
kono
parents:
diff changeset
891 if (! desc_is_active (qp, t, sr))
kono
parents:
diff changeset
892 return;
kono
parents:
diff changeset
893
kono
parents:
diff changeset
894 if (x)
kono
parents:
diff changeset
895 where = UNW_WHERE_BR;
kono
parents:
diff changeset
896 else if (ytreg & 0x80)
kono
parents:
diff changeset
897 where = UNW_WHERE_FR;
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 r = sr->curr.reg + decode_abreg (abreg, 0);
kono
parents:
diff changeset
900 r->where = where;
kono
parents:
diff changeset
901 r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
kono
parents:
diff changeset
902 r->val = ytreg & 0x7f;
kono
parents:
diff changeset
903 }
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 static inline void
kono
parents:
diff changeset
906 desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
kono
parents:
diff changeset
907 unw_word pspoff, struct unw_state_record *sr)
kono
parents:
diff changeset
908 {
kono
parents:
diff changeset
909 struct unw_reg_info *r;
kono
parents:
diff changeset
910
kono
parents:
diff changeset
911 if (! desc_is_active (qp, t, sr))
kono
parents:
diff changeset
912 return;
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 r = sr->curr.reg + decode_abreg (abreg, 1);
kono
parents:
diff changeset
915 r->where = UNW_WHERE_PSPREL;
kono
parents:
diff changeset
916 r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
kono
parents:
diff changeset
917 r->val = 0x10 - 4*pspoff;
kono
parents:
diff changeset
918 }
kono
parents:
diff changeset
919
kono
parents:
diff changeset
920 static inline void
kono
parents:
diff changeset
921 desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
kono
parents:
diff changeset
922 unw_word spoff, struct unw_state_record *sr)
kono
parents:
diff changeset
923 {
kono
parents:
diff changeset
924 struct unw_reg_info *r;
kono
parents:
diff changeset
925
kono
parents:
diff changeset
926 if (! desc_is_active (qp, t, sr))
kono
parents:
diff changeset
927 return;
kono
parents:
diff changeset
928
kono
parents:
diff changeset
929 r = sr->curr.reg + decode_abreg (abreg, 1);
kono
parents:
diff changeset
930 r->where = UNW_WHERE_SPREL;
kono
parents:
diff changeset
931 r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
kono
parents:
diff changeset
932 r->val = 4*spoff;
kono
parents:
diff changeset
933 }
kono
parents:
diff changeset
934
kono
parents:
diff changeset
935
kono
parents:
diff changeset
936 #define UNW_DEC_BAD_CODE(code) abort ();
kono
parents:
diff changeset
937
kono
parents:
diff changeset
938 /* Region headers. */
kono
parents:
diff changeset
939 #define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg)
kono
parents:
diff changeset
940 #define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg)
kono
parents:
diff changeset
941
kono
parents:
diff changeset
942 /* Prologue descriptors. */
kono
parents:
diff changeset
943 #define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg)
kono
parents:
diff changeset
944 #define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg)
kono
parents:
diff changeset
945 #define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg)
kono
parents:
diff changeset
946 #define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg)
kono
parents:
diff changeset
947 #define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg)
kono
parents:
diff changeset
948 #define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg)
kono
parents:
diff changeset
949 #define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg)
kono
parents:
diff changeset
950 #define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg)
kono
parents:
diff changeset
951 #define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg)
kono
parents:
diff changeset
952 #define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg)
kono
parents:
diff changeset
953 #define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg)
kono
parents:
diff changeset
954 #define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg)
kono
parents:
diff changeset
955 #define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg)
kono
parents:
diff changeset
956 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
kono
parents:
diff changeset
957 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
kono
parents:
diff changeset
958 #define UNW_DEC_PRIUNAT_GR(fmt,r,arg) desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
kono
parents:
diff changeset
959 #define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
kono
parents:
diff changeset
960 #define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
kono
parents:
diff changeset
961 #define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg)
kono
parents:
diff changeset
962 #define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg)
kono
parents:
diff changeset
963 #define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg))
kono
parents:
diff changeset
964
kono
parents:
diff changeset
965 /* Body descriptors. */
kono
parents:
diff changeset
966 #define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg)
kono
parents:
diff changeset
967 #define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg)
kono
parents:
diff changeset
968 #define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg)
kono
parents:
diff changeset
969
kono
parents:
diff changeset
970 /* General unwind descriptors. */
kono
parents:
diff changeset
971 #define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg)
kono
parents:
diff changeset
972 #define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg)
kono
parents:
diff changeset
973 #define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) desc_spill_psprel_p(p,t,a,o,arg)
kono
parents:
diff changeset
974 #define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) desc_spill_psprel_p(0,t,a,o,arg)
kono
parents:
diff changeset
975 #define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg)
kono
parents:
diff changeset
976 #define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg)
kono
parents:
diff changeset
977 #define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg)
kono
parents:
diff changeset
978 #define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg)
kono
parents:
diff changeset
979
kono
parents:
diff changeset
980
kono
parents:
diff changeset
981 /*
kono
parents:
diff changeset
982 * Generic IA-64 unwind info decoder.
kono
parents:
diff changeset
983 *
kono
parents:
diff changeset
984 * This file is used both by the Linux kernel and objdump. Please keep
kono
parents:
diff changeset
985 * the copies of this file in sync.
kono
parents:
diff changeset
986 *
kono
parents:
diff changeset
987 * You need to customize the decoder by defining the following
kono
parents:
diff changeset
988 * macros/constants before including this file:
kono
parents:
diff changeset
989 *
kono
parents:
diff changeset
990 * Types:
kono
parents:
diff changeset
991 * unw_word Unsigned integer type with at least 64 bits
kono
parents:
diff changeset
992 *
kono
parents:
diff changeset
993 * Register names:
kono
parents:
diff changeset
994 * UNW_REG_BSP
kono
parents:
diff changeset
995 * UNW_REG_BSPSTORE
kono
parents:
diff changeset
996 * UNW_REG_FPSR
kono
parents:
diff changeset
997 * UNW_REG_LC
kono
parents:
diff changeset
998 * UNW_REG_PFS
kono
parents:
diff changeset
999 * UNW_REG_PR
kono
parents:
diff changeset
1000 * UNW_REG_RNAT
kono
parents:
diff changeset
1001 * UNW_REG_PSP
kono
parents:
diff changeset
1002 * UNW_REG_RP
kono
parents:
diff changeset
1003 * UNW_REG_UNAT
kono
parents:
diff changeset
1004 *
kono
parents:
diff changeset
1005 * Decoder action macros:
kono
parents:
diff changeset
1006 * UNW_DEC_BAD_CODE(code)
kono
parents:
diff changeset
1007 * UNW_DEC_ABI(fmt,abi,context,arg)
kono
parents:
diff changeset
1008 * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
kono
parents:
diff changeset
1009 * UNW_DEC_BR_MEM(fmt,brmask,arg)
kono
parents:
diff changeset
1010 * UNW_DEC_COPY_STATE(fmt,label,arg)
kono
parents:
diff changeset
1011 * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
kono
parents:
diff changeset
1012 * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
kono
parents:
diff changeset
1013 * UNW_DEC_FR_MEM(fmt,frmask,arg)
kono
parents:
diff changeset
1014 * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
kono
parents:
diff changeset
1015 * UNW_DEC_GR_MEM(fmt,grmask,arg)
kono
parents:
diff changeset
1016 * UNW_DEC_LABEL_STATE(fmt,label,arg)
kono
parents:
diff changeset
1017 * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
kono
parents:
diff changeset
1018 * UNW_DEC_MEM_STACK_V(fmt,t,arg)
kono
parents:
diff changeset
1019 * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
kono
parents:
diff changeset
1020 * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
kono
parents:
diff changeset
1021 * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
kono
parents:
diff changeset
1022 * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
kono
parents:
diff changeset
1023 * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
kono
parents:
diff changeset
1024 * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
kono
parents:
diff changeset
1025 * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
kono
parents:
diff changeset
1026 * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
kono
parents:
diff changeset
1027 * UNW_DEC_REG_REG(fmt,src,dst,arg)
kono
parents:
diff changeset
1028 * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
kono
parents:
diff changeset
1029 * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
kono
parents:
diff changeset
1030 * UNW_DEC_RESTORE(fmt,t,abreg,arg)
kono
parents:
diff changeset
1031 * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
kono
parents:
diff changeset
1032 * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
kono
parents:
diff changeset
1033 * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
kono
parents:
diff changeset
1034 * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
kono
parents:
diff changeset
1035 * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
kono
parents:
diff changeset
1036 * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
kono
parents:
diff changeset
1037 * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
kono
parents:
diff changeset
1038 * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
kono
parents:
diff changeset
1039 * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
kono
parents:
diff changeset
1040 */
kono
parents:
diff changeset
1041
kono
parents:
diff changeset
1042 static unw_word
kono
parents:
diff changeset
1043 unw_decode_uleb128 (unsigned char **dpp)
kono
parents:
diff changeset
1044 {
kono
parents:
diff changeset
1045 unsigned shift = 0;
kono
parents:
diff changeset
1046 unw_word byte, result = 0;
kono
parents:
diff changeset
1047 unsigned char *bp = *dpp;
kono
parents:
diff changeset
1048
kono
parents:
diff changeset
1049 while (1)
kono
parents:
diff changeset
1050 {
kono
parents:
diff changeset
1051 byte = *bp++;
kono
parents:
diff changeset
1052 result |= (byte & 0x7f) << shift;
kono
parents:
diff changeset
1053 if ((byte & 0x80) == 0)
kono
parents:
diff changeset
1054 break;
kono
parents:
diff changeset
1055 shift += 7;
kono
parents:
diff changeset
1056 }
kono
parents:
diff changeset
1057 *dpp = bp;
kono
parents:
diff changeset
1058 return result;
kono
parents:
diff changeset
1059 }
kono
parents:
diff changeset
1060
kono
parents:
diff changeset
1061 static unsigned char *
kono
parents:
diff changeset
1062 unw_decode_x1 (unsigned char *dp,
kono
parents:
diff changeset
1063 unsigned char code __attribute__((unused)),
kono
parents:
diff changeset
1064 void *arg)
kono
parents:
diff changeset
1065 {
kono
parents:
diff changeset
1066 unsigned char byte1, abreg;
kono
parents:
diff changeset
1067 unw_word t, off;
kono
parents:
diff changeset
1068
kono
parents:
diff changeset
1069 byte1 = *dp++;
kono
parents:
diff changeset
1070 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1071 off = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1072 abreg = (byte1 & 0x7f);
kono
parents:
diff changeset
1073 if (byte1 & 0x80)
kono
parents:
diff changeset
1074 UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
kono
parents:
diff changeset
1075 else
kono
parents:
diff changeset
1076 UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
kono
parents:
diff changeset
1077 return dp;
kono
parents:
diff changeset
1078 }
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 static unsigned char *
kono
parents:
diff changeset
1081 unw_decode_x2 (unsigned char *dp,
kono
parents:
diff changeset
1082 unsigned char code __attribute__((unused)),
kono
parents:
diff changeset
1083 void *arg)
kono
parents:
diff changeset
1084 {
kono
parents:
diff changeset
1085 unsigned char byte1, byte2, abreg, x, ytreg;
kono
parents:
diff changeset
1086 unw_word t;
kono
parents:
diff changeset
1087
kono
parents:
diff changeset
1088 byte1 = *dp++; byte2 = *dp++;
kono
parents:
diff changeset
1089 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1090 abreg = (byte1 & 0x7f);
kono
parents:
diff changeset
1091 ytreg = byte2;
kono
parents:
diff changeset
1092 x = (byte1 >> 7) & 1;
kono
parents:
diff changeset
1093 if ((byte1 & 0x80) == 0 && ytreg == 0)
kono
parents:
diff changeset
1094 UNW_DEC_RESTORE(X2, t, abreg, arg);
kono
parents:
diff changeset
1095 else
kono
parents:
diff changeset
1096 UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
kono
parents:
diff changeset
1097 return dp;
kono
parents:
diff changeset
1098 }
kono
parents:
diff changeset
1099
kono
parents:
diff changeset
1100 static unsigned char *
kono
parents:
diff changeset
1101 unw_decode_x3 (unsigned char *dp,
kono
parents:
diff changeset
1102 unsigned char code __attribute__((unused)),
kono
parents:
diff changeset
1103 void *arg)
kono
parents:
diff changeset
1104 {
kono
parents:
diff changeset
1105 unsigned char byte1, byte2, abreg, qp;
kono
parents:
diff changeset
1106 unw_word t, off;
kono
parents:
diff changeset
1107
kono
parents:
diff changeset
1108 byte1 = *dp++; byte2 = *dp++;
kono
parents:
diff changeset
1109 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1110 off = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1111
kono
parents:
diff changeset
1112 qp = (byte1 & 0x3f);
kono
parents:
diff changeset
1113 abreg = (byte2 & 0x7f);
kono
parents:
diff changeset
1114
kono
parents:
diff changeset
1115 if (byte1 & 0x80)
kono
parents:
diff changeset
1116 UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
kono
parents:
diff changeset
1117 else
kono
parents:
diff changeset
1118 UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
kono
parents:
diff changeset
1119 return dp;
kono
parents:
diff changeset
1120 }
kono
parents:
diff changeset
1121
kono
parents:
diff changeset
1122 static unsigned char *
kono
parents:
diff changeset
1123 unw_decode_x4 (unsigned char *dp,
kono
parents:
diff changeset
1124 unsigned char code __attribute__((unused)),
kono
parents:
diff changeset
1125 void *arg)
kono
parents:
diff changeset
1126 {
kono
parents:
diff changeset
1127 unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
kono
parents:
diff changeset
1128 unw_word t;
kono
parents:
diff changeset
1129
kono
parents:
diff changeset
1130 byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
kono
parents:
diff changeset
1131 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1132
kono
parents:
diff changeset
1133 qp = (byte1 & 0x3f);
kono
parents:
diff changeset
1134 abreg = (byte2 & 0x7f);
kono
parents:
diff changeset
1135 x = (byte2 >> 7) & 1;
kono
parents:
diff changeset
1136 ytreg = byte3;
kono
parents:
diff changeset
1137
kono
parents:
diff changeset
1138 if ((byte2 & 0x80) == 0 && byte3 == 0)
kono
parents:
diff changeset
1139 UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
kono
parents:
diff changeset
1140 else
kono
parents:
diff changeset
1141 UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
kono
parents:
diff changeset
1142 return dp;
kono
parents:
diff changeset
1143 }
kono
parents:
diff changeset
1144
kono
parents:
diff changeset
1145 static unsigned char *
kono
parents:
diff changeset
1146 unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1147 {
kono
parents:
diff changeset
1148 int body = (code & 0x20) != 0;
kono
parents:
diff changeset
1149 unw_word rlen;
kono
parents:
diff changeset
1150
kono
parents:
diff changeset
1151 rlen = (code & 0x1f);
kono
parents:
diff changeset
1152 UNW_DEC_PROLOGUE(R1, body, rlen, arg);
kono
parents:
diff changeset
1153 return dp;
kono
parents:
diff changeset
1154 }
kono
parents:
diff changeset
1155
kono
parents:
diff changeset
1156 static unsigned char *
kono
parents:
diff changeset
1157 unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1158 {
kono
parents:
diff changeset
1159 unsigned char byte1, mask, grsave;
kono
parents:
diff changeset
1160 unw_word rlen;
kono
parents:
diff changeset
1161
kono
parents:
diff changeset
1162 byte1 = *dp++;
kono
parents:
diff changeset
1163
kono
parents:
diff changeset
1164 mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
kono
parents:
diff changeset
1165 grsave = (byte1 & 0x7f);
kono
parents:
diff changeset
1166 rlen = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1167 UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
kono
parents:
diff changeset
1168 return dp;
kono
parents:
diff changeset
1169 }
kono
parents:
diff changeset
1170
kono
parents:
diff changeset
1171 static unsigned char *
kono
parents:
diff changeset
1172 unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1173 {
kono
parents:
diff changeset
1174 unw_word rlen;
kono
parents:
diff changeset
1175
kono
parents:
diff changeset
1176 rlen = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1177 UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
kono
parents:
diff changeset
1178 return dp;
kono
parents:
diff changeset
1179 }
kono
parents:
diff changeset
1180
kono
parents:
diff changeset
1181 static unsigned char *
kono
parents:
diff changeset
1182 unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1183 {
kono
parents:
diff changeset
1184 unsigned char brmask = (code & 0x1f);
kono
parents:
diff changeset
1185
kono
parents:
diff changeset
1186 UNW_DEC_BR_MEM(P1, brmask, arg);
kono
parents:
diff changeset
1187 return dp;
kono
parents:
diff changeset
1188 }
kono
parents:
diff changeset
1189
kono
parents:
diff changeset
1190 static unsigned char *
kono
parents:
diff changeset
1191 unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1192 {
kono
parents:
diff changeset
1193 if ((code & 0x10) == 0)
kono
parents:
diff changeset
1194 {
kono
parents:
diff changeset
1195 unsigned char byte1 = *dp++;
kono
parents:
diff changeset
1196
kono
parents:
diff changeset
1197 UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
kono
parents:
diff changeset
1198 (byte1 & 0x7f), arg);
kono
parents:
diff changeset
1199 }
kono
parents:
diff changeset
1200 else if ((code & 0x08) == 0)
kono
parents:
diff changeset
1201 {
kono
parents:
diff changeset
1202 unsigned char byte1 = *dp++, r, dst;
kono
parents:
diff changeset
1203
kono
parents:
diff changeset
1204 r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
kono
parents:
diff changeset
1205 dst = (byte1 & 0x7f);
kono
parents:
diff changeset
1206 switch (r)
kono
parents:
diff changeset
1207 {
kono
parents:
diff changeset
1208 case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
kono
parents:
diff changeset
1209 case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
kono
parents:
diff changeset
1210 case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
kono
parents:
diff changeset
1211 case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
kono
parents:
diff changeset
1212 case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
kono
parents:
diff changeset
1213 case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
kono
parents:
diff changeset
1214 case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
kono
parents:
diff changeset
1215 case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
kono
parents:
diff changeset
1216 case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
kono
parents:
diff changeset
1217 case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
kono
parents:
diff changeset
1218 case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
kono
parents:
diff changeset
1219 case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
kono
parents:
diff changeset
1220 default: UNW_DEC_BAD_CODE(r); break;
kono
parents:
diff changeset
1221 }
kono
parents:
diff changeset
1222 }
kono
parents:
diff changeset
1223 else if ((code & 0x7) == 0)
kono
parents:
diff changeset
1224 UNW_DEC_SPILL_MASK(P4, dp, arg);
kono
parents:
diff changeset
1225 else if ((code & 0x7) == 1)
kono
parents:
diff changeset
1226 {
kono
parents:
diff changeset
1227 unw_word grmask, frmask, byte1, byte2, byte3;
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
kono
parents:
diff changeset
1230 grmask = ((byte1 >> 4) & 0xf);
kono
parents:
diff changeset
1231 frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
kono
parents:
diff changeset
1232 UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
kono
parents:
diff changeset
1233 }
kono
parents:
diff changeset
1234 else
kono
parents:
diff changeset
1235 UNW_DEC_BAD_CODE(code);
kono
parents:
diff changeset
1236 return dp;
kono
parents:
diff changeset
1237 }
kono
parents:
diff changeset
1238
kono
parents:
diff changeset
1239 static unsigned char *
kono
parents:
diff changeset
1240 unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1241 {
kono
parents:
diff changeset
1242 int gregs = (code & 0x10) != 0;
kono
parents:
diff changeset
1243 unsigned char mask = (code & 0x0f);
kono
parents:
diff changeset
1244
kono
parents:
diff changeset
1245 if (gregs)
kono
parents:
diff changeset
1246 UNW_DEC_GR_MEM(P6, mask, arg);
kono
parents:
diff changeset
1247 else
kono
parents:
diff changeset
1248 UNW_DEC_FR_MEM(P6, mask, arg);
kono
parents:
diff changeset
1249 return dp;
kono
parents:
diff changeset
1250 }
kono
parents:
diff changeset
1251
kono
parents:
diff changeset
1252 static unsigned char *
kono
parents:
diff changeset
1253 unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1254 {
kono
parents:
diff changeset
1255 unsigned char r, byte1, byte2;
kono
parents:
diff changeset
1256 unw_word t, size;
kono
parents:
diff changeset
1257
kono
parents:
diff changeset
1258 if ((code & 0x10) == 0)
kono
parents:
diff changeset
1259 {
kono
parents:
diff changeset
1260 r = (code & 0xf);
kono
parents:
diff changeset
1261 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1262 switch (r)
kono
parents:
diff changeset
1263 {
kono
parents:
diff changeset
1264 case 0:
kono
parents:
diff changeset
1265 size = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1266 UNW_DEC_MEM_STACK_F(P7, t, size, arg);
kono
parents:
diff changeset
1267 break;
kono
parents:
diff changeset
1268
kono
parents:
diff changeset
1269 case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
kono
parents:
diff changeset
1270 case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
kono
parents:
diff changeset
1271 case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
kono
parents:
diff changeset
1272 case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
kono
parents:
diff changeset
1273 case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
kono
parents:
diff changeset
1274 case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
kono
parents:
diff changeset
1275 case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
kono
parents:
diff changeset
1276 case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
kono
parents:
diff changeset
1277 case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
kono
parents:
diff changeset
1278 case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
kono
parents:
diff changeset
1279 case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
kono
parents:
diff changeset
1280 case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
kono
parents:
diff changeset
1281 case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
kono
parents:
diff changeset
1282 case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
kono
parents:
diff changeset
1283 case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
kono
parents:
diff changeset
1284 default: UNW_DEC_BAD_CODE(r); break;
kono
parents:
diff changeset
1285 }
kono
parents:
diff changeset
1286 }
kono
parents:
diff changeset
1287 else
kono
parents:
diff changeset
1288 {
kono
parents:
diff changeset
1289 switch (code & 0xf)
kono
parents:
diff changeset
1290 {
kono
parents:
diff changeset
1291 case 0x0: /* p8 */
kono
parents:
diff changeset
1292 {
kono
parents:
diff changeset
1293 r = *dp++;
kono
parents:
diff changeset
1294 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1295 switch (r)
kono
parents:
diff changeset
1296 {
kono
parents:
diff changeset
1297 case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
kono
parents:
diff changeset
1298 case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
kono
parents:
diff changeset
1299 case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
kono
parents:
diff changeset
1300 case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
kono
parents:
diff changeset
1301 case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
kono
parents:
diff changeset
1302 case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
kono
parents:
diff changeset
1303 case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
kono
parents:
diff changeset
1304 case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
kono
parents:
diff changeset
1305 case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
kono
parents:
diff changeset
1306 case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
kono
parents:
diff changeset
1307 case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
kono
parents:
diff changeset
1308 case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
kono
parents:
diff changeset
1309 case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
kono
parents:
diff changeset
1310 case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
kono
parents:
diff changeset
1311 case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
kono
parents:
diff changeset
1312 case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
kono
parents:
diff changeset
1313 case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
kono
parents:
diff changeset
1314 case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
kono
parents:
diff changeset
1315 case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
kono
parents:
diff changeset
1316 default: UNW_DEC_BAD_CODE(r); break;
kono
parents:
diff changeset
1317 }
kono
parents:
diff changeset
1318 }
kono
parents:
diff changeset
1319 break;
kono
parents:
diff changeset
1320
kono
parents:
diff changeset
1321 case 0x1:
kono
parents:
diff changeset
1322 byte1 = *dp++; byte2 = *dp++;
kono
parents:
diff changeset
1323 UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
kono
parents:
diff changeset
1324 break;
kono
parents:
diff changeset
1325
kono
parents:
diff changeset
1326 case 0xf: /* p10 */
kono
parents:
diff changeset
1327 byte1 = *dp++; byte2 = *dp++;
kono
parents:
diff changeset
1328 UNW_DEC_ABI(P10, byte1, byte2, arg);
kono
parents:
diff changeset
1329 break;
kono
parents:
diff changeset
1330
kono
parents:
diff changeset
1331 case 0x9:
kono
parents:
diff changeset
1332 return unw_decode_x1 (dp, code, arg);
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 case 0xa:
kono
parents:
diff changeset
1335 return unw_decode_x2 (dp, code, arg);
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 case 0xb:
kono
parents:
diff changeset
1338 return unw_decode_x3 (dp, code, arg);
kono
parents:
diff changeset
1339
kono
parents:
diff changeset
1340 case 0xc:
kono
parents:
diff changeset
1341 return unw_decode_x4 (dp, code, arg);
kono
parents:
diff changeset
1342
kono
parents:
diff changeset
1343 default:
kono
parents:
diff changeset
1344 UNW_DEC_BAD_CODE(code);
kono
parents:
diff changeset
1345 break;
kono
parents:
diff changeset
1346 }
kono
parents:
diff changeset
1347 }
kono
parents:
diff changeset
1348 return dp;
kono
parents:
diff changeset
1349 }
kono
parents:
diff changeset
1350
kono
parents:
diff changeset
1351 static unsigned char *
kono
parents:
diff changeset
1352 unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1353 {
kono
parents:
diff changeset
1354 unw_word label = (code & 0x1f);
kono
parents:
diff changeset
1355
kono
parents:
diff changeset
1356 if ((code & 0x20) != 0)
kono
parents:
diff changeset
1357 UNW_DEC_COPY_STATE(B1, label, arg);
kono
parents:
diff changeset
1358 else
kono
parents:
diff changeset
1359 UNW_DEC_LABEL_STATE(B1, label, arg);
kono
parents:
diff changeset
1360 return dp;
kono
parents:
diff changeset
1361 }
kono
parents:
diff changeset
1362
kono
parents:
diff changeset
1363 static unsigned char *
kono
parents:
diff changeset
1364 unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1365 {
kono
parents:
diff changeset
1366 unw_word t;
kono
parents:
diff changeset
1367
kono
parents:
diff changeset
1368 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1369 UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
kono
parents:
diff changeset
1370 return dp;
kono
parents:
diff changeset
1371 }
kono
parents:
diff changeset
1372
kono
parents:
diff changeset
1373 static unsigned char *
kono
parents:
diff changeset
1374 unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
kono
parents:
diff changeset
1375 {
kono
parents:
diff changeset
1376 unw_word t, ecount, label;
kono
parents:
diff changeset
1377
kono
parents:
diff changeset
1378 if ((code & 0x10) == 0)
kono
parents:
diff changeset
1379 {
kono
parents:
diff changeset
1380 t = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1381 ecount = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1382 UNW_DEC_EPILOGUE(B3, t, ecount, arg);
kono
parents:
diff changeset
1383 }
kono
parents:
diff changeset
1384 else if ((code & 0x07) == 0)
kono
parents:
diff changeset
1385 {
kono
parents:
diff changeset
1386 label = unw_decode_uleb128 (&dp);
kono
parents:
diff changeset
1387 if ((code & 0x08) != 0)
kono
parents:
diff changeset
1388 UNW_DEC_COPY_STATE(B4, label, arg);
kono
parents:
diff changeset
1389 else
kono
parents:
diff changeset
1390 UNW_DEC_LABEL_STATE(B4, label, arg);
kono
parents:
diff changeset
1391 }
kono
parents:
diff changeset
1392 else
kono
parents:
diff changeset
1393 switch (code & 0x7)
kono
parents:
diff changeset
1394 {
kono
parents:
diff changeset
1395 case 1: return unw_decode_x1 (dp, code, arg);
kono
parents:
diff changeset
1396 case 2: return unw_decode_x2 (dp, code, arg);
kono
parents:
diff changeset
1397 case 3: return unw_decode_x3 (dp, code, arg);
kono
parents:
diff changeset
1398 case 4: return unw_decode_x4 (dp, code, arg);
kono
parents:
diff changeset
1399 default: UNW_DEC_BAD_CODE(code); break;
kono
parents:
diff changeset
1400 }
kono
parents:
diff changeset
1401 return dp;
kono
parents:
diff changeset
1402 }
kono
parents:
diff changeset
1403
kono
parents:
diff changeset
1404 typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
kono
parents:
diff changeset
1405
kono
parents:
diff changeset
1406 static const unw_decoder unw_decode_table[2][8] =
kono
parents:
diff changeset
1407 {
kono
parents:
diff changeset
1408 /* prologue table: */
kono
parents:
diff changeset
1409 {
kono
parents:
diff changeset
1410 unw_decode_r1, /* 0 */
kono
parents:
diff changeset
1411 unw_decode_r1,
kono
parents:
diff changeset
1412 unw_decode_r2,
kono
parents:
diff changeset
1413 unw_decode_r3,
kono
parents:
diff changeset
1414 unw_decode_p1, /* 4 */
kono
parents:
diff changeset
1415 unw_decode_p2_p5,
kono
parents:
diff changeset
1416 unw_decode_p6,
kono
parents:
diff changeset
1417 unw_decode_p7_p10
kono
parents:
diff changeset
1418 },
kono
parents:
diff changeset
1419 {
kono
parents:
diff changeset
1420 unw_decode_r1, /* 0 */
kono
parents:
diff changeset
1421 unw_decode_r1,
kono
parents:
diff changeset
1422 unw_decode_r2,
kono
parents:
diff changeset
1423 unw_decode_r3,
kono
parents:
diff changeset
1424 unw_decode_b1, /* 4 */
kono
parents:
diff changeset
1425 unw_decode_b1,
kono
parents:
diff changeset
1426 unw_decode_b2,
kono
parents:
diff changeset
1427 unw_decode_b3_x4
kono
parents:
diff changeset
1428 }
kono
parents:
diff changeset
1429 };
kono
parents:
diff changeset
1430
kono
parents:
diff changeset
1431 /*
kono
parents:
diff changeset
1432 * Decode one descriptor and return address of next descriptor.
kono
parents:
diff changeset
1433 */
kono
parents:
diff changeset
1434 static inline unsigned char *
kono
parents:
diff changeset
1435 unw_decode (unsigned char *dp, int inside_body, void *arg)
kono
parents:
diff changeset
1436 {
kono
parents:
diff changeset
1437 unw_decoder decoder;
kono
parents:
diff changeset
1438 unsigned char code;
kono
parents:
diff changeset
1439
kono
parents:
diff changeset
1440 code = *dp++;
kono
parents:
diff changeset
1441 decoder = unw_decode_table[inside_body][code >> 5];
kono
parents:
diff changeset
1442 dp = (*decoder) (dp, code, arg);
kono
parents:
diff changeset
1443 return dp;
kono
parents:
diff changeset
1444 }
kono
parents:
diff changeset
1445
kono
parents:
diff changeset
1446
kono
parents:
diff changeset
1447 /* RSE helper functions. */
kono
parents:
diff changeset
1448
kono
parents:
diff changeset
1449 static inline unw_word
kono
parents:
diff changeset
1450 ia64_rse_slot_num (unw_word *addr)
kono
parents:
diff changeset
1451 {
kono
parents:
diff changeset
1452 return (((unw_word) addr) >> 3) & 0x3f;
kono
parents:
diff changeset
1453 }
kono
parents:
diff changeset
1454
kono
parents:
diff changeset
1455 /* Return TRUE if ADDR is the address of an RNAT slot. */
kono
parents:
diff changeset
1456 static inline unw_word
kono
parents:
diff changeset
1457 ia64_rse_is_rnat_slot (unw_word *addr)
kono
parents:
diff changeset
1458 {
kono
parents:
diff changeset
1459 return ia64_rse_slot_num (addr) == 0x3f;
kono
parents:
diff changeset
1460 }
kono
parents:
diff changeset
1461
kono
parents:
diff changeset
1462 /* Returns the address of the RNAT slot that covers the slot at
kono
parents:
diff changeset
1463 address SLOT_ADDR. */
kono
parents:
diff changeset
1464 static inline unw_word *
kono
parents:
diff changeset
1465 ia64_rse_rnat_addr (unw_word *slot_addr)
kono
parents:
diff changeset
1466 {
kono
parents:
diff changeset
1467 return (unw_word *) ((unw_word) slot_addr | (0x3f << 3));
kono
parents:
diff changeset
1468 }
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 /* Calculate the number of registers in the dirty partition starting at
kono
parents:
diff changeset
1471 BSPSTORE with a size of DIRTY bytes. This isn't simply DIRTY
kono
parents:
diff changeset
1472 divided by eight because the 64th slot is used to store ar.rnat. */
kono
parents:
diff changeset
1473 static inline unw_word
kono
parents:
diff changeset
1474 ia64_rse_num_regs (unw_word *bspstore, unw_word *bsp)
kono
parents:
diff changeset
1475 {
kono
parents:
diff changeset
1476 unw_word slots = (bsp - bspstore);
kono
parents:
diff changeset
1477
kono
parents:
diff changeset
1478 return slots - (ia64_rse_slot_num (bspstore) + slots)/0x40;
kono
parents:
diff changeset
1479 }
kono
parents:
diff changeset
1480
kono
parents:
diff changeset
1481 /* The inverse of the above: given bspstore and the number of
kono
parents:
diff changeset
1482 registers, calculate ar.bsp. */
kono
parents:
diff changeset
1483 static inline unw_word *
kono
parents:
diff changeset
1484 ia64_rse_skip_regs (unw_word *addr, int num_regs)
kono
parents:
diff changeset
1485 {
kono
parents:
diff changeset
1486 int delta = ia64_rse_slot_num (addr) + num_regs;
kono
parents:
diff changeset
1487
kono
parents:
diff changeset
1488 if (num_regs < 0)
kono
parents:
diff changeset
1489 delta -= 0x3e;
kono
parents:
diff changeset
1490 return addr + num_regs + delta/0x3f;
kono
parents:
diff changeset
1491 }
kono
parents:
diff changeset
1492
kono
parents:
diff changeset
1493
kono
parents:
diff changeset
1494 /* Copy register backing store from SRC to DST, LEN words
kono
parents:
diff changeset
1495 (which include both saved registers and nat collections).
kono
parents:
diff changeset
1496 DST_RNAT is a partial nat collection for DST. SRC and DST
kono
parents:
diff changeset
1497 don't have to be equal modulo 64 slots, so it cannot be
kono
parents:
diff changeset
1498 done with a simple memcpy as the nat collections will be
kono
parents:
diff changeset
1499 at different relative offsets and need to be combined together. */
kono
parents:
diff changeset
1500 static void
kono
parents:
diff changeset
1501 ia64_copy_rbs (struct _Unwind_Context *info, unw_word dst,
kono
parents:
diff changeset
1502 unw_word src, unw_word len, unw_word dst_rnat)
kono
parents:
diff changeset
1503 {
kono
parents:
diff changeset
1504 unw_word count;
kono
parents:
diff changeset
1505 unw_word src_rnat;
kono
parents:
diff changeset
1506 unw_word shift1, shift2;
kono
parents:
diff changeset
1507
kono
parents:
diff changeset
1508 len <<= 3;
kono
parents:
diff changeset
1509 dst_rnat &= (1ULL << ((dst >> 3) & 0x3f)) - 1;
kono
parents:
diff changeset
1510 src_rnat = src >= info->regstk_top
kono
parents:
diff changeset
1511 ? info->rnat : *(unw_word *) (src | 0x1f8);
kono
parents:
diff changeset
1512 src_rnat &= ~((1ULL << ((src >> 3) & 0x3f)) - 1);
kono
parents:
diff changeset
1513 /* Just to make sure. */
kono
parents:
diff changeset
1514 src_rnat &= ~(1ULL << 63);
kono
parents:
diff changeset
1515 shift1 = ((dst - src) >> 3) & 0x3f;
kono
parents:
diff changeset
1516 if ((dst & 0x1f8) < (src & 0x1f8))
kono
parents:
diff changeset
1517 shift1--;
kono
parents:
diff changeset
1518 shift2 = 0x3f - shift1;
kono
parents:
diff changeset
1519 if ((dst & 0x1f8) >= (src & 0x1f8))
kono
parents:
diff changeset
1520 {
kono
parents:
diff changeset
1521 count = ~dst & 0x1f8;
kono
parents:
diff changeset
1522 goto first;
kono
parents:
diff changeset
1523 }
kono
parents:
diff changeset
1524 count = ~src & 0x1f8;
kono
parents:
diff changeset
1525 goto second;
kono
parents:
diff changeset
1526 while (len > 0)
kono
parents:
diff changeset
1527 {
kono
parents:
diff changeset
1528 src_rnat = src >= info->regstk_top
kono
parents:
diff changeset
1529 ? info->rnat : *(unw_word *) (src | 0x1f8);
kono
parents:
diff changeset
1530 /* Just to make sure. */
kono
parents:
diff changeset
1531 src_rnat &= ~(1ULL << 63);
kono
parents:
diff changeset
1532 count = shift2 << 3;
kono
parents:
diff changeset
1533 first:
kono
parents:
diff changeset
1534 if (count > len)
kono
parents:
diff changeset
1535 count = len;
kono
parents:
diff changeset
1536 memcpy ((char *) dst, (char *) src, count);
kono
parents:
diff changeset
1537 dst += count;
kono
parents:
diff changeset
1538 src += count;
kono
parents:
diff changeset
1539 len -= count;
kono
parents:
diff changeset
1540 dst_rnat |= (src_rnat << shift1) & ~(1ULL << 63);
kono
parents:
diff changeset
1541 if (len <= 0)
kono
parents:
diff changeset
1542 break;
kono
parents:
diff changeset
1543 *(unw_word *) dst = dst_rnat;
kono
parents:
diff changeset
1544 dst += 8;
kono
parents:
diff changeset
1545 dst_rnat = 0;
kono
parents:
diff changeset
1546 count = shift1 << 3;
kono
parents:
diff changeset
1547 second:
kono
parents:
diff changeset
1548 if (count > len)
kono
parents:
diff changeset
1549 count = len;
kono
parents:
diff changeset
1550 memcpy ((char *) dst, (char *) src, count);
kono
parents:
diff changeset
1551 dst += count;
kono
parents:
diff changeset
1552 src += count + 8;
kono
parents:
diff changeset
1553 len -= count + 8;
kono
parents:
diff changeset
1554 dst_rnat |= (src_rnat >> shift2);
kono
parents:
diff changeset
1555 }
kono
parents:
diff changeset
1556 if ((dst & 0x1f8) == 0x1f8)
kono
parents:
diff changeset
1557 {
kono
parents:
diff changeset
1558 *(unw_word *) dst = dst_rnat;
kono
parents:
diff changeset
1559 dst += 8;
kono
parents:
diff changeset
1560 dst_rnat = 0;
kono
parents:
diff changeset
1561 }
kono
parents:
diff changeset
1562 /* Set info->regstk_top to lowest rbs address which will use
kono
parents:
diff changeset
1563 info->rnat collection. */
kono
parents:
diff changeset
1564 info->regstk_top = dst & ~0x1ffULL;
kono
parents:
diff changeset
1565 info->rnat = dst_rnat;
kono
parents:
diff changeset
1566 }
kono
parents:
diff changeset
1567
kono
parents:
diff changeset
1568 /* Unwind accessors. */
kono
parents:
diff changeset
1569
kono
parents:
diff changeset
1570 static void
kono
parents:
diff changeset
1571 unw_access_gr (struct _Unwind_Context *info, int regnum,
kono
parents:
diff changeset
1572 unw_word *val, char *nat, int write)
kono
parents:
diff changeset
1573 {
kono
parents:
diff changeset
1574 unw_word *addr, *nat_addr = 0, nat_mask = 0, dummy_nat;
kono
parents:
diff changeset
1575 struct unw_ireg *ireg;
kono
parents:
diff changeset
1576
kono
parents:
diff changeset
1577 if ((unsigned) regnum - 1 >= 127)
kono
parents:
diff changeset
1578 abort ();
kono
parents:
diff changeset
1579
kono
parents:
diff changeset
1580 if (regnum < 1)
kono
parents:
diff changeset
1581 {
kono
parents:
diff changeset
1582 nat_addr = addr = &dummy_nat;
kono
parents:
diff changeset
1583 dummy_nat = 0;
kono
parents:
diff changeset
1584 }
kono
parents:
diff changeset
1585 else if (regnum < 32)
kono
parents:
diff changeset
1586 {
kono
parents:
diff changeset
1587 /* Access a non-stacked register. */
kono
parents:
diff changeset
1588 ireg = &info->ireg[regnum - 2];
kono
parents:
diff changeset
1589 addr = ireg->loc;
kono
parents:
diff changeset
1590 if (addr)
kono
parents:
diff changeset
1591 {
kono
parents:
diff changeset
1592 nat_addr = addr + ireg->nat.off;
kono
parents:
diff changeset
1593 switch (ireg->nat.type)
kono
parents:
diff changeset
1594 {
kono
parents:
diff changeset
1595 case UNW_NAT_VAL:
kono
parents:
diff changeset
1596 /* Simulate getf.sig/setf.sig. */
kono
parents:
diff changeset
1597 if (write)
kono
parents:
diff changeset
1598 {
kono
parents:
diff changeset
1599 if (*nat)
kono
parents:
diff changeset
1600 {
kono
parents:
diff changeset
1601 /* Write NaTVal and be done with it. */
kono
parents:
diff changeset
1602 addr[0] = 0;
kono
parents:
diff changeset
1603 addr[1] = 0x1fffe;
kono
parents:
diff changeset
1604 return;
kono
parents:
diff changeset
1605 }
kono
parents:
diff changeset
1606 addr[1] = 0x1003e;
kono
parents:
diff changeset
1607 }
kono
parents:
diff changeset
1608 else if (addr[0] == 0 && addr[1] == 0x1ffe)
kono
parents:
diff changeset
1609 {
kono
parents:
diff changeset
1610 /* Return NaT and be done with it. */
kono
parents:
diff changeset
1611 *val = 0;
kono
parents:
diff changeset
1612 *nat = 1;
kono
parents:
diff changeset
1613 return;
kono
parents:
diff changeset
1614 }
kono
parents:
diff changeset
1615 /* FALLTHRU */
kono
parents:
diff changeset
1616
kono
parents:
diff changeset
1617 case UNW_NAT_NONE:
kono
parents:
diff changeset
1618 dummy_nat = 0;
kono
parents:
diff changeset
1619 nat_addr = &dummy_nat;
kono
parents:
diff changeset
1620 break;
kono
parents:
diff changeset
1621
kono
parents:
diff changeset
1622 case UNW_NAT_MEMSTK:
kono
parents:
diff changeset
1623 nat_mask = 1UL << ((unw_word) addr & 0x1f8)/8;
kono
parents:
diff changeset
1624 break;
kono
parents:
diff changeset
1625
kono
parents:
diff changeset
1626 case UNW_NAT_REGSTK:
kono
parents:
diff changeset
1627 if ((unw_word) addr >= info->regstk_top)
kono
parents:
diff changeset
1628 nat_addr = &info->rnat;
kono
parents:
diff changeset
1629 else
kono
parents:
diff changeset
1630 nat_addr = ia64_rse_rnat_addr (addr);
kono
parents:
diff changeset
1631 nat_mask = 1ULL << ia64_rse_slot_num (addr);
kono
parents:
diff changeset
1632 break;
kono
parents:
diff changeset
1633 }
kono
parents:
diff changeset
1634 }
kono
parents:
diff changeset
1635 }
kono
parents:
diff changeset
1636 else
kono
parents:
diff changeset
1637 {
kono
parents:
diff changeset
1638 /* Access a stacked register. */
kono
parents:
diff changeset
1639 addr = ia64_rse_skip_regs ((unw_word *) info->bsp, regnum - 32);
kono
parents:
diff changeset
1640 if ((unw_word) addr >= info->regstk_top)
kono
parents:
diff changeset
1641 nat_addr = &info->rnat;
kono
parents:
diff changeset
1642 else
kono
parents:
diff changeset
1643 nat_addr = ia64_rse_rnat_addr (addr);
kono
parents:
diff changeset
1644 nat_mask = 1UL << ia64_rse_slot_num (addr);
kono
parents:
diff changeset
1645 }
kono
parents:
diff changeset
1646
kono
parents:
diff changeset
1647 if (write)
kono
parents:
diff changeset
1648 {
kono
parents:
diff changeset
1649 *addr = *val;
kono
parents:
diff changeset
1650 if (*nat)
kono
parents:
diff changeset
1651 *nat_addr |= nat_mask;
kono
parents:
diff changeset
1652 else
kono
parents:
diff changeset
1653 *nat_addr &= ~nat_mask;
kono
parents:
diff changeset
1654 }
kono
parents:
diff changeset
1655 else
kono
parents:
diff changeset
1656 {
kono
parents:
diff changeset
1657 *val = *addr;
kono
parents:
diff changeset
1658 *nat = (*nat_addr & nat_mask) != 0;
kono
parents:
diff changeset
1659 }
kono
parents:
diff changeset
1660 }
kono
parents:
diff changeset
1661
kono
parents:
diff changeset
1662 /* Get the value of register REG as saved in CONTEXT. */
kono
parents:
diff changeset
1663
kono
parents:
diff changeset
1664 _Unwind_Word
kono
parents:
diff changeset
1665 _Unwind_GetGR (struct _Unwind_Context *context, int index)
kono
parents:
diff changeset
1666 {
kono
parents:
diff changeset
1667 _Unwind_Word ret;
kono
parents:
diff changeset
1668 char nat;
kono
parents:
diff changeset
1669
kono
parents:
diff changeset
1670 if (index == 1)
kono
parents:
diff changeset
1671 return context->gp;
kono
parents:
diff changeset
1672 else if (index >= 15 && index <= 18)
kono
parents:
diff changeset
1673 return context->eh_data[index - 15];
kono
parents:
diff changeset
1674 else
kono
parents:
diff changeset
1675 unw_access_gr (context, index, &ret, &nat, 0);
kono
parents:
diff changeset
1676
kono
parents:
diff changeset
1677 return ret;
kono
parents:
diff changeset
1678 }
kono
parents:
diff changeset
1679
kono
parents:
diff changeset
1680 /* Overwrite the saved value for register REG in CONTEXT with VAL. */
kono
parents:
diff changeset
1681
kono
parents:
diff changeset
1682 void
kono
parents:
diff changeset
1683 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
kono
parents:
diff changeset
1684 {
kono
parents:
diff changeset
1685 char nat = 0;
kono
parents:
diff changeset
1686
kono
parents:
diff changeset
1687 if (index == 1)
kono
parents:
diff changeset
1688 context->gp = val;
kono
parents:
diff changeset
1689 else if (index >= 15 && index <= 18)
kono
parents:
diff changeset
1690 context->eh_data[index - 15] = val;
kono
parents:
diff changeset
1691 else
kono
parents:
diff changeset
1692 unw_access_gr (context, index, &val, &nat, 1);
kono
parents:
diff changeset
1693 }
kono
parents:
diff changeset
1694
kono
parents:
diff changeset
1695 /* Retrieve the return address for CONTEXT. */
kono
parents:
diff changeset
1696
kono
parents:
diff changeset
1697 inline _Unwind_Ptr
kono
parents:
diff changeset
1698 _Unwind_GetIP (struct _Unwind_Context *context)
kono
parents:
diff changeset
1699 {
kono
parents:
diff changeset
1700 return context->rp;
kono
parents:
diff changeset
1701 }
kono
parents:
diff changeset
1702
kono
parents:
diff changeset
1703 inline _Unwind_Ptr
kono
parents:
diff changeset
1704 _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
kono
parents:
diff changeset
1705 {
kono
parents:
diff changeset
1706 *ip_before_insn = 0;
kono
parents:
diff changeset
1707 return context->rp;
kono
parents:
diff changeset
1708 }
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 /* Overwrite the return address for CONTEXT with VAL. */
kono
parents:
diff changeset
1711
kono
parents:
diff changeset
1712 inline void
kono
parents:
diff changeset
1713 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
kono
parents:
diff changeset
1714 {
kono
parents:
diff changeset
1715 context->rp = val;
kono
parents:
diff changeset
1716 }
kono
parents:
diff changeset
1717
kono
parents:
diff changeset
1718 void *
kono
parents:
diff changeset
1719 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
kono
parents:
diff changeset
1720 {
kono
parents:
diff changeset
1721 return context->lsda;
kono
parents:
diff changeset
1722 }
kono
parents:
diff changeset
1723
kono
parents:
diff changeset
1724 _Unwind_Ptr
kono
parents:
diff changeset
1725 _Unwind_GetRegionStart (struct _Unwind_Context *context)
kono
parents:
diff changeset
1726 {
kono
parents:
diff changeset
1727 return context->region_start;
kono
parents:
diff changeset
1728 }
kono
parents:
diff changeset
1729
kono
parents:
diff changeset
1730 void *
kono
parents:
diff changeset
1731 _Unwind_FindEnclosingFunction (void *pc)
kono
parents:
diff changeset
1732 {
kono
parents:
diff changeset
1733 struct unw_table_entry *entp, ent;
kono
parents:
diff changeset
1734 unw_word segment_base, gp;
kono
parents:
diff changeset
1735
kono
parents:
diff changeset
1736 entp = _Unwind_FindTableEntry (pc, &segment_base, &gp, &ent);
kono
parents:
diff changeset
1737 if (entp == NULL)
kono
parents:
diff changeset
1738 return NULL;
kono
parents:
diff changeset
1739 else
kono
parents:
diff changeset
1740 return (void *)(segment_base + entp->start_offset);
kono
parents:
diff changeset
1741 }
kono
parents:
diff changeset
1742
kono
parents:
diff changeset
1743 /* Get the value of the CFA as saved in CONTEXT. In GCC/Dwarf2 parlance,
kono
parents:
diff changeset
1744 the CFA is the value of the stack pointer on entry; In IA-64 unwind
kono
parents:
diff changeset
1745 parlance, this is the PSP. */
kono
parents:
diff changeset
1746
kono
parents:
diff changeset
1747 _Unwind_Word
kono
parents:
diff changeset
1748 _Unwind_GetCFA (struct _Unwind_Context *context)
kono
parents:
diff changeset
1749 {
kono
parents:
diff changeset
1750 return (_Unwind_Ptr) context->psp;
kono
parents:
diff changeset
1751 }
kono
parents:
diff changeset
1752
kono
parents:
diff changeset
1753 /* Get the value of the Backing Store Pointer as saved in CONTEXT. */
kono
parents:
diff changeset
1754
kono
parents:
diff changeset
1755 _Unwind_Word
kono
parents:
diff changeset
1756 _Unwind_GetBSP (struct _Unwind_Context *context)
kono
parents:
diff changeset
1757 {
kono
parents:
diff changeset
1758 return (_Unwind_Ptr) context->bsp;
kono
parents:
diff changeset
1759 }
kono
parents:
diff changeset
1760
kono
parents:
diff changeset
1761 #include "md-unwind-support.h"
kono
parents:
diff changeset
1762
kono
parents:
diff changeset
1763 /* By default, assume personality routine interface compatibility with
kono
parents:
diff changeset
1764 our expectations. */
kono
parents:
diff changeset
1765 #ifndef MD_UNW_COMPATIBLE_PERSONALITY_P
kono
parents:
diff changeset
1766 #define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) 1
kono
parents:
diff changeset
1767 #endif
kono
parents:
diff changeset
1768
kono
parents:
diff changeset
1769
kono
parents:
diff changeset
1770 static _Unwind_Reason_Code
kono
parents:
diff changeset
1771 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
kono
parents:
diff changeset
1772 {
kono
parents:
diff changeset
1773 struct unw_table_entry *entp, ent;
kono
parents:
diff changeset
1774 unw_word *unw, header, length;
kono
parents:
diff changeset
1775 unsigned char *insn, *insn_end;
kono
parents:
diff changeset
1776 unw_word segment_base;
kono
parents:
diff changeset
1777 struct unw_reg_info *r;
kono
parents:
diff changeset
1778
kono
parents:
diff changeset
1779 memset (fs, 0, sizeof (*fs));
kono
parents:
diff changeset
1780 for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
kono
parents:
diff changeset
1781 r->when = UNW_WHEN_NEVER;
kono
parents:
diff changeset
1782 context->lsda = 0;
kono
parents:
diff changeset
1783
kono
parents:
diff changeset
1784 entp = _Unwind_FindTableEntry ((void *) context->rp,
kono
parents:
diff changeset
1785 &segment_base, &context->gp, &ent);
kono
parents:
diff changeset
1786 if (entp == NULL)
kono
parents:
diff changeset
1787 {
kono
parents:
diff changeset
1788 /* Couldn't find unwind info for this function. Try an
kono
parents:
diff changeset
1789 os-specific fallback mechanism. This will necessarily
kono
parents:
diff changeset
1790 not provide a personality routine or LSDA. */
kono
parents:
diff changeset
1791 #ifdef MD_FALLBACK_FRAME_STATE_FOR
kono
parents:
diff changeset
1792 if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)
kono
parents:
diff changeset
1793 return _URC_NO_REASON;
kono
parents:
diff changeset
1794 #endif
kono
parents:
diff changeset
1795
kono
parents:
diff changeset
1796 /* [SCRA 11.4.1] A leaf function with no memory stack, no exception
kono
parents:
diff changeset
1797 handlers, and which keeps the return value in B0 does not need
kono
parents:
diff changeset
1798 an unwind table entry.
kono
parents:
diff changeset
1799
kono
parents:
diff changeset
1800 This can only happen in the frame after unwinding through a signal
kono
parents:
diff changeset
1801 handler. Avoid infinite looping by requiring that B0 != RP.
kono
parents:
diff changeset
1802 RP == 0 terminates the chain. */
kono
parents:
diff changeset
1803 if (context->br_loc[0]
kono
parents:
diff changeset
1804 && *context->br_loc[0] != context->rp
kono
parents:
diff changeset
1805 && context->rp != 0)
kono
parents:
diff changeset
1806 goto skip_unwind_info;
kono
parents:
diff changeset
1807
kono
parents:
diff changeset
1808 return _URC_END_OF_STACK;
kono
parents:
diff changeset
1809 }
kono
parents:
diff changeset
1810
kono
parents:
diff changeset
1811 context->region_start = entp->start_offset + segment_base;
kono
parents:
diff changeset
1812 fs->when_target = ((context->rp & -16) - context->region_start) / 16 * 3
kono
parents:
diff changeset
1813 + (context->rp & 15);
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 unw = (unw_word *) (entp->info_offset + segment_base);
kono
parents:
diff changeset
1816 header = *unw;
kono
parents:
diff changeset
1817 length = UNW_LENGTH (header);
kono
parents:
diff changeset
1818
kono
parents:
diff changeset
1819 /* Some operating systems use the personality routine slot in way not
kono
parents:
diff changeset
1820 compatible with what we expect. For instance, OpenVMS uses this slot to
kono
parents:
diff changeset
1821 designate "condition handlers" with very different arguments than what we
kono
parents:
diff changeset
1822 would be providing. Such cases are typically identified from OS specific
kono
parents:
diff changeset
1823 bits in the unwind information block header, and checked by the target
kono
parents:
diff changeset
1824 MD_UNW_COMPATIBLE_PERSONALITY_P macro.
kono
parents:
diff changeset
1825
kono
parents:
diff changeset
1826 We just pretend there is no personality from our standpoint in such
kono
parents:
diff changeset
1827 situations, and expect GCC not to set the identifying bits itself so that
kono
parents:
diff changeset
1828 compatible personalities for GCC compiled code are called.
kono
parents:
diff changeset
1829
kono
parents:
diff changeset
1830 Of course, this raises the question of what combinations of native/GCC
kono
parents:
diff changeset
1831 calls can be expected to behave properly exception handling-wise. We are
kono
parents:
diff changeset
1832 not to provide a magic answer here, merely to prevent crashes assuming
kono
parents:
diff changeset
1833 users know what they are doing.
kono
parents:
diff changeset
1834
kono
parents:
diff changeset
1835 ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK as well. */
kono
parents:
diff changeset
1836
kono
parents:
diff changeset
1837 if (MD_UNW_COMPATIBLE_PERSONALITY_P (header)
kono
parents:
diff changeset
1838 && (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header)))
kono
parents:
diff changeset
1839 {
kono
parents:
diff changeset
1840 fs->personality =
kono
parents:
diff changeset
1841 *(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp);
kono
parents:
diff changeset
1842 context->lsda = unw + length + 2;
kono
parents:
diff changeset
1843 }
kono
parents:
diff changeset
1844
kono
parents:
diff changeset
1845 insn = (unsigned char *) (unw + 1);
kono
parents:
diff changeset
1846 insn_end = (unsigned char *) (unw + 1 + length);
kono
parents:
diff changeset
1847 while (!fs->done && insn < insn_end)
kono
parents:
diff changeset
1848 insn = unw_decode (insn, fs->in_body, fs);
kono
parents:
diff changeset
1849
kono
parents:
diff changeset
1850 free_label_states (fs->labeled_states);
kono
parents:
diff changeset
1851 free_state_stack (&fs->curr);
kono
parents:
diff changeset
1852
kono
parents:
diff changeset
1853 #ifdef ENABLE_MALLOC_CHECKING
kono
parents:
diff changeset
1854 if (reg_state_alloced || labeled_state_alloced)
kono
parents:
diff changeset
1855 abort ();
kono
parents:
diff changeset
1856 #endif
kono
parents:
diff changeset
1857
kono
parents:
diff changeset
1858 /* If we're in the epilogue, sp has been restored and all values
kono
parents:
diff changeset
1859 on the memory stack below psp also have been restored. */
kono
parents:
diff changeset
1860 if (fs->when_target > fs->epilogue_start)
kono
parents:
diff changeset
1861 {
kono
parents:
diff changeset
1862 struct unw_reg_info *r;
kono
parents:
diff changeset
1863
kono
parents:
diff changeset
1864 fs->curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
kono
parents:
diff changeset
1865 fs->curr.reg[UNW_REG_PSP].val = 0;
kono
parents:
diff changeset
1866 for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
kono
parents:
diff changeset
1867 if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
kono
parents:
diff changeset
1868 || r->where == UNW_WHERE_SPREL)
kono
parents:
diff changeset
1869 r->where = UNW_WHERE_NONE;
kono
parents:
diff changeset
1870 }
kono
parents:
diff changeset
1871
kono
parents:
diff changeset
1872 skip_unwind_info:
kono
parents:
diff changeset
1873 /* If RP didn't get saved, generate entry for the return link register. */
kono
parents:
diff changeset
1874 if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
kono
parents:
diff changeset
1875 {
kono
parents:
diff changeset
1876 fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
kono
parents:
diff changeset
1877 fs->curr.reg[UNW_REG_RP].when = -1;
kono
parents:
diff changeset
1878 fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg;
kono
parents:
diff changeset
1879 }
kono
parents:
diff changeset
1880
kono
parents:
diff changeset
1881 /* There is a subtlety for the frame after unwinding through a signal
kono
parents:
diff changeset
1882 handler: should we restore the cfm as usual or the pfs? We can't
kono
parents:
diff changeset
1883 restore both because we use br.ret to resume execution of user code.
kono
parents:
diff changeset
1884 For other frames the procedure is by definition non-leaf so the pfs
kono
parents:
diff changeset
1885 is saved and restored and thus effectively dead in the body; only
kono
parents:
diff changeset
1886 the cfm need therefore be restored.
kono
parents:
diff changeset
1887
kono
parents:
diff changeset
1888 Here we have 2 cases:
kono
parents:
diff changeset
1889 - either the pfs is saved and restored and thus effectively dead
kono
parents:
diff changeset
1890 like in regular frames; then we do nothing special and restore
kono
parents:
diff changeset
1891 the cfm.
kono
parents:
diff changeset
1892 - or the pfs is not saved and thus live; but in that case the
kono
parents:
diff changeset
1893 procedure is necessarily leaf so the cfm is effectively dead
kono
parents:
diff changeset
1894 and we restore the pfs. */
kono
parents:
diff changeset
1895 if (context->signal_pfs_loc)
kono
parents:
diff changeset
1896 {
kono
parents:
diff changeset
1897 if (fs->curr.reg[UNW_REG_PFS].when >= fs->when_target)
kono
parents:
diff changeset
1898 context->pfs_loc = context->signal_pfs_loc;
kono
parents:
diff changeset
1899 context->signal_pfs_loc = NULL;
kono
parents:
diff changeset
1900 }
kono
parents:
diff changeset
1901
kono
parents:
diff changeset
1902 return _URC_NO_REASON;
kono
parents:
diff changeset
1903 }
kono
parents:
diff changeset
1904
kono
parents:
diff changeset
1905 static void
kono
parents:
diff changeset
1906 uw_update_reg_address (struct _Unwind_Context *context,
kono
parents:
diff changeset
1907 _Unwind_FrameState *fs,
kono
parents:
diff changeset
1908 enum unw_register_index regno)
kono
parents:
diff changeset
1909 {
kono
parents:
diff changeset
1910 struct unw_reg_info *r = fs->curr.reg + regno;
kono
parents:
diff changeset
1911 void *addr;
kono
parents:
diff changeset
1912 unw_word rval;
kono
parents:
diff changeset
1913
kono
parents:
diff changeset
1914 if (r->where == UNW_WHERE_NONE || r->when >= fs->when_target)
kono
parents:
diff changeset
1915 return;
kono
parents:
diff changeset
1916
kono
parents:
diff changeset
1917 rval = r->val;
kono
parents:
diff changeset
1918 switch (r->where)
kono
parents:
diff changeset
1919 {
kono
parents:
diff changeset
1920 case UNW_WHERE_GR:
kono
parents:
diff changeset
1921 if (rval >= 32)
kono
parents:
diff changeset
1922 addr = ia64_rse_skip_regs ((unw_word *) context->bsp, rval - 32);
kono
parents:
diff changeset
1923 else if (rval >= 2)
kono
parents:
diff changeset
1924 addr = context->ireg[rval - 2].loc;
kono
parents:
diff changeset
1925 else if (rval == 0)
kono
parents:
diff changeset
1926 {
kono
parents:
diff changeset
1927 static const unw_word dummy;
kono
parents:
diff changeset
1928 addr = (void *) &dummy;
kono
parents:
diff changeset
1929 }
kono
parents:
diff changeset
1930 else
kono
parents:
diff changeset
1931 abort ();
kono
parents:
diff changeset
1932 break;
kono
parents:
diff changeset
1933
kono
parents:
diff changeset
1934 case UNW_WHERE_FR:
kono
parents:
diff changeset
1935 if (rval >= 2 && rval < 32)
kono
parents:
diff changeset
1936 addr = context->fr_loc[rval - 2];
kono
parents:
diff changeset
1937 else
kono
parents:
diff changeset
1938 abort ();
kono
parents:
diff changeset
1939 break;
kono
parents:
diff changeset
1940
kono
parents:
diff changeset
1941 case UNW_WHERE_BR:
kono
parents:
diff changeset
1942 /* Note that while RVAL can only be 1-5 from normal descriptors,
kono
parents:
diff changeset
1943 we can want to look at B0, B6 and B7 due to having manually unwound a
kono
parents:
diff changeset
1944 signal frame. */
kono
parents:
diff changeset
1945 if (rval < 8)
kono
parents:
diff changeset
1946 addr = context->br_loc[rval];
kono
parents:
diff changeset
1947 else
kono
parents:
diff changeset
1948 abort ();
kono
parents:
diff changeset
1949 break;
kono
parents:
diff changeset
1950
kono
parents:
diff changeset
1951 case UNW_WHERE_SPREL:
kono
parents:
diff changeset
1952 addr = (void *)(context->sp + rval);
kono
parents:
diff changeset
1953 break;
kono
parents:
diff changeset
1954
kono
parents:
diff changeset
1955 case UNW_WHERE_PSPREL:
kono
parents:
diff changeset
1956 addr = (void *)(context->psp + rval);
kono
parents:
diff changeset
1957 break;
kono
parents:
diff changeset
1958
kono
parents:
diff changeset
1959 default:
kono
parents:
diff changeset
1960 abort ();
kono
parents:
diff changeset
1961 }
kono
parents:
diff changeset
1962
kono
parents:
diff changeset
1963 switch (regno)
kono
parents:
diff changeset
1964 {
kono
parents:
diff changeset
1965 case UNW_REG_R2 ... UNW_REG_R31:
kono
parents:
diff changeset
1966 context->ireg[regno - UNW_REG_R2].loc = addr;
kono
parents:
diff changeset
1967 switch (r->where)
kono
parents:
diff changeset
1968 {
kono
parents:
diff changeset
1969 case UNW_WHERE_GR:
kono
parents:
diff changeset
1970 if (rval >= 32)
kono
parents:
diff changeset
1971 {
kono
parents:
diff changeset
1972 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
kono
parents:
diff changeset
1973 context->ireg[regno - UNW_REG_R2].nat.off
kono
parents:
diff changeset
1974 = context->pri_unat_loc - (unw_word *) addr;
kono
parents:
diff changeset
1975 }
kono
parents:
diff changeset
1976 else if (rval >= 2)
kono
parents:
diff changeset
1977 {
kono
parents:
diff changeset
1978 context->ireg[regno - UNW_REG_R2].nat
kono
parents:
diff changeset
1979 = context->ireg[rval - 2].nat;
kono
parents:
diff changeset
1980 }
kono
parents:
diff changeset
1981 else if (rval == 0)
kono
parents:
diff changeset
1982 {
kono
parents:
diff changeset
1983 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
kono
parents:
diff changeset
1984 context->ireg[regno - UNW_REG_R2].nat.off = 0;
kono
parents:
diff changeset
1985 }
kono
parents:
diff changeset
1986 else
kono
parents:
diff changeset
1987 abort ();
kono
parents:
diff changeset
1988 break;
kono
parents:
diff changeset
1989
kono
parents:
diff changeset
1990 case UNW_WHERE_FR:
kono
parents:
diff changeset
1991 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_VAL;
kono
parents:
diff changeset
1992 context->ireg[regno - UNW_REG_R2].nat.off = 0;
kono
parents:
diff changeset
1993 break;
kono
parents:
diff changeset
1994
kono
parents:
diff changeset
1995 case UNW_WHERE_BR:
kono
parents:
diff changeset
1996 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
kono
parents:
diff changeset
1997 context->ireg[regno - UNW_REG_R2].nat.off = 0;
kono
parents:
diff changeset
1998 break;
kono
parents:
diff changeset
1999
kono
parents:
diff changeset
2000 case UNW_WHERE_PSPREL:
kono
parents:
diff changeset
2001 case UNW_WHERE_SPREL:
kono
parents:
diff changeset
2002 context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
kono
parents:
diff changeset
2003 context->ireg[regno - UNW_REG_R2].nat.off
kono
parents:
diff changeset
2004 = context->pri_unat_loc - (unw_word *) addr;
kono
parents:
diff changeset
2005 break;
kono
parents:
diff changeset
2006
kono
parents:
diff changeset
2007 default:
kono
parents:
diff changeset
2008 abort ();
kono
parents:
diff changeset
2009 }
kono
parents:
diff changeset
2010 break;
kono
parents:
diff changeset
2011
kono
parents:
diff changeset
2012 case UNW_REG_F2 ... UNW_REG_F31:
kono
parents:
diff changeset
2013 context->fr_loc[regno - UNW_REG_F2] = addr;
kono
parents:
diff changeset
2014 break;
kono
parents:
diff changeset
2015
kono
parents:
diff changeset
2016 case UNW_REG_B1 ... UNW_REG_B5:
kono
parents:
diff changeset
2017 context->br_loc[regno - UNW_REG_B0] = addr;
kono
parents:
diff changeset
2018 break;
kono
parents:
diff changeset
2019
kono
parents:
diff changeset
2020 case UNW_REG_BSP:
kono
parents:
diff changeset
2021 context->bsp_loc = addr;
kono
parents:
diff changeset
2022 break;
kono
parents:
diff changeset
2023 case UNW_REG_BSPSTORE:
kono
parents:
diff changeset
2024 context->bspstore_loc = addr;
kono
parents:
diff changeset
2025 break;
kono
parents:
diff changeset
2026 case UNW_REG_PFS:
kono
parents:
diff changeset
2027 context->pfs_loc = addr;
kono
parents:
diff changeset
2028 break;
kono
parents:
diff changeset
2029 case UNW_REG_RP:
kono
parents:
diff changeset
2030 context->rp = *(unw_word *)addr;
kono
parents:
diff changeset
2031 break;
kono
parents:
diff changeset
2032 case UNW_REG_UNAT:
kono
parents:
diff changeset
2033 context->unat_loc = addr;
kono
parents:
diff changeset
2034 break;
kono
parents:
diff changeset
2035 case UNW_REG_PR:
kono
parents:
diff changeset
2036 context->pr = *(unw_word *) addr;
kono
parents:
diff changeset
2037 break;
kono
parents:
diff changeset
2038 case UNW_REG_LC:
kono
parents:
diff changeset
2039 context->lc_loc = addr;
kono
parents:
diff changeset
2040 break;
kono
parents:
diff changeset
2041 case UNW_REG_FPSR:
kono
parents:
diff changeset
2042 context->fpsr_loc = addr;
kono
parents:
diff changeset
2043 break;
kono
parents:
diff changeset
2044
kono
parents:
diff changeset
2045 case UNW_REG_PSP:
kono
parents:
diff changeset
2046 context->psp = *(unw_word *)addr;
kono
parents:
diff changeset
2047 break;
kono
parents:
diff changeset
2048
kono
parents:
diff changeset
2049 default:
kono
parents:
diff changeset
2050 abort ();
kono
parents:
diff changeset
2051 }
kono
parents:
diff changeset
2052 }
kono
parents:
diff changeset
2053
kono
parents:
diff changeset
2054 static void
kono
parents:
diff changeset
2055 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
kono
parents:
diff changeset
2056 {
kono
parents:
diff changeset
2057 int i;
kono
parents:
diff changeset
2058
kono
parents:
diff changeset
2059 #ifdef MD_HANDLE_UNWABI
kono
parents:
diff changeset
2060 MD_HANDLE_UNWABI (context, fs);
kono
parents:
diff changeset
2061 #endif
kono
parents:
diff changeset
2062
kono
parents:
diff changeset
2063 context->sp = context->psp;
kono
parents:
diff changeset
2064
kono
parents:
diff changeset
2065 /* First, set PSP. Subsequent instructions may depend on this value. */
kono
parents:
diff changeset
2066 if (fs->when_target > fs->curr.reg[UNW_REG_PSP].when)
kono
parents:
diff changeset
2067 {
kono
parents:
diff changeset
2068 if (fs->curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
kono
parents:
diff changeset
2069 context->psp = context->psp + fs->curr.reg[UNW_REG_PSP].val;
kono
parents:
diff changeset
2070 else
kono
parents:
diff changeset
2071 uw_update_reg_address (context, fs, UNW_REG_PSP);
kono
parents:
diff changeset
2072 }
kono
parents:
diff changeset
2073
kono
parents:
diff changeset
2074 /* Determine the location of the primary UNaT. */
kono
parents:
diff changeset
2075 {
kono
parents:
diff changeset
2076 int i;
kono
parents:
diff changeset
2077 if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
kono
parents:
diff changeset
2078 i = UNW_REG_PRI_UNAT_MEM;
kono
parents:
diff changeset
2079 else if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when)
kono
parents:
diff changeset
2080 i = UNW_REG_PRI_UNAT_GR;
kono
parents:
diff changeset
2081 else if (fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when
kono
parents:
diff changeset
2082 > fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
kono
parents:
diff changeset
2083 i = UNW_REG_PRI_UNAT_MEM;
kono
parents:
diff changeset
2084 else
kono
parents:
diff changeset
2085 i = UNW_REG_PRI_UNAT_GR;
kono
parents:
diff changeset
2086 uw_update_reg_address (context, fs, i);
kono
parents:
diff changeset
2087 }
kono
parents:
diff changeset
2088
kono
parents:
diff changeset
2089 /* Compute the addresses of all registers saved in this frame. */
kono
parents:
diff changeset
2090 for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
kono
parents:
diff changeset
2091 uw_update_reg_address (context, fs, i);
kono
parents:
diff changeset
2092
kono
parents:
diff changeset
2093 /* Unwind BSP for the local registers allocated this frame. */
kono
parents:
diff changeset
2094 /* ??? What to do with stored BSP or BSPSTORE registers. */
kono
parents:
diff changeset
2095 /* We assert that we are either at a call site, or we have
kono
parents:
diff changeset
2096 just unwound through a signal frame. In either case
kono
parents:
diff changeset
2097 pfs_loc is valid. */
kono
parents:
diff changeset
2098 if (!(fs -> no_reg_stack_frame))
kono
parents:
diff changeset
2099 {
kono
parents:
diff changeset
2100 unw_word pfs = *context->pfs_loc;
kono
parents:
diff changeset
2101 unw_word sol = (pfs >> 7) & 0x7f;
kono
parents:
diff changeset
2102 context->bsp = (unw_word)
kono
parents:
diff changeset
2103 ia64_rse_skip_regs ((unw_word *) context->bsp, -sol);
kono
parents:
diff changeset
2104 }
kono
parents:
diff changeset
2105 }
kono
parents:
diff changeset
2106
kono
parents:
diff changeset
2107 static void
kono
parents:
diff changeset
2108 uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
kono
parents:
diff changeset
2109 {
kono
parents:
diff changeset
2110 uw_update_context (context, fs);
kono
parents:
diff changeset
2111 }
kono
parents:
diff changeset
2112
kono
parents:
diff changeset
2113 /* Fill in CONTEXT for top-of-stack. The only valid registers at this
kono
parents:
diff changeset
2114 level will be the return address and the CFA. Note that CFA = SP+16. */
kono
parents:
diff changeset
2115
kono
parents:
diff changeset
2116 #define uw_init_context(CONTEXT) \
kono
parents:
diff changeset
2117 do { \
kono
parents:
diff changeset
2118 /* ??? There is a whole lot o code in uw_install_context that \
kono
parents:
diff changeset
2119 tries to avoid spilling the entire machine state here. We \
kono
parents:
diff changeset
2120 should try to make that work again. */ \
kono
parents:
diff changeset
2121 __builtin_unwind_init(); \
kono
parents:
diff changeset
2122 uw_init_context_1 (CONTEXT, __builtin_ia64_bsp ()); \
kono
parents:
diff changeset
2123 } while (0)
kono
parents:
diff changeset
2124
kono
parents:
diff changeset
2125 static void __attribute__((noinline))
kono
parents:
diff changeset
2126 uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
kono
parents:
diff changeset
2127 {
kono
parents:
diff changeset
2128 void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
kono
parents:
diff changeset
2129 /* Set psp to the caller's stack pointer. */
kono
parents:
diff changeset
2130 void *psp = __builtin_dwarf_cfa () - 16;
kono
parents:
diff changeset
2131 _Unwind_FrameState fs;
kono
parents:
diff changeset
2132 unw_word rnat, tmp1, tmp2;
kono
parents:
diff changeset
2133
kono
parents:
diff changeset
2134 /* Flush the register stack to memory so that we can access it.
kono
parents:
diff changeset
2135 Get rse nat collection for the last incomplete rbs chunk of
kono
parents:
diff changeset
2136 registers at the same time. For this RSE needs to be turned
kono
parents:
diff changeset
2137 into the mandatory only mode. */
kono
parents:
diff changeset
2138 asm ("mov.m %1 = ar.rsc;;\n\t"
kono
parents:
diff changeset
2139 "and %2 = 0x1c, %1;;\n\t"
kono
parents:
diff changeset
2140 "mov.m ar.rsc = %2;;\n\t"
kono
parents:
diff changeset
2141 "flushrs;;\n\t"
kono
parents:
diff changeset
2142 "mov.m %0 = ar.rnat;;\n\t"
kono
parents:
diff changeset
2143 "mov.m ar.rsc = %1\n\t"
kono
parents:
diff changeset
2144 : "=r" (rnat), "=r" (tmp1), "=r" (tmp2));
kono
parents:
diff changeset
2145
kono
parents:
diff changeset
2146 memset (context, 0, sizeof (struct _Unwind_Context));
kono
parents:
diff changeset
2147 context->bsp = (unw_word) bsp;
kono
parents:
diff changeset
2148 /* Set context->regstk_top to lowest rbs address which will use
kono
parents:
diff changeset
2149 context->rnat collection. */
kono
parents:
diff changeset
2150 context->regstk_top = context->bsp & ~0x1ffULL;
kono
parents:
diff changeset
2151 context->rnat = rnat;
kono
parents:
diff changeset
2152 context->psp = (unw_word) psp;
kono
parents:
diff changeset
2153 context->rp = (unw_word) rp;
kono
parents:
diff changeset
2154 asm ("mov %0 = sp" : "=r" (context->sp));
kono
parents:
diff changeset
2155 asm ("mov %0 = pr" : "=r" (context->pr));
kono
parents:
diff changeset
2156 context->pri_unat_loc = &context->initial_unat; /* ??? */
kono
parents:
diff changeset
2157
kono
parents:
diff changeset
2158 if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
kono
parents:
diff changeset
2159 abort ();
kono
parents:
diff changeset
2160
kono
parents:
diff changeset
2161 uw_update_context (context, &fs);
kono
parents:
diff changeset
2162 }
kono
parents:
diff changeset
2163
kono
parents:
diff changeset
2164 /* Install (i.e. longjmp to) the contents of TARGET. */
kono
parents:
diff changeset
2165
kono
parents:
diff changeset
2166 static void __attribute__((noreturn))
kono
parents:
diff changeset
2167 uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2168 struct _Unwind_Context *target,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2169 unsigned long frames __attribute__((unused)))
111
kono
parents:
diff changeset
2170 {
kono
parents:
diff changeset
2171 unw_word ireg_buf[4], ireg_nat = 0, ireg_pr = 0;
kono
parents:
diff changeset
2172 unw_word saved_lc;
kono
parents:
diff changeset
2173 int i;
kono
parents:
diff changeset
2174
kono
parents:
diff changeset
2175 /* ??? LC is a fixed register so the call to __builtin_unwind_init in
kono
parents:
diff changeset
2176 uw_init_context doesn't cause it to be saved. In case it isn't in
kono
parents:
diff changeset
2177 the user frames either, we need to manually do so here, lest it be
kono
parents:
diff changeset
2178 clobbered by the loop just below. */
kono
parents:
diff changeset
2179 if (target->lc_loc == NULL)
kono
parents:
diff changeset
2180 {
kono
parents:
diff changeset
2181 register unw_word lc asm ("ar.lc");
kono
parents:
diff changeset
2182 saved_lc = lc;
kono
parents:
diff changeset
2183 target->lc_loc = &saved_lc;
kono
parents:
diff changeset
2184 }
kono
parents:
diff changeset
2185
kono
parents:
diff changeset
2186 /* Copy integer register data from the target context to a
kono
parents:
diff changeset
2187 temporary buffer. Do this so that we can frob AR.UNAT
kono
parents:
diff changeset
2188 to get the NaT bits for these registers set properly. */
kono
parents:
diff changeset
2189 for (i = 4; i <= 7; ++i)
kono
parents:
diff changeset
2190 {
kono
parents:
diff changeset
2191 char nat;
kono
parents:
diff changeset
2192 void *t = target->ireg[i - 2].loc;
kono
parents:
diff changeset
2193 if (t)
kono
parents:
diff changeset
2194 {
kono
parents:
diff changeset
2195 unw_access_gr (target, i, &ireg_buf[i - 4], &nat, 0);
kono
parents:
diff changeset
2196 ireg_nat |= (unw_word)nat << (((size_t)&ireg_buf[i - 4] >> 3) & 0x3f);
kono
parents:
diff changeset
2197 /* Set p6 - p9. */
kono
parents:
diff changeset
2198 ireg_pr |= 4L << i;
kono
parents:
diff changeset
2199 }
kono
parents:
diff changeset
2200 }
kono
parents:
diff changeset
2201
kono
parents:
diff changeset
2202 /* The value in uc_bsp that we've computed is that for the
kono
parents:
diff changeset
2203 target function. The value that we install below will be
kono
parents:
diff changeset
2204 adjusted by the BR.RET instruction based on the contents
kono
parents:
diff changeset
2205 of AR.PFS. So we must unadjust that here. */
kono
parents:
diff changeset
2206 target->bsp = (unw_word)
kono
parents:
diff changeset
2207 ia64_rse_skip_regs ((unw_word *)target->bsp,
kono
parents:
diff changeset
2208 (*target->pfs_loc >> 7) & 0x7f);
kono
parents:
diff changeset
2209
kono
parents:
diff changeset
2210 if (target->bsp < target->regstk_top)
kono
parents:
diff changeset
2211 target->rnat = *ia64_rse_rnat_addr ((unw_word *) target->bsp);
kono
parents:
diff changeset
2212
kono
parents:
diff changeset
2213 /* Provide assembly with the offsets into the _Unwind_Context. */
kono
parents:
diff changeset
2214 asm volatile ("uc_rnat = %0"
kono
parents:
diff changeset
2215 : : "i"(offsetof (struct _Unwind_Context, rnat)));
kono
parents:
diff changeset
2216 asm volatile ("uc_bsp = %0"
kono
parents:
diff changeset
2217 : : "i"(offsetof (struct _Unwind_Context, bsp)));
kono
parents:
diff changeset
2218 asm volatile ("uc_psp = %0"
kono
parents:
diff changeset
2219 : : "i"(offsetof (struct _Unwind_Context, psp)));
kono
parents:
diff changeset
2220 asm volatile ("uc_rp = %0"
kono
parents:
diff changeset
2221 : : "i"(offsetof (struct _Unwind_Context, rp)));
kono
parents:
diff changeset
2222 asm volatile ("uc_pr = %0"
kono
parents:
diff changeset
2223 : : "i"(offsetof (struct _Unwind_Context, pr)));
kono
parents:
diff changeset
2224 asm volatile ("uc_gp = %0"
kono
parents:
diff changeset
2225 : : "i"(offsetof (struct _Unwind_Context, gp)));
kono
parents:
diff changeset
2226 asm volatile ("uc_pfs_loc = %0"
kono
parents:
diff changeset
2227 : : "i"(offsetof (struct _Unwind_Context, pfs_loc)));
kono
parents:
diff changeset
2228 asm volatile ("uc_unat_loc = %0"
kono
parents:
diff changeset
2229 : : "i"(offsetof (struct _Unwind_Context, unat_loc)));
kono
parents:
diff changeset
2230 asm volatile ("uc_lc_loc = %0"
kono
parents:
diff changeset
2231 : : "i"(offsetof (struct _Unwind_Context, lc_loc)));
kono
parents:
diff changeset
2232 asm volatile ("uc_fpsr_loc = %0"
kono
parents:
diff changeset
2233 : : "i"(offsetof (struct _Unwind_Context, fpsr_loc)));
kono
parents:
diff changeset
2234 asm volatile ("uc_eh_data = %0"
kono
parents:
diff changeset
2235 : : "i"(offsetof (struct _Unwind_Context, eh_data)));
kono
parents:
diff changeset
2236 asm volatile ("uc_br_loc = %0"
kono
parents:
diff changeset
2237 : : "i"(offsetof (struct _Unwind_Context, br_loc)));
kono
parents:
diff changeset
2238 asm volatile ("uc_fr_loc = %0"
kono
parents:
diff changeset
2239 : : "i"(offsetof (struct _Unwind_Context, fr_loc)));
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 asm volatile (
kono
parents:
diff changeset
2242 /* Load up call-saved non-window integer registers from ireg_buf. */
kono
parents:
diff changeset
2243 "add r20 = 8, %1 \n\t"
kono
parents:
diff changeset
2244 "mov ar.unat = %2 \n\t"
kono
parents:
diff changeset
2245 "mov pr = %3, 0x3c0 \n\t"
kono
parents:
diff changeset
2246 ";; \n\t"
kono
parents:
diff changeset
2247 "(p6) ld8.fill r4 = [%1] \n\t"
kono
parents:
diff changeset
2248 "(p7) ld8.fill r5 = [r20] \n\t"
kono
parents:
diff changeset
2249 "add r21 = uc_br_loc + 16, %0 \n\t"
kono
parents:
diff changeset
2250 "adds %1 = 16, %1 \n\t"
kono
parents:
diff changeset
2251 "adds r20 = 16, r20 \n\t"
kono
parents:
diff changeset
2252 ";; \n\t"
kono
parents:
diff changeset
2253 "(p8) ld8.fill r6 = [%1] \n\t"
kono
parents:
diff changeset
2254 "(p9) ld8.fill r7 = [r20] \n\t"
kono
parents:
diff changeset
2255 "add r20 = uc_br_loc + 8, %0 \n\t"
kono
parents:
diff changeset
2256 ";; \n\t"
kono
parents:
diff changeset
2257 /* Load up call-saved branch registers. */
kono
parents:
diff changeset
2258 "ld8 r22 = [r20], 16 \n\t"
kono
parents:
diff changeset
2259 "ld8 r23 = [r21], 16 \n\t"
kono
parents:
diff changeset
2260 ";; \n\t"
kono
parents:
diff changeset
2261 "ld8 r24 = [r20], 16 \n\t"
kono
parents:
diff changeset
2262 "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 32)\n\t"
kono
parents:
diff changeset
2263 ";; \n\t"
kono
parents:
diff changeset
2264 "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 40)\n\t"
kono
parents:
diff changeset
2265 "ld8 r27 = [r21], 24 \n\t"
kono
parents:
diff changeset
2266 "cmp.ne p6, p0 = r0, r22 \n\t"
kono
parents:
diff changeset
2267 ";; \n\t"
kono
parents:
diff changeset
2268 "ld8 r28 = [r20], 8 \n\t"
kono
parents:
diff changeset
2269 "(p6) ld8 r22 = [r22] \n\t"
kono
parents:
diff changeset
2270 "cmp.ne p7, p0 = r0, r23 \n\t"
kono
parents:
diff changeset
2271 ";; \n\t"
kono
parents:
diff changeset
2272 "(p7) ld8 r23 = [r23] \n\t"
kono
parents:
diff changeset
2273 "cmp.ne p8, p0 = r0, r24 \n\t"
kono
parents:
diff changeset
2274 ";; \n\t"
kono
parents:
diff changeset
2275 "(p8) ld8 r24 = [r24] \n\t"
kono
parents:
diff changeset
2276 "(p6) mov b1 = r22 \n\t"
kono
parents:
diff changeset
2277 "cmp.ne p9, p0 = r0, r25 \n\t"
kono
parents:
diff changeset
2278 ";; \n\t"
kono
parents:
diff changeset
2279 "(p9) ld8 r25 = [r25] \n\t"
kono
parents:
diff changeset
2280 "(p7) mov b2 = r23 \n\t"
kono
parents:
diff changeset
2281 "cmp.ne p6, p0 = r0, r26 \n\t"
kono
parents:
diff changeset
2282 ";; \n\t"
kono
parents:
diff changeset
2283 "(p6) ld8 r26 = [r26] \n\t"
kono
parents:
diff changeset
2284 "(p8) mov b3 = r24 \n\t"
kono
parents:
diff changeset
2285 "cmp.ne p7, p0 = r0, r27 \n\t"
kono
parents:
diff changeset
2286 ";; \n\t"
kono
parents:
diff changeset
2287 /* Load up call-saved fp registers. */
kono
parents:
diff changeset
2288 "(p7) ldf.fill f2 = [r27] \n\t"
kono
parents:
diff changeset
2289 "(p9) mov b4 = r25 \n\t"
kono
parents:
diff changeset
2290 "cmp.ne p8, p0 = r0, r28 \n\t"
kono
parents:
diff changeset
2291 ";; \n\t"
kono
parents:
diff changeset
2292 "(p8) ldf.fill f3 = [r28] \n\t"
kono
parents:
diff changeset
2293 "(p6) mov b5 = r26 \n\t"
kono
parents:
diff changeset
2294 ";; \n\t"
kono
parents:
diff changeset
2295 "ld8 r29 = [r20], 16*8 - 4*8 \n\t"
kono
parents:
diff changeset
2296 "ld8 r30 = [r21], 17*8 - 5*8 \n\t"
kono
parents:
diff changeset
2297 ";; \n\t"
kono
parents:
diff changeset
2298 "ld8 r22 = [r20], 16 \n\t"
kono
parents:
diff changeset
2299 "ld8 r23 = [r21], 16 \n\t"
kono
parents:
diff changeset
2300 ";; \n\t"
kono
parents:
diff changeset
2301 "ld8 r24 = [r20], 16 \n\t"
kono
parents:
diff changeset
2302 "ld8 r25 = [r21] \n\t"
kono
parents:
diff changeset
2303 "cmp.ne p6, p0 = r0, r29 \n\t"
kono
parents:
diff changeset
2304 ";; \n\t"
kono
parents:
diff changeset
2305 "ld8 r26 = [r20], 8 \n\t"
kono
parents:
diff changeset
2306 "(p6) ldf.fill f4 = [r29] \n\t"
kono
parents:
diff changeset
2307 "cmp.ne p7, p0 = r0, r30 \n\t"
kono
parents:
diff changeset
2308 ";; \n\t"
kono
parents:
diff changeset
2309 "ld8 r27 = [r20], 8 \n\t"
kono
parents:
diff changeset
2310 "(p7) ldf.fill f5 = [r30] \n\t"
kono
parents:
diff changeset
2311 "cmp.ne p6, p0 = r0, r22 \n\t"
kono
parents:
diff changeset
2312 ";; \n\t"
kono
parents:
diff changeset
2313 "ld8 r28 = [r20], 8 \n\t"
kono
parents:
diff changeset
2314 "(p6) ldf.fill f16 = [r22] \n\t"
kono
parents:
diff changeset
2315 "cmp.ne p7, p0 = r0, r23 \n\t"
kono
parents:
diff changeset
2316 ";; \n\t"
kono
parents:
diff changeset
2317 "ld8 r29 = [r20], 8 \n\t"
kono
parents:
diff changeset
2318 "(p7) ldf.fill f17 = [r23] \n\t"
kono
parents:
diff changeset
2319 "cmp.ne p6, p0 = r0, r24 \n\t"
kono
parents:
diff changeset
2320 ";; \n\t"
kono
parents:
diff changeset
2321 "ld8 r22 = [r20], 8 \n\t"
kono
parents:
diff changeset
2322 "(p6) ldf.fill f18 = [r24] \n\t"
kono
parents:
diff changeset
2323 "cmp.ne p7, p0 = r0, r25 \n\t"
kono
parents:
diff changeset
2324 ";; \n\t"
kono
parents:
diff changeset
2325 "ld8 r23 = [r20], 8 \n\t"
kono
parents:
diff changeset
2326 "(p7) ldf.fill f19 = [r25] \n\t"
kono
parents:
diff changeset
2327 "cmp.ne p6, p0 = r0, r26 \n\t"
kono
parents:
diff changeset
2328 ";; \n\t"
kono
parents:
diff changeset
2329 "ld8 r24 = [r20], 8 \n\t"
kono
parents:
diff changeset
2330 "(p6) ldf.fill f20 = [r26] \n\t"
kono
parents:
diff changeset
2331 "cmp.ne p7, p0 = r0, r27 \n\t"
kono
parents:
diff changeset
2332 ";; \n\t"
kono
parents:
diff changeset
2333 "ld8 r25 = [r20], 8 \n\t"
kono
parents:
diff changeset
2334 "(p7) ldf.fill f21 = [r27] \n\t"
kono
parents:
diff changeset
2335 "cmp.ne p6, p0 = r0, r28 \n\t"
kono
parents:
diff changeset
2336 ";; \n\t"
kono
parents:
diff changeset
2337 "ld8 r26 = [r20], 8 \n\t"
kono
parents:
diff changeset
2338 "(p6) ldf.fill f22 = [r28] \n\t"
kono
parents:
diff changeset
2339 "cmp.ne p7, p0 = r0, r29 \n\t"
kono
parents:
diff changeset
2340 ";; \n\t"
kono
parents:
diff changeset
2341 "ld8 r27 = [r20], 8 \n\t"
kono
parents:
diff changeset
2342 ";; \n\t"
kono
parents:
diff changeset
2343 "ld8 r28 = [r20], 8 \n\t"
kono
parents:
diff changeset
2344 "(p7) ldf.fill f23 = [r29] \n\t"
kono
parents:
diff changeset
2345 "cmp.ne p6, p0 = r0, r22 \n\t"
kono
parents:
diff changeset
2346 ";; \n\t"
kono
parents:
diff changeset
2347 "ld8 r29 = [r20], 8 \n\t"
kono
parents:
diff changeset
2348 "(p6) ldf.fill f24 = [r22] \n\t"
kono
parents:
diff changeset
2349 "cmp.ne p7, p0 = r0, r23 \n\t"
kono
parents:
diff changeset
2350 ";; \n\t"
kono
parents:
diff changeset
2351 "(p7) ldf.fill f25 = [r23] \n\t"
kono
parents:
diff changeset
2352 "cmp.ne p6, p0 = r0, r24 \n\t"
kono
parents:
diff changeset
2353 "cmp.ne p7, p0 = r0, r25 \n\t"
kono
parents:
diff changeset
2354 ";; \n\t"
kono
parents:
diff changeset
2355 "(p6) ldf.fill f26 = [r24] \n\t"
kono
parents:
diff changeset
2356 "(p7) ldf.fill f27 = [r25] \n\t"
kono
parents:
diff changeset
2357 "cmp.ne p6, p0 = r0, r26 \n\t"
kono
parents:
diff changeset
2358 ";; \n\t"
kono
parents:
diff changeset
2359 "(p6) ldf.fill f28 = [r26] \n\t"
kono
parents:
diff changeset
2360 "cmp.ne p7, p0 = r0, r27 \n\t"
kono
parents:
diff changeset
2361 "cmp.ne p6, p0 = r0, r28 \n\t"
kono
parents:
diff changeset
2362 ";; \n\t"
kono
parents:
diff changeset
2363 "(p7) ldf.fill f29 = [r27] \n\t"
kono
parents:
diff changeset
2364 "(p6) ldf.fill f30 = [r28] \n\t"
kono
parents:
diff changeset
2365 "cmp.ne p7, p0 = r0, r29 \n\t"
kono
parents:
diff changeset
2366 ";; \n\t"
kono
parents:
diff changeset
2367 "(p7) ldf.fill f31 = [r29] \n\t"
kono
parents:
diff changeset
2368 "add r20 = uc_rnat, %0 \n\t"
kono
parents:
diff changeset
2369 "add r21 = uc_bsp, %0 \n\t"
kono
parents:
diff changeset
2370 ";; \n\t"
kono
parents:
diff changeset
2371 /* Load the balance of the thread state from the context. */
kono
parents:
diff changeset
2372 "ld8 r22 = [r20], uc_psp - uc_rnat \n\t"
kono
parents:
diff changeset
2373 "ld8 r23 = [r21], uc_gp - uc_bsp \n\t"
kono
parents:
diff changeset
2374 ";; \n\t"
kono
parents:
diff changeset
2375 "ld8 r24 = [r20], uc_pfs_loc - uc_psp \n\t"
kono
parents:
diff changeset
2376 "ld8 r1 = [r21], uc_rp - uc_gp \n\t"
kono
parents:
diff changeset
2377 ";; \n\t"
kono
parents:
diff changeset
2378 "ld8 r25 = [r20], uc_unat_loc - uc_pfs_loc\n\t"
kono
parents:
diff changeset
2379 "ld8 r26 = [r21], uc_pr - uc_rp \n\t"
kono
parents:
diff changeset
2380 ";; \n\t"
kono
parents:
diff changeset
2381 "ld8 r27 = [r20], uc_lc_loc - uc_unat_loc\n\t"
kono
parents:
diff changeset
2382 "ld8 r28 = [r21], uc_fpsr_loc - uc_pr \n\t"
kono
parents:
diff changeset
2383 ";; \n\t"
kono
parents:
diff changeset
2384 "ld8 r29 = [r20], uc_eh_data - uc_lc_loc\n\t"
kono
parents:
diff changeset
2385 "ld8 r30 = [r21], uc_eh_data + 8 - uc_fpsr_loc\n\t"
kono
parents:
diff changeset
2386 ";; \n\t"
kono
parents:
diff changeset
2387 /* Load data for the exception handler. */
kono
parents:
diff changeset
2388 "ld8 r15 = [r20], 16 \n\t"
kono
parents:
diff changeset
2389 "ld8 r16 = [r21], 16 \n\t"
kono
parents:
diff changeset
2390 ";; \n\t"
kono
parents:
diff changeset
2391 "ld8 r17 = [r20] \n\t"
kono
parents:
diff changeset
2392 "ld8 r18 = [r21] \n\t"
kono
parents:
diff changeset
2393 ";; \n\t"
kono
parents:
diff changeset
2394 /* Install the balance of the thread state loaded above. */
kono
parents:
diff changeset
2395 "cmp.ne p6, p0 = r0, r25 \n\t"
kono
parents:
diff changeset
2396 "cmp.ne p7, p0 = r0, r27 \n\t"
kono
parents:
diff changeset
2397 ";; \n\t"
kono
parents:
diff changeset
2398 "(p6) ld8 r25 = [r25] \n\t"
kono
parents:
diff changeset
2399 "(p7) ld8 r27 = [r27] \n\t"
kono
parents:
diff changeset
2400 ";; \n\t"
kono
parents:
diff changeset
2401 "(p7) mov.m ar.unat = r27 \n\t"
kono
parents:
diff changeset
2402 "(p6) mov.i ar.pfs = r25 \n\t"
kono
parents:
diff changeset
2403 "cmp.ne p9, p0 = r0, r29 \n\t"
kono
parents:
diff changeset
2404 ";; \n\t"
kono
parents:
diff changeset
2405 "(p9) ld8 r29 = [r29] \n\t"
kono
parents:
diff changeset
2406 "cmp.ne p6, p0 = r0, r30 \n\t"
kono
parents:
diff changeset
2407 ";; \n\t"
kono
parents:
diff changeset
2408 "(p6) ld8 r30 = [r30] \n\t"
kono
parents:
diff changeset
2409 /* Don't clobber p6-p9, which are in use at present. */
kono
parents:
diff changeset
2410 "mov pr = r28, ~0x3c0 \n\t"
kono
parents:
diff changeset
2411 "(p9) mov.i ar.lc = r29 \n\t"
kono
parents:
diff changeset
2412 ";; \n\t"
kono
parents:
diff changeset
2413 "mov.m r25 = ar.rsc \n\t"
kono
parents:
diff changeset
2414 "(p6) mov.m ar.fpsr = r30 \n\t"
kono
parents:
diff changeset
2415 ";; \n\t"
kono
parents:
diff changeset
2416 "and r29 = 0x1c, r25 \n\t"
kono
parents:
diff changeset
2417 "mov b0 = r26 \n\t"
kono
parents:
diff changeset
2418 ";; \n\t"
kono
parents:
diff changeset
2419 "mov.m ar.rsc = r29 \n\t"
kono
parents:
diff changeset
2420 ";; \n\t"
kono
parents:
diff changeset
2421 /* This must be done before setting AR.BSPSTORE, otherwise
kono
parents:
diff changeset
2422 AR.BSP will be initialized with a random displacement
kono
parents:
diff changeset
2423 below the value we want, based on the current number of
kono
parents:
diff changeset
2424 dirty stacked registers. */
kono
parents:
diff changeset
2425 "loadrs \n\t"
kono
parents:
diff changeset
2426 "invala \n\t"
kono
parents:
diff changeset
2427 ";; \n\t"
kono
parents:
diff changeset
2428 "mov.m ar.bspstore = r23 \n\t"
kono
parents:
diff changeset
2429 ";; \n\t"
kono
parents:
diff changeset
2430 "mov.m ar.rnat = r22 \n\t"
kono
parents:
diff changeset
2431 ";; \n\t"
kono
parents:
diff changeset
2432 "mov.m ar.rsc = r25 \n\t"
kono
parents:
diff changeset
2433 "mov sp = r24 \n\t"
kono
parents:
diff changeset
2434 "br.ret.sptk.few b0"
kono
parents:
diff changeset
2435 : : "r"(target), "r"(ireg_buf), "r"(ireg_nat), "r"(ireg_pr)
kono
parents:
diff changeset
2436 : "r15", "r16", "r17", "r18", "r20", "r21", "r22",
kono
parents:
diff changeset
2437 "r23", "r24", "r25", "r26", "r27", "r28", "r29",
kono
parents:
diff changeset
2438 "r30", "r31");
kono
parents:
diff changeset
2439 /* NOTREACHED */
kono
parents:
diff changeset
2440 while (1);
kono
parents:
diff changeset
2441 }
kono
parents:
diff changeset
2442
kono
parents:
diff changeset
2443 static inline _Unwind_Ptr
kono
parents:
diff changeset
2444 uw_identify_context (struct _Unwind_Context *context)
kono
parents:
diff changeset
2445 {
kono
parents:
diff changeset
2446 return _Unwind_GetIP (context);
kono
parents:
diff changeset
2447 }
kono
parents:
diff changeset
2448
kono
parents:
diff changeset
2449 #include "unwind.inc"
kono
parents:
diff changeset
2450
kono
parents:
diff changeset
2451 #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
kono
parents:
diff changeset
2452 alias (_Unwind_Backtrace);
kono
parents:
diff changeset
2453 alias (_Unwind_DeleteException);
kono
parents:
diff changeset
2454 alias (_Unwind_FindEnclosingFunction);
kono
parents:
diff changeset
2455 alias (_Unwind_ForcedUnwind);
kono
parents:
diff changeset
2456 alias (_Unwind_GetBSP);
kono
parents:
diff changeset
2457 alias (_Unwind_GetCFA);
kono
parents:
diff changeset
2458 alias (_Unwind_GetGR);
kono
parents:
diff changeset
2459 alias (_Unwind_GetIP);
kono
parents:
diff changeset
2460 alias (_Unwind_GetLanguageSpecificData);
kono
parents:
diff changeset
2461 alias (_Unwind_GetRegionStart);
kono
parents:
diff changeset
2462 alias (_Unwind_RaiseException);
kono
parents:
diff changeset
2463 alias (_Unwind_Resume);
kono
parents:
diff changeset
2464 alias (_Unwind_Resume_or_Rethrow);
kono
parents:
diff changeset
2465 alias (_Unwind_SetGR);
kono
parents:
diff changeset
2466 alias (_Unwind_SetIP);
kono
parents:
diff changeset
2467 #endif
kono
parents:
diff changeset
2468
kono
parents:
diff changeset
2469 #endif