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