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