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