xref: /netbsd/sys/arch/ia64/unwind/decode.c (revision 6550d01e)
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