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