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