Initial import
[external/libunwind.git] / src / ia64 / unwind_decoder.h
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2001-2002 Hewlett-Packard Co
3         Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5 This file is part of libunwind.
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25
26 /*
27  * Generic IA-64 unwind info decoder.
28  *
29  * This file is used both by the Linux kernel and objdump.  Please keep
30  * the two copies of this file in sync.
31  *
32  * You need to customize the decoder by defining the following
33  * macros/constants before including this file:
34  *
35  *  Types:
36  *      unw_word        Unsigned integer type with at least 64 bits
37  *
38  *  Register names:
39  *      UNW_REG_BSP
40  *      UNW_REG_BSPSTORE
41  *      UNW_REG_FPSR
42  *      UNW_REG_LC
43  *      UNW_REG_PFS
44  *      UNW_REG_PR
45  *      UNW_REG_RNAT
46  *      UNW_REG_PSP
47  *      UNW_REG_RP
48  *      UNW_REG_UNAT
49  *
50  *  Decoder action macros:
51  *      UNW_DEC_BAD_CODE(code)
52  *      UNW_DEC_ABI(fmt,abi,context,arg)
53  *      UNW_DEC_BR_GR(fmt,brmask,gr,arg)
54  *      UNW_DEC_BR_MEM(fmt,brmask,arg)
55  *      UNW_DEC_COPY_STATE(fmt,label,arg)
56  *      UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
57  *      UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
58  *      UNW_DEC_FR_MEM(fmt,frmask,arg)
59  *      UNW_DEC_GR_GR(fmt,grmask,gr,arg)
60  *      UNW_DEC_GR_MEM(fmt,grmask,arg)
61  *      UNW_DEC_LABEL_STATE(fmt,label,arg)
62  *      UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
63  *      UNW_DEC_MEM_STACK_V(fmt,t,arg)
64  *      UNW_DEC_PRIUNAT_GR(fmt,r,arg)
65  *      UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
66  *      UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
67  *      UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
68  *      UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
69  *      UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
70  *      UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
71  *      UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
72  *      UNW_DEC_REG_REG(fmt,src,dst,arg)
73  *      UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
74  *      UNW_DEC_REG_WHEN(fmt,reg,t,arg)
75  *      UNW_DEC_RESTORE(fmt,t,abreg,arg)
76  *      UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
77  *      UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
78  *      UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
79  *      UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
80  *      UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
81  *      UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
82  *      UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
83  *      UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
84  *      UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
85  */
86
87 static unw_word
88 unw_decode_uleb128 (unsigned char **dpp)
89 {
90   unsigned shift = 0;
91   unw_word byte, result = 0;
92   unsigned char *bp = *dpp;
93
94   while (1)
95     {
96       byte = *bp++;
97       result |= (byte & 0x7f) << shift;
98       if ((byte & 0x80) == 0)
99         break;
100       shift += 7;
101     }
102   *dpp = bp;
103   return result;
104 }
105
106 static unsigned char *
107 unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg)
108 {
109   unsigned char byte1, abreg;
110   unw_word t, off;
111
112   byte1 = *dp++;
113   t = unw_decode_uleb128 (&dp);
114   off = unw_decode_uleb128 (&dp);
115   abreg = (byte1 & 0x7f);
116   if (byte1 & 0x80)
117           UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
118   else
119           UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
120   return dp;
121 }
122
123 static unsigned char *
124 unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg)
125 {
126   unsigned char byte1, byte2, abreg, x, ytreg;
127   unw_word t;
128
129   byte1 = *dp++; byte2 = *dp++;
130   t = unw_decode_uleb128 (&dp);
131   abreg = (byte1 & 0x7f);
132   ytreg = byte2;
133   x = (byte1 >> 7) & 1;
134   if ((byte1 & 0x80) == 0 && ytreg == 0)
135     UNW_DEC_RESTORE(X2, t, abreg, arg);
136   else
137     UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
138   return dp;
139 }
140
141 static unsigned char *
142 unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg)
143 {
144   unsigned char byte1, byte2, abreg, qp;
145   unw_word t, off;
146
147   byte1 = *dp++; byte2 = *dp++;
148   t = unw_decode_uleb128 (&dp);
149   off = unw_decode_uleb128 (&dp);
150
151   qp = (byte1 & 0x3f);
152   abreg = (byte2 & 0x7f);
153
154   if (byte1 & 0x80)
155     UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
156   else
157     UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
158   return dp;
159 }
160
161 static unsigned char *
162 unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg)
163 {
164   unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
165   unw_word t;
166
167   byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
168   t = unw_decode_uleb128 (&dp);
169
170   qp = (byte1 & 0x3f);
171   abreg = (byte2 & 0x7f);
172   x = (byte2 >> 7) & 1;
173   ytreg = byte3;
174
175   if ((byte2 & 0x80) == 0 && byte3 == 0)
176     UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
177   else
178     UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
179   return dp;
180 }
181
182 static inline unsigned char *
183 unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
184 {
185   int body = (code & 0x20) != 0;
186   unw_word rlen;
187
188   rlen = (code & 0x1f);
189   UNW_DEC_PROLOGUE(R1, body, rlen, arg);
190   return dp;
191 }
192
193 static inline unsigned char *
194 unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
195 {
196   unsigned char byte1, mask, grsave;
197   unw_word rlen;
198
199   byte1 = *dp++;
200
201   mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
202   grsave = (byte1 & 0x7f);
203   rlen = unw_decode_uleb128 (&dp);
204   UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
205   return dp;
206 }
207
208 static inline unsigned char *
209 unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
210 {
211   unw_word rlen;
212
213   rlen = unw_decode_uleb128 (&dp);
214   UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
215   return dp;
216 }
217
218 static inline unsigned char *
219 unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
220 {
221   unsigned char brmask = (code & 0x1f);
222
223   UNW_DEC_BR_MEM(P1, brmask, arg);
224   return dp;
225 }
226
227 static inline unsigned char *
228 unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
229 {
230   if ((code & 0x10) == 0)
231     {
232       unsigned char byte1 = *dp++;
233
234       UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
235                     (byte1 & 0x7f), arg);
236     }
237   else if ((code & 0x08) == 0)
238     {
239       unsigned char byte1 = *dp++, r, dst;
240
241       r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
242       dst = (byte1 & 0x7f);
243       switch (r)
244         {
245         case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
246         case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
247         case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
248         case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
249         case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
250         case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
251         case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
252         case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
253         case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
254         case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
255         case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
256         case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
257         default: UNW_DEC_BAD_CODE(r); break;
258         }
259     }
260   else if ((code & 0x7) == 0)
261     UNW_DEC_SPILL_MASK(P4, dp, arg);
262   else if ((code & 0x7) == 1)
263     {
264       unw_word grmask, frmask, byte1, byte2, byte3;
265
266       byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
267       grmask = ((byte1 >> 4) & 0xf);
268       frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
269       UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
270     }
271   else
272     UNW_DEC_BAD_CODE(code);
273   return dp;
274 }
275
276 static inline unsigned char *
277 unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
278 {
279   int gregs = (code & 0x10) != 0;
280   unsigned char mask = (code & 0x0f);
281
282   if (gregs)
283     UNW_DEC_GR_MEM(P6, mask, arg);
284   else
285     UNW_DEC_FR_MEM(P6, mask, arg);
286   return dp;
287 }
288
289 static inline unsigned char *
290 unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
291 {
292   unsigned char r, byte1, byte2;
293   unw_word t, size;
294
295   if ((code & 0x10) == 0)
296     {
297       r = (code & 0xf);
298       t = unw_decode_uleb128 (&dp);
299       switch (r)
300         {
301         case 0:
302           size = unw_decode_uleb128 (&dp);
303           UNW_DEC_MEM_STACK_F(P7, t, size, arg);
304           break;
305
306         case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
307         case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
308         case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
309         case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
310         case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
311         case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
312         case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
313         case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
314         case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
315         case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
316         case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
317         case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
318         case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
319         case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
320         case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
321         default: UNW_DEC_BAD_CODE(r); break;
322         }
323     }
324   else
325     {
326       switch (code & 0xf)
327         {
328         case 0x0: /* p8 */
329           {
330             r = *dp++;
331             t = unw_decode_uleb128 (&dp);
332             switch (r)
333               {
334               case  1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
335               case  2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
336               case  3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
337               case  4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
338               case  5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
339               case  6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
340               case  7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
341               case  8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
342               case  9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
343               case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
344               case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
345               case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
346               case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
347               case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
348               case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
349               case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
350               case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
351               case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
352               case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
353               default: UNW_DEC_BAD_CODE(r); break;
354             }
355           }
356           break;
357
358         case 0x1:
359           byte1 = *dp++; byte2 = *dp++;
360           UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
361           break;
362
363         case 0xf: /* p10 */
364           byte1 = *dp++; byte2 = *dp++;
365           UNW_DEC_ABI(P10, byte1, byte2, arg);
366           break;
367
368         case 0x9:
369           return unw_decode_x1 (dp, code, arg);
370
371         case 0xa:
372           return unw_decode_x2 (dp, code, arg);
373
374         case 0xb:
375           return unw_decode_x3 (dp, code, arg);
376
377         case 0xc:
378           return unw_decode_x4 (dp, code, arg);
379
380         default:
381           UNW_DEC_BAD_CODE(code);
382           break;
383         }
384     }
385   return dp;
386 }
387
388 static inline unsigned char *
389 unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
390 {
391   unw_word label = (code & 0x1f);
392
393   if ((code & 0x20) != 0)
394     UNW_DEC_COPY_STATE(B1, label, arg);
395   else
396     UNW_DEC_LABEL_STATE(B1, label, arg);
397   return dp;
398 }
399
400 static inline unsigned char *
401 unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
402 {
403   unw_word t;
404
405   t = unw_decode_uleb128 (&dp);
406   UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
407   return dp;
408 }
409
410 static inline unsigned char *
411 unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
412 {
413   unw_word t, ecount, label;
414
415   if ((code & 0x10) == 0)
416     {
417       t = unw_decode_uleb128 (&dp);
418       ecount = unw_decode_uleb128 (&dp);
419       UNW_DEC_EPILOGUE(B3, t, ecount, arg);
420     }
421   else if ((code & 0x07) == 0)
422     {
423       label = unw_decode_uleb128 (&dp);
424       if ((code & 0x08) != 0)
425         UNW_DEC_COPY_STATE(B4, label, arg);
426       else
427         UNW_DEC_LABEL_STATE(B4, label, arg);
428     }
429   else
430     switch (code & 0x7)
431       {
432       case 1: return unw_decode_x1 (dp, code, arg);
433       case 2: return unw_decode_x2 (dp, code, arg);
434       case 3: return unw_decode_x3 (dp, code, arg);
435       case 4: return unw_decode_x4 (dp, code, arg);
436       default: UNW_DEC_BAD_CODE(code); break;
437       }
438   return dp;
439 }
440
441 typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
442
443 /*
444  * Decode one descriptor and return address of next descriptor.
445  */
446 static inline unsigned char *
447 unw_decode (unsigned char *dp, int inside_body, void *arg)
448 {
449   unsigned char code, primary;
450
451   code = *dp++;
452   primary = code >> 5;
453
454   if (primary < 2)
455     dp = unw_decode_r1 (dp, code, arg);
456   else if (primary == 2)
457     dp = unw_decode_r2 (dp, code, arg);
458   else if (primary == 3)
459     dp = unw_decode_r3 (dp, code, arg);
460   else if (inside_body)
461     switch (primary)
462       {
463       case 4:
464       case 5: dp = unw_decode_b1 (dp, code, arg); break;
465       case 6: dp = unw_decode_b2 (dp, code, arg); break;
466       case 7: dp = unw_decode_b3_x4 (dp, code, arg); break;
467       }
468   else
469     switch (primary)
470       {
471       case 4: dp = unw_decode_p1 (dp, code, arg); break;
472       case 5: dp = unw_decode_p2_p5 (dp, code, arg); break;
473       case 6: dp = unw_decode_p6 (dp, code, arg); break;
474       case 7: dp = unw_decode_p7_p10 (dp, code, arg); break;
475       }
476   return dp;
477 }