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