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