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