1 /* $NetBSD: decode.c,v 1.2 2006/11/24 21:20:05 wiz Exp $ */ 2 3 /* Contributed to the NetBSD foundation by Cherry G. Mathew 4 * This file contains routines to decode unwind descriptors into 5 * easily an readable data structure ( unwind_desc ) 6 * This is the lowest layer of the unwind stack hierarchy. 7 */ 8 9 #include <sys/cdefs.h> 10 #include <sys/types.h> 11 #include <sys/param.h> 12 #include <sys/systm.h> 13 14 #include <ia64/unwind/decode.h> 15 16 /* Decode ULE128 string */ 17 18 char * 19 unwind_decode_ule128(char *buf, unsigned long *val) 20 { 21 int i = 0; 22 23 val[0] = 0; 24 do { 25 val[0] += ((buf[i] & 0x7f) << (i * 7)); 26 27 }while((0x80 & buf[i++]) && (i < 9)); 28 29 if(i > 9) { 30 printf("Warning: ULE128 won't fit in an unsigned long. decode aborted!!!\n"); 31 return 0; 32 } 33 34 buf+= i; 35 return buf; 36 } 37 38 39 char * 40 unwind_decode_R1(char *buf, union unwind_desc *uwd) 41 { 42 43 if(!IS_R1(buf[0])) return NULL; 44 uwd->R1.r = ((buf[0] & 0x20) == 0x20); 45 uwd->R1.rlen = (buf[0] & 0x1f); 46 buf++; 47 return buf; 48 } 49 50 char * 51 unwind_decode_R2(char *buf, union unwind_desc *uwd) 52 { 53 54 if(!IS_R2(buf[0])) return NULL; 55 56 uwd->R2.mask = (((buf[0] & 0x07) << 1) | ( (buf[1] >> 7) & 0xff)); 57 uwd->R2.grsave = (buf[1] & 0x7f); 58 59 buf += 2; 60 buf = unwind_decode_ule128(buf, &uwd->R2.rlen); 61 return buf; 62 } 63 64 char * 65 unwind_decode_R3(char *buf, union unwind_desc *uwd) 66 { 67 68 if(!IS_R3(buf[0])) return NULL; 69 70 uwd->R3.r = ((buf[0] & 0x03) == 0x01); 71 72 buf++; 73 buf = unwind_decode_ule128(buf, &uwd->R3.rlen); 74 return buf; 75 } 76 77 char * 78 unwind_decode_P1(char *buf, union unwind_desc *uwd) 79 { 80 81 82 if(!IS_P1(buf[0])) return NULL; 83 84 uwd->P1.brmask = (buf[0] & 0x1f); 85 buf++; 86 return buf; 87 } 88 89 char * 90 unwind_decode_P2(char *buf, union unwind_desc *uwd) 91 { 92 93 if(!IS_P2(buf[0])) return NULL; 94 95 uwd->P2.brmask = (((buf[0] & 0x0f) << 1) | ( (buf[1] >> 7) & 0xff)); 96 uwd->P2.gr = (buf[1] & 0x7f); 97 buf += 2; 98 return buf; 99 } 100 101 char * 102 unwind_decode_P3(char *buf, union unwind_desc *uwd) 103 { 104 105 if(!IS_P3(buf[0])) return NULL; 106 107 uwd->P3.r = (((0x07 & buf[0]) << 1) | ((0x80 & buf[1]) >> 7)); 108 uwd->P3.grbr = (buf[1] & 0x7f); 109 buf +=2; 110 return buf; 111 } 112 113 char * 114 unwind_decode_P4(char *buf, union unwind_desc *uwd, vsize_t len) 115 { 116 117 if(!IS_P4(buf[0])) return NULL; 118 119 uwd->P4.imask = 0; /* XXX: Unimplemented */ 120 121 /* XXX: adjust buf for imask length on return!!! 122 * don't know the length of imask here. 123 */ 124 buf += roundup(len << 1, 8); 125 return buf; 126 } 127 128 char * 129 unwind_decode_P5(char *buf, union unwind_desc *uwd) 130 { 131 132 if(!IS_P5(buf[0])) return NULL; 133 134 uwd->P5.grmask = (buf[1] >> 4); 135 uwd->P5.frmask = ((buf[1] & 0x0f << 16) | (buf[2] << 8) | buf[3]); 136 buf += 4; 137 return buf; 138 } 139 140 char * 141 unwind_decode_P6(char *buf, union unwind_desc *uwd) 142 { 143 144 if(!IS_P6(buf[0])) return NULL; 145 146 uwd->P6.r = ((buf[0] & 0x10) == 0x10); 147 uwd->P6.rmask = (buf[0] & 0x0f); 148 buf++; 149 return buf; 150 } 151 152 153 char * 154 unwind_decode_P7(char *buf, union unwind_desc *uwd) 155 { 156 157 if (!IS_P7(buf[0])) return NULL; 158 159 uwd->P7.r = (buf[0] & 0x0f); 160 161 buf++; 162 163 buf = unwind_decode_ule128(buf, &uwd->P7.t); 164 if (uwd->P7.r == 0) /* memstack_f */ 165 buf = unwind_decode_ule128(buf, &uwd->P7.size); 166 return buf; 167 } 168 169 char * 170 unwind_decode_P8(char *buf, union unwind_desc *uwd) 171 { 172 173 if(!IS_P8(buf[0])) return NULL; 174 175 uwd->P8.r = buf[1]; 176 177 buf +=2; 178 buf = unwind_decode_ule128(buf, &uwd->P8.t); 179 return buf; 180 } 181 182 char * 183 unwind_decode_P9(char *buf, union unwind_desc *uwd) 184 { 185 186 187 if(!IS_P9(buf[0])) return NULL; 188 189 uwd->P9.grmask = buf[1] & 0x0f; 190 uwd->P9.gr = buf[2] & 0x7f; 191 buf += 3; 192 return buf; 193 } 194 195 196 char * 197 unwind_decode_P10(char *buf, union unwind_desc *uwd) 198 { 199 200 201 if(!IS_P10(buf[0])) return NULL; 202 203 uwd->P10.abi = buf[1]; 204 uwd->P10.context = buf[2]; 205 buf += 3; 206 return buf; 207 } 208 209 char * 210 unwind_decode_B1(char *buf, union unwind_desc *uwd) 211 { 212 213 214 if(!IS_B1(buf[0])) return NULL; 215 216 uwd->B1.r = ((buf[0] & 0x20) == 0x20); 217 uwd->B1.label = (buf[0] & 0x1f); 218 219 buf++; 220 return buf; 221 } 222 223 char * 224 unwind_decode_B2(char *buf, union unwind_desc *uwd) 225 { 226 227 228 if(!IS_B2(buf[0])) return NULL; 229 230 uwd->B2.ecount = (buf[0] & 0x1f); 231 232 buf++; 233 buf = unwind_decode_ule128(buf, &uwd->B2.t); 234 return buf; 235 } 236 237 char * 238 unwind_decode_B3(char *buf, union unwind_desc *uwd) 239 { 240 241 242 if(!IS_B3(buf[0])) return NULL; 243 244 buf++; 245 buf = unwind_decode_ule128(buf, &uwd->B3.t); 246 buf = unwind_decode_ule128(buf, &uwd->B3.ecount); 247 return buf; 248 } 249 250 char * 251 unwind_decode_B4(char *buf, union unwind_desc *uwd) 252 { 253 254 255 if(!IS_B4(buf[0])) return NULL; 256 257 uwd->B4.r = ((buf[0] & 0x08) == 0x08); 258 259 buf++; 260 buf = unwind_decode_ule128(buf, &uwd->B4.label); 261 return buf; 262 } 263 264 265 char * 266 unwind_decode_X1(char *buf, union unwind_desc *uwd) 267 { 268 269 270 if(!IS_X1(buf[0])) return NULL; 271 272 uwd->X1.r = ((buf[1] & 0x80) == 0x80); 273 uwd->X1.a = ((buf[1] & 0x40) == 0x40); 274 uwd->X1.b = ((buf[1] & 0x20) == 0x20); 275 uwd->X1.reg = (buf[1] & 0x1f); 276 277 buf += 2; 278 buf = unwind_decode_ule128(buf, &uwd->X1.t); 279 buf = unwind_decode_ule128(buf, &uwd->X1.offset); 280 return buf; 281 } 282 283 284 char * 285 unwind_decode_X2(char *buf, union unwind_desc *uwd) 286 { 287 288 289 if(!IS_X2(buf[0])) return NULL; 290 291 uwd->X2.x = ((buf[1] & 0x80) == 0x80); 292 uwd->X2.a = ((buf[1] & 0x40) == 0x40); 293 uwd->X2.b = ((buf[1] & 0x20) == 0x20); 294 uwd->X2.reg = (buf[1] & 0x1f); 295 uwd->X2.y = ((buf[2] & 0x80) == 0x80); 296 uwd->X2.treg = (buf[2] & 0x7f); 297 298 buf += 3; 299 buf = unwind_decode_ule128(buf, &uwd->X2.t); 300 return buf; 301 } 302 303 char * 304 unwind_decode_X3(char *buf, union unwind_desc *uwd) 305 { 306 307 308 if(!IS_X3(buf[0])) return NULL; 309 310 uwd->X3.r = ((buf[1] & 0x80) == 0x80); 311 uwd->X3.qp = (buf[1] & 0x3f); 312 uwd->X3.a = ((buf[1] & 0x40) == 0x40); 313 uwd->X3.b = ((buf[1] & 0x20) == 0x20); 314 uwd->X3.reg = (buf[1] & 0x1f); 315 316 buf += 3; 317 buf = unwind_decode_ule128(buf, &uwd->X3.t); 318 buf = unwind_decode_ule128(buf, &uwd->X3.offset ); 319 return buf; 320 } 321 322 char * 323 unwind_decode_X4(char *buf, union unwind_desc *uwd) 324 { 325 326 327 if(!IS_X4(buf[0])) return NULL; 328 329 uwd->X4.qp = (buf[1] & 0x3f); 330 uwd->X4.x = ((buf[2] & 0x80) == 0x80); 331 uwd->X4.a = ((buf[2] & 0x40) == 0x40); 332 uwd->X4.b = ((buf[2] & 0x20) == 0x20); 333 uwd->X4.reg = (buf[2] & 0x1f); 334 uwd->X4.y = ((buf[3] & 0x80) == 0x80); 335 uwd->X4.treg = (buf[3] & 0x7f); 336 337 buf +=4; 338 buf = unwind_decode_ule128(buf, &uwd->X4.t); 339 return buf; 340 } 341 342