Import binutils-2.20
[dragonfly.git] / contrib / binutils-2.20 / binutils / unwind-ia64.c
1 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2    Copyright 2000, 2001, 2002, 2003, 2005, 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 }