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