1*3d8817e4Smiod /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2*3d8817e4Smiod Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3*3d8817e4Smiod Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4*3d8817e4Smiod
5*3d8817e4Smiod This file is part of GNU Binutils.
6*3d8817e4Smiod
7*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
8*3d8817e4Smiod it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
10*3d8817e4Smiod any later version.
11*3d8817e4Smiod
12*3d8817e4Smiod This program is distributed in the hope that it will be useful,
13*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*3d8817e4Smiod GNU General Public License for more details.
16*3d8817e4Smiod
17*3d8817e4Smiod You should have received a copy of the GNU General Public License
18*3d8817e4Smiod along with this program; if not, write to the Free Software
19*3d8817e4Smiod Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20*3d8817e4Smiod
21*3d8817e4Smiod #include "unwind-ia64.h"
22*3d8817e4Smiod #include <stdio.h>
23*3d8817e4Smiod #include <string.h>
24*3d8817e4Smiod
25*3d8817e4Smiod #if __GNUC__ >= 2
26*3d8817e4Smiod /* Define BFD64 here, even if our default architecture is 32 bit ELF
27*3d8817e4Smiod as this will allow us to read in and parse 64bit and 32bit ELF files.
28*3d8817e4Smiod Only do this if we believe that the compiler can support a 64 bit
29*3d8817e4Smiod data type. For now we only rely on GCC being able to do this. */
30*3d8817e4Smiod #define BFD64
31*3d8817e4Smiod #endif
32*3d8817e4Smiod #include "bfd.h"
33*3d8817e4Smiod
34*3d8817e4Smiod static bfd_vma unw_rlen = 0;
35*3d8817e4Smiod
36*3d8817e4Smiod static void unw_print_brmask (char *, unsigned int);
37*3d8817e4Smiod static void unw_print_grmask (char *, unsigned int);
38*3d8817e4Smiod static void unw_print_frmask (char *, unsigned int);
39*3d8817e4Smiod static void unw_print_abreg (char *, unsigned int);
40*3d8817e4Smiod static void unw_print_xyreg (char *, unsigned int, unsigned int);
41*3d8817e4Smiod
42*3d8817e4Smiod static void
unw_print_brmask(char * cp,unsigned int mask)43*3d8817e4Smiod unw_print_brmask (char *cp, unsigned int mask)
44*3d8817e4Smiod {
45*3d8817e4Smiod int sep = 0;
46*3d8817e4Smiod int i;
47*3d8817e4Smiod
48*3d8817e4Smiod for (i = 0; mask && (i < 5); ++i)
49*3d8817e4Smiod {
50*3d8817e4Smiod if (mask & 1)
51*3d8817e4Smiod {
52*3d8817e4Smiod if (sep)
53*3d8817e4Smiod *cp++ = ',';
54*3d8817e4Smiod *cp++ = 'b';
55*3d8817e4Smiod *cp++ = i + 1 + '0';
56*3d8817e4Smiod sep = 1;
57*3d8817e4Smiod }
58*3d8817e4Smiod mask >>= 1;
59*3d8817e4Smiod }
60*3d8817e4Smiod *cp = '\0';
61*3d8817e4Smiod }
62*3d8817e4Smiod
63*3d8817e4Smiod static void
unw_print_grmask(char * cp,unsigned int mask)64*3d8817e4Smiod unw_print_grmask (char *cp, unsigned int mask)
65*3d8817e4Smiod {
66*3d8817e4Smiod int sep = 0;
67*3d8817e4Smiod int i;
68*3d8817e4Smiod
69*3d8817e4Smiod for (i = 0; i < 4; ++i)
70*3d8817e4Smiod {
71*3d8817e4Smiod if (mask & 1)
72*3d8817e4Smiod {
73*3d8817e4Smiod if (sep)
74*3d8817e4Smiod *cp++ = ',';
75*3d8817e4Smiod *cp++ = 'r';
76*3d8817e4Smiod *cp++ = i + 4 + '0';
77*3d8817e4Smiod sep = 1;
78*3d8817e4Smiod }
79*3d8817e4Smiod mask >>= 1;
80*3d8817e4Smiod }
81*3d8817e4Smiod *cp = '\0';
82*3d8817e4Smiod }
83*3d8817e4Smiod
84*3d8817e4Smiod static void
unw_print_frmask(char * cp,unsigned int mask)85*3d8817e4Smiod unw_print_frmask (char *cp, unsigned int mask)
86*3d8817e4Smiod {
87*3d8817e4Smiod int sep = 0;
88*3d8817e4Smiod int i;
89*3d8817e4Smiod
90*3d8817e4Smiod for (i = 0; i < 20; ++i)
91*3d8817e4Smiod {
92*3d8817e4Smiod if (mask & 1)
93*3d8817e4Smiod {
94*3d8817e4Smiod if (sep)
95*3d8817e4Smiod *cp++ = ',';
96*3d8817e4Smiod *cp++ = 'f';
97*3d8817e4Smiod if (i < 4)
98*3d8817e4Smiod *cp++ = i + 2 + '0';
99*3d8817e4Smiod else
100*3d8817e4Smiod {
101*3d8817e4Smiod *cp++ = (i + 2) / 10 + 1 + '0';
102*3d8817e4Smiod *cp++ = (i + 2) % 10 + '0';
103*3d8817e4Smiod }
104*3d8817e4Smiod sep = 1;
105*3d8817e4Smiod }
106*3d8817e4Smiod mask >>= 1;
107*3d8817e4Smiod }
108*3d8817e4Smiod *cp = '\0';
109*3d8817e4Smiod }
110*3d8817e4Smiod
111*3d8817e4Smiod static void
unw_print_abreg(char * cp,unsigned int abreg)112*3d8817e4Smiod unw_print_abreg (char *cp, unsigned int abreg)
113*3d8817e4Smiod {
114*3d8817e4Smiod static const char *special_reg[16] =
115*3d8817e4Smiod {
116*3d8817e4Smiod "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
117*3d8817e4Smiod "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
118*3d8817e4Smiod "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
119*3d8817e4Smiod };
120*3d8817e4Smiod
121*3d8817e4Smiod switch ((abreg >> 5) & 0x3)
122*3d8817e4Smiod {
123*3d8817e4Smiod case 0: /* gr */
124*3d8817e4Smiod sprintf (cp, "r%u", (abreg & 0x1f));
125*3d8817e4Smiod break;
126*3d8817e4Smiod
127*3d8817e4Smiod case 1: /* fr */
128*3d8817e4Smiod sprintf (cp, "f%u", (abreg & 0x1f));
129*3d8817e4Smiod break;
130*3d8817e4Smiod
131*3d8817e4Smiod case 2: /* br */
132*3d8817e4Smiod sprintf (cp, "b%u", (abreg & 0x1f));
133*3d8817e4Smiod break;
134*3d8817e4Smiod
135*3d8817e4Smiod case 3: /* special */
136*3d8817e4Smiod strcpy (cp, special_reg[abreg & 0xf]);
137*3d8817e4Smiod break;
138*3d8817e4Smiod }
139*3d8817e4Smiod }
140*3d8817e4Smiod
141*3d8817e4Smiod static void
unw_print_xyreg(char * cp,unsigned int x,unsigned int ytreg)142*3d8817e4Smiod unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
143*3d8817e4Smiod {
144*3d8817e4Smiod switch ((x << 1) | ((ytreg >> 7) & 1))
145*3d8817e4Smiod {
146*3d8817e4Smiod case 0: /* gr */
147*3d8817e4Smiod sprintf (cp, "r%u", (ytreg & 0x1f));
148*3d8817e4Smiod break;
149*3d8817e4Smiod
150*3d8817e4Smiod case 1: /* fr */
151*3d8817e4Smiod sprintf (cp, "f%u", (ytreg & 0x1f));
152*3d8817e4Smiod break;
153*3d8817e4Smiod
154*3d8817e4Smiod case 2: /* br */
155*3d8817e4Smiod sprintf (cp, "b%u", (ytreg & 0x1f));
156*3d8817e4Smiod break;
157*3d8817e4Smiod }
158*3d8817e4Smiod }
159*3d8817e4Smiod
160*3d8817e4Smiod #define UNW_REG_BSP "bsp"
161*3d8817e4Smiod #define UNW_REG_BSPSTORE "bspstore"
162*3d8817e4Smiod #define UNW_REG_FPSR "fpsr"
163*3d8817e4Smiod #define UNW_REG_LC "lc"
164*3d8817e4Smiod #define UNW_REG_PFS "pfs"
165*3d8817e4Smiod #define UNW_REG_PR "pr"
166*3d8817e4Smiod #define UNW_REG_PSP "psp"
167*3d8817e4Smiod #define UNW_REG_RNAT "rnat"
168*3d8817e4Smiod #define UNW_REG_RP "rp"
169*3d8817e4Smiod #define UNW_REG_UNAT "unat"
170*3d8817e4Smiod
171*3d8817e4Smiod typedef bfd_vma unw_word;
172*3d8817e4Smiod
173*3d8817e4Smiod #define UNW_DEC_BAD_CODE(code) \
174*3d8817e4Smiod printf ("Unknown code 0x%02x\n", code)
175*3d8817e4Smiod
176*3d8817e4Smiod #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \
177*3d8817e4Smiod do \
178*3d8817e4Smiod { \
179*3d8817e4Smiod unw_rlen = rlen; \
180*3d8817e4Smiod *(int *)arg = body; \
181*3d8817e4Smiod printf (" %s:%s(rlen=%lu)\n", \
182*3d8817e4Smiod fmt, body ? "body" : "prologue", (unsigned long) rlen); \
183*3d8817e4Smiod } \
184*3d8817e4Smiod while (0)
185*3d8817e4Smiod
186*3d8817e4Smiod #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \
187*3d8817e4Smiod do \
188*3d8817e4Smiod { \
189*3d8817e4Smiod char regname[16], maskstr[64], *sep; \
190*3d8817e4Smiod \
191*3d8817e4Smiod unw_rlen = rlen; \
192*3d8817e4Smiod *(int *)arg = 0; \
193*3d8817e4Smiod \
194*3d8817e4Smiod maskstr[0] = '\0'; \
195*3d8817e4Smiod sep = ""; \
196*3d8817e4Smiod if (mask & 0x8) \
197*3d8817e4Smiod { \
198*3d8817e4Smiod strcat (maskstr, "rp"); \
199*3d8817e4Smiod sep = ","; \
200*3d8817e4Smiod } \
201*3d8817e4Smiod if (mask & 0x4) \
202*3d8817e4Smiod { \
203*3d8817e4Smiod strcat (maskstr, sep); \
204*3d8817e4Smiod strcat (maskstr, "ar.pfs"); \
205*3d8817e4Smiod sep = ","; \
206*3d8817e4Smiod } \
207*3d8817e4Smiod if (mask & 0x2) \
208*3d8817e4Smiod { \
209*3d8817e4Smiod strcat (maskstr, sep); \
210*3d8817e4Smiod strcat (maskstr, "psp"); \
211*3d8817e4Smiod sep = ","; \
212*3d8817e4Smiod } \
213*3d8817e4Smiod if (mask & 0x1) \
214*3d8817e4Smiod { \
215*3d8817e4Smiod strcat (maskstr, sep); \
216*3d8817e4Smiod strcat (maskstr, "pr"); \
217*3d8817e4Smiod } \
218*3d8817e4Smiod sprintf (regname, "r%u", grsave); \
219*3d8817e4Smiod printf (" %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \
220*3d8817e4Smiod fmt, maskstr, regname, (unsigned long) rlen); \
221*3d8817e4Smiod } \
222*3d8817e4Smiod while (0)
223*3d8817e4Smiod
224*3d8817e4Smiod #define UNW_DEC_FR_MEM(fmt, frmask, arg) \
225*3d8817e4Smiod do \
226*3d8817e4Smiod { \
227*3d8817e4Smiod char frstr[200]; \
228*3d8817e4Smiod \
229*3d8817e4Smiod unw_print_frmask (frstr, frmask); \
230*3d8817e4Smiod printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \
231*3d8817e4Smiod } \
232*3d8817e4Smiod while (0)
233*3d8817e4Smiod
234*3d8817e4Smiod #define UNW_DEC_GR_MEM(fmt, grmask, arg) \
235*3d8817e4Smiod do \
236*3d8817e4Smiod { \
237*3d8817e4Smiod char grstr[200]; \
238*3d8817e4Smiod \
239*3d8817e4Smiod unw_print_grmask (grstr, grmask); \
240*3d8817e4Smiod printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \
241*3d8817e4Smiod } \
242*3d8817e4Smiod while (0)
243*3d8817e4Smiod
244*3d8817e4Smiod #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \
245*3d8817e4Smiod do \
246*3d8817e4Smiod { \
247*3d8817e4Smiod char frstr[200], grstr[20]; \
248*3d8817e4Smiod \
249*3d8817e4Smiod unw_print_grmask (grstr, grmask); \
250*3d8817e4Smiod unw_print_frmask (frstr, frmask); \
251*3d8817e4Smiod printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr); \
252*3d8817e4Smiod } \
253*3d8817e4Smiod while (0)
254*3d8817e4Smiod
255*3d8817e4Smiod #define UNW_DEC_BR_MEM(fmt, brmask, arg) \
256*3d8817e4Smiod do \
257*3d8817e4Smiod { \
258*3d8817e4Smiod char brstr[20]; \
259*3d8817e4Smiod \
260*3d8817e4Smiod unw_print_brmask (brstr, brmask); \
261*3d8817e4Smiod printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \
262*3d8817e4Smiod } \
263*3d8817e4Smiod while (0)
264*3d8817e4Smiod
265*3d8817e4Smiod #define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \
266*3d8817e4Smiod do \
267*3d8817e4Smiod { \
268*3d8817e4Smiod char brstr[20]; \
269*3d8817e4Smiod \
270*3d8817e4Smiod unw_print_brmask (brstr, brmask); \
271*3d8817e4Smiod printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \
272*3d8817e4Smiod } \
273*3d8817e4Smiod while (0)
274*3d8817e4Smiod
275*3d8817e4Smiod #define UNW_DEC_REG_GR(fmt, src, dst, arg) \
276*3d8817e4Smiod printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
277*3d8817e4Smiod
278*3d8817e4Smiod #define UNW_DEC_RP_BR(fmt, dst, arg) \
279*3d8817e4Smiod printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
280*3d8817e4Smiod
281*3d8817e4Smiod #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \
282*3d8817e4Smiod printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
283*3d8817e4Smiod
284*3d8817e4Smiod #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \
285*3d8817e4Smiod printf ("\t%s:%s_sprel(spoff=0x%lx)\n", \
286*3d8817e4Smiod fmt, reg, 4*(unsigned long)spoff)
287*3d8817e4Smiod
288*3d8817e4Smiod #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \
289*3d8817e4Smiod printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n", \
290*3d8817e4Smiod fmt, reg, 4*(unsigned long)pspoff)
291*3d8817e4Smiod
292*3d8817e4Smiod #define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \
293*3d8817e4Smiod do \
294*3d8817e4Smiod { \
295*3d8817e4Smiod char grstr[20]; \
296*3d8817e4Smiod \
297*3d8817e4Smiod unw_print_grmask (grstr, grmask); \
298*3d8817e4Smiod printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \
299*3d8817e4Smiod } \
300*3d8817e4Smiod while (0)
301*3d8817e4Smiod
302*3d8817e4Smiod #define UNW_DEC_ABI(fmt, abi, context, arg) \
303*3d8817e4Smiod do \
304*3d8817e4Smiod { \
305*3d8817e4Smiod static const char *abiname[] = \
306*3d8817e4Smiod { \
307*3d8817e4Smiod "@svr4", "@hpux", "@nt" \
308*3d8817e4Smiod }; \
309*3d8817e4Smiod char buf[20]; \
310*3d8817e4Smiod const char *abistr = buf; \
311*3d8817e4Smiod \
312*3d8817e4Smiod if (abi < 3) \
313*3d8817e4Smiod abistr = abiname[abi]; \
314*3d8817e4Smiod else \
315*3d8817e4Smiod sprintf (buf, "0x%x", abi); \
316*3d8817e4Smiod printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n", \
317*3d8817e4Smiod fmt, abistr, context); \
318*3d8817e4Smiod } \
319*3d8817e4Smiod while (0)
320*3d8817e4Smiod
321*3d8817e4Smiod #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \
322*3d8817e4Smiod printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
323*3d8817e4Smiod
324*3d8817e4Smiod #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \
325*3d8817e4Smiod printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
326*3d8817e4Smiod
327*3d8817e4Smiod #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \
328*3d8817e4Smiod printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
329*3d8817e4Smiod
330*3d8817e4Smiod #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \
331*3d8817e4Smiod printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n", \
332*3d8817e4Smiod fmt, 4*(unsigned long)pspoff)
333*3d8817e4Smiod
334*3d8817e4Smiod #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \
335*3d8817e4Smiod printf ("\t%s:priunat_sprel(spoff=0x%lx)\n", \
336*3d8817e4Smiod fmt, 4*(unsigned long)spoff)
337*3d8817e4Smiod
338*3d8817e4Smiod #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \
339*3d8817e4Smiod printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n", \
340*3d8817e4Smiod fmt, (unsigned long) t, 16*(unsigned long)size)
341*3d8817e4Smiod
342*3d8817e4Smiod #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \
343*3d8817e4Smiod printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
344*3d8817e4Smiod
345*3d8817e4Smiod #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \
346*3d8817e4Smiod printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \
347*3d8817e4Smiod fmt, 4*(unsigned long)pspoff)
348*3d8817e4Smiod
349*3d8817e4Smiod #define UNW_DEC_SPILL_MASK(fmt, dp, arg) \
350*3d8817e4Smiod do \
351*3d8817e4Smiod { \
352*3d8817e4Smiod static const char *spill_type = "-frb"; \
353*3d8817e4Smiod unsigned const char *imaskp = dp; \
354*3d8817e4Smiod unsigned char mask = 0; \
355*3d8817e4Smiod bfd_vma insn = 0; \
356*3d8817e4Smiod \
357*3d8817e4Smiod printf ("\t%s:spill_mask(imask=[", fmt); \
358*3d8817e4Smiod for (insn = 0; insn < unw_rlen; ++insn) \
359*3d8817e4Smiod { \
360*3d8817e4Smiod if ((insn % 4) == 0) \
361*3d8817e4Smiod mask = *imaskp++; \
362*3d8817e4Smiod if (insn > 0 && (insn % 3) == 0) \
363*3d8817e4Smiod putchar (','); \
364*3d8817e4Smiod putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]); \
365*3d8817e4Smiod } \
366*3d8817e4Smiod printf ("])\n"); \
367*3d8817e4Smiod dp = imaskp; \
368*3d8817e4Smiod } \
369*3d8817e4Smiod while (0)
370*3d8817e4Smiod
371*3d8817e4Smiod #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \
372*3d8817e4Smiod do \
373*3d8817e4Smiod { \
374*3d8817e4Smiod char regname[20]; \
375*3d8817e4Smiod \
376*3d8817e4Smiod unw_print_abreg (regname, abreg); \
377*3d8817e4Smiod printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \
378*3d8817e4Smiod fmt, regname, (unsigned long) t, 4*(unsigned long)off); \
379*3d8817e4Smiod } \
380*3d8817e4Smiod while (0)
381*3d8817e4Smiod
382*3d8817e4Smiod #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \
383*3d8817e4Smiod do \
384*3d8817e4Smiod { \
385*3d8817e4Smiod char regname[20]; \
386*3d8817e4Smiod \
387*3d8817e4Smiod unw_print_abreg (regname, abreg); \
388*3d8817e4Smiod printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \
389*3d8817e4Smiod fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff); \
390*3d8817e4Smiod } \
391*3d8817e4Smiod while (0)
392*3d8817e4Smiod
393*3d8817e4Smiod #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \
394*3d8817e4Smiod do \
395*3d8817e4Smiod { \
396*3d8817e4Smiod char regname[20]; \
397*3d8817e4Smiod \
398*3d8817e4Smiod unw_print_abreg (regname, abreg); \
399*3d8817e4Smiod printf ("\t%s:restore(t=%lu,reg=%s)\n", \
400*3d8817e4Smiod fmt, (unsigned long) t, regname); \
401*3d8817e4Smiod } \
402*3d8817e4Smiod while (0)
403*3d8817e4Smiod
404*3d8817e4Smiod #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \
405*3d8817e4Smiod do \
406*3d8817e4Smiod { \
407*3d8817e4Smiod char abregname[20], tregname[20]; \
408*3d8817e4Smiod \
409*3d8817e4Smiod unw_print_abreg (abregname, abreg); \
410*3d8817e4Smiod unw_print_xyreg (tregname, x, ytreg); \
411*3d8817e4Smiod printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n", \
412*3d8817e4Smiod fmt, (unsigned long) t, abregname, tregname); \
413*3d8817e4Smiod } \
414*3d8817e4Smiod while (0)
415*3d8817e4Smiod
416*3d8817e4Smiod #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \
417*3d8817e4Smiod do \
418*3d8817e4Smiod { \
419*3d8817e4Smiod char regname[20]; \
420*3d8817e4Smiod \
421*3d8817e4Smiod unw_print_abreg (regname, abreg); \
422*3d8817e4Smiod printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \
423*3d8817e4Smiod fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff); \
424*3d8817e4Smiod } \
425*3d8817e4Smiod while (0)
426*3d8817e4Smiod
427*3d8817e4Smiod #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \
428*3d8817e4Smiod do \
429*3d8817e4Smiod { \
430*3d8817e4Smiod char regname[20]; \
431*3d8817e4Smiod \
432*3d8817e4Smiod unw_print_abreg (regname, abreg); \
433*3d8817e4Smiod printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\
434*3d8817e4Smiod fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\
435*3d8817e4Smiod } \
436*3d8817e4Smiod while (0)
437*3d8817e4Smiod
438*3d8817e4Smiod #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \
439*3d8817e4Smiod do \
440*3d8817e4Smiod { \
441*3d8817e4Smiod char regname[20]; \
442*3d8817e4Smiod \
443*3d8817e4Smiod unw_print_abreg (regname, abreg); \
444*3d8817e4Smiod printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n", \
445*3d8817e4Smiod fmt, qp, (unsigned long) t, regname); \
446*3d8817e4Smiod } \
447*3d8817e4Smiod while (0)
448*3d8817e4Smiod
449*3d8817e4Smiod #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \
450*3d8817e4Smiod do \
451*3d8817e4Smiod { \
452*3d8817e4Smiod char regname[20], tregname[20]; \
453*3d8817e4Smiod \
454*3d8817e4Smiod unw_print_abreg (regname, abreg); \
455*3d8817e4Smiod unw_print_xyreg (tregname, x, ytreg); \
456*3d8817e4Smiod printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n", \
457*3d8817e4Smiod fmt, qp, (unsigned long) t, regname, tregname); \
458*3d8817e4Smiod } \
459*3d8817e4Smiod while (0)
460*3d8817e4Smiod
461*3d8817e4Smiod #define UNW_DEC_LABEL_STATE(fmt, label, arg) \
462*3d8817e4Smiod printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
463*3d8817e4Smiod
464*3d8817e4Smiod #define UNW_DEC_COPY_STATE(fmt, label, arg) \
465*3d8817e4Smiod printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
466*3d8817e4Smiod
467*3d8817e4Smiod #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \
468*3d8817e4Smiod printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n", \
469*3d8817e4Smiod fmt, (unsigned long) t, (unsigned long) ecount)
470*3d8817e4Smiod
471*3d8817e4Smiod /*
472*3d8817e4Smiod * Generic IA-64 unwind info decoder.
473*3d8817e4Smiod *
474*3d8817e4Smiod * This file is used both by the Linux kernel and objdump. Please
475*3d8817e4Smiod * keep the two copies of this file in sync (modulo differences in the
476*3d8817e4Smiod * prototypes...).
477*3d8817e4Smiod *
478*3d8817e4Smiod * You need to customize the decoder by defining the following
479*3d8817e4Smiod * macros/constants before including this file:
480*3d8817e4Smiod *
481*3d8817e4Smiod * Types:
482*3d8817e4Smiod * unw_word Unsigned integer type with at least 64 bits
483*3d8817e4Smiod *
484*3d8817e4Smiod * Register names:
485*3d8817e4Smiod * UNW_REG_BSP
486*3d8817e4Smiod * UNW_REG_BSPSTORE
487*3d8817e4Smiod * UNW_REG_FPSR
488*3d8817e4Smiod * UNW_REG_LC
489*3d8817e4Smiod * UNW_REG_PFS
490*3d8817e4Smiod * UNW_REG_PR
491*3d8817e4Smiod * UNW_REG_RNAT
492*3d8817e4Smiod * UNW_REG_PSP
493*3d8817e4Smiod * UNW_REG_RP
494*3d8817e4Smiod * UNW_REG_UNAT
495*3d8817e4Smiod *
496*3d8817e4Smiod * Decoder action macros:
497*3d8817e4Smiod * UNW_DEC_BAD_CODE(code)
498*3d8817e4Smiod * UNW_DEC_ABI(fmt,abi,context,arg)
499*3d8817e4Smiod * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
500*3d8817e4Smiod * UNW_DEC_BR_MEM(fmt,brmask,arg)
501*3d8817e4Smiod * UNW_DEC_COPY_STATE(fmt,label,arg)
502*3d8817e4Smiod * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
503*3d8817e4Smiod * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
504*3d8817e4Smiod * UNW_DEC_FR_MEM(fmt,frmask,arg)
505*3d8817e4Smiod * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
506*3d8817e4Smiod * UNW_DEC_GR_MEM(fmt,grmask,arg)
507*3d8817e4Smiod * UNW_DEC_LABEL_STATE(fmt,label,arg)
508*3d8817e4Smiod * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
509*3d8817e4Smiod * UNW_DEC_MEM_STACK_V(fmt,t,arg)
510*3d8817e4Smiod * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
511*3d8817e4Smiod * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
512*3d8817e4Smiod * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
513*3d8817e4Smiod * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
514*3d8817e4Smiod * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
515*3d8817e4Smiod * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
516*3d8817e4Smiod * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
517*3d8817e4Smiod * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
518*3d8817e4Smiod * UNW_DEC_REG_REG(fmt,src,dst,arg)
519*3d8817e4Smiod * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
520*3d8817e4Smiod * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
521*3d8817e4Smiod * UNW_DEC_RESTORE(fmt,t,abreg,arg)
522*3d8817e4Smiod * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
523*3d8817e4Smiod * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
524*3d8817e4Smiod * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
525*3d8817e4Smiod * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
526*3d8817e4Smiod * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
527*3d8817e4Smiod * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
528*3d8817e4Smiod * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
529*3d8817e4Smiod * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
530*3d8817e4Smiod * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
531*3d8817e4Smiod */
532*3d8817e4Smiod
533*3d8817e4Smiod static unw_word unw_decode_uleb128 (const unsigned char **);
534*3d8817e4Smiod static const unsigned char *unw_decode_x1
535*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
536*3d8817e4Smiod static const unsigned char *unw_decode_x2
537*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
538*3d8817e4Smiod static const unsigned char *unw_decode_x3
539*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
540*3d8817e4Smiod static const unsigned char *unw_decode_x4
541*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
542*3d8817e4Smiod static const unsigned char *unw_decode_r1
543*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
544*3d8817e4Smiod static const unsigned char *unw_decode_r2
545*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
546*3d8817e4Smiod static const unsigned char *unw_decode_r3
547*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
548*3d8817e4Smiod static const unsigned char *unw_decode_p1
549*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
550*3d8817e4Smiod static const unsigned char *unw_decode_p2_p5
551*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
552*3d8817e4Smiod static const unsigned char *unw_decode_p6
553*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
554*3d8817e4Smiod static const unsigned char *unw_decode_p7_p10
555*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
556*3d8817e4Smiod static const unsigned char *unw_decode_b1
557*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
558*3d8817e4Smiod static const unsigned char *unw_decode_b2
559*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
560*3d8817e4Smiod static const unsigned char *unw_decode_b3_x4
561*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
562*3d8817e4Smiod
563*3d8817e4Smiod static unw_word
unw_decode_uleb128(const unsigned char ** dpp)564*3d8817e4Smiod unw_decode_uleb128 (const unsigned char **dpp)
565*3d8817e4Smiod {
566*3d8817e4Smiod unsigned shift = 0;
567*3d8817e4Smiod unw_word byte, result = 0;
568*3d8817e4Smiod const unsigned char *bp = *dpp;
569*3d8817e4Smiod
570*3d8817e4Smiod while (1)
571*3d8817e4Smiod {
572*3d8817e4Smiod byte = *bp++;
573*3d8817e4Smiod result |= (byte & 0x7f) << shift;
574*3d8817e4Smiod
575*3d8817e4Smiod if ((byte & 0x80) == 0)
576*3d8817e4Smiod break;
577*3d8817e4Smiod
578*3d8817e4Smiod shift += 7;
579*3d8817e4Smiod }
580*3d8817e4Smiod
581*3d8817e4Smiod *dpp = bp;
582*3d8817e4Smiod
583*3d8817e4Smiod return result;
584*3d8817e4Smiod }
585*3d8817e4Smiod
586*3d8817e4Smiod static const unsigned char *
unw_decode_x1(const unsigned char * dp,unsigned int code ATTRIBUTE_UNUSED,void * arg ATTRIBUTE_UNUSED)587*3d8817e4Smiod unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
588*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
589*3d8817e4Smiod {
590*3d8817e4Smiod unsigned char byte1, abreg;
591*3d8817e4Smiod unw_word t, off;
592*3d8817e4Smiod
593*3d8817e4Smiod byte1 = *dp++;
594*3d8817e4Smiod t = unw_decode_uleb128 (&dp);
595*3d8817e4Smiod off = unw_decode_uleb128 (&dp);
596*3d8817e4Smiod abreg = (byte1 & 0x7f);
597*3d8817e4Smiod if (byte1 & 0x80)
598*3d8817e4Smiod UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
599*3d8817e4Smiod else
600*3d8817e4Smiod UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
601*3d8817e4Smiod return dp;
602*3d8817e4Smiod }
603*3d8817e4Smiod
604*3d8817e4Smiod static const unsigned char *
unw_decode_x2(const unsigned char * dp,unsigned int code ATTRIBUTE_UNUSED,void * arg ATTRIBUTE_UNUSED)605*3d8817e4Smiod unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
606*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
607*3d8817e4Smiod {
608*3d8817e4Smiod unsigned char byte1, byte2, abreg, x, ytreg;
609*3d8817e4Smiod unw_word t;
610*3d8817e4Smiod
611*3d8817e4Smiod byte1 = *dp++;
612*3d8817e4Smiod byte2 = *dp++;
613*3d8817e4Smiod t = unw_decode_uleb128 (&dp);
614*3d8817e4Smiod abreg = (byte1 & 0x7f);
615*3d8817e4Smiod ytreg = byte2;
616*3d8817e4Smiod x = (byte1 >> 7) & 1;
617*3d8817e4Smiod if ((byte1 & 0x80) == 0 && ytreg == 0)
618*3d8817e4Smiod UNW_DEC_RESTORE ("X2", t, abreg, arg);
619*3d8817e4Smiod else
620*3d8817e4Smiod UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg);
621*3d8817e4Smiod return dp;
622*3d8817e4Smiod }
623*3d8817e4Smiod
624*3d8817e4Smiod static const unsigned char *
unw_decode_x3(const unsigned char * dp,unsigned int code ATTRIBUTE_UNUSED,void * arg ATTRIBUTE_UNUSED)625*3d8817e4Smiod unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
626*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
627*3d8817e4Smiod {
628*3d8817e4Smiod unsigned char byte1, byte2, abreg, qp;
629*3d8817e4Smiod unw_word t, off;
630*3d8817e4Smiod
631*3d8817e4Smiod byte1 = *dp++;
632*3d8817e4Smiod byte2 = *dp++;
633*3d8817e4Smiod t = unw_decode_uleb128 (&dp);
634*3d8817e4Smiod off = unw_decode_uleb128 (&dp);
635*3d8817e4Smiod
636*3d8817e4Smiod qp = (byte1 & 0x3f);
637*3d8817e4Smiod abreg = (byte2 & 0x7f);
638*3d8817e4Smiod
639*3d8817e4Smiod if (byte1 & 0x80)
640*3d8817e4Smiod UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
641*3d8817e4Smiod else
642*3d8817e4Smiod UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
643*3d8817e4Smiod return dp;
644*3d8817e4Smiod }
645*3d8817e4Smiod
646*3d8817e4Smiod static const unsigned char *
unw_decode_x4(const unsigned char * dp,unsigned int code ATTRIBUTE_UNUSED,void * arg ATTRIBUTE_UNUSED)647*3d8817e4Smiod unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
648*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
649*3d8817e4Smiod {
650*3d8817e4Smiod unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
651*3d8817e4Smiod unw_word t;
652*3d8817e4Smiod
653*3d8817e4Smiod byte1 = *dp++;
654*3d8817e4Smiod byte2 = *dp++;
655*3d8817e4Smiod byte3 = *dp++;
656*3d8817e4Smiod t = unw_decode_uleb128 (&dp);
657*3d8817e4Smiod
658*3d8817e4Smiod qp = (byte1 & 0x3f);
659*3d8817e4Smiod abreg = (byte2 & 0x7f);
660*3d8817e4Smiod x = (byte2 >> 7) & 1;
661*3d8817e4Smiod ytreg = byte3;
662*3d8817e4Smiod
663*3d8817e4Smiod if ((byte2 & 0x80) == 0 && byte3 == 0)
664*3d8817e4Smiod UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
665*3d8817e4Smiod else
666*3d8817e4Smiod UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
667*3d8817e4Smiod return dp;
668*3d8817e4Smiod }
669*3d8817e4Smiod
670*3d8817e4Smiod static const unsigned char *
unw_decode_r1(const unsigned char * dp,unsigned int code,void * arg)671*3d8817e4Smiod unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
672*3d8817e4Smiod {
673*3d8817e4Smiod int body = (code & 0x20) != 0;
674*3d8817e4Smiod unw_word rlen;
675*3d8817e4Smiod
676*3d8817e4Smiod rlen = (code & 0x1f);
677*3d8817e4Smiod UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
678*3d8817e4Smiod return dp;
679*3d8817e4Smiod }
680*3d8817e4Smiod
681*3d8817e4Smiod static const unsigned char *
unw_decode_r2(const unsigned char * dp,unsigned int code,void * arg)682*3d8817e4Smiod unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg)
683*3d8817e4Smiod {
684*3d8817e4Smiod unsigned char byte1, mask, grsave;
685*3d8817e4Smiod unw_word rlen;
686*3d8817e4Smiod
687*3d8817e4Smiod byte1 = *dp++;
688*3d8817e4Smiod
689*3d8817e4Smiod mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
690*3d8817e4Smiod grsave = (byte1 & 0x7f);
691*3d8817e4Smiod rlen = unw_decode_uleb128 (& dp);
692*3d8817e4Smiod UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
693*3d8817e4Smiod return dp;
694*3d8817e4Smiod }
695*3d8817e4Smiod
696*3d8817e4Smiod static const unsigned char *
unw_decode_r3(const unsigned char * dp,unsigned int code,void * arg)697*3d8817e4Smiod unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg)
698*3d8817e4Smiod {
699*3d8817e4Smiod unw_word rlen;
700*3d8817e4Smiod
701*3d8817e4Smiod rlen = unw_decode_uleb128 (& dp);
702*3d8817e4Smiod UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
703*3d8817e4Smiod return dp;
704*3d8817e4Smiod }
705*3d8817e4Smiod
706*3d8817e4Smiod static const unsigned char *
unw_decode_p1(const unsigned char * dp,unsigned int code,void * arg ATTRIBUTE_UNUSED)707*3d8817e4Smiod unw_decode_p1 (const unsigned char *dp, unsigned int code,
708*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
709*3d8817e4Smiod {
710*3d8817e4Smiod unsigned char brmask = (code & 0x1f);
711*3d8817e4Smiod
712*3d8817e4Smiod UNW_DEC_BR_MEM ("P1", brmask, arg);
713*3d8817e4Smiod return dp;
714*3d8817e4Smiod }
715*3d8817e4Smiod
716*3d8817e4Smiod static const unsigned char *
unw_decode_p2_p5(const unsigned char * dp,unsigned int code,void * arg ATTRIBUTE_UNUSED)717*3d8817e4Smiod unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
718*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
719*3d8817e4Smiod {
720*3d8817e4Smiod if ((code & 0x10) == 0)
721*3d8817e4Smiod {
722*3d8817e4Smiod unsigned char byte1 = *dp++;
723*3d8817e4Smiod
724*3d8817e4Smiod UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
725*3d8817e4Smiod (byte1 & 0x7f), arg);
726*3d8817e4Smiod }
727*3d8817e4Smiod else if ((code & 0x08) == 0)
728*3d8817e4Smiod {
729*3d8817e4Smiod unsigned char byte1 = *dp++, r, dst;
730*3d8817e4Smiod
731*3d8817e4Smiod r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
732*3d8817e4Smiod dst = (byte1 & 0x7f);
733*3d8817e4Smiod switch (r)
734*3d8817e4Smiod {
735*3d8817e4Smiod case 0:
736*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
737*3d8817e4Smiod break;
738*3d8817e4Smiod case 1:
739*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
740*3d8817e4Smiod break;
741*3d8817e4Smiod case 2:
742*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
743*3d8817e4Smiod break;
744*3d8817e4Smiod case 3:
745*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
746*3d8817e4Smiod break;
747*3d8817e4Smiod case 4:
748*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
749*3d8817e4Smiod break;
750*3d8817e4Smiod case 5:
751*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
752*3d8817e4Smiod break;
753*3d8817e4Smiod case 6:
754*3d8817e4Smiod UNW_DEC_RP_BR ("P3", dst, arg);
755*3d8817e4Smiod break;
756*3d8817e4Smiod case 7:
757*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
758*3d8817e4Smiod break;
759*3d8817e4Smiod case 8:
760*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
761*3d8817e4Smiod break;
762*3d8817e4Smiod case 9:
763*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
764*3d8817e4Smiod break;
765*3d8817e4Smiod case 10:
766*3d8817e4Smiod UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
767*3d8817e4Smiod break;
768*3d8817e4Smiod case 11:
769*3d8817e4Smiod UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
770*3d8817e4Smiod break;
771*3d8817e4Smiod default:
772*3d8817e4Smiod UNW_DEC_BAD_CODE (r);
773*3d8817e4Smiod break;
774*3d8817e4Smiod }
775*3d8817e4Smiod }
776*3d8817e4Smiod else if ((code & 0x7) == 0)
777*3d8817e4Smiod UNW_DEC_SPILL_MASK ("P4", dp, arg);
778*3d8817e4Smiod else if ((code & 0x7) == 1)
779*3d8817e4Smiod {
780*3d8817e4Smiod unw_word grmask, frmask, byte1, byte2, byte3;
781*3d8817e4Smiod
782*3d8817e4Smiod byte1 = *dp++;
783*3d8817e4Smiod byte2 = *dp++;
784*3d8817e4Smiod byte3 = *dp++;
785*3d8817e4Smiod grmask = ((byte1 >> 4) & 0xf);
786*3d8817e4Smiod frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
787*3d8817e4Smiod UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
788*3d8817e4Smiod }
789*3d8817e4Smiod else
790*3d8817e4Smiod UNW_DEC_BAD_CODE (code);
791*3d8817e4Smiod
792*3d8817e4Smiod return dp;
793*3d8817e4Smiod }
794*3d8817e4Smiod
795*3d8817e4Smiod static const unsigned char *
unw_decode_p6(const unsigned char * dp,unsigned int code,void * arg ATTRIBUTE_UNUSED)796*3d8817e4Smiod unw_decode_p6 (const unsigned char *dp, unsigned int code,
797*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
798*3d8817e4Smiod {
799*3d8817e4Smiod int gregs = (code & 0x10) != 0;
800*3d8817e4Smiod unsigned char mask = (code & 0x0f);
801*3d8817e4Smiod
802*3d8817e4Smiod if (gregs)
803*3d8817e4Smiod UNW_DEC_GR_MEM ("P6", mask, arg);
804*3d8817e4Smiod else
805*3d8817e4Smiod UNW_DEC_FR_MEM ("P6", mask, arg);
806*3d8817e4Smiod return dp;
807*3d8817e4Smiod }
808*3d8817e4Smiod
809*3d8817e4Smiod static const unsigned char *
unw_decode_p7_p10(const unsigned char * dp,unsigned int code,void * arg)810*3d8817e4Smiod unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
811*3d8817e4Smiod {
812*3d8817e4Smiod unsigned char r, byte1, byte2;
813*3d8817e4Smiod unw_word t, size;
814*3d8817e4Smiod
815*3d8817e4Smiod if ((code & 0x10) == 0)
816*3d8817e4Smiod {
817*3d8817e4Smiod r = (code & 0xf);
818*3d8817e4Smiod t = unw_decode_uleb128 (&dp);
819*3d8817e4Smiod switch (r)
820*3d8817e4Smiod {
821*3d8817e4Smiod case 0:
822*3d8817e4Smiod size = unw_decode_uleb128 (&dp);
823*3d8817e4Smiod UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
824*3d8817e4Smiod break;
825*3d8817e4Smiod
826*3d8817e4Smiod case 1:
827*3d8817e4Smiod UNW_DEC_MEM_STACK_V ("P7", t, arg);
828*3d8817e4Smiod break;
829*3d8817e4Smiod case 2:
830*3d8817e4Smiod UNW_DEC_SPILL_BASE ("P7", t, arg);
831*3d8817e4Smiod break;
832*3d8817e4Smiod case 3:
833*3d8817e4Smiod UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
834*3d8817e4Smiod break;
835*3d8817e4Smiod case 4:
836*3d8817e4Smiod UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
837*3d8817e4Smiod break;
838*3d8817e4Smiod case 5:
839*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
840*3d8817e4Smiod break;
841*3d8817e4Smiod case 6:
842*3d8817e4Smiod UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
843*3d8817e4Smiod break;
844*3d8817e4Smiod case 7:
845*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
846*3d8817e4Smiod break;
847*3d8817e4Smiod case 8:
848*3d8817e4Smiod UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
849*3d8817e4Smiod break;
850*3d8817e4Smiod case 9:
851*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
852*3d8817e4Smiod break;
853*3d8817e4Smiod case 10:
854*3d8817e4Smiod UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
855*3d8817e4Smiod break;
856*3d8817e4Smiod case 11:
857*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
858*3d8817e4Smiod break;
859*3d8817e4Smiod case 12:
860*3d8817e4Smiod UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
861*3d8817e4Smiod break;
862*3d8817e4Smiod case 13:
863*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
864*3d8817e4Smiod break;
865*3d8817e4Smiod case 14:
866*3d8817e4Smiod UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
867*3d8817e4Smiod break;
868*3d8817e4Smiod case 15:
869*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
870*3d8817e4Smiod break;
871*3d8817e4Smiod default:
872*3d8817e4Smiod UNW_DEC_BAD_CODE (r);
873*3d8817e4Smiod break;
874*3d8817e4Smiod }
875*3d8817e4Smiod }
876*3d8817e4Smiod else
877*3d8817e4Smiod {
878*3d8817e4Smiod switch (code & 0xf)
879*3d8817e4Smiod {
880*3d8817e4Smiod case 0x0: /* p8 */
881*3d8817e4Smiod {
882*3d8817e4Smiod r = *dp++;
883*3d8817e4Smiod t = unw_decode_uleb128 (&dp);
884*3d8817e4Smiod switch (r)
885*3d8817e4Smiod {
886*3d8817e4Smiod case 1:
887*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
888*3d8817e4Smiod break;
889*3d8817e4Smiod case 2:
890*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
891*3d8817e4Smiod break;
892*3d8817e4Smiod case 3:
893*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
894*3d8817e4Smiod break;
895*3d8817e4Smiod case 4:
896*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
897*3d8817e4Smiod break;
898*3d8817e4Smiod case 5:
899*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
900*3d8817e4Smiod break;
901*3d8817e4Smiod case 6:
902*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
903*3d8817e4Smiod break;
904*3d8817e4Smiod case 7:
905*3d8817e4Smiod UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
906*3d8817e4Smiod break;
907*3d8817e4Smiod case 8:
908*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
909*3d8817e4Smiod break;
910*3d8817e4Smiod case 9:
911*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
912*3d8817e4Smiod break;
913*3d8817e4Smiod case 10:
914*3d8817e4Smiod UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
915*3d8817e4Smiod break;
916*3d8817e4Smiod case 11:
917*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
918*3d8817e4Smiod break;
919*3d8817e4Smiod case 12:
920*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
921*3d8817e4Smiod break;
922*3d8817e4Smiod case 13:
923*3d8817e4Smiod UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
924*3d8817e4Smiod break;
925*3d8817e4Smiod case 14:
926*3d8817e4Smiod UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
927*3d8817e4Smiod break;
928*3d8817e4Smiod case 15:
929*3d8817e4Smiod UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
930*3d8817e4Smiod break;
931*3d8817e4Smiod case 16:
932*3d8817e4Smiod UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
933*3d8817e4Smiod break;
934*3d8817e4Smiod case 17:
935*3d8817e4Smiod UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
936*3d8817e4Smiod break;
937*3d8817e4Smiod case 18:
938*3d8817e4Smiod UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
939*3d8817e4Smiod break;
940*3d8817e4Smiod case 19:
941*3d8817e4Smiod UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
942*3d8817e4Smiod break;
943*3d8817e4Smiod default:
944*3d8817e4Smiod UNW_DEC_BAD_CODE (r);
945*3d8817e4Smiod break;
946*3d8817e4Smiod }
947*3d8817e4Smiod }
948*3d8817e4Smiod break;
949*3d8817e4Smiod
950*3d8817e4Smiod case 0x1:
951*3d8817e4Smiod byte1 = *dp++;
952*3d8817e4Smiod byte2 = *dp++;
953*3d8817e4Smiod UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
954*3d8817e4Smiod break;
955*3d8817e4Smiod
956*3d8817e4Smiod case 0xf: /* p10 */
957*3d8817e4Smiod byte1 = *dp++;
958*3d8817e4Smiod byte2 = *dp++;
959*3d8817e4Smiod UNW_DEC_ABI ("P10", byte1, byte2, arg);
960*3d8817e4Smiod break;
961*3d8817e4Smiod
962*3d8817e4Smiod case 0x9:
963*3d8817e4Smiod return unw_decode_x1 (dp, code, arg);
964*3d8817e4Smiod
965*3d8817e4Smiod case 0xa:
966*3d8817e4Smiod return unw_decode_x2 (dp, code, arg);
967*3d8817e4Smiod
968*3d8817e4Smiod case 0xb:
969*3d8817e4Smiod return unw_decode_x3 (dp, code, arg);
970*3d8817e4Smiod
971*3d8817e4Smiod case 0xc:
972*3d8817e4Smiod return unw_decode_x4 (dp, code, arg);
973*3d8817e4Smiod
974*3d8817e4Smiod default:
975*3d8817e4Smiod UNW_DEC_BAD_CODE (code);
976*3d8817e4Smiod break;
977*3d8817e4Smiod }
978*3d8817e4Smiod }
979*3d8817e4Smiod return dp;
980*3d8817e4Smiod }
981*3d8817e4Smiod
982*3d8817e4Smiod static const unsigned char *
unw_decode_b1(const unsigned char * dp,unsigned int code,void * arg ATTRIBUTE_UNUSED)983*3d8817e4Smiod unw_decode_b1 (const unsigned char *dp, unsigned int code,
984*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
985*3d8817e4Smiod {
986*3d8817e4Smiod unw_word label = (code & 0x1f);
987*3d8817e4Smiod
988*3d8817e4Smiod if ((code & 0x20) != 0)
989*3d8817e4Smiod UNW_DEC_COPY_STATE ("B1", label, arg);
990*3d8817e4Smiod else
991*3d8817e4Smiod UNW_DEC_LABEL_STATE ("B1", label, arg);
992*3d8817e4Smiod return dp;
993*3d8817e4Smiod }
994*3d8817e4Smiod
995*3d8817e4Smiod static const unsigned char *
unw_decode_b2(const unsigned char * dp,unsigned int code,void * arg ATTRIBUTE_UNUSED)996*3d8817e4Smiod unw_decode_b2 (const unsigned char *dp, unsigned int code,
997*3d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
998*3d8817e4Smiod {
999*3d8817e4Smiod unw_word t;
1000*3d8817e4Smiod
1001*3d8817e4Smiod t = unw_decode_uleb128 (& dp);
1002*3d8817e4Smiod UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
1003*3d8817e4Smiod return dp;
1004*3d8817e4Smiod }
1005*3d8817e4Smiod
1006*3d8817e4Smiod static const unsigned char *
unw_decode_b3_x4(const unsigned char * dp,unsigned int code,void * arg)1007*3d8817e4Smiod unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
1008*3d8817e4Smiod {
1009*3d8817e4Smiod unw_word t, ecount, label;
1010*3d8817e4Smiod
1011*3d8817e4Smiod if ((code & 0x10) == 0)
1012*3d8817e4Smiod {
1013*3d8817e4Smiod t = unw_decode_uleb128 (&dp);
1014*3d8817e4Smiod ecount = unw_decode_uleb128 (&dp);
1015*3d8817e4Smiod UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
1016*3d8817e4Smiod }
1017*3d8817e4Smiod else if ((code & 0x07) == 0)
1018*3d8817e4Smiod {
1019*3d8817e4Smiod label = unw_decode_uleb128 (&dp);
1020*3d8817e4Smiod if ((code & 0x08) != 0)
1021*3d8817e4Smiod UNW_DEC_COPY_STATE ("B4", label, arg);
1022*3d8817e4Smiod else
1023*3d8817e4Smiod UNW_DEC_LABEL_STATE ("B4", label, arg);
1024*3d8817e4Smiod }
1025*3d8817e4Smiod else
1026*3d8817e4Smiod switch (code & 0x7)
1027*3d8817e4Smiod {
1028*3d8817e4Smiod case 1:
1029*3d8817e4Smiod return unw_decode_x1 (dp, code, arg);
1030*3d8817e4Smiod case 2:
1031*3d8817e4Smiod return unw_decode_x2 (dp, code, arg);
1032*3d8817e4Smiod case 3:
1033*3d8817e4Smiod return unw_decode_x3 (dp, code, arg);
1034*3d8817e4Smiod case 4:
1035*3d8817e4Smiod return unw_decode_x4 (dp, code, arg);
1036*3d8817e4Smiod default:
1037*3d8817e4Smiod UNW_DEC_BAD_CODE (code);
1038*3d8817e4Smiod break;
1039*3d8817e4Smiod }
1040*3d8817e4Smiod return dp;
1041*3d8817e4Smiod }
1042*3d8817e4Smiod
1043*3d8817e4Smiod typedef const unsigned char *(*unw_decoder)
1044*3d8817e4Smiod (const unsigned char *, unsigned int, void *);
1045*3d8817e4Smiod
1046*3d8817e4Smiod static unw_decoder unw_decode_table[2][8] =
1047*3d8817e4Smiod {
1048*3d8817e4Smiod /* prologue table: */
1049*3d8817e4Smiod {
1050*3d8817e4Smiod unw_decode_r1, /* 0 */
1051*3d8817e4Smiod unw_decode_r1,
1052*3d8817e4Smiod unw_decode_r2,
1053*3d8817e4Smiod unw_decode_r3,
1054*3d8817e4Smiod unw_decode_p1, /* 4 */
1055*3d8817e4Smiod unw_decode_p2_p5,
1056*3d8817e4Smiod unw_decode_p6,
1057*3d8817e4Smiod unw_decode_p7_p10
1058*3d8817e4Smiod },
1059*3d8817e4Smiod {
1060*3d8817e4Smiod unw_decode_r1, /* 0 */
1061*3d8817e4Smiod unw_decode_r1,
1062*3d8817e4Smiod unw_decode_r2,
1063*3d8817e4Smiod unw_decode_r3,
1064*3d8817e4Smiod unw_decode_b1, /* 4 */
1065*3d8817e4Smiod unw_decode_b1,
1066*3d8817e4Smiod unw_decode_b2,
1067*3d8817e4Smiod unw_decode_b3_x4
1068*3d8817e4Smiod }
1069*3d8817e4Smiod };
1070*3d8817e4Smiod
1071*3d8817e4Smiod /* Decode one descriptor and return address of next descriptor. */
1072*3d8817e4Smiod const unsigned char *
unw_decode(const unsigned char * dp,int inside_body,void * ptr_inside_body)1073*3d8817e4Smiod unw_decode (const unsigned char *dp, int inside_body,
1074*3d8817e4Smiod void *ptr_inside_body)
1075*3d8817e4Smiod {
1076*3d8817e4Smiod unw_decoder decoder;
1077*3d8817e4Smiod unsigned char code;
1078*3d8817e4Smiod
1079*3d8817e4Smiod code = *dp++;
1080*3d8817e4Smiod decoder = unw_decode_table[inside_body][code >> 5];
1081*3d8817e4Smiod return (*decoder) (dp, code, ptr_inside_body);
1082*3d8817e4Smiod }
1083