Home | History | Annotate | Line # | Download | only in unwind
      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