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