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