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