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