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