Refer to "options" not "switches"
[binutils.git] / binutils / unwind-ia64.c
blobd3f4b616d8d2426d055bf3034d1ed3b7ed587296
1 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2 Copyright 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)
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 belive 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 PARAMS ((char *, unsigned int));
37 static void unw_print_grmask PARAMS ((char *, unsigned int));
38 static void unw_print_frmask PARAMS ((char *, unsigned int));
39 static void unw_print_abreg PARAMS ((char *, unsigned int));
40 static void unw_print_xyreg PARAMS ((char *, unsigned int, unsigned int));
42 static void
43 unw_print_brmask (cp, mask)
44 char * cp;
45 unsigned int mask;
47 char *sep = "";
48 int i;
50 for (i = 0; mask && (i < 5); ++i)
52 if (mask & 1)
54 cp += sprintf (cp, "%sb%u", sep, i + 1);
55 sep = ",";
57 mask >>= 1;
59 *cp = '\0';
62 static void
63 unw_print_grmask (cp, mask)
64 char * cp;
65 unsigned int mask;
67 char *sep = "";
68 int i;
70 *cp = '\0';
71 for (i = 0; i < 4; ++i)
73 if (mask & 1)
75 cp += sprintf (cp, "%sr%u", sep, i + 4);
76 sep = ",";
78 mask >>= 1;
82 static void
83 unw_print_frmask (cp, mask)
84 char * cp;
85 unsigned int mask;
87 char *sep = "";
88 int i;
90 *cp = '\0';
91 for (i = 0; i < 20; ++i)
93 if (mask & 1)
95 cp += sprintf (cp, "%sf%u", sep, (i < 4) ? (i + 2) : (i + 12));
96 sep = ",";
98 mask >>= 1;
102 static void
103 unw_print_abreg (cp, abreg)
104 char * cp;
105 unsigned int abreg;
107 static const char *special_reg[16] =
109 "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
110 "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
111 "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
114 switch ((abreg >> 5) & 0x3)
116 case 0: /* gr */
117 sprintf (cp, "r%u", (abreg & 0x1f));
118 break;
120 case 1: /* fr */
121 sprintf (cp, "f%u", (abreg & 0x1f));
122 break;
124 case 2: /* br */
125 sprintf (cp, "b%u", (abreg & 0x1f));
126 break;
128 case 3: /* special */
129 strcpy (cp, special_reg[abreg & 0xf]);
130 break;
134 static void
135 unw_print_xyreg (cp, x, ytreg)
136 char * cp;
137 unsigned int x;
138 unsigned int ytreg;
140 switch ((x << 1) | ((ytreg >> 7) & 1))
142 case 0: /* gr */
143 sprintf (cp, "r%u", (ytreg & 0x1f));
144 break;
146 case 1: /* fr */
147 sprintf (cp, "f%u", (ytreg & 0x1f));
148 break;
150 case 2: /* br */
151 sprintf (cp, "b%u", (ytreg & 0x1f));
152 break;
156 #define UNW_REG_BSP "bsp"
157 #define UNW_REG_BSPSTORE "bspstore"
158 #define UNW_REG_FPSR "fpsr"
159 #define UNW_REG_LC "lc"
160 #define UNW_REG_PFS "pfs"
161 #define UNW_REG_PR "pr"
162 #define UNW_REG_PSP "psp"
163 #define UNW_REG_RNAT "rnat"
164 #define UNW_REG_RP "rp"
165 #define UNW_REG_UNAT "unat"
167 typedef bfd_vma unw_word;
169 #define UNW_DEC_BAD_CODE(code) \
170 printf ("Unknown code 0x%02x\n", code)
172 #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \
173 do \
175 unw_rlen = rlen; \
176 *(int *)arg = body; \
177 printf (" %s:%s(rlen=%lu)\n", \
178 fmt, body ? "body" : "prologue", (unsigned long) rlen); \
180 while (0)
182 #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \
183 do \
185 char regname[16], maskstr[64], *sep; \
187 unw_rlen = rlen; \
188 *(int *)arg = 0; \
190 maskstr[0] = '\0'; \
191 sep = ""; \
192 if (mask & 0x8) \
194 strcat (maskstr, "rp"); \
195 sep = ","; \
197 if (mask & 0x4) \
199 strcat (maskstr, sep); \
200 strcat (maskstr, "ar.pfs"); \
201 sep = ","; \
203 if (mask & 0x2) \
205 strcat (maskstr, sep); \
206 strcat (maskstr, "psp"); \
207 sep = ","; \
209 if (mask & 0x1) \
211 strcat (maskstr, sep); \
212 strcat (maskstr, "pr"); \
214 sprintf (regname, "r%u", grsave); \
215 printf (" %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \
216 fmt, maskstr, regname, (unsigned long) rlen); \
218 while (0)
220 #define UNW_DEC_FR_MEM(fmt, frmask, arg) \
221 do \
223 char frstr[200]; \
225 unw_print_frmask (frstr, frmask); \
226 printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \
228 while (0)
230 #define UNW_DEC_GR_MEM(fmt, grmask, arg) \
231 do \
233 char grstr[200]; \
235 unw_print_grmask (grstr, grmask); \
236 printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \
238 while (0)
240 #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \
241 do \
243 char frstr[200], grstr[20]; \
245 unw_print_grmask (grstr, grmask); \
246 unw_print_frmask (frstr, frmask); \
247 printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr); \
249 while (0)
251 #define UNW_DEC_BR_MEM(fmt, brmask, arg) \
252 do \
254 char brstr[20]; \
256 unw_print_brmask (brstr, brmask); \
257 printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \
259 while (0)
261 #define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \
262 do \
264 char brstr[20]; \
266 unw_print_brmask (brstr, brmask); \
267 printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \
269 while (0)
271 #define UNW_DEC_REG_GR(fmt, src, dst, arg) \
272 printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
274 #define UNW_DEC_RP_BR(fmt, dst, arg) \
275 printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
277 #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \
278 printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
280 #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \
281 printf ("\t%s:%s_sprel(spoff=0x%lx)\n", \
282 fmt, reg, 4*(unsigned long)spoff)
284 #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \
285 printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n", \
286 fmt, reg, 4*(unsigned long)pspoff)
288 #define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \
289 do \
291 char grstr[20]; \
293 unw_print_grmask (grstr, grmask); \
294 printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \
296 while (0)
298 #define UNW_DEC_ABI(fmt, abi, context, arg) \
299 do \
301 static const char *abiname[] = \
303 "@svr4", "@hpux", "@nt" \
304 }; \
305 char buf[20]; \
306 const char *abistr = buf; \
308 if (abi < 3) \
309 abistr = abiname[abi]; \
310 else \
311 sprintf (buf, "0x%x", abi); \
312 printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n", \
313 fmt, abistr, context); \
315 while (0)
317 #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \
318 printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
320 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \
321 printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
323 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \
324 printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
326 #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \
327 printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n", \
328 fmt, 4*(unsigned long)pspoff)
330 #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \
331 printf ("\t%s:priunat_sprel(spoff=0x%lx)\n", \
332 fmt, 4*(unsigned long)spoff)
334 #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \
335 printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n", \
336 fmt, (unsigned long) t, 16*(unsigned long)size)
338 #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \
339 printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
341 #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \
342 printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \
343 fmt, 4*(unsigned long)pspoff)
345 #define UNW_DEC_SPILL_MASK(fmt, dp, arg) \
346 do \
348 static const char * spill_type = "-frb"; \
349 unsigned const char * imaskp = dp; \
350 unsigned char mask = 0; \
351 bfd_vma insn = 0; \
353 printf ("\t%s:spill_mask(imask=[", fmt); \
354 for (insn = 0; insn < unw_rlen; ++insn) \
356 if ((insn % 4) == 0) \
357 mask = *imaskp++; \
358 if (insn > 0 && (insn % 3) == 0) \
359 putchar (','); \
360 putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]); \
362 printf ("])\n"); \
363 dp = imaskp; \
365 while (0)
367 #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \
368 do \
370 char regname[10]; \
372 unw_print_abreg (regname, abreg); \
373 printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \
374 fmt, regname, (unsigned long) t, 4*(unsigned long)off); \
376 while (0)
378 #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \
379 do \
381 char regname[10]; \
383 unw_print_abreg (regname, abreg); \
384 printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \
385 fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff); \
387 while (0)
389 #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \
390 do \
392 char regname[10]; \
394 unw_print_abreg (regname, abreg); \
395 printf ("\t%s:restore(t=%lu,reg=%s)\n", \
396 fmt, (unsigned long) t, regname); \
398 while (0)
400 #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \
401 do \
403 char abregname[10], tregname[10]; \
405 unw_print_abreg (abregname, abreg); \
406 unw_print_xyreg (tregname, x, ytreg); \
407 printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n", \
408 fmt, (unsigned long) t, abregname, tregname); \
410 while (0)
412 #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \
413 do \
415 char regname[20]; \
417 unw_print_abreg (regname, abreg); \
418 printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \
419 fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff); \
421 while (0)
423 #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \
424 do \
426 char regname[20]; \
428 unw_print_abreg (regname, abreg); \
429 printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\
430 fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\
432 while (0)
434 #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \
435 do \
437 char regname[20]; \
439 unw_print_abreg (regname, abreg); \
440 printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n", \
441 fmt, qp, (unsigned long) t, regname); \
443 while (0)
445 #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \
446 do \
448 char regname[20], tregname[20]; \
450 unw_print_abreg (regname, abreg); \
451 unw_print_xyreg (tregname, x, ytreg); \
452 printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n", \
453 fmt, qp, (unsigned long) t, regname, tregname); \
455 while (0)
457 #define UNW_DEC_LABEL_STATE(fmt, label, arg) \
458 printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
460 #define UNW_DEC_COPY_STATE(fmt, label, arg) \
461 printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
463 #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \
464 printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n", \
465 fmt, (unsigned long) t, (unsigned long) ecount)
468 * Generic IA-64 unwind info decoder.
470 * This file is used both by the Linux kernel and objdump. Please
471 * keep the two copies of this file in sync (modulo differences in the
472 * prototypes...).
474 * You need to customize the decoder by defining the following
475 * macros/constants before including this file:
477 * Types:
478 * unw_word Unsigned integer type with at least 64 bits
480 * Register names:
481 * UNW_REG_BSP
482 * UNW_REG_BSPSTORE
483 * UNW_REG_FPSR
484 * UNW_REG_LC
485 * UNW_REG_PFS
486 * UNW_REG_PR
487 * UNW_REG_RNAT
488 * UNW_REG_PSP
489 * UNW_REG_RP
490 * UNW_REG_UNAT
492 * Decoder action macros:
493 * UNW_DEC_BAD_CODE(code)
494 * UNW_DEC_ABI(fmt,abi,context,arg)
495 * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
496 * UNW_DEC_BR_MEM(fmt,brmask,arg)
497 * UNW_DEC_COPY_STATE(fmt,label,arg)
498 * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
499 * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
500 * UNW_DEC_FR_MEM(fmt,frmask,arg)
501 * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
502 * UNW_DEC_GR_MEM(fmt,grmask,arg)
503 * UNW_DEC_LABEL_STATE(fmt,label,arg)
504 * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
505 * UNW_DEC_MEM_STACK_V(fmt,t,arg)
506 * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
507 * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
508 * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
509 * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
510 * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
511 * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
512 * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
513 * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
514 * UNW_DEC_REG_REG(fmt,src,dst,arg)
515 * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
516 * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
517 * UNW_DEC_RESTORE(fmt,t,abreg,arg)
518 * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
519 * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
520 * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
521 * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
522 * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
523 * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
524 * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
525 * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
526 * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
529 static unw_word unw_decode_uleb128 PARAMS ((const unsigned char **));
530 static const unsigned char *unw_decode_x1 PARAMS ((const unsigned char *,
531 unsigned int, void *));
532 static const unsigned char *unw_decode_x2 PARAMS ((const unsigned char *,
533 unsigned int, void *));
534 static const unsigned char *unw_decode_x3 PARAMS ((const unsigned char *,
535 unsigned int, void *));
536 static const unsigned char *unw_decode_x4 PARAMS ((const unsigned char *,
537 unsigned int, void *));
538 static const unsigned char *unw_decode_r1 PARAMS ((const unsigned char *,
539 unsigned int, void *));
540 static const unsigned char *unw_decode_r2 PARAMS ((const unsigned char *,
541 unsigned int, void *));
542 static const unsigned char *unw_decode_r3 PARAMS ((const unsigned char *,
543 unsigned int, void *));
544 static const unsigned char *unw_decode_p1 PARAMS ((const unsigned char *,
545 unsigned int, void *));
546 static const unsigned char *unw_decode_p2_p5 PARAMS ((const unsigned char *,
547 unsigned int, void *));
548 static const unsigned char *unw_decode_p6 PARAMS ((const unsigned char *,
549 unsigned int, void *));
550 static const unsigned char *unw_decode_p7_p10 PARAMS ((const unsigned char *,
551 unsigned int, void *));
552 static const unsigned char *unw_decode_b1 PARAMS ((const unsigned char *,
553 unsigned int, void *));
554 static const unsigned char *unw_decode_b2 PARAMS ((const unsigned char *,
555 unsigned int, void *));
556 static const unsigned char *unw_decode_b3_x4 PARAMS ((const unsigned char *,
557 unsigned int, void *));
559 static unw_word
560 unw_decode_uleb128 (dpp)
561 const unsigned char **dpp;
563 unsigned shift = 0;
564 unw_word byte, result = 0;
565 const unsigned char *bp = *dpp;
567 while (1)
569 byte = *bp++;
570 result |= (byte & 0x7f) << shift;
572 if ((byte & 0x80) == 0)
573 break;
575 shift += 7;
578 *dpp = bp;
580 return result;
583 static const unsigned char *
584 unw_decode_x1 (dp, code, arg)
585 const unsigned char * dp;
586 unsigned int code ATTRIBUTE_UNUSED;
587 void * arg ATTRIBUTE_UNUSED;
589 unsigned char byte1, abreg;
590 unw_word t, off;
592 byte1 = *dp++;
593 t = unw_decode_uleb128 (&dp);
594 off = unw_decode_uleb128 (&dp);
595 abreg = (byte1 & 0x7f);
596 if (byte1 & 0x80)
597 UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
598 else
599 UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
600 return dp;
603 static const unsigned char *
604 unw_decode_x2 (dp, code, arg)
605 const unsigned char * dp;
606 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 (dp, code, arg)
627 const unsigned char * dp;
628 unsigned int code ATTRIBUTE_UNUSED;
629 void * arg ATTRIBUTE_UNUSED;
631 unsigned char byte1, byte2, abreg, qp;
632 unw_word t, off;
634 byte1 = *dp++;
635 byte2 = *dp++;
636 t = unw_decode_uleb128 (&dp);
637 off = unw_decode_uleb128 (&dp);
639 qp = (byte1 & 0x3f);
640 abreg = (byte2 & 0x7f);
642 if (byte1 & 0x80)
643 UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
644 else
645 UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
646 return dp;
649 static const unsigned char *
650 unw_decode_x4 (dp, code, arg)
651 const unsigned char * dp;
652 unsigned int code ATTRIBUTE_UNUSED;
653 void * arg ATTRIBUTE_UNUSED;
655 unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
656 unw_word t;
658 byte1 = *dp++;
659 byte2 = *dp++;
660 byte3 = *dp++;
661 t = unw_decode_uleb128 (&dp);
663 qp = (byte1 & 0x3f);
664 abreg = (byte2 & 0x7f);
665 x = (byte2 >> 7) & 1;
666 ytreg = byte3;
668 if ((byte2 & 0x80) == 0 && byte3 == 0)
669 UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
670 else
671 UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
672 return dp;
675 static const unsigned char *
676 unw_decode_r1 (dp, code, arg)
677 const unsigned char *dp;
678 unsigned int code;
679 void *arg;
681 int body = (code & 0x20) != 0;
682 unw_word rlen;
684 rlen = (code & 0x1f);
685 UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
686 return dp;
689 static const unsigned char *
690 unw_decode_r2 (dp, code, arg)
691 const unsigned char *dp;
692 unsigned int code;
693 void *arg;
695 unsigned char byte1, mask, grsave;
696 unw_word rlen;
698 byte1 = *dp++;
700 mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
701 grsave = (byte1 & 0x7f);
702 rlen = unw_decode_uleb128 (& dp);
703 UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
704 return dp;
707 static const unsigned char *
708 unw_decode_r3 (dp, code, arg)
709 const unsigned char *dp;
710 unsigned int code;
711 void *arg;
713 unw_word rlen;
715 rlen = unw_decode_uleb128 (& dp);
716 UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
717 return dp;
720 static const unsigned char *
721 unw_decode_p1 (dp, code, arg)
722 const unsigned char * dp;
723 unsigned int code;
724 void * arg ATTRIBUTE_UNUSED;
726 unsigned char brmask = (code & 0x1f);
728 UNW_DEC_BR_MEM ("P1", brmask, arg);
729 return dp;
732 static const unsigned char *
733 unw_decode_p2_p5 (dp, code, arg)
734 const unsigned char * dp;
735 unsigned int code;
736 void * arg ATTRIBUTE_UNUSED;
738 if ((code & 0x10) == 0)
740 unsigned char byte1 = *dp++;
742 UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
743 (byte1 & 0x7f), arg);
745 else if ((code & 0x08) == 0)
747 unsigned char byte1 = *dp++, r, dst;
749 r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
750 dst = (byte1 & 0x7f);
751 switch (r)
753 case 0:
754 UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
755 break;
756 case 1:
757 UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
758 break;
759 case 2:
760 UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
761 break;
762 case 3:
763 UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
764 break;
765 case 4:
766 UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
767 break;
768 case 5:
769 UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
770 break;
771 case 6:
772 UNW_DEC_RP_BR ("P3", dst, arg);
773 break;
774 case 7:
775 UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
776 break;
777 case 8:
778 UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
779 break;
780 case 9:
781 UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
782 break;
783 case 10:
784 UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
785 break;
786 case 11:
787 UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
788 break;
789 default:
790 UNW_DEC_BAD_CODE (r);
791 break;
794 else if ((code & 0x7) == 0)
795 UNW_DEC_SPILL_MASK ("P4", dp, arg);
796 else if ((code & 0x7) == 1)
798 unw_word grmask, frmask, byte1, byte2, byte3;
800 byte1 = *dp++;
801 byte2 = *dp++;
802 byte3 = *dp++;
803 grmask = ((byte1 >> 4) & 0xf);
804 frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
805 UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
807 else
808 UNW_DEC_BAD_CODE (code);
810 return dp;
813 static const unsigned char *
814 unw_decode_p6 (dp, code, arg)
815 const unsigned char * dp;
816 unsigned int code;
817 void * arg ATTRIBUTE_UNUSED;
819 int gregs = (code & 0x10) != 0;
820 unsigned char mask = (code & 0x0f);
822 if (gregs)
823 UNW_DEC_GR_MEM ("P6", mask, arg);
824 else
825 UNW_DEC_FR_MEM ("P6", mask, arg);
826 return dp;
829 static const unsigned char *
830 unw_decode_p7_p10 (dp, code, arg)
831 const unsigned char *dp;
832 unsigned int code;
833 void *arg;
835 unsigned char r, byte1, byte2;
836 unw_word t, size;
838 if ((code & 0x10) == 0)
840 r = (code & 0xf);
841 t = unw_decode_uleb128 (&dp);
842 switch (r)
844 case 0:
845 size = unw_decode_uleb128 (&dp);
846 UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
847 break;
849 case 1:
850 UNW_DEC_MEM_STACK_V ("P7", t, arg);
851 break;
852 case 2:
853 UNW_DEC_SPILL_BASE ("P7", t, arg);
854 break;
855 case 3:
856 UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
857 break;
858 case 4:
859 UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
860 break;
861 case 5:
862 UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
863 break;
864 case 6:
865 UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
866 break;
867 case 7:
868 UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
869 break;
870 case 8:
871 UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
872 break;
873 case 9:
874 UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
875 break;
876 case 10:
877 UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
878 break;
879 case 11:
880 UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
881 break;
882 case 12:
883 UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
884 break;
885 case 13:
886 UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
887 break;
888 case 14:
889 UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
890 break;
891 case 15:
892 UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
893 break;
894 default:
895 UNW_DEC_BAD_CODE (r);
896 break;
899 else
901 switch (code & 0xf)
903 case 0x0: /* p8 */
905 r = *dp++;
906 t = unw_decode_uleb128 (&dp);
907 switch (r)
909 case 1:
910 UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
911 break;
912 case 2:
913 UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
914 break;
915 case 3:
916 UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
917 break;
918 case 4:
919 UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
920 break;
921 case 5:
922 UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
923 break;
924 case 6:
925 UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
926 break;
927 case 7:
928 UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
929 break;
930 case 8:
931 UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
932 break;
933 case 9:
934 UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
935 break;
936 case 10:
937 UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
938 break;
939 case 11:
940 UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
941 break;
942 case 12:
943 UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
944 break;
945 case 13:
946 UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
947 break;
948 case 14:
949 UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
950 break;
951 case 15:
952 UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
953 break;
954 case 16:
955 UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
956 break;
957 case 17:
958 UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
959 break;
960 case 18:
961 UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
962 break;
963 case 19:
964 UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
965 break;
966 default:
967 UNW_DEC_BAD_CODE (r);
968 break;
971 break;
973 case 0x1:
974 byte1 = *dp++;
975 byte2 = *dp++;
976 UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
977 break;
979 case 0xf: /* p10 */
980 byte1 = *dp++;
981 byte2 = *dp++;
982 UNW_DEC_ABI ("P10", byte1, byte2, arg);
983 break;
985 case 0x9:
986 return unw_decode_x1 (dp, code, arg);
988 case 0xa:
989 return unw_decode_x2 (dp, code, arg);
991 case 0xb:
992 return unw_decode_x3 (dp, code, arg);
994 case 0xc:
995 return unw_decode_x4 (dp, code, arg);
997 default:
998 UNW_DEC_BAD_CODE (code);
999 break;
1002 return dp;
1005 static const unsigned char *
1006 unw_decode_b1 (dp, code, arg)
1007 const unsigned char * dp;
1008 unsigned int code;
1009 void * arg ATTRIBUTE_UNUSED;
1011 unw_word label = (code & 0x1f);
1013 if ((code & 0x20) != 0)
1014 UNW_DEC_COPY_STATE ("B1", label, arg);
1015 else
1016 UNW_DEC_LABEL_STATE ("B1", label, arg);
1017 return dp;
1020 static const unsigned char *
1021 unw_decode_b2 (dp, code, arg)
1022 const unsigned char * dp;
1023 unsigned int code;
1024 void * arg ATTRIBUTE_UNUSED;
1026 unw_word t;
1028 t = unw_decode_uleb128 (& dp);
1029 UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
1030 return dp;
1033 static const unsigned char *
1034 unw_decode_b3_x4 (dp, code, arg)
1035 const unsigned char *dp;
1036 unsigned int code;
1037 void *arg;
1039 unw_word t, ecount, label;
1041 if ((code & 0x10) == 0)
1043 t = unw_decode_uleb128 (&dp);
1044 ecount = unw_decode_uleb128 (&dp);
1045 UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
1047 else if ((code & 0x07) == 0)
1049 label = unw_decode_uleb128 (&dp);
1050 if ((code & 0x08) != 0)
1051 UNW_DEC_COPY_STATE ("B4", label, arg);
1052 else
1053 UNW_DEC_LABEL_STATE ("B4", label, arg);
1055 else
1056 switch (code & 0x7)
1058 case 1:
1059 return unw_decode_x1 (dp, code, arg);
1060 case 2:
1061 return unw_decode_x2 (dp, code, arg);
1062 case 3:
1063 return unw_decode_x3 (dp, code, arg);
1064 case 4:
1065 return unw_decode_x4 (dp, code, arg);
1066 default:
1067 UNW_DEC_BAD_CODE (code);
1068 break;
1070 return dp;
1073 typedef const unsigned char *(*unw_decoder)
1074 PARAMS ((const unsigned char *, unsigned char, void *));
1076 static unw_decoder unw_decode_table[2][8] =
1078 /* prologue table: */
1080 unw_decode_r1, /* 0 */
1081 unw_decode_r1,
1082 unw_decode_r2,
1083 unw_decode_r3,
1084 unw_decode_p1, /* 4 */
1085 unw_decode_p2_p5,
1086 unw_decode_p6,
1087 unw_decode_p7_p10
1090 unw_decode_r1, /* 0 */
1091 unw_decode_r1,
1092 unw_decode_r2,
1093 unw_decode_r3,
1094 unw_decode_b1, /* 4 */
1095 unw_decode_b1,
1096 unw_decode_b2,
1097 unw_decode_b3_x4
1101 /* Decode one descriptor and return address of next descriptor. */
1102 const unsigned char *
1103 unw_decode (dp, inside_body, ptr_inside_body)
1104 const unsigned char * dp;
1105 int inside_body;
1106 void * ptr_inside_body;
1108 unw_decoder decoder;
1109 unsigned char code;
1111 code = *dp++;
1112 decoder = unw_decode_table[inside_body][code >> 5];
1113 return (*decoder) (dp, code, ptr_inside_body);