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