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