120253Sjoerg/* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
220302Sjoerg   Copyright (C) 2000-2017 Free Software Foundation, Inc.
320302Sjoerg
420253Sjoerg   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
520253Sjoerg
620253Sjoerg   This file is part of GNU Binutils.
720253Sjoerg
820253Sjoerg   This program is free software; you can redistribute it and/or modify
920302Sjoerg   it under the terms of the GNU General Public License as published by
1020253Sjoerg   the Free Software Foundation; either version 3, or (at your option)
1120253Sjoerg   any later version.
1220253Sjoerg
1320253Sjoerg   This program is distributed in the hope that it will be useful,
1420302Sjoerg   but WITHOUT ANY WARRANTY; without even the implied warranty of
1520253Sjoerg   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1620253Sjoerg   GNU General Public License for more details.
1720302Sjoerg
1820253Sjoerg   You should have received a copy of the GNU General Public License
1920253Sjoerg   along with this program; if not, write to the Free Software
2020253Sjoerg   Foundation, 51 Franklin Street - Fifth Floor, Boston,
2120253Sjoerg   MA 02110-1301, USA.  */
2220253Sjoerg
2320253Sjoerg#include "config.h"
2420253Sjoerg#include "unwind-ia64.h"
2544229Sdavidn#include <stdio.h>
2620253Sjoerg#include <string.h>
2720253Sjoerg
2830259Scharnier#if __GNUC__ >= 2
2930259Scharnier/* Define BFD64 here, even if our default architecture is 32 bit ELF
3050479Speter   as this will allow us to read in and parse 64bit and 32bit ELF files.
3130259Scharnier   Only do this if we believe that the compiler can support a 64 bit
3230259Scharnier   data type.  For now we only rely on GCC being able to do this.  */
33287084Sbapt#define BFD64
34287084Sbapt#endif
35287084Sbapt#include "bfd.h"
36287084Sbapt
37287084Sbaptstatic bfd_vma unw_rlen = 0;
38319267Sasomers
3930259Scharnierstatic void unw_print_brmask (char *, unsigned int);
40287084Sbaptstatic void unw_print_grmask (char *, unsigned int);
4130259Scharnierstatic void unw_print_frmask (char *, unsigned int);
42287084Sbaptstatic void unw_print_abreg (char *, unsigned int);
4320253Sjoergstatic void unw_print_xyreg (char *, unsigned int, unsigned int);
44287084Sbapt
45287084Sbaptstatic void
46287084Sbaptunw_print_brmask (char *cp, unsigned int mask)
47287084Sbapt{
4830259Scharnier  int sep = 0;
49287084Sbapt  int i;
50287084Sbapt
5120253Sjoerg  for (i = 0; mask && (i < 5); ++i)
52287084Sbapt    {
53287084Sbapt      if (mask & 1)
5420253Sjoerg	{
5520253Sjoerg	  if (sep)
56287084Sbapt	    *cp++ = ',';
5720253Sjoerg	  *cp++ = 'b';
5823318Sache	  *cp++ = i + 1 + '0';
5922394Sdavidn	  sep = 1;
6052512Sdavidn	}
6124214Sache      mask >>= 1;
62287084Sbapt    }
63287084Sbapt  *cp = '\0';
64287084Sbapt}
65287084Sbapt
66287084Sbaptstatic void
67287084Sbaptunw_print_grmask (char *cp, unsigned int mask)
68287084Sbapt{
69287084Sbapt  int sep = 0;
70287084Sbapt  int i;
71287084Sbapt
72287084Sbapt  for (i = 0; i < 4; ++i)
73287084Sbapt    {
74287084Sbapt      if (mask & 1)
7520253Sjoerg	{
76287084Sbapt	  if (sep)
77287084Sbapt	    *cp++ = ',';
78287084Sbapt	  *cp++ = 'r';
79287084Sbapt	  *cp++ = i + 4 + '0';
80287084Sbapt	  sep = 1;
81287084Sbapt	}
82287084Sbapt      mask >>= 1;
83287084Sbapt    }
84287084Sbapt  *cp = '\0';
85287084Sbapt}
86287084Sbapt
87287084Sbaptstatic void
88287084Sbaptunw_print_frmask (char *cp, unsigned int mask)
89285092Sbapt{
90287084Sbapt  int sep = 0;
91285092Sbapt  int i;
92287084Sbapt
93287084Sbapt  for (i = 0; i < 20; ++i)
94285092Sbapt    {
95287084Sbapt      if (mask & 1)
96287084Sbapt	{
97285092Sbapt	  if (sep)
98287084Sbapt	    *cp++ = ',';
99285092Sbapt	  *cp++ = 'f';
100287084Sbapt	  if (i < 4)
101287084Sbapt	    *cp++ = i + 2 + '0';
102287084Sbapt	  else
103287084Sbapt	    {
10420267Sjoerg	      *cp++ = (i + 2) / 10 + 1 + '0';
10520267Sjoerg	      *cp++ = (i + 2) % 10 + '0';
106287084Sbapt	    }
107287084Sbapt	  sep = 1;
108287084Sbapt	}
10920253Sjoerg      mask >>= 1;
110287084Sbapt    }
111293684Sbapt  *cp = '\0';
112293684Sbapt}
113287084Sbapt
114293684Sbaptstatic void
115287084Sbaptunw_print_abreg (char *cp, unsigned int abreg)
11621052Sdavidn{
11721052Sdavidn  static const char * const special_reg[16] =
118287084Sbapt  {
119287084Sbapt    "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
120287084Sbapt    "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
121287084Sbapt    "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
12221052Sdavidn  };
123287084Sbapt
124287084Sbapt  switch ((abreg >> 5) & 0x3)
125287084Sbapt    {
126287084Sbapt    case 0: /* gr */
127287084Sbapt      sprintf (cp, "r%u", (abreg & 0x1f));
128287084Sbapt      break;
129287084Sbapt
13020253Sjoerg    case 1: /* fr */
131287084Sbapt      sprintf (cp, "f%u", (abreg & 0x1f));
13220253Sjoerg      break;
133287084Sbapt
134287084Sbapt    case 2: /* br */
135287084Sbapt      sprintf (cp, "b%u", (abreg & 0x1f));
136287084Sbapt      break;
137287084Sbapt
138287084Sbapt    case 3: /* special */
139287084Sbapt      strcpy (cp, special_reg[abreg & 0xf]);
14020253Sjoerg      break;
141287084Sbapt    }
14220253Sjoerg}
14320253Sjoerg
144287084Sbaptstatic void
145287084Sbaptunw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
146287084Sbapt{
147287084Sbapt  switch ((x << 1) | ((ytreg >> 7) & 1))
14820253Sjoerg    {
14952527Sdavidn    case 0: /* gr */
150287084Sbapt      sprintf (cp, "r%u", (ytreg & 0x1f));
151287084Sbapt      break;
15220253Sjoerg
153287084Sbapt    case 1: /* fr */
154287084Sbapt      sprintf (cp, "f%u", (ytreg & 0x1f));
155287084Sbapt      break;
156287084Sbapt
157287084Sbapt    case 2: /* br */
15820253Sjoerg      sprintf (cp, "b%u", (ytreg & 0x1f));
159287084Sbapt      break;
160287084Sbapt    }
16152527Sdavidn}
162287084Sbapt
163287084Sbapt#define UNW_REG_BSP		"bsp"
164287084Sbapt#define UNW_REG_BSPSTORE	"bspstore"
165287084Sbapt#define UNW_REG_FPSR		"fpsr"
16620253Sjoerg#define UNW_REG_LC		"lc"
16752527Sdavidn#define UNW_REG_PFS		"pfs"
168287084Sbapt#define UNW_REG_PR		"pr"
169287084Sbapt#define UNW_REG_PSP		"psp"
170287084Sbapt#define UNW_REG_RNAT		"rnat"
171287084Sbapt#define UNW_REG_RP		"rp"
172287084Sbapt#define UNW_REG_UNAT		"unat"
17320253Sjoerg
174287084Sbapttypedef bfd_vma unw_word;
175287084Sbapt
176287084Sbapt#define UNW_DEC_BAD_CODE(code)			\
177287084Sbapt    printf ("Unknown code 0x%02x\n", code)
178287084Sbapt
179287084Sbapt#define UNW_DEC_PROLOGUE(fmt, body, rlen, arg)					\
180287084Sbapt  do										\
181287084Sbapt    {										\
18220253Sjoerg      unw_rlen = rlen;								\
183287084Sbapt      *(int *)arg = body;							\
184287084Sbapt      printf ("    %s:%s(rlen=%lu)\n",						\
185287084Sbapt	      fmt, body ? "body" : "prologue", (unsigned long) rlen);		\
186287084Sbapt    }										\
18720253Sjoerg  while (0)
188287084Sbapt
189287084Sbapt#define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg)			\
19052527Sdavidn  do										\
191287084Sbapt    {										\
192287084Sbapt      char regname[16], maskstr[64], *sep;					\
193287084Sbapt										\
194287084Sbapt      unw_rlen = rlen;								\
195287084Sbapt      *(int *)arg = 0;								\
196287084Sbapt										\
197287084Sbapt      maskstr[0] = '\0';							\
198287084Sbapt      sep = "";									\
199287084Sbapt      if (mask & 0x8)								\
200287084Sbapt	{									\
201287084Sbapt	  strcat (maskstr, "rp");						\
202287084Sbapt	  sep = ",";								\
20320253Sjoerg	}									\
204287084Sbapt      if (mask & 0x4)								\
205287084Sbapt	{									\
206287084Sbapt	  strcat (maskstr, sep);						\
207287084Sbapt	  strcat (maskstr, "ar.pfs");						\
208287084Sbapt	  sep = ",";								\
209287084Sbapt	}									\
210287084Sbapt      if (mask & 0x2)								\
21152527Sdavidn	{									\
212287084Sbapt	  strcat (maskstr, sep);						\
213287084Sbapt	  strcat (maskstr, "psp");						\
214287084Sbapt	  sep = ",";								\
215287084Sbapt	}									\
216287084Sbapt      if (mask & 0x1)								\
217287084Sbapt	{									\
218287084Sbapt	  strcat (maskstr, sep);						\
219287084Sbapt	  strcat (maskstr, "pr");						\
220287084Sbapt	}									\
221287084Sbapt      sprintf (regname, "r%u", grsave);						\
222287084Sbapt      printf ("    %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n",		\
223287084Sbapt	      fmt, maskstr, regname, (unsigned long) rlen);			\
224287084Sbapt    }										\
22520253Sjoerg  while (0)
22664918Sgreen
227287084Sbapt#define UNW_DEC_FR_MEM(fmt, frmask, arg)			\
228287084Sbapt  do								\
22964918Sgreen    {								\
23064918Sgreen      char frstr[200];						\
231287084Sbapt								\
23220253Sjoerg      unw_print_frmask (frstr, frmask);				\
233287084Sbapt      printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr);	\
234287084Sbapt    }								\
23520253Sjoerg  while (0)
236287084Sbapt
237287084Sbapt#define UNW_DEC_GR_MEM(fmt, grmask, arg)			\
238287084Sbapt  do								\
239287084Sbapt    {								\
240287084Sbapt      char grstr[200];						\
24120253Sjoerg								\
242287084Sbapt      unw_print_grmask (grstr, grmask);				\
243287084Sbapt      printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr);	\
244287084Sbapt    }								\
24520253Sjoerg  while (0)
246287084Sbapt
247287084Sbapt#define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg)				\
248287084Sbapt  do										\
249287084Sbapt    {										\
250287084Sbapt      char frstr[200], grstr[20];						\
25120253Sjoerg										\
252287084Sbapt      unw_print_grmask (grstr, grmask);						\
253287084Sbapt      unw_print_frmask (frstr, frmask);						\
254285092Sbapt      printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr);	\
255287084Sbapt    }										\
256285092Sbapt  while (0)
257287084Sbapt
258287084Sbapt#define UNW_DEC_BR_MEM(fmt, brmask, arg)				\
25921330Sdavidn  do									\
260287084Sbapt    {									\
26121330Sdavidn      char brstr[20];							\
262287084Sbapt									\
263287084Sbapt      unw_print_brmask (brstr, brmask);					\
264287084Sbapt      printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr);		\
265287084Sbapt    }									\
266287084Sbapt  while (0)
267287084Sbapt
268287084Sbapt#define UNW_DEC_BR_GR(fmt, brmask, gr, arg)				\
269287084Sbapt  do									\
270287084Sbapt    {									\
271287084Sbapt      char brstr[20];							\
272287084Sbapt									\
273287084Sbapt      unw_print_brmask (brstr, brmask);					\
274287084Sbapt      printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr);	\
275287084Sbapt    }									\
276287084Sbapt  while (0)
277287084Sbapt
278292025Sbapt#define UNW_DEC_REG_GR(fmt, src, dst, arg)		\
27920253Sjoerg  printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
280287084Sbapt
281287084Sbapt#define UNW_DEC_RP_BR(fmt, dst, arg)		\
282274082Sbapt  printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
283287084Sbapt
284287084Sbapt#define UNW_DEC_REG_WHEN(fmt, reg, t, arg)				\
285242349Sbapt  printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
286292025Sbapt
287292025Sbapt#define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg)		\
288292025Sbapt  printf ("\t%s:%s_sprel(spoff=0x%lx)\n",		\
289242349Sbapt	  fmt, reg, 4*(unsigned long)spoff)
290292025Sbapt
291292025Sbapt#define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg)		\
292292025Sbapt  printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n",		\
293292025Sbapt	  fmt, reg, 4*(unsigned long)pspoff)
294292025Sbapt
295292025Sbapt#define UNW_DEC_GR_GR(fmt, grmask, gr, arg)				\
29661759Sdavidn  do									\
297292025Sbapt    {									\
298292025Sbapt      char grstr[20];							\
299287084Sbapt									\
30061759Sdavidn      unw_print_grmask (grstr, grmask);					\
30120253Sjoerg      printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr);		\
302287084Sbapt    }									\
303287084Sbapt  while (0)
30420253Sjoerg
305287084Sbapt#define UNW_DEC_ABI(fmt, abi, context, arg)			\
306287084Sbapt  do								\
307287084Sbapt    {								\
308287084Sbapt      static const char * const abiname[] =			\
309287084Sbapt      {								\
310287084Sbapt	"@svr4", "@hpux", "@nt"					\
311287084Sbapt      };							\
312287084Sbapt      char buf[20];						\
313287084Sbapt      const char *abistr = buf;					\
314287084Sbapt								\
315287084Sbapt      if (abi < 3)						\
316287084Sbapt	abistr = abiname[abi];					\
317287084Sbapt      else							\
318287084Sbapt	sprintf (buf, "0x%x", abi);				\
31920253Sjoerg      printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n",		\
32052527Sdavidn	      fmt, abistr, context);				\
321287084Sbapt    }								\
322287084Sbapt  while (0)
32352527Sdavidn
324287084Sbapt#define UNW_DEC_PRIUNAT_GR(fmt, r, arg)		\
32520253Sjoerg  printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
32620253Sjoerg
327287084Sbapt#define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg)				\
328287084Sbapt  printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
32920253Sjoerg
33020253Sjoerg#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg)				\
331287084Sbapt  printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
33220253Sjoerg
33320253Sjoerg#define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg)		\
33420253Sjoerg  printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n",		\
33520253Sjoerg	  fmt, 4*(unsigned long)pspoff)
33620253Sjoerg
337285536Sbapt#define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg)		\
338285092Sbapt  printf ("\t%s:priunat_sprel(spoff=0x%lx)\n",		\
33920253Sjoerg	  fmt, 4*(unsigned long)spoff)
340285092Sbapt
341287084Sbapt#define UNW_DEC_MEM_STACK_F(fmt, t, size, arg)		\
342287084Sbapt  printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n",		\
343287084Sbapt	  fmt, (unsigned long) t, 16*(unsigned long)size)
344287084Sbapt
345287084Sbapt#define UNW_DEC_MEM_STACK_V(fmt, t, arg)				\
346287084Sbapt  printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
347287084Sbapt
348287084Sbapt#define UNW_DEC_SPILL_BASE(fmt, pspoff, arg)			\
349287084Sbapt  printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n",		\
350287084Sbapt	  fmt, 4*(unsigned long)pspoff)
351287084Sbapt
352287084Sbapt#define UNW_DEC_SPILL_MASK(fmt, dp, arg, end)				\
353287084Sbapt  do									\
354287084Sbapt    {									\
355287084Sbapt      static const char *spill_type = "-frb";				\
35620253Sjoerg      unsigned const char *imaskp = dp;					\
357287084Sbapt      unsigned char mask = 0;						\
358287084Sbapt      bfd_vma insn = 0;							\
359287084Sbapt      									\
360287084Sbapt      /* PR 18420.  */							\
361287084Sbapt      if ((dp + (unw_rlen / 4)) > end)					\
362287084Sbapt	{								\
363287084Sbapt	  printf ("\nERROR: unwind length too long (0x%lx > 0x%lx)\n\n",\
364287084Sbapt		  (long) (unw_rlen / 4), (long)(end - dp));		\
36520253Sjoerg	  /* FIXME: Should we reset unw_rlen ?  */			\
366287084Sbapt	  break;							\
367287084Sbapt	}								\
368287084Sbapt      printf ("\t%s:spill_mask(imask=[", fmt);					\
369287084Sbapt      for (insn = 0; insn < unw_rlen; ++insn)					\
370287084Sbapt	{									\
37120253Sjoerg	  if ((insn % 4) == 0)							\
372287084Sbapt	    mask = *imaskp++;							\
373287084Sbapt	  if (insn > 0 && (insn % 3) == 0)					\
374287084Sbapt	    putchar (',');							\
375287084Sbapt	  putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]);	\
376287084Sbapt	}									\
377287084Sbapt      printf ("])\n");								\
378287084Sbapt      dp = imaskp;								\
37920253Sjoerg    }										\
38020253Sjoerg  while (0)
381287084Sbapt
382287084Sbapt#define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg)				\
38320253Sjoerg  do										\
38420253Sjoerg    {										\
38520253Sjoerg      char regname[20];								\
38620253Sjoerg										\
38720253Sjoerg      unw_print_abreg (regname, abreg);						\
38820253Sjoerg      printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n",			\
38920253Sjoerg	      fmt, regname, (unsigned long) t, 4*(unsigned long)off);		\
39044229Sdavidn    }										\
391287084Sbapt  while (0)
392287084Sbapt
393287084Sbapt#define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg)			\
394287084Sbapt  do										\
39520253Sjoerg    {										\
39620253Sjoerg      char regname[20];								\
397272192Sdteske										\
398272192Sdteske      unw_print_abreg (regname, abreg);						\
39920267Sjoerg      printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n",		\
40020253Sjoerg	      fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff);	\
401287084Sbapt    }										\
40220253Sjoerg  while (0)
40320253Sjoerg
40420253Sjoerg#define UNW_DEC_RESTORE(fmt, t, abreg, arg)			\
40520253Sjoerg  do								\
40620253Sjoerg    {								\
40720253Sjoerg      char regname[20];						\
40820253Sjoerg								\
40920253Sjoerg      unw_print_abreg (regname, abreg);				\
41020253Sjoerg      printf ("\t%s:restore(t=%lu,reg=%s)\n",			\
41120253Sjoerg	      fmt, (unsigned long) t, regname);			\
412285536Sbapt    }								\
413285536Sbapt  while (0)
414287084Sbapt
415287084Sbapt#define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg)		\
416287084Sbapt  do								\
417287084Sbapt    {								\
418287084Sbapt      char abregname[20], tregname[20];				\
419287084Sbapt								\
42044229Sdavidn      unw_print_abreg (abregname, abreg);			\
42120267Sjoerg      unw_print_xyreg (tregname, x, ytreg);			\
42220267Sjoerg      printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n",		\
42320253Sjoerg	      fmt, (unsigned long) t, abregname, tregname);	\
42444229Sdavidn    }								\
425287084Sbapt  while (0)
42620253Sjoerg
42720253Sjoerg#define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg)			    \
428287084Sbapt  do										    \
429287084Sbapt    {										    \
43020253Sjoerg      char regname[20];								    \
431285092Sbapt										    \
43220253Sjoerg      unw_print_abreg (regname, abreg);						    \
433287084Sbapt      printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n",		    \
434287084Sbapt	      fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff);	    \
43520253Sjoerg    }										    \
436285092Sbapt  while (0)
437285092Sbapt
438285092Sbapt#define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg)		\
439285092Sbapt  do									\
440285092Sbapt    {									\
44120253Sjoerg      char regname[20];							\
44220253Sjoerg									\
443287084Sbapt      unw_print_abreg (regname, abreg);					\
44420253Sjoerg      printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\
44520253Sjoerg	      fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\
44620253Sjoerg    }									\
44720253Sjoerg  while (0)
44820253Sjoerg
44920253Sjoerg#define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg)			\
45020253Sjoerg  do									\
45120253Sjoerg    {									\
45220253Sjoerg      char regname[20];							\
45320253Sjoerg									\
45420253Sjoerg      unw_print_abreg (regname, abreg);					\
455130633Srobert      printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n",			\
45620253Sjoerg	      fmt, qp, (unsigned long) t, regname);			\
45720253Sjoerg    }									\
45820253Sjoerg  while (0)
45920253Sjoerg
46020253Sjoerg#define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg)		\
461285092Sbapt  do									\
46220253Sjoerg    {									\
46320253Sjoerg      char regname[20], tregname[20];					\
46420253Sjoerg									\
46520253Sjoerg      unw_print_abreg (regname, abreg);					\
466285092Sbapt      unw_print_xyreg (tregname, x, ytreg);				\
46720253Sjoerg      printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n",	\
46820253Sjoerg	      fmt, qp, (unsigned long) t, regname, tregname);		\
46920253Sjoerg    }									\
47020253Sjoerg  while (0)
47120253Sjoerg
47230259Scharnier#define UNW_DEC_LABEL_STATE(fmt, label, arg)				\
47330259Scharnier  printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
47420253Sjoerg
47520253Sjoerg#define UNW_DEC_COPY_STATE(fmt, label, arg)				\
47620253Sjoerg  printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
47720253Sjoerg
478287084Sbapt#define UNW_DEC_EPILOGUE(fmt, t, ecount, arg)		\
479287084Sbapt  printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n",		\
48020253Sjoerg	  fmt, (unsigned long) t, (unsigned long) ecount)
48120253Sjoerg
482287084Sbapt/*
48320253Sjoerg * Generic IA-64 unwind info decoder.
48420253Sjoerg *
485179365Santoine * This file is used both by the Linux kernel and objdump.  Please
48620253Sjoerg * keep the two copies of this file in sync (modulo differences in the
487179365Santoine * prototypes...).
488179365Santoine *
489287084Sbapt * You need to customize the decoder by defining the following
49020253Sjoerg * macros/constants before including this file:
49120253Sjoerg *
49220253Sjoerg *  Types:
493179365Santoine *	unw_word	Unsigned integer type with at least 64 bits
494231994Skevlo *
49520253Sjoerg *  Register names:
496319267Sasomers *	UNW_REG_BSP
49720253Sjoerg *	UNW_REG_BSPSTORE
49820253Sjoerg *	UNW_REG_FPSR
49920253Sjoerg *	UNW_REG_LC
50020253Sjoerg *	UNW_REG_PFS
501179365Santoine *	UNW_REG_PR
502181785Sache *	UNW_REG_RNAT
503179365Santoine *	UNW_REG_PSP
50420253Sjoerg *	UNW_REG_RP
505231994Skevlo *	UNW_REG_UNAT
506231994Skevlo *
507231994Skevlo *  Decoder action macros:
508319267Sasomers *	UNW_DEC_BAD_CODE(code)
509319267Sasomers *	UNW_DEC_ABI(fmt,abi,context,arg)
510319267Sasomers *	UNW_DEC_BR_GR(fmt,brmask,gr,arg)
51120253Sjoerg *	UNW_DEC_BR_MEM(fmt,brmask,arg)
51220253Sjoerg *	UNW_DEC_COPY_STATE(fmt,label,arg)
513287084Sbapt *	UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
514287084Sbapt *	UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
51520253Sjoerg *	UNW_DEC_FR_MEM(fmt,frmask,arg)
51620253Sjoerg *	UNW_DEC_GR_GR(fmt,grmask,gr,arg)
51720253Sjoerg *	UNW_DEC_GR_MEM(fmt,grmask,arg)
51820253Sjoerg *	UNW_DEC_LABEL_STATE(fmt,label,arg)
51920253Sjoerg *	UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
520326849Seugen *	UNW_DEC_MEM_STACK_V(fmt,t,arg)
521326849Seugen *	UNW_DEC_PRIUNAT_GR(fmt,r,arg)
522326849Seugen *	UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
52373563Skris *	UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
52420253Sjoerg *	UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
525181785Sache *	UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
52620253Sjoerg *	UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
52720253Sjoerg *	UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
52820253Sjoerg *	UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
52920253Sjoerg *	UNW_DEC_REG_REG(fmt,src,dst,arg)
53020253Sjoerg *	UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
531287084Sbapt *	UNW_DEC_REG_WHEN(fmt,reg,t,arg)
53261957Sache *	UNW_DEC_RESTORE(fmt,t,abreg,arg)
53320712Sdavidn *	UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
53420253Sjoerg *	UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
53520253Sjoerg *	UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
53620253Sjoerg *	UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
53720253Sjoerg *	UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
538326849Seugen *	UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
539326849Seugen *	UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
540326849Seugen *	UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
541326849Seugen *	UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
542326849Seugen */
54320253Sjoerg
54420253Sjoergstatic unw_word
54520253Sjoergunw_decode_uleb128 (const unsigned char **dpp)
54620253Sjoerg{
54720253Sjoerg  unsigned shift = 0;
54820253Sjoerg  unw_word byte, result = 0;
549285092Sbapt  const unsigned char *bp = *dpp;
550287084Sbapt
551285092Sbapt  while (1)
552287084Sbapt    {
553287084Sbapt      byte = *bp++;
554287084Sbapt      result |= (byte & 0x7f) << shift;
555287084Sbapt
556287084Sbapt      if ((byte & 0x80) == 0)
557287084Sbapt	break;
558287084Sbapt
55920253Sjoerg      shift += 7;
560287084Sbapt    }
561287084Sbapt
562287084Sbapt  *dpp = bp;
563287084Sbapt
564287084Sbapt  return result;
565287084Sbapt}
566285092Sbapt
567287084Sbaptstatic const unsigned char *
568287084Sbaptunw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
569287084Sbapt	       void *arg ATTRIBUTE_UNUSED)
570287084Sbapt{
571287084Sbapt  unsigned char byte1, abreg;
572287084Sbapt  unw_word t, off;
573287084Sbapt
574287084Sbapt  byte1 = *dp++;
575287084Sbapt  t = unw_decode_uleb128 (&dp);
576287084Sbapt  off = unw_decode_uleb128 (&dp);
577285092Sbapt  abreg = (byte1 & 0x7f);
578285092Sbapt  if (byte1 & 0x80)
579285092Sbapt    UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
580287084Sbapt  else
581285092Sbapt    UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
582287084Sbapt  return dp;
583287084Sbapt}
584287084Sbapt
585285092Sbaptstatic const unsigned char *
586287084Sbaptunw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
587287084Sbapt	       void *arg ATTRIBUTE_UNUSED)
588287084Sbapt{
589285092Sbapt  unsigned char byte1, byte2, abreg, x, ytreg;
590287084Sbapt  unw_word t;
591287084Sbapt
592360326Sdim  byte1 = *dp++;
593287084Sbapt  byte2 = *dp++;
594287084Sbapt  t = unw_decode_uleb128 (&dp);
595287084Sbapt  abreg = (byte1 & 0x7f);
596287084Sbapt  ytreg = byte2;
597287084Sbapt  x = (byte1 >> 7) & 1;
598287084Sbapt  if ((byte1 & 0x80) == 0 && ytreg == 0)
599287084Sbapt    UNW_DEC_RESTORE ("X2", t, abreg, arg);
600287084Sbapt  else
601287084Sbapt    UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg);
602287084Sbapt  return dp;
603287084Sbapt}
604287084Sbapt
605287084Sbaptstatic const unsigned char *
606287084Sbaptunw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
607287084Sbapt	       void *arg ATTRIBUTE_UNUSED)
608287084Sbapt{
609287084Sbapt  unsigned char byte1, byte2, abreg, qp;
610287084Sbapt  unw_word t, off;
611287084Sbapt
612287084Sbapt  byte1 = *dp++;
613287084Sbapt  byte2 = *dp++;
61420267Sjoerg  t = unw_decode_uleb128 (&dp);
615287084Sbapt  off = unw_decode_uleb128 (&dp);
61620267Sjoerg
61720267Sjoerg  qp = (byte1 & 0x3f);
61820253Sjoerg  abreg = (byte2 & 0x7f);
619287084Sbapt
620287084Sbapt  if (byte1 & 0x80)
621287084Sbapt    UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
62220253Sjoerg  else
62320253Sjoerg    UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
624285092Sbapt  return dp;
625285092Sbapt}
62620253Sjoerg
627109961Sgadstatic const unsigned char *
628285092Sbaptunw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
629109961Sgad	       void *arg ATTRIBUTE_UNUSED)
63020253Sjoerg{
631109961Sgad  unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
632109961Sgad  unw_word t;
633109961Sgad
634109961Sgad  byte1 = *dp++;
635330695Sdab  byte2 = *dp++;
636109961Sgad  byte3 = *dp++;
637109961Sgad  t = unw_decode_uleb128 (&dp);
638109961Sgad
639109961Sgad  qp = (byte1 & 0x3f);
640109961Sgad  abreg = (byte2 & 0x7f);
641109961Sgad  x = (byte2 >> 7) & 1;
642109961Sgad  ytreg = byte3;
643109961Sgad
64420253Sjoerg  if ((byte2 & 0x80) == 0 && byte3 == 0)
645109961Sgad    UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
646109961Sgad  else
647292026Sbapt    UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
648292026Sbapt  return dp;
649109961Sgad}
650109961Sgad
651109961Sgadstatic const unsigned char *
652109961Sgadunw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg,
653109961Sgad	       const unsigned char * end ATTRIBUTE_UNUSED)
654109961Sgad{
655109961Sgad  int body = (code & 0x20) != 0;
656109961Sgad  unw_word rlen;
657109961Sgad
658109961Sgad  rlen = (code & 0x1f);
659109961Sgad  UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
660109961Sgad  return dp;
661109961Sgad}
662109961Sgad
663109961Sgadstatic const unsigned char *
664109961Sgadunw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg,
665109961Sgad	       const unsigned char * end ATTRIBUTE_UNUSED)
666109961Sgad{
667109961Sgad  unsigned char byte1, mask, grsave;
668109961Sgad  unw_word rlen;
669109961Sgad
670109961Sgad  byte1 = *dp++;
671109961Sgad
672109961Sgad  mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
673109961Sgad  grsave = (byte1 & 0x7f);
674228673Sdim  rlen = unw_decode_uleb128 (& dp);
675109961Sgad  UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
676109961Sgad  return dp;
677109961Sgad}
678287084Sbapt
679109961Sgadstatic const unsigned char *
680285092Sbaptunw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg,
681285092Sbapt	       const unsigned char * end ATTRIBUTE_UNUSED)
68220253Sjoerg{
68320253Sjoerg  unw_word rlen;
68420253Sjoerg
68520253Sjoerg  rlen = unw_decode_uleb128 (& dp);
68620253Sjoerg  UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
68720253Sjoerg  return dp;
68820253Sjoerg}
68920253Sjoerg
69020253Sjoergstatic const unsigned char *
69120253Sjoergunw_decode_p1 (const unsigned char *dp, unsigned int code,
69220253Sjoerg	       void *arg ATTRIBUTE_UNUSED,
69320253Sjoerg	       const unsigned char * end ATTRIBUTE_UNUSED)
69420253Sjoerg{
69520253Sjoerg  unsigned char brmask = (code & 0x1f);
69620253Sjoerg
69720253Sjoerg  UNW_DEC_BR_MEM ("P1", brmask, arg);
69820253Sjoerg  return dp;
69920253Sjoerg}
70020253Sjoerg
701287084Sbaptstatic const unsigned char *
702287084Sbaptunw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
70320253Sjoerg		  void *arg ATTRIBUTE_UNUSED,
70420253Sjoerg		  const unsigned char * end)
70520253Sjoerg{
70620253Sjoerg  if ((code & 0x10) == 0)
70720253Sjoerg    {
70820253Sjoerg      unsigned char byte1 = *dp++;
70920747Sdavidn
71020747Sdavidn      UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
71185145Sache		     (byte1 & 0x7f), arg);
71220747Sdavidn    }
713287084Sbapt  else if ((code & 0x08) == 0)
714287084Sbapt    {
715287084Sbapt      unsigned char byte1 = *dp++, r, dst;
716287084Sbapt
717287084Sbapt      r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
718287084Sbapt      dst = (byte1 & 0x7f);
719287084Sbapt      switch (r)
720287084Sbapt	{
72120747Sdavidn	case 0:
722287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
723287084Sbapt	  break;
72420747Sdavidn	case 1:
725287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
726287084Sbapt	  break;
727287084Sbapt	case 2:
728287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
729287084Sbapt	  break;
730287084Sbapt	case 3:
731287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
732287084Sbapt	  break;
733287084Sbapt	case 4:
734287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
735287084Sbapt	  break;
736287084Sbapt	case 5:
737287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
738287084Sbapt	  break;
739287084Sbapt	case 6:
740287084Sbapt	  UNW_DEC_RP_BR ("P3", dst, arg);
741287084Sbapt	  break;
742287084Sbapt	case 7:
743287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
744287084Sbapt	  break;
745287084Sbapt	case 8:
746287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
747287084Sbapt	  break;
748287084Sbapt	case 9:
749287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
750287084Sbapt	  break;
751287084Sbapt	case 10:
752287084Sbapt	  UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
753287084Sbapt	  break;
754287084Sbapt	case 11:
755287084Sbapt	  UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
756287084Sbapt	  break;
757287084Sbapt	default:
758287084Sbapt	  UNW_DEC_BAD_CODE (r);
759287084Sbapt	  break;
760287084Sbapt	}
761287084Sbapt    }
762287084Sbapt  else if ((code & 0x7) == 0)
763287084Sbapt    UNW_DEC_SPILL_MASK ("P4", dp, arg, end);
764287084Sbapt  else if ((code & 0x7) == 1)
765287084Sbapt    {
766287084Sbapt      unw_word grmask, frmask, byte1, byte2, byte3;
767287084Sbapt
768287084Sbapt      byte1 = *dp++;
769287084Sbapt      byte2 = *dp++;
770287084Sbapt      byte3 = *dp++;
771287084Sbapt      grmask = ((byte1 >> 4) & 0xf);
772287084Sbapt      frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
773287084Sbapt      UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
774287084Sbapt    }
775287084Sbapt  else
776287084Sbapt    UNW_DEC_BAD_CODE (code);
777287084Sbapt
778287084Sbapt  return dp;
779287084Sbapt}
780287084Sbapt
781287084Sbaptstatic const unsigned char *
782287084Sbaptunw_decode_p6 (const unsigned char *dp, unsigned int code,
783287084Sbapt	       void *arg ATTRIBUTE_UNUSED,
784287084Sbapt	       const unsigned char * end ATTRIBUTE_UNUSED)
785287084Sbapt{
786287084Sbapt  int gregs = (code & 0x10) != 0;
787287084Sbapt  unsigned char mask = (code & 0x0f);
788287084Sbapt
789287084Sbapt  if (gregs)
790287084Sbapt    UNW_DEC_GR_MEM ("P6", mask, arg);
791287084Sbapt  else
792287084Sbapt    UNW_DEC_FR_MEM ("P6", mask, arg);
793287084Sbapt  return dp;
794287084Sbapt}
795287084Sbapt
796287084Sbaptstatic const unsigned char *
797287084Sbaptunw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg,
798287084Sbapt		   const unsigned char * end ATTRIBUTE_UNUSED)
799287084Sbapt{
800287084Sbapt  unsigned char r, byte1, byte2;
801287084Sbapt  unw_word t, size;
802287084Sbapt
803287084Sbapt  if ((code & 0x10) == 0)
804287084Sbapt    {
805287084Sbapt      r = (code & 0xf);
806287084Sbapt      t = unw_decode_uleb128 (&dp);
807287084Sbapt      switch (r)
808287084Sbapt	{
809287084Sbapt	case 0:
810287084Sbapt	  size = unw_decode_uleb128 (&dp);
811287084Sbapt	  UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
812287084Sbapt	  break;
813287084Sbapt
814287084Sbapt	case 1:
815287084Sbapt	  UNW_DEC_MEM_STACK_V ("P7", t, arg);
816293682Sbapt	  break;
817287084Sbapt	case 2:
818287084Sbapt	  UNW_DEC_SPILL_BASE ("P7", t, arg);
819287084Sbapt	  break;
820287084Sbapt	case 3:
821287084Sbapt	  UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
822287084Sbapt	  break;
823287084Sbapt	case 4:
824287084Sbapt	  UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
825287084Sbapt	  break;
826287084Sbapt	case 5:
827287084Sbapt	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
828287084Sbapt	  break;
829287084Sbapt	case 6:
830287084Sbapt	  UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
831287084Sbapt	  break;
832287084Sbapt	case 7:
833287084Sbapt	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
834287084Sbapt	  break;
835287084Sbapt	case 8:
836287084Sbapt	  UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
837287084Sbapt	  break;
838287084Sbapt	case 9:
839287084Sbapt	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
840287084Sbapt	  break;
841287084Sbapt	case 10:
842287084Sbapt	  UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
843287084Sbapt	  break;
844287084Sbapt	case 11:
845287084Sbapt	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
846287084Sbapt	  break;
847287084Sbapt	case 12:
848287084Sbapt	  UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
849287084Sbapt	  break;
850287084Sbapt	case 13:
851287084Sbapt	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
852287084Sbapt	  break;
853287084Sbapt	case 14:
854287084Sbapt	  UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
855287084Sbapt	  break;
856287084Sbapt	case 15:
857287084Sbapt	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
858287084Sbapt	  break;
859287084Sbapt	default:
860287084Sbapt	  UNW_DEC_BAD_CODE (r);
861287084Sbapt	  break;
862287084Sbapt	}
863287084Sbapt    }
864287084Sbapt  else
865287084Sbapt    {
866287084Sbapt      switch (code & 0xf)
867287084Sbapt	{
868287084Sbapt	case 0x0:		/* p8 */
869287084Sbapt	  {
870287084Sbapt	    r = *dp++;
871287084Sbapt	    t = unw_decode_uleb128 (&dp);
872287084Sbapt	    switch (r)
873287084Sbapt	      {
874287084Sbapt	      case 1:
875287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
876287084Sbapt		break;
877287084Sbapt	      case 2:
878287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
879287084Sbapt		break;
880287084Sbapt	      case 3:
881287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
882287084Sbapt		break;
883287084Sbapt	      case 4:
884287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
885287084Sbapt		break;
886287084Sbapt	      case 5:
887287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
888287084Sbapt		break;
889287084Sbapt	      case 6:
890287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
891287084Sbapt		break;
892287084Sbapt	      case 7:
893287084Sbapt		UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
894287084Sbapt		break;
895287084Sbapt	      case 8:
896287084Sbapt		UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
897287084Sbapt		break;
898287084Sbapt	      case 9:
899287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
900287084Sbapt		break;
901287084Sbapt	      case 10:
902287084Sbapt		UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
903287084Sbapt		break;
904287084Sbapt	      case 11:
905287084Sbapt		UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
906287084Sbapt		break;
907287084Sbapt	      case 12:
908287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
909287084Sbapt		break;
910287084Sbapt	      case 13:
911287084Sbapt		UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
912287084Sbapt		break;
913287084Sbapt	      case 14:
914287084Sbapt		UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
915287084Sbapt		break;
916287084Sbapt	      case 15:
917287084Sbapt		UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
918287084Sbapt		break;
919287084Sbapt	      case 16:
920287084Sbapt		UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
921287084Sbapt		break;
922287084Sbapt	      case 17:
923287084Sbapt		UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
924287084Sbapt		break;
925287084Sbapt	      case 18:
926287084Sbapt		UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
927287084Sbapt		break;
928287084Sbapt	      case 19:
929287084Sbapt		UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
930287084Sbapt		break;
931287084Sbapt	      default:
932287084Sbapt		UNW_DEC_BAD_CODE (r);
933287084Sbapt		break;
934287084Sbapt	      }
935287084Sbapt	  }
936287084Sbapt	  break;
937287084Sbapt
938287084Sbapt	case 0x1:
939287084Sbapt	  byte1 = *dp++;
940287084Sbapt	  byte2 = *dp++;
941287084Sbapt	  UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
942287084Sbapt	  break;
943287084Sbapt
944287084Sbapt	case 0xf:		/* p10 */
945287084Sbapt	  byte1 = *dp++;
946287084Sbapt	  byte2 = *dp++;
947287084Sbapt	  UNW_DEC_ABI ("P10", byte1, byte2, arg);
948287084Sbapt	  break;
949287084Sbapt
950287084Sbapt	case 0x9:
951287084Sbapt	  return unw_decode_x1 (dp, code, arg);
952287084Sbapt
953287084Sbapt	case 0xa:
954287084Sbapt	  return unw_decode_x2 (dp, code, arg);
955287084Sbapt
956287084Sbapt	case 0xb:
957287084Sbapt	  return unw_decode_x3 (dp, code, arg);
958287084Sbapt
959287084Sbapt	case 0xc:
960287084Sbapt	  return unw_decode_x4 (dp, code, arg);
961287084Sbapt
962287084Sbapt	default:
963287084Sbapt	  UNW_DEC_BAD_CODE (code);
964287084Sbapt	  break;
965287084Sbapt	}
966287084Sbapt    }
967287084Sbapt  return dp;
968287084Sbapt}
969287084Sbapt
970287084Sbaptstatic const unsigned char *
971287084Sbaptunw_decode_b1 (const unsigned char *dp, unsigned int code,
972287084Sbapt	       void *arg ATTRIBUTE_UNUSED,
973287084Sbapt	       const unsigned char * end ATTRIBUTE_UNUSED)
974287084Sbapt{
975287084Sbapt  unw_word label = (code & 0x1f);
976287084Sbapt
977287084Sbapt  if ((code & 0x20) != 0)
978287084Sbapt    UNW_DEC_COPY_STATE ("B1", label, arg);
979287084Sbapt  else
980287084Sbapt    UNW_DEC_LABEL_STATE ("B1", label, arg);
981287084Sbapt  return dp;
982287084Sbapt}
983287084Sbapt
984287084Sbaptstatic const unsigned char *
985287084Sbaptunw_decode_b2 (const unsigned char *dp, unsigned int code,
986287084Sbapt	       void *arg ATTRIBUTE_UNUSED,
987287084Sbapt	       const unsigned char * end ATTRIBUTE_UNUSED)
988287084Sbapt{
989287084Sbapt  unw_word t;
990287084Sbapt
991287084Sbapt  t = unw_decode_uleb128 (& dp);
992287084Sbapt  UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
993287084Sbapt  return dp;
994287084Sbapt}
995287084Sbapt
996287084Sbaptstatic const unsigned char *
997287084Sbaptunw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg,
998287084Sbapt		  const unsigned char * end ATTRIBUTE_UNUSED)
999287084Sbapt{
1000287084Sbapt  unw_word t, ecount, label;
1001287084Sbapt
1002287084Sbapt  if ((code & 0x10) == 0)
1003287084Sbapt    {
1004287084Sbapt      t = unw_decode_uleb128 (&dp);
1005287084Sbapt      ecount = unw_decode_uleb128 (&dp);
1006287084Sbapt      UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
1007287084Sbapt    }
1008287084Sbapt  else if ((code & 0x07) == 0)
1009287084Sbapt    {
1010287084Sbapt      label = unw_decode_uleb128 (&dp);
1011287084Sbapt      if ((code & 0x08) != 0)
1012287084Sbapt	UNW_DEC_COPY_STATE ("B4", label, arg);
1013287084Sbapt      else
1014287084Sbapt	UNW_DEC_LABEL_STATE ("B4", label, arg);
1015287084Sbapt    }
1016287084Sbapt  else
1017287084Sbapt    switch (code & 0x7)
1018287084Sbapt      {
1019287084Sbapt      case 1:
1020287084Sbapt	return unw_decode_x1 (dp, code, arg);
1021287084Sbapt      case 2:
1022287084Sbapt	return unw_decode_x2 (dp, code, arg);
1023287084Sbapt      case 3:
1024287084Sbapt	return unw_decode_x3 (dp, code, arg);
1025287084Sbapt      case 4:
1026287084Sbapt	return unw_decode_x4 (dp, code, arg);
1027287084Sbapt      default:
1028287084Sbapt	UNW_DEC_BAD_CODE (code);
1029287084Sbapt	break;
1030287084Sbapt      }
1031287084Sbapt  return dp;
1032287084Sbapt}
1033287084Sbapt
1034287084Sbapttypedef const unsigned char *(*unw_decoder)
1035287084Sbapt  (const unsigned char *, unsigned int, void *, const unsigned char *);
1036287084Sbapt
1037287084Sbaptstatic const unw_decoder unw_decode_table[2][8] =
1038287084Sbapt  {
1039287084Sbapt    /* prologue table: */
1040287084Sbapt    {
1041287084Sbapt      unw_decode_r1,		/* 0 */
1042287084Sbapt      unw_decode_r1,
1043287084Sbapt      unw_decode_r2,
1044287084Sbapt      unw_decode_r3,
1045287084Sbapt      unw_decode_p1,		/* 4 */
1046287084Sbapt      unw_decode_p2_p5,
1047287084Sbapt      unw_decode_p6,
1048287084Sbapt      unw_decode_p7_p10
1049287084Sbapt    },
1050287084Sbapt    {
1051287084Sbapt      unw_decode_r1,		/* 0 */
1052287084Sbapt      unw_decode_r1,
1053287084Sbapt      unw_decode_r2,
1054287084Sbapt      unw_decode_r3,
1055287084Sbapt      unw_decode_b1,		/* 4 */
1056287084Sbapt      unw_decode_b1,
1057287084Sbapt      unw_decode_b2,
1058287084Sbapt      unw_decode_b3_x4
1059287084Sbapt    }
1060287084Sbapt  };
1061287084Sbapt
1062287084Sbapt/* Decode one descriptor and return address of next descriptor.  */
1063287084Sbaptconst unsigned char *
1064287084Sbaptunw_decode (const unsigned char *dp, int inside_body,
1065287084Sbapt	    void *ptr_inside_body, const unsigned char * end)
1066287084Sbapt{
1067287084Sbapt  unw_decoder decoder;
1068287084Sbapt  unsigned char code;
1069287084Sbapt
1070287084Sbapt  code = *dp++;
1071287084Sbapt  decoder = unw_decode_table[inside_body][code >> 5];
1072287084Sbapt  return (*decoder) (dp, code, ptr_inside_body, end);
1073287084Sbapt}
1074287084Sbapt