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