1 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2 Copyright (c) 2000, 2001 Free Software Foundation, Inc.
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
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 2, or (at your option)
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "unwind-ia64.h"
26 /* Define BFD64 here, even if our default architecture is 32 bit ELF
27 as this will allow us to read in and parse 64bit and 32bit ELF files.
28 Only do this if we belive that the compiler can support a 64 bit
29 data type. For now we only rely on GCC being able to do this. */
34 static bfd_vma unw_rlen
= 0;
37 unw_print_brmask (cp
, mask
)
44 for (i
= 0; mask
&& (i
< 5); ++i
)
48 cp
+= sprintf (cp
, "%sb%u", sep
, i
+ 1);
57 unw_print_grmask (cp
, mask
)
65 for (i
= 0; i
< 4; ++i
)
69 cp
+= sprintf (cp
, "%sr%u", sep
, i
+ 4);
77 unw_print_frmask (cp
, mask
)
85 for (i
= 0; i
< 20; ++i
)
89 cp
+= sprintf (cp
, "%sf%u", sep
, (i
< 4) ? (i
+ 2) : (i
+ 12));
97 unw_print_abreg (cp
, abreg
)
101 static const char *special_reg
[16] =
103 "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
104 "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
105 "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
108 switch ((abreg
>> 5) & 0x3)
111 sprintf (cp
, "r%u", (abreg
& 0x1f));
115 sprintf (cp
, "f%u", (abreg
& 0x1f));
119 sprintf (cp
, "b%u", (abreg
& 0x1f));
122 case 3: /* special */
123 strcpy (cp
, special_reg
[abreg
& 0xf]);
129 unw_print_xyreg (cp
, x
, ytreg
)
134 switch ((x
<< 1) | ((ytreg
>> 7) & 1))
137 sprintf (cp
, "r%u", (ytreg
& 0x1f));
141 sprintf (cp
, "f%u", (ytreg
& 0x1f));
145 sprintf (cp
, "b%u", (ytreg
& 0x1f));
150 #define UNW_REG_BSP "bsp"
151 #define UNW_REG_BSPSTORE "bspstore"
152 #define UNW_REG_FPSR "fpsr"
153 #define UNW_REG_LC "lc"
154 #define UNW_REG_PFS "pfs"
155 #define UNW_REG_PR "pr"
156 #define UNW_REG_PSP "psp"
157 #define UNW_REG_RNAT "rnat"
158 #define UNW_REG_RP "rp"
159 #define UNW_REG_UNAT "unat"
161 typedef bfd_vma unw_word
;
165 #define UNW_DEC_BAD_CODE(code) \
166 printf ("Unknown code 0x%02x\n", code)
168 #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \
172 *(int *)arg = body; \
173 printf (" "STR(fmt)":%s(rlen=%lu)\n", \
174 body ? "body" : "prologue", (unsigned long) rlen); \
178 #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \
181 char regname[16], maskstr[64], *sep; \
190 strcat (maskstr, "rp"); \
195 strcat (maskstr, sep); \
196 strcat (maskstr, "ar.pfs"); \
201 strcat (maskstr, sep); \
202 strcat (maskstr, "psp"); \
207 strcat (maskstr, sep); \
208 strcat (maskstr, "pr"); \
210 sprintf (regname, "r%u", grsave); \
211 printf (" "STR(fmt)":prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \
212 maskstr, regname, (unsigned long) rlen); \
216 #define UNW_DEC_FR_MEM(fmt, frmask, arg) \
221 unw_print_frmask (frstr, frmask); \
222 printf ("\t"STR(fmt)":fr_mem(frmask=[%s])\n", frstr); \
226 #define UNW_DEC_GR_MEM(fmt, grmask, arg) \
231 unw_print_grmask (grstr, grmask); \
232 printf ("\t"STR(fmt)":gr_mem(grmask=[%s])\n", grstr); \
236 #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \
239 char frstr[200], grstr[20]; \
241 unw_print_grmask (grstr, grmask); \
242 unw_print_frmask (frstr, frmask); \
243 printf ("\t"STR(fmt)":frgr_mem(grmask=[%s],frmask=[%s])\n", grstr, frstr);\
247 #define UNW_DEC_BR_MEM(fmt, brmask, arg) \
252 unw_print_brmask (brstr, brmask); \
253 printf ("\t"STR(fmt)":br_mem(brmask=[%s])\n", brstr); \
257 #define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \
262 unw_print_brmask (brstr, brmask); \
263 printf ("\t"STR(fmt)":br_gr(brmask=[%s],gr=r%u)\n", brstr, gr); \
267 #define UNW_DEC_REG_GR(fmt, src, dst, arg) \
268 printf ("\t"STR(fmt)":%s_gr(reg=r%u)\n", src, dst)
270 #define UNW_DEC_RP_BR(fmt, dst, arg) \
271 printf ("\t"STR(fmt)":rp_br(reg=b%u)\n", dst)
273 #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \
274 printf ("\t"STR(fmt)":%s_when(t=%lu)\n", reg, (unsigned long) t)
276 #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \
277 printf ("\t"STR(fmt)":%s_sprel(spoff=0x%lx)\n", \
278 reg, 4*(unsigned long)spoff)
280 #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \
281 printf ("\t"STR(fmt)":%s_psprel(pspoff=0x10-0x%lx)\n", \
282 reg, 4*(unsigned long)pspoff)
284 #define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \
289 unw_print_grmask (grstr, grmask); \
290 printf ("\t"STR(fmt)":gr_gr(grmask=[%s],r%u)\n", grstr, gr); \
294 #define UNW_DEC_ABI(fmt, abi, context, arg) \
297 static const char *abiname[] = \
299 "@svr4", "@hpux", "@nt" \
302 const char *abistr = buf; \
305 abistr = abiname[abi]; \
307 sprintf (buf, "0x%x", abi); \
308 printf ("\t"STR(fmt)":unwabi(abi=%s,context=0x%02x)\n", \
313 #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \
314 printf ("\t"STR(fmt)":priunat_gr(reg=r%u)\n", r)
316 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \
317 printf ("\t"STR(fmt)":priunat_when_gr(t=%lu)\n", (unsigned long) t)
319 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \
320 printf ("\t"STR(fmt)":priunat_when_mem(t=%lu)\n", (unsigned long) t)
322 #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \
323 printf ("\t"STR(fmt)":priunat_psprel(pspoff=0x10-0x%lx)\n", \
324 4*(unsigned long)pspoff)
326 #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \
327 printf ("\t"STR(fmt)":priunat_sprel(spoff=0x%lx)\n", \
328 4*(unsigned long)spoff)
330 #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \
331 printf ("\t"STR(fmt)":mem_stack_f(t=%lu,size=%lu)\n", \
332 (unsigned long) t, 16*(unsigned long)size)
334 #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \
335 printf ("\t"STR(fmt)":mem_stack_v(t=%lu)\n", (unsigned long) t)
337 #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \
338 printf ("\t"STR(fmt)":spill_base(pspoff=0x10-0x%lx)\n", \
339 4*(unsigned long)pspoff)
341 #define UNW_DEC_SPILL_MASK(fmt, dp, arg) \
344 static const char * spill_type = "-frb"; \
345 unsigned const char * imaskp = dp; \
346 unsigned char mask = 0; \
349 printf ("\t"STR (fmt)":spill_mask(imask=["); \
350 for (insn = 0; insn < unw_rlen; ++insn) \
352 if ((insn % 4) == 0) \
354 if (insn > 0 && (insn % 3) == 0) \
356 putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]); \
363 #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \
368 unw_print_abreg (regname, abreg); \
369 printf ("\t"STR(fmt)":spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \
370 regname, (unsigned long) t, 4*(unsigned long)off); \
374 #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \
379 unw_print_abreg (regname, abreg); \
380 printf ("\t"STR(fmt)":spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \
381 regname, (unsigned long) t, 4*(unsigned long)pspoff); \
385 #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \
390 unw_print_abreg (regname, abreg); \
391 printf ("\t"STR(fmt)":restore(t=%lu,reg=%s)\n", \
392 (unsigned long) t, regname); \
396 #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \
399 char abregname[10], tregname[10]; \
401 unw_print_abreg (abregname, abreg); \
402 unw_print_xyreg (tregname, x, ytreg); \
403 printf ("\t"STR(fmt)":spill_reg(t=%lu,reg=%s,treg=%s)\n", \
404 (unsigned long) t, abregname, tregname); \
408 #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \
413 unw_print_abreg (regname, abreg); \
414 printf ("\t"STR(fmt)":spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \
415 qp, (unsigned long) t, regname, 4 * (unsigned long)spoff); \
419 #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \
424 unw_print_abreg (regname, abreg); \
425 printf ("\t"STR (fmt) \
426 ":spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\
427 qp, (unsigned long) t, regname, 4*(unsigned long)pspoff); \
431 #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \
436 unw_print_abreg (regname, abreg); \
437 printf ("\t"STR(fmt)":restore_p(qp=p%u,t=%lu,reg=%s)\n", \
438 qp, (unsigned long) t, regname); \
442 #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \
445 char regname[20], tregname[20]; \
447 unw_print_abreg (regname, abreg); \
448 unw_print_xyreg (tregname, x, ytreg); \
449 printf ("\t"STR(fmt)":spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n",\
450 qp, (unsigned long) t, regname, tregname); \
454 #define UNW_DEC_LABEL_STATE(fmt, label, arg) \
455 printf ("\t"STR(fmt)":label_state(label=%lu)\n", (unsigned long) label)
457 #define UNW_DEC_COPY_STATE(fmt, label, arg) \
458 printf ("\t"STR(fmt)":copy_state(label=%lu)\n", (unsigned long) label)
460 #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \
461 printf ("\t"STR(fmt)":epilogue(t=%lu,ecount=%lu)\n", \
462 (unsigned long) t, (unsigned long) ecount)
465 * Generic IA-64 unwind info decoder.
467 * This file is used both by the Linux kernel and objdump. Please
468 * keep the two copies of this file in sync (modulo differences in the
471 * You need to customize the decoder by defining the following
472 * macros/constants before including this file:
475 * unw_word Unsigned integer type with at least 64 bits
489 * Decoder action macros:
490 * UNW_DEC_BAD_CODE(code)
491 * UNW_DEC_ABI(fmt,abi,context,arg)
492 * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
493 * UNW_DEC_BR_MEM(fmt,brmask,arg)
494 * UNW_DEC_COPY_STATE(fmt,label,arg)
495 * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
496 * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
497 * UNW_DEC_FR_MEM(fmt,frmask,arg)
498 * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
499 * UNW_DEC_GR_MEM(fmt,grmask,arg)
500 * UNW_DEC_LABEL_STATE(fmt,label,arg)
501 * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
502 * UNW_DEC_MEM_STACK_V(fmt,t,arg)
503 * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
504 * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
505 * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
506 * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
507 * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
508 * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
509 * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
510 * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
511 * UNW_DEC_REG_REG(fmt,src,dst,arg)
512 * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
513 * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
514 * UNW_DEC_RESTORE(fmt,t,abreg,arg)
515 * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
516 * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
517 * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
518 * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
519 * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
520 * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
521 * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
522 * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
523 * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
526 static unw_word unw_decode_uleb128
PARAMS ((const unsigned char **));
527 static const unsigned char *unw_decode_x1
PARAMS ((const unsigned char *,
528 unsigned char, void *));
529 static const unsigned char *unw_decode_x2
PARAMS ((const unsigned char *,
530 unsigned char, void *));
531 static const unsigned char *unw_decode_x3
PARAMS ((const unsigned char *,
532 unsigned char, void *));
533 static const unsigned char *unw_decode_x4
PARAMS ((const unsigned char *,
534 unsigned char, void *));
535 static const unsigned char *unw_decode_r1
PARAMS ((const unsigned char *,
536 unsigned char, void *));
537 static const unsigned char *unw_decode_r2
PARAMS ((const unsigned char *,
538 unsigned char, void *));
539 static const unsigned char *unw_decode_r3
PARAMS ((const unsigned char *,
540 unsigned char, void *));
541 static const unsigned char *unw_decode_p1
PARAMS ((const unsigned char *,
542 unsigned char, void *));
543 static const unsigned char *unw_decode_p2_p5
PARAMS ((const unsigned char *,
544 unsigned char, void *));
545 static const unsigned char *unw_decode_p6
PARAMS ((const unsigned char *,
546 unsigned char, void *));
547 static const unsigned char *unw_decode_p7_p10
PARAMS ((const unsigned char *,
548 unsigned char, void *));
549 static const unsigned char *unw_decode_b1
PARAMS ((const unsigned char *,
550 unsigned char, void *));
551 static const unsigned char *unw_decode_b2
PARAMS ((const unsigned char *,
552 unsigned char, void *));
553 static const unsigned char *unw_decode_b3_x4
PARAMS ((const unsigned char *,
554 unsigned char, void *));
557 unw_decode_uleb128 (dpp
)
558 const unsigned char **dpp
;
561 unw_word byte
, result
= 0;
562 const unsigned char *bp
= *dpp
;
567 result
|= (byte
& 0x7f) << shift
;
569 if ((byte
& 0x80) == 0)
580 static const unsigned char *
581 unw_decode_x1 (dp
, code
, arg
)
582 const unsigned char * dp
;
584 void * arg ATTRIBUTE_UNUSED
;
586 unsigned char byte1
, abreg
;
590 t
= unw_decode_uleb128 (&dp
);
591 off
= unw_decode_uleb128 (&dp
);
592 abreg
= (byte1
& 0x7f);
594 UNW_DEC_SPILL_SPREL (X1
, t
, abreg
, off
, arg
);
596 UNW_DEC_SPILL_PSPREL (X1
, t
, abreg
, off
, arg
);
600 static const unsigned char *
601 unw_decode_x2 (dp
, code
, arg
)
602 const unsigned char * dp
;
604 void * arg ATTRIBUTE_UNUSED
;
606 unsigned char byte1
, byte2
, abreg
, x
, ytreg
;
611 t
= unw_decode_uleb128 (&dp
);
612 abreg
= (byte1
& 0x7f);
614 x
= (byte1
>> 7) & 1;
615 if ((byte1
& 0x80) == 0 && ytreg
== 0)
616 UNW_DEC_RESTORE (X2
, t
, abreg
, arg
);
618 UNW_DEC_SPILL_REG (X2
, t
, abreg
, x
, ytreg
, arg
);
622 static const unsigned char *
623 unw_decode_x3 (dp
, code
, arg
)
624 const unsigned char * dp
;
626 void * arg ATTRIBUTE_UNUSED
;
628 unsigned char byte1
, byte2
, abreg
, qp
;
633 t
= unw_decode_uleb128 (&dp
);
634 off
= unw_decode_uleb128 (&dp
);
637 abreg
= (byte2
& 0x7f);
640 UNW_DEC_SPILL_SPREL_P (X3
, qp
, t
, abreg
, off
, arg
);
642 UNW_DEC_SPILL_PSPREL_P (X3
, qp
, t
, abreg
, off
, arg
);
646 static const unsigned char *
647 unw_decode_x4 (dp
, code
, arg
)
648 const unsigned char * dp
;
650 void * arg ATTRIBUTE_UNUSED
;
652 unsigned char byte1
, byte2
, byte3
, qp
, abreg
, x
, ytreg
;
658 t
= unw_decode_uleb128 (&dp
);
661 abreg
= (byte2
& 0x7f);
662 x
= (byte2
>> 7) & 1;
665 if ((byte2
& 0x80) == 0 && byte3
== 0)
666 UNW_DEC_RESTORE_P (X4
, qp
, t
, abreg
, arg
);
668 UNW_DEC_SPILL_REG_P (X4
, qp
, t
, abreg
, x
, ytreg
, arg
);
672 static const unsigned char *
673 unw_decode_r1 (dp
, code
, arg
)
674 const unsigned char *dp
;
678 int body
= (code
& 0x20) != 0;
681 rlen
= (code
& 0x1f);
682 UNW_DEC_PROLOGUE (R1
, body
, rlen
, arg
);
686 static const unsigned char *
687 unw_decode_r2 (dp
, code
, arg
)
688 const unsigned char *dp
;
692 unsigned char byte1
, mask
, grsave
;
697 mask
= ((code
& 0x7) << 1) | ((byte1
>> 7) & 1);
698 grsave
= (byte1
& 0x7f);
699 rlen
= unw_decode_uleb128 (& dp
);
700 UNW_DEC_PROLOGUE_GR (R2
, rlen
, mask
, grsave
, arg
);
704 static const unsigned char *
705 unw_decode_r3 (dp
, code
, arg
)
706 const unsigned char *dp
;
712 rlen
= unw_decode_uleb128 (& dp
);
713 UNW_DEC_PROLOGUE (R3
, ((code
& 0x3) == 1), rlen
, arg
);
717 static const unsigned char *
718 unw_decode_p1 (dp
, code
, arg
)
719 const unsigned char * dp
;
721 void * arg ATTRIBUTE_UNUSED
;
723 unsigned char brmask
= (code
& 0x1f);
725 UNW_DEC_BR_MEM (P1
, brmask
, arg
);
729 static const unsigned char *
730 unw_decode_p2_p5 (dp
, code
, arg
)
731 const unsigned char * dp
;
733 void * arg ATTRIBUTE_UNUSED
;
735 if ((code
& 0x10) == 0)
737 unsigned char byte1
= *dp
++;
739 UNW_DEC_BR_GR (P2
, ((code
& 0xf) << 1) | ((byte1
>> 7) & 1),
740 (byte1
& 0x7f), arg
);
742 else if ((code
& 0x08) == 0)
744 unsigned char byte1
= *dp
++, r
, dst
;
746 r
= ((code
& 0x7) << 1) | ((byte1
>> 7) & 1);
747 dst
= (byte1
& 0x7f);
751 UNW_DEC_REG_GR (P3
, UNW_REG_PSP
, dst
, arg
);
754 UNW_DEC_REG_GR (P3
, UNW_REG_RP
, dst
, arg
);
757 UNW_DEC_REG_GR (P3
, UNW_REG_PFS
, dst
, arg
);
760 UNW_DEC_REG_GR (P3
, UNW_REG_PR
, dst
, arg
);
763 UNW_DEC_REG_GR (P3
, UNW_REG_UNAT
, dst
, arg
);
766 UNW_DEC_REG_GR (P3
, UNW_REG_LC
, dst
, arg
);
769 UNW_DEC_RP_BR (P3
, dst
, arg
);
772 UNW_DEC_REG_GR (P3
, UNW_REG_RNAT
, dst
, arg
);
775 UNW_DEC_REG_GR (P3
, UNW_REG_BSP
, dst
, arg
);
778 UNW_DEC_REG_GR (P3
, UNW_REG_BSPSTORE
, dst
, arg
);
781 UNW_DEC_REG_GR (P3
, UNW_REG_FPSR
, dst
, arg
);
784 UNW_DEC_PRIUNAT_GR (P3
, dst
, arg
);
787 UNW_DEC_BAD_CODE (r
);
791 else if ((code
& 0x7) == 0)
792 UNW_DEC_SPILL_MASK (P4
, dp
, arg
);
793 else if ((code
& 0x7) == 1)
795 unw_word grmask
, frmask
, byte1
, byte2
, byte3
;
800 grmask
= ((byte1
>> 4) & 0xf);
801 frmask
= ((byte1
& 0xf) << 16) | (byte2
<< 8) | byte3
;
802 UNW_DEC_FRGR_MEM (P5
, grmask
, frmask
, arg
);
805 UNW_DEC_BAD_CODE (code
);
810 static const unsigned char *
811 unw_decode_p6 (dp
, code
, arg
)
812 const unsigned char * dp
;
814 void * arg ATTRIBUTE_UNUSED
;
816 int gregs
= (code
& 0x10) != 0;
817 unsigned char mask
= (code
& 0x0f);
820 UNW_DEC_GR_MEM (P6
, mask
, arg
);
822 UNW_DEC_FR_MEM (P6
, mask
, arg
);
826 static const unsigned char *
827 unw_decode_p7_p10 (dp
, code
, arg
)
828 const unsigned char *dp
;
832 unsigned char r
, byte1
, byte2
;
835 if ((code
& 0x10) == 0)
838 t
= unw_decode_uleb128 (&dp
);
842 size
= unw_decode_uleb128 (&dp
);
843 UNW_DEC_MEM_STACK_F (P7
, t
, size
, arg
);
847 UNW_DEC_MEM_STACK_V (P7
, t
, arg
);
850 UNW_DEC_SPILL_BASE (P7
, t
, arg
);
853 UNW_DEC_REG_SPREL (P7
, UNW_REG_PSP
, t
, arg
);
856 UNW_DEC_REG_WHEN (P7
, UNW_REG_RP
, t
, arg
);
859 UNW_DEC_REG_PSPREL (P7
, UNW_REG_RP
, t
, arg
);
862 UNW_DEC_REG_WHEN (P7
, UNW_REG_PFS
, t
, arg
);
865 UNW_DEC_REG_PSPREL (P7
, UNW_REG_PFS
, t
, arg
);
868 UNW_DEC_REG_WHEN (P7
, UNW_REG_PR
, t
, arg
);
871 UNW_DEC_REG_PSPREL (P7
, UNW_REG_PR
, t
, arg
);
874 UNW_DEC_REG_WHEN (P7
, UNW_REG_LC
, t
, arg
);
877 UNW_DEC_REG_PSPREL (P7
, UNW_REG_LC
, t
, arg
);
880 UNW_DEC_REG_WHEN (P7
, UNW_REG_UNAT
, t
, arg
);
883 UNW_DEC_REG_PSPREL (P7
, UNW_REG_UNAT
, t
, arg
);
886 UNW_DEC_REG_WHEN (P7
, UNW_REG_FPSR
, t
, arg
);
889 UNW_DEC_REG_PSPREL (P7
, UNW_REG_FPSR
, t
, arg
);
892 UNW_DEC_BAD_CODE (r
);
903 t
= unw_decode_uleb128 (&dp
);
907 UNW_DEC_REG_SPREL (P8
, UNW_REG_RP
, t
, arg
);
910 UNW_DEC_REG_SPREL (P8
, UNW_REG_PFS
, t
, arg
);
913 UNW_DEC_REG_SPREL (P8
, UNW_REG_PR
, t
, arg
);
916 UNW_DEC_REG_SPREL (P8
, UNW_REG_LC
, t
, arg
);
919 UNW_DEC_REG_SPREL (P8
, UNW_REG_UNAT
, t
, arg
);
922 UNW_DEC_REG_SPREL (P8
, UNW_REG_FPSR
, t
, arg
);
925 UNW_DEC_REG_WHEN (P8
, UNW_REG_BSP
, t
, arg
);
928 UNW_DEC_REG_PSPREL (P8
, UNW_REG_BSP
, t
, arg
);
931 UNW_DEC_REG_SPREL (P8
, UNW_REG_BSP
, t
, arg
);
934 UNW_DEC_REG_WHEN (P8
, UNW_REG_BSPSTORE
, t
, arg
);
937 UNW_DEC_REG_PSPREL (P8
, UNW_REG_BSPSTORE
, t
, arg
);
940 UNW_DEC_REG_SPREL (P8
, UNW_REG_BSPSTORE
, t
, arg
);
943 UNW_DEC_REG_WHEN (P8
, UNW_REG_RNAT
, t
, arg
);
946 UNW_DEC_REG_PSPREL (P8
, UNW_REG_RNAT
, t
, arg
);
949 UNW_DEC_REG_SPREL (P8
, UNW_REG_RNAT
, t
, arg
);
952 UNW_DEC_PRIUNAT_WHEN_GR (P8
, t
, arg
);
955 UNW_DEC_PRIUNAT_PSPREL (P8
, t
, arg
);
958 UNW_DEC_PRIUNAT_SPREL (P8
, t
, arg
);
961 UNW_DEC_PRIUNAT_WHEN_MEM (P8
, t
, arg
);
964 UNW_DEC_BAD_CODE (r
);
973 UNW_DEC_GR_GR (P9
, (byte1
& 0xf), (byte2
& 0x7f), arg
);
979 UNW_DEC_ABI (P10
, byte1
, byte2
, arg
);
983 return unw_decode_x1 (dp
, code
, arg
);
986 return unw_decode_x2 (dp
, code
, arg
);
989 return unw_decode_x3 (dp
, code
, arg
);
992 return unw_decode_x4 (dp
, code
, arg
);
995 UNW_DEC_BAD_CODE (code
);
1002 static const unsigned char *
1003 unw_decode_b1 (dp
, code
, arg
)
1004 const unsigned char * dp
;
1006 void * arg ATTRIBUTE_UNUSED
;
1008 unw_word label
= (code
& 0x1f);
1010 if ((code
& 0x20) != 0)
1011 UNW_DEC_COPY_STATE (B1
, label
, arg
);
1013 UNW_DEC_LABEL_STATE (B1
, label
, arg
);
1017 static const unsigned char *
1018 unw_decode_b2 (dp
, code
, arg
)
1019 const unsigned char * dp
;
1021 void * arg ATTRIBUTE_UNUSED
;
1025 t
= unw_decode_uleb128 (& dp
);
1026 UNW_DEC_EPILOGUE (B2
, t
, (code
& 0x1f), arg
);
1030 static const unsigned char *
1031 unw_decode_b3_x4 (dp
, code
, arg
)
1032 const unsigned char *dp
;
1036 unw_word t
, ecount
, label
;
1038 if ((code
& 0x10) == 0)
1040 t
= unw_decode_uleb128 (&dp
);
1041 ecount
= unw_decode_uleb128 (&dp
);
1042 UNW_DEC_EPILOGUE (B3
, t
, ecount
, arg
);
1044 else if ((code
& 0x07) == 0)
1046 label
= unw_decode_uleb128 (&dp
);
1047 if ((code
& 0x08) != 0)
1048 UNW_DEC_COPY_STATE (B4
, label
, arg
);
1050 UNW_DEC_LABEL_STATE (B4
, label
, arg
);
1056 return unw_decode_x1 (dp
, code
, arg
);
1058 return unw_decode_x2 (dp
, code
, arg
);
1060 return unw_decode_x3 (dp
, code
, arg
);
1062 return unw_decode_x4 (dp
, code
, arg
);
1064 UNW_DEC_BAD_CODE (code
);
1070 typedef const unsigned char *(*unw_decoder
)
1071 PARAMS ((const unsigned char *, unsigned char, void *));
1073 static unw_decoder unw_decode_table
[2][8] =
1075 /* prologue table: */
1077 unw_decode_r1
, /* 0 */
1081 unw_decode_p1
, /* 4 */
1087 unw_decode_r1
, /* 0 */
1091 unw_decode_b1
, /* 4 */
1098 /* Decode one descriptor and return address of next descriptor. */
1099 const unsigned char *
1100 unw_decode (dp
, inside_body
, ptr_inside_body
)
1101 const unsigned char * dp
;
1103 void * ptr_inside_body
;
1105 unw_decoder decoder
;
1109 decoder
= unw_decode_table
[inside_body
][code
>> 5];
1110 return (*decoder
) (dp
, code
, ptr_inside_body
);