2004-02-02 Jeff Johnston <jjohnstn@redhat.com>
[binutils.git] / binutils / unwind-ia64.c
blob2e7e726e4bfb758e7db50df161da3021245191bf
1 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2 Copyright 2000, 2001, 2003 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)
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "unwind-ia64.h"
22 #include <stdio.h>
23 #include <string.h>
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"
34 static bfd_vma unw_rlen = 0;
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);
42 static void
43 unw_print_brmask (char *cp, unsigned int mask)
45 int sep = 0;
46 int i;
48 for (i = 0; mask && (i < 5); ++i)
50 if (mask & 1)
52 if (sep)
53 *cp++ = ',';
54 *cp++ = 'b';
55 *cp++ = i + 1 + '0';
56 sep = 1;
58 mask >>= 1;
60 *cp = '\0';
63 static void
64 unw_print_grmask (char *cp, unsigned int mask)
66 int sep = 0;
67 int i;
69 for (i = 0; i < 4; ++i)
71 if (mask & 1)
73 if (sep)
74 *cp++ = ',';
75 *cp++ = 'r';
76 *cp++ = i + 4 + '0';
77 sep = 1;
79 mask >>= 1;
81 *cp = '\0';
84 static void
85 unw_print_frmask (char *cp, unsigned int mask)
87 int sep = 0;
88 int i;
90 for (i = 0; i < 20; ++i)
92 if (mask & 1)
94 if (sep)
95 *cp++ = ',';
96 *cp++ = 'f';
97 if (i < 4)
98 *cp++ = i + 2 + '0';
99 else
101 *cp++ = (i + 2) / 10 + 1 + '0';
102 *cp++ = (i + 2) % 10 + '0';
104 sep = 1;
106 mask >>= 1;
108 *cp = '\0';
111 static void
112 unw_print_abreg (char *cp, unsigned int abreg)
114 static const char *special_reg[16] =
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"
121 switch ((abreg >> 5) & 0x3)
123 case 0: /* gr */
124 sprintf (cp, "r%u", (abreg & 0x1f));
125 break;
127 case 1: /* fr */
128 sprintf (cp, "f%u", (abreg & 0x1f));
129 break;
131 case 2: /* br */
132 sprintf (cp, "b%u", (abreg & 0x1f));
133 break;
135 case 3: /* special */
136 strcpy (cp, special_reg[abreg & 0xf]);
137 break;
141 static void
142 unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
144 switch ((x << 1) | ((ytreg >> 7) & 1))
146 case 0: /* gr */
147 sprintf (cp, "r%u", (ytreg & 0x1f));
148 break;
150 case 1: /* fr */
151 sprintf (cp, "f%u", (ytreg & 0x1f));
152 break;
154 case 2: /* br */
155 sprintf (cp, "b%u", (ytreg & 0x1f));
156 break;
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"
171 typedef bfd_vma unw_word;
173 #define UNW_DEC_BAD_CODE(code) \
174 printf ("Unknown code 0x%02x\n", code)
176 #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \
177 do \
179 unw_rlen = rlen; \
180 *(int *)arg = body; \
181 printf (" %s:%s(rlen=%lu)\n", \
182 fmt, body ? "body" : "prologue", (unsigned long) rlen); \
184 while (0)
186 #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \
187 do \
189 char regname[16], maskstr[64], *sep; \
191 unw_rlen = rlen; \
192 *(int *)arg = 0; \
194 maskstr[0] = '\0'; \
195 sep = ""; \
196 if (mask & 0x8) \
198 strcat (maskstr, "rp"); \
199 sep = ","; \
201 if (mask & 0x4) \
203 strcat (maskstr, sep); \
204 strcat (maskstr, "ar.pfs"); \
205 sep = ","; \
207 if (mask & 0x2) \
209 strcat (maskstr, sep); \
210 strcat (maskstr, "psp"); \
211 sep = ","; \
213 if (mask & 0x1) \
215 strcat (maskstr, sep); \
216 strcat (maskstr, "pr"); \
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); \
222 while (0)
224 #define UNW_DEC_FR_MEM(fmt, frmask, arg) \
225 do \
227 char frstr[200]; \
229 unw_print_frmask (frstr, frmask); \
230 printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \
232 while (0)
234 #define UNW_DEC_GR_MEM(fmt, grmask, arg) \
235 do \
237 char grstr[200]; \
239 unw_print_grmask (grstr, grmask); \
240 printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \
242 while (0)
244 #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \
245 do \
247 char frstr[200], grstr[20]; \
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); \
253 while (0)
255 #define UNW_DEC_BR_MEM(fmt, brmask, arg) \
256 do \
258 char brstr[20]; \
260 unw_print_brmask (brstr, brmask); \
261 printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \
263 while (0)
265 #define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \
266 do \
268 char brstr[20]; \
270 unw_print_brmask (brstr, brmask); \
271 printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \
273 while (0)
275 #define UNW_DEC_REG_GR(fmt, src, dst, arg) \
276 printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
278 #define UNW_DEC_RP_BR(fmt, dst, arg) \
279 printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
281 #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \
282 printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
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)
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)
292 #define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \
293 do \
295 char grstr[20]; \
297 unw_print_grmask (grstr, grmask); \
298 printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \
300 while (0)
302 #define UNW_DEC_ABI(fmt, abi, context, arg) \
303 do \
305 static const char *abiname[] = \
307 "@svr4", "@hpux", "@nt" \
308 }; \
309 char buf[20]; \
310 const char *abistr = buf; \
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); \
319 while (0)
321 #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \
322 printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
324 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \
325 printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
327 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \
328 printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
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)
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)
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)
342 #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \
343 printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
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)
349 #define UNW_DEC_SPILL_MASK(fmt, dp, arg) \
350 do \
352 static const char *spill_type = "-frb"; \
353 unsigned const char *imaskp = dp; \
354 unsigned char mask = 0; \
355 bfd_vma insn = 0; \
357 printf ("\t%s:spill_mask(imask=[", fmt); \
358 for (insn = 0; insn < unw_rlen; ++insn) \
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]); \
366 printf ("])\n"); \
367 dp = imaskp; \
369 while (0)
371 #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \
372 do \
374 char regname[10]; \
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); \
380 while (0)
382 #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \
383 do \
385 char regname[10]; \
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); \
391 while (0)
393 #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \
394 do \
396 char regname[10]; \
398 unw_print_abreg (regname, abreg); \
399 printf ("\t%s:restore(t=%lu,reg=%s)\n", \
400 fmt, (unsigned long) t, regname); \
402 while (0)
404 #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \
405 do \
407 char abregname[10], tregname[10]; \
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); \
414 while (0)
416 #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \
417 do \
419 char regname[20]; \
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); \
425 while (0)
427 #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \
428 do \
430 char regname[20]; \
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);\
436 while (0)
438 #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \
439 do \
441 char regname[20]; \
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); \
447 while (0)
449 #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \
450 do \
452 char regname[20], tregname[20]; \
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); \
459 while (0)
461 #define UNW_DEC_LABEL_STATE(fmt, label, arg) \
462 printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
464 #define UNW_DEC_COPY_STATE(fmt, label, arg) \
465 printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
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)
472 * Generic IA-64 unwind info decoder.
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...).
478 * You need to customize the decoder by defining the following
479 * macros/constants before including this file:
481 * Types:
482 * unw_word Unsigned integer type with at least 64 bits
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
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)
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 *);
563 static unw_word
564 unw_decode_uleb128 (const unsigned char **dpp)
566 unsigned shift = 0;
567 unw_word byte, result = 0;
568 const unsigned char *bp = *dpp;
570 while (1)
572 byte = *bp++;
573 result |= (byte & 0x7f) << shift;
575 if ((byte & 0x80) == 0)
576 break;
578 shift += 7;
581 *dpp = bp;
583 return result;
586 static const unsigned char *
587 unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
588 void *arg ATTRIBUTE_UNUSED)
590 unsigned char byte1, abreg;
591 unw_word t, off;
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;
604 static const unsigned char *
605 unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
606 void *arg ATTRIBUTE_UNUSED)
608 unsigned char byte1, byte2, abreg, x, ytreg;
609 unw_word t;
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;
624 static const unsigned char *
625 unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
626 void *arg ATTRIBUTE_UNUSED)
628 unsigned char byte1, byte2, abreg, qp;
629 unw_word t, off;
631 byte1 = *dp++;
632 byte2 = *dp++;
633 t = unw_decode_uleb128 (&dp);
634 off = unw_decode_uleb128 (&dp);
636 qp = (byte1 & 0x3f);
637 abreg = (byte2 & 0x7f);
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;
646 static const unsigned char *
647 unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
648 void *arg ATTRIBUTE_UNUSED)
650 unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
651 unw_word t;
653 byte1 = *dp++;
654 byte2 = *dp++;
655 byte3 = *dp++;
656 t = unw_decode_uleb128 (&dp);
658 qp = (byte1 & 0x3f);
659 abreg = (byte2 & 0x7f);
660 x = (byte2 >> 7) & 1;
661 ytreg = byte3;
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;
670 static const unsigned char *
671 unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
673 int body = (code & 0x20) != 0;
674 unw_word rlen;
676 rlen = (code & 0x1f);
677 UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
678 return dp;
681 static const unsigned char *
682 unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg)
684 unsigned char byte1, mask, grsave;
685 unw_word rlen;
687 byte1 = *dp++;
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;
696 static const unsigned char *
697 unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg)
699 unw_word rlen;
701 rlen = unw_decode_uleb128 (& dp);
702 UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
703 return dp;
706 static const unsigned char *
707 unw_decode_p1 (const unsigned char *dp, unsigned int code,
708 void *arg ATTRIBUTE_UNUSED)
710 unsigned char brmask = (code & 0x1f);
712 UNW_DEC_BR_MEM ("P1", brmask, arg);
713 return dp;
716 static const unsigned char *
717 unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
718 void *arg ATTRIBUTE_UNUSED)
720 if ((code & 0x10) == 0)
722 unsigned char byte1 = *dp++;
724 UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
725 (byte1 & 0x7f), arg);
727 else if ((code & 0x08) == 0)
729 unsigned char byte1 = *dp++, r, dst;
731 r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
732 dst = (byte1 & 0x7f);
733 switch (r)
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;
776 else if ((code & 0x7) == 0)
777 UNW_DEC_SPILL_MASK ("P4", dp, arg);
778 else if ((code & 0x7) == 1)
780 unw_word grmask, frmask, byte1, byte2, byte3;
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);
789 else
790 UNW_DEC_BAD_CODE (code);
792 return dp;
795 static const unsigned char *
796 unw_decode_p6 (const unsigned char *dp, unsigned int code,
797 void *arg ATTRIBUTE_UNUSED)
799 int gregs = (code & 0x10) != 0;
800 unsigned char mask = (code & 0x0f);
802 if (gregs)
803 UNW_DEC_GR_MEM ("P6", mask, arg);
804 else
805 UNW_DEC_FR_MEM ("P6", mask, arg);
806 return dp;
809 static const unsigned char *
810 unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
812 unsigned char r, byte1, byte2;
813 unw_word t, size;
815 if ((code & 0x10) == 0)
817 r = (code & 0xf);
818 t = unw_decode_uleb128 (&dp);
819 switch (r)
821 case 0:
822 size = unw_decode_uleb128 (&dp);
823 UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
824 break;
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;
876 else
878 switch (code & 0xf)
880 case 0x0: /* p8 */
882 r = *dp++;
883 t = unw_decode_uleb128 (&dp);
884 switch (r)
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;
948 break;
950 case 0x1:
951 byte1 = *dp++;
952 byte2 = *dp++;
953 UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
954 break;
956 case 0xf: /* p10 */
957 byte1 = *dp++;
958 byte2 = *dp++;
959 UNW_DEC_ABI ("P10", byte1, byte2, arg);
960 break;
962 case 0x9:
963 return unw_decode_x1 (dp, code, arg);
965 case 0xa:
966 return unw_decode_x2 (dp, code, arg);
968 case 0xb:
969 return unw_decode_x3 (dp, code, arg);
971 case 0xc:
972 return unw_decode_x4 (dp, code, arg);
974 default:
975 UNW_DEC_BAD_CODE (code);
976 break;
979 return dp;
982 static const unsigned char *
983 unw_decode_b1 (const unsigned char *dp, unsigned int code,
984 void *arg ATTRIBUTE_UNUSED)
986 unw_word label = (code & 0x1f);
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;
995 static const unsigned char *
996 unw_decode_b2 (const unsigned char *dp, unsigned int code,
997 void *arg ATTRIBUTE_UNUSED)
999 unw_word t;
1001 t = unw_decode_uleb128 (& dp);
1002 UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
1003 return dp;
1006 static const unsigned char *
1007 unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
1009 unw_word t, ecount, label;
1011 if ((code & 0x10) == 0)
1013 t = unw_decode_uleb128 (&dp);
1014 ecount = unw_decode_uleb128 (&dp);
1015 UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
1017 else if ((code & 0x07) == 0)
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);
1025 else
1026 switch (code & 0x7)
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;
1040 return dp;
1043 typedef const unsigned char *(*unw_decoder)
1044 (const unsigned char *, unsigned int, void *);
1046 static unw_decoder unw_decode_table[2][8] =
1048 /* prologue table: */
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
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
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)
1076 unw_decoder decoder;
1077 unsigned char code;
1079 code = *dp++;
1080 decoder = unw_decode_table[inside_body][code >> 5];
1081 return (*decoder) (dp, code, ptr_inside_body);