2009-06-19 Tristan Gingold <gingold@adacore.com>
[binutils.git] / binutils / unwind-ia64.c
blobad1827cdfba6c86fd90543c295c57d5ce903dabd
1 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2 Copyright 2000, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5 This file is part of GNU Binutils.
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 3, or (at your option)
10 any later version.
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.
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,
20 MA 02110-1301, USA. */
22 #include "unwind-ia64.h"
23 #include <stdio.h>
24 #include <string.h>
26 #if __GNUC__ >= 2
27 /* Define BFD64 here, even if our default architecture is 32 bit ELF
28 as this will allow us to read in and parse 64bit and 32bit ELF files.
29 Only do this if we believe that the compiler can support a 64 bit
30 data type. For now we only rely on GCC being able to do this. */
31 #define BFD64
32 #endif
33 #include "bfd.h"
35 static bfd_vma unw_rlen = 0;
37 static void unw_print_brmask (char *, unsigned int);
38 static void unw_print_grmask (char *, unsigned int);
39 static void unw_print_frmask (char *, unsigned int);
40 static void unw_print_abreg (char *, unsigned int);
41 static void unw_print_xyreg (char *, unsigned int, unsigned int);
43 static void
44 unw_print_brmask (char *cp, unsigned int mask)
46 int sep = 0;
47 int i;
49 for (i = 0; mask && (i < 5); ++i)
51 if (mask & 1)
53 if (sep)
54 *cp++ = ',';
55 *cp++ = 'b';
56 *cp++ = i + 1 + '0';
57 sep = 1;
59 mask >>= 1;
61 *cp = '\0';
64 static void
65 unw_print_grmask (char *cp, unsigned int mask)
67 int sep = 0;
68 int i;
70 for (i = 0; i < 4; ++i)
72 if (mask & 1)
74 if (sep)
75 *cp++ = ',';
76 *cp++ = 'r';
77 *cp++ = i + 4 + '0';
78 sep = 1;
80 mask >>= 1;
82 *cp = '\0';
85 static void
86 unw_print_frmask (char *cp, unsigned int mask)
88 int sep = 0;
89 int i;
91 for (i = 0; i < 20; ++i)
93 if (mask & 1)
95 if (sep)
96 *cp++ = ',';
97 *cp++ = 'f';
98 if (i < 4)
99 *cp++ = i + 2 + '0';
100 else
102 *cp++ = (i + 2) / 10 + 1 + '0';
103 *cp++ = (i + 2) % 10 + '0';
105 sep = 1;
107 mask >>= 1;
109 *cp = '\0';
112 static void
113 unw_print_abreg (char *cp, unsigned int abreg)
115 static const char *special_reg[16] =
117 "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
118 "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
119 "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
122 switch ((abreg >> 5) & 0x3)
124 case 0: /* gr */
125 sprintf (cp, "r%u", (abreg & 0x1f));
126 break;
128 case 1: /* fr */
129 sprintf (cp, "f%u", (abreg & 0x1f));
130 break;
132 case 2: /* br */
133 sprintf (cp, "b%u", (abreg & 0x1f));
134 break;
136 case 3: /* special */
137 strcpy (cp, special_reg[abreg & 0xf]);
138 break;
142 static void
143 unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
145 switch ((x << 1) | ((ytreg >> 7) & 1))
147 case 0: /* gr */
148 sprintf (cp, "r%u", (ytreg & 0x1f));
149 break;
151 case 1: /* fr */
152 sprintf (cp, "f%u", (ytreg & 0x1f));
153 break;
155 case 2: /* br */
156 sprintf (cp, "b%u", (ytreg & 0x1f));
157 break;
161 #define UNW_REG_BSP "bsp"
162 #define UNW_REG_BSPSTORE "bspstore"
163 #define UNW_REG_FPSR "fpsr"
164 #define UNW_REG_LC "lc"
165 #define UNW_REG_PFS "pfs"
166 #define UNW_REG_PR "pr"
167 #define UNW_REG_PSP "psp"
168 #define UNW_REG_RNAT "rnat"
169 #define UNW_REG_RP "rp"
170 #define UNW_REG_UNAT "unat"
172 typedef bfd_vma unw_word;
174 #define UNW_DEC_BAD_CODE(code) \
175 printf ("Unknown code 0x%02x\n", code)
177 #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \
178 do \
180 unw_rlen = rlen; \
181 *(int *)arg = body; \
182 printf (" %s:%s(rlen=%lu)\n", \
183 fmt, body ? "body" : "prologue", (unsigned long) rlen); \
185 while (0)
187 #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \
188 do \
190 char regname[16], maskstr[64], *sep; \
192 unw_rlen = rlen; \
193 *(int *)arg = 0; \
195 maskstr[0] = '\0'; \
196 sep = ""; \
197 if (mask & 0x8) \
199 strcat (maskstr, "rp"); \
200 sep = ","; \
202 if (mask & 0x4) \
204 strcat (maskstr, sep); \
205 strcat (maskstr, "ar.pfs"); \
206 sep = ","; \
208 if (mask & 0x2) \
210 strcat (maskstr, sep); \
211 strcat (maskstr, "psp"); \
212 sep = ","; \
214 if (mask & 0x1) \
216 strcat (maskstr, sep); \
217 strcat (maskstr, "pr"); \
219 sprintf (regname, "r%u", grsave); \
220 printf (" %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \
221 fmt, maskstr, regname, (unsigned long) rlen); \
223 while (0)
225 #define UNW_DEC_FR_MEM(fmt, frmask, arg) \
226 do \
228 char frstr[200]; \
230 unw_print_frmask (frstr, frmask); \
231 printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \
233 while (0)
235 #define UNW_DEC_GR_MEM(fmt, grmask, arg) \
236 do \
238 char grstr[200]; \
240 unw_print_grmask (grstr, grmask); \
241 printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \
243 while (0)
245 #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \
246 do \
248 char frstr[200], grstr[20]; \
250 unw_print_grmask (grstr, grmask); \
251 unw_print_frmask (frstr, frmask); \
252 printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr); \
254 while (0)
256 #define UNW_DEC_BR_MEM(fmt, brmask, arg) \
257 do \
259 char brstr[20]; \
261 unw_print_brmask (brstr, brmask); \
262 printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \
264 while (0)
266 #define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \
267 do \
269 char brstr[20]; \
271 unw_print_brmask (brstr, brmask); \
272 printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \
274 while (0)
276 #define UNW_DEC_REG_GR(fmt, src, dst, arg) \
277 printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
279 #define UNW_DEC_RP_BR(fmt, dst, arg) \
280 printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
282 #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \
283 printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
285 #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \
286 printf ("\t%s:%s_sprel(spoff=0x%lx)\n", \
287 fmt, reg, 4*(unsigned long)spoff)
289 #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \
290 printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n", \
291 fmt, reg, 4*(unsigned long)pspoff)
293 #define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \
294 do \
296 char grstr[20]; \
298 unw_print_grmask (grstr, grmask); \
299 printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \
301 while (0)
303 #define UNW_DEC_ABI(fmt, abi, context, arg) \
304 do \
306 static const char *abiname[] = \
308 "@svr4", "@hpux", "@nt" \
309 }; \
310 char buf[20]; \
311 const char *abistr = buf; \
313 if (abi < 3) \
314 abistr = abiname[abi]; \
315 else \
316 sprintf (buf, "0x%x", abi); \
317 printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n", \
318 fmt, abistr, context); \
320 while (0)
322 #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \
323 printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
325 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \
326 printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
328 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \
329 printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
331 #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \
332 printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n", \
333 fmt, 4*(unsigned long)pspoff)
335 #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \
336 printf ("\t%s:priunat_sprel(spoff=0x%lx)\n", \
337 fmt, 4*(unsigned long)spoff)
339 #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \
340 printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n", \
341 fmt, (unsigned long) t, 16*(unsigned long)size)
343 #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \
344 printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
346 #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \
347 printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \
348 fmt, 4*(unsigned long)pspoff)
350 #define UNW_DEC_SPILL_MASK(fmt, dp, arg) \
351 do \
353 static const char *spill_type = "-frb"; \
354 unsigned const char *imaskp = dp; \
355 unsigned char mask = 0; \
356 bfd_vma insn = 0; \
358 printf ("\t%s:spill_mask(imask=[", fmt); \
359 for (insn = 0; insn < unw_rlen; ++insn) \
361 if ((insn % 4) == 0) \
362 mask = *imaskp++; \
363 if (insn > 0 && (insn % 3) == 0) \
364 putchar (','); \
365 putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]); \
367 printf ("])\n"); \
368 dp = imaskp; \
370 while (0)
372 #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \
373 do \
375 char regname[20]; \
377 unw_print_abreg (regname, abreg); \
378 printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \
379 fmt, regname, (unsigned long) t, 4*(unsigned long)off); \
381 while (0)
383 #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \
384 do \
386 char regname[20]; \
388 unw_print_abreg (regname, abreg); \
389 printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \
390 fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff); \
392 while (0)
394 #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \
395 do \
397 char regname[20]; \
399 unw_print_abreg (regname, abreg); \
400 printf ("\t%s:restore(t=%lu,reg=%s)\n", \
401 fmt, (unsigned long) t, regname); \
403 while (0)
405 #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \
406 do \
408 char abregname[20], tregname[20]; \
410 unw_print_abreg (abregname, abreg); \
411 unw_print_xyreg (tregname, x, ytreg); \
412 printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n", \
413 fmt, (unsigned long) t, abregname, tregname); \
415 while (0)
417 #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \
418 do \
420 char regname[20]; \
422 unw_print_abreg (regname, abreg); \
423 printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \
424 fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff); \
426 while (0)
428 #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \
429 do \
431 char regname[20]; \
433 unw_print_abreg (regname, abreg); \
434 printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\
435 fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\
437 while (0)
439 #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \
440 do \
442 char regname[20]; \
444 unw_print_abreg (regname, abreg); \
445 printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n", \
446 fmt, qp, (unsigned long) t, regname); \
448 while (0)
450 #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \
451 do \
453 char regname[20], tregname[20]; \
455 unw_print_abreg (regname, abreg); \
456 unw_print_xyreg (tregname, x, ytreg); \
457 printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n", \
458 fmt, qp, (unsigned long) t, regname, tregname); \
460 while (0)
462 #define UNW_DEC_LABEL_STATE(fmt, label, arg) \
463 printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
465 #define UNW_DEC_COPY_STATE(fmt, label, arg) \
466 printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
468 #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \
469 printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n", \
470 fmt, (unsigned long) t, (unsigned long) ecount)
473 * Generic IA-64 unwind info decoder.
475 * This file is used both by the Linux kernel and objdump. Please
476 * keep the two copies of this file in sync (modulo differences in the
477 * prototypes...).
479 * You need to customize the decoder by defining the following
480 * macros/constants before including this file:
482 * Types:
483 * unw_word Unsigned integer type with at least 64 bits
485 * Register names:
486 * UNW_REG_BSP
487 * UNW_REG_BSPSTORE
488 * UNW_REG_FPSR
489 * UNW_REG_LC
490 * UNW_REG_PFS
491 * UNW_REG_PR
492 * UNW_REG_RNAT
493 * UNW_REG_PSP
494 * UNW_REG_RP
495 * UNW_REG_UNAT
497 * Decoder action macros:
498 * UNW_DEC_BAD_CODE(code)
499 * UNW_DEC_ABI(fmt,abi,context,arg)
500 * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
501 * UNW_DEC_BR_MEM(fmt,brmask,arg)
502 * UNW_DEC_COPY_STATE(fmt,label,arg)
503 * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
504 * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
505 * UNW_DEC_FR_MEM(fmt,frmask,arg)
506 * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
507 * UNW_DEC_GR_MEM(fmt,grmask,arg)
508 * UNW_DEC_LABEL_STATE(fmt,label,arg)
509 * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
510 * UNW_DEC_MEM_STACK_V(fmt,t,arg)
511 * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
512 * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
513 * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
514 * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
515 * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
516 * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
517 * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
518 * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
519 * UNW_DEC_REG_REG(fmt,src,dst,arg)
520 * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
521 * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
522 * UNW_DEC_RESTORE(fmt,t,abreg,arg)
523 * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
524 * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
525 * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
526 * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
527 * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
528 * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
529 * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
530 * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
531 * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
534 static unw_word unw_decode_uleb128 (const unsigned char **);
535 static const unsigned char *unw_decode_x1
536 (const unsigned char *, unsigned int, void *);
537 static const unsigned char *unw_decode_x2
538 (const unsigned char *, unsigned int, void *);
539 static const unsigned char *unw_decode_x3
540 (const unsigned char *, unsigned int, void *);
541 static const unsigned char *unw_decode_x4
542 (const unsigned char *, unsigned int, void *);
543 static const unsigned char *unw_decode_r1
544 (const unsigned char *, unsigned int, void *);
545 static const unsigned char *unw_decode_r2
546 (const unsigned char *, unsigned int, void *);
547 static const unsigned char *unw_decode_r3
548 (const unsigned char *, unsigned int, void *);
549 static const unsigned char *unw_decode_p1
550 (const unsigned char *, unsigned int, void *);
551 static const unsigned char *unw_decode_p2_p5
552 (const unsigned char *, unsigned int, void *);
553 static const unsigned char *unw_decode_p6
554 (const unsigned char *, unsigned int, void *);
555 static const unsigned char *unw_decode_p7_p10
556 (const unsigned char *, unsigned int, void *);
557 static const unsigned char *unw_decode_b1
558 (const unsigned char *, unsigned int, void *);
559 static const unsigned char *unw_decode_b2
560 (const unsigned char *, unsigned int, void *);
561 static const unsigned char *unw_decode_b3_x4
562 (const unsigned char *, unsigned int, void *);
564 static unw_word
565 unw_decode_uleb128 (const unsigned char **dpp)
567 unsigned shift = 0;
568 unw_word byte, result = 0;
569 const unsigned char *bp = *dpp;
571 while (1)
573 byte = *bp++;
574 result |= (byte & 0x7f) << shift;
576 if ((byte & 0x80) == 0)
577 break;
579 shift += 7;
582 *dpp = bp;
584 return result;
587 static const unsigned char *
588 unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
589 void *arg ATTRIBUTE_UNUSED)
591 unsigned char byte1, abreg;
592 unw_word t, off;
594 byte1 = *dp++;
595 t = unw_decode_uleb128 (&dp);
596 off = unw_decode_uleb128 (&dp);
597 abreg = (byte1 & 0x7f);
598 if (byte1 & 0x80)
599 UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
600 else
601 UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
602 return dp;
605 static const unsigned char *
606 unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
607 void *arg ATTRIBUTE_UNUSED)
609 unsigned char byte1, byte2, abreg, x, ytreg;
610 unw_word t;
612 byte1 = *dp++;
613 byte2 = *dp++;
614 t = unw_decode_uleb128 (&dp);
615 abreg = (byte1 & 0x7f);
616 ytreg = byte2;
617 x = (byte1 >> 7) & 1;
618 if ((byte1 & 0x80) == 0 && ytreg == 0)
619 UNW_DEC_RESTORE ("X2", t, abreg, arg);
620 else
621 UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg);
622 return dp;
625 static const unsigned char *
626 unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
627 void *arg ATTRIBUTE_UNUSED)
629 unsigned char byte1, byte2, abreg, qp;
630 unw_word t, off;
632 byte1 = *dp++;
633 byte2 = *dp++;
634 t = unw_decode_uleb128 (&dp);
635 off = unw_decode_uleb128 (&dp);
637 qp = (byte1 & 0x3f);
638 abreg = (byte2 & 0x7f);
640 if (byte1 & 0x80)
641 UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
642 else
643 UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
644 return dp;
647 static const unsigned char *
648 unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
649 void *arg ATTRIBUTE_UNUSED)
651 unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
652 unw_word t;
654 byte1 = *dp++;
655 byte2 = *dp++;
656 byte3 = *dp++;
657 t = unw_decode_uleb128 (&dp);
659 qp = (byte1 & 0x3f);
660 abreg = (byte2 & 0x7f);
661 x = (byte2 >> 7) & 1;
662 ytreg = byte3;
664 if ((byte2 & 0x80) == 0 && byte3 == 0)
665 UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
666 else
667 UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
668 return dp;
671 static const unsigned char *
672 unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
674 int body = (code & 0x20) != 0;
675 unw_word rlen;
677 rlen = (code & 0x1f);
678 UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
679 return dp;
682 static const unsigned char *
683 unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg)
685 unsigned char byte1, mask, grsave;
686 unw_word rlen;
688 byte1 = *dp++;
690 mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
691 grsave = (byte1 & 0x7f);
692 rlen = unw_decode_uleb128 (& dp);
693 UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
694 return dp;
697 static const unsigned char *
698 unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg)
700 unw_word rlen;
702 rlen = unw_decode_uleb128 (& dp);
703 UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
704 return dp;
707 static const unsigned char *
708 unw_decode_p1 (const unsigned char *dp, unsigned int code,
709 void *arg ATTRIBUTE_UNUSED)
711 unsigned char brmask = (code & 0x1f);
713 UNW_DEC_BR_MEM ("P1", brmask, arg);
714 return dp;
717 static const unsigned char *
718 unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
719 void *arg ATTRIBUTE_UNUSED)
721 if ((code & 0x10) == 0)
723 unsigned char byte1 = *dp++;
725 UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
726 (byte1 & 0x7f), arg);
728 else if ((code & 0x08) == 0)
730 unsigned char byte1 = *dp++, r, dst;
732 r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
733 dst = (byte1 & 0x7f);
734 switch (r)
736 case 0:
737 UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
738 break;
739 case 1:
740 UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
741 break;
742 case 2:
743 UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
744 break;
745 case 3:
746 UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
747 break;
748 case 4:
749 UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
750 break;
751 case 5:
752 UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
753 break;
754 case 6:
755 UNW_DEC_RP_BR ("P3", dst, arg);
756 break;
757 case 7:
758 UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
759 break;
760 case 8:
761 UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
762 break;
763 case 9:
764 UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
765 break;
766 case 10:
767 UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
768 break;
769 case 11:
770 UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
771 break;
772 default:
773 UNW_DEC_BAD_CODE (r);
774 break;
777 else if ((code & 0x7) == 0)
778 UNW_DEC_SPILL_MASK ("P4", dp, arg);
779 else if ((code & 0x7) == 1)
781 unw_word grmask, frmask, byte1, byte2, byte3;
783 byte1 = *dp++;
784 byte2 = *dp++;
785 byte3 = *dp++;
786 grmask = ((byte1 >> 4) & 0xf);
787 frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
788 UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
790 else
791 UNW_DEC_BAD_CODE (code);
793 return dp;
796 static const unsigned char *
797 unw_decode_p6 (const unsigned char *dp, unsigned int code,
798 void *arg ATTRIBUTE_UNUSED)
800 int gregs = (code & 0x10) != 0;
801 unsigned char mask = (code & 0x0f);
803 if (gregs)
804 UNW_DEC_GR_MEM ("P6", mask, arg);
805 else
806 UNW_DEC_FR_MEM ("P6", mask, arg);
807 return dp;
810 static const unsigned char *
811 unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
813 unsigned char r, byte1, byte2;
814 unw_word t, size;
816 if ((code & 0x10) == 0)
818 r = (code & 0xf);
819 t = unw_decode_uleb128 (&dp);
820 switch (r)
822 case 0:
823 size = unw_decode_uleb128 (&dp);
824 UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
825 break;
827 case 1:
828 UNW_DEC_MEM_STACK_V ("P7", t, arg);
829 break;
830 case 2:
831 UNW_DEC_SPILL_BASE ("P7", t, arg);
832 break;
833 case 3:
834 UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
835 break;
836 case 4:
837 UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
838 break;
839 case 5:
840 UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
841 break;
842 case 6:
843 UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
844 break;
845 case 7:
846 UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
847 break;
848 case 8:
849 UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
850 break;
851 case 9:
852 UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
853 break;
854 case 10:
855 UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
856 break;
857 case 11:
858 UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
859 break;
860 case 12:
861 UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
862 break;
863 case 13:
864 UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
865 break;
866 case 14:
867 UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
868 break;
869 case 15:
870 UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
871 break;
872 default:
873 UNW_DEC_BAD_CODE (r);
874 break;
877 else
879 switch (code & 0xf)
881 case 0x0: /* p8 */
883 r = *dp++;
884 t = unw_decode_uleb128 (&dp);
885 switch (r)
887 case 1:
888 UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
889 break;
890 case 2:
891 UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
892 break;
893 case 3:
894 UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
895 break;
896 case 4:
897 UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
898 break;
899 case 5:
900 UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
901 break;
902 case 6:
903 UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
904 break;
905 case 7:
906 UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
907 break;
908 case 8:
909 UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
910 break;
911 case 9:
912 UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
913 break;
914 case 10:
915 UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
916 break;
917 case 11:
918 UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
919 break;
920 case 12:
921 UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
922 break;
923 case 13:
924 UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
925 break;
926 case 14:
927 UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
928 break;
929 case 15:
930 UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
931 break;
932 case 16:
933 UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
934 break;
935 case 17:
936 UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
937 break;
938 case 18:
939 UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
940 break;
941 case 19:
942 UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
943 break;
944 default:
945 UNW_DEC_BAD_CODE (r);
946 break;
949 break;
951 case 0x1:
952 byte1 = *dp++;
953 byte2 = *dp++;
954 UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
955 break;
957 case 0xf: /* p10 */
958 byte1 = *dp++;
959 byte2 = *dp++;
960 UNW_DEC_ABI ("P10", byte1, byte2, arg);
961 break;
963 case 0x9:
964 return unw_decode_x1 (dp, code, arg);
966 case 0xa:
967 return unw_decode_x2 (dp, code, arg);
969 case 0xb:
970 return unw_decode_x3 (dp, code, arg);
972 case 0xc:
973 return unw_decode_x4 (dp, code, arg);
975 default:
976 UNW_DEC_BAD_CODE (code);
977 break;
980 return dp;
983 static const unsigned char *
984 unw_decode_b1 (const unsigned char *dp, unsigned int code,
985 void *arg ATTRIBUTE_UNUSED)
987 unw_word label = (code & 0x1f);
989 if ((code & 0x20) != 0)
990 UNW_DEC_COPY_STATE ("B1", label, arg);
991 else
992 UNW_DEC_LABEL_STATE ("B1", label, arg);
993 return dp;
996 static const unsigned char *
997 unw_decode_b2 (const unsigned char *dp, unsigned int code,
998 void *arg ATTRIBUTE_UNUSED)
1000 unw_word t;
1002 t = unw_decode_uleb128 (& dp);
1003 UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
1004 return dp;
1007 static const unsigned char *
1008 unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
1010 unw_word t, ecount, label;
1012 if ((code & 0x10) == 0)
1014 t = unw_decode_uleb128 (&dp);
1015 ecount = unw_decode_uleb128 (&dp);
1016 UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
1018 else if ((code & 0x07) == 0)
1020 label = unw_decode_uleb128 (&dp);
1021 if ((code & 0x08) != 0)
1022 UNW_DEC_COPY_STATE ("B4", label, arg);
1023 else
1024 UNW_DEC_LABEL_STATE ("B4", label, arg);
1026 else
1027 switch (code & 0x7)
1029 case 1:
1030 return unw_decode_x1 (dp, code, arg);
1031 case 2:
1032 return unw_decode_x2 (dp, code, arg);
1033 case 3:
1034 return unw_decode_x3 (dp, code, arg);
1035 case 4:
1036 return unw_decode_x4 (dp, code, arg);
1037 default:
1038 UNW_DEC_BAD_CODE (code);
1039 break;
1041 return dp;
1044 typedef const unsigned char *(*unw_decoder)
1045 (const unsigned char *, unsigned int, void *);
1047 static unw_decoder unw_decode_table[2][8] =
1049 /* prologue table: */
1051 unw_decode_r1, /* 0 */
1052 unw_decode_r1,
1053 unw_decode_r2,
1054 unw_decode_r3,
1055 unw_decode_p1, /* 4 */
1056 unw_decode_p2_p5,
1057 unw_decode_p6,
1058 unw_decode_p7_p10
1061 unw_decode_r1, /* 0 */
1062 unw_decode_r1,
1063 unw_decode_r2,
1064 unw_decode_r3,
1065 unw_decode_b1, /* 4 */
1066 unw_decode_b1,
1067 unw_decode_b2,
1068 unw_decode_b3_x4
1072 /* Decode one descriptor and return address of next descriptor. */
1073 const unsigned char *
1074 unw_decode (const unsigned char *dp, int inside_body,
1075 void *ptr_inside_body)
1077 unw_decoder decoder;
1078 unsigned char code;
1080 code = *dp++;
1081 decoder = unw_decode_table[inside_body][code >> 5];
1082 return (*decoder) (dp, code, ptr_inside_body);