xref: /netbsd-src/sys/arch/ia64/unwind/stackframe.c (revision e0ba28d784a721fb0d56acb887e7d71150ebf749)
1*e0ba28d7Sdholland /*	$NetBSD: stackframe.c,v 1.9 2016/07/31 19:33:18 dholland Exp $	*/
2ba7cbe76Scherry 
3ba7cbe76Scherry /* Contributed to the NetBSD foundation by Cherry G. Mathew <cherry@mahiti.org>
4ba7cbe76Scherry  * This file contains routines to use decoded unwind descriptor entries
5ba7cbe76Scherry  * to build a stack configuration. The unwinder consults the stack
6ba7cbe76Scherry  * configuration to fetch registers used to unwind the frame.
7ba7cbe76Scherry  * References:
8ba7cbe76Scherry  *	[1] section. 11.4.2.6., Itanium Software Conventions and
9ba7cbe76Scherry  *			Runtime Architecture Guide.
10ba7cbe76Scherry  */
11ba7cbe76Scherry 
12ba7cbe76Scherry #include <sys/cdefs.h>
13ba7cbe76Scherry #include <sys/param.h>
14ba7cbe76Scherry #include <sys/systm.h>
15ba7cbe76Scherry 
16ba7cbe76Scherry 
17ba7cbe76Scherry #include <ia64/unwind/decode.h>
18ba7cbe76Scherry #include <ia64/unwind/stackframe.h>
19ba7cbe76Scherry 
20ba7cbe76Scherry //#define UNWIND_DIAGNOSTIC
21ba7cbe76Scherry 
22d6aeeea2Sdholland /*
23d6aeeea2Sdholland  * Global variables:
24d6aeeea2Sdholland  * array of struct recordchain
25d6aeeea2Sdholland  * size of record chain array.
26ba7cbe76Scherry  */
27ba7cbe76Scherry struct recordchain strc[MAXSTATERECS];
28ba7cbe76Scherry int rec_cnt = 0;
29ba7cbe76Scherry 
30d6aeeea2Sdholland /*
31d6aeeea2Sdholland  * Build a recordchain of a region, given the pointer to unwind table
32ba7cbe76Scherry  * entry, and the number of entries to decode.
33ba7cbe76Scherry  */
34d6aeeea2Sdholland void
buildrecordchain(uint64_t unwind_infop,struct recordchain * xxx)35d6aeeea2Sdholland buildrecordchain(uint64_t unwind_infop, struct recordchain *xxx)
36ba7cbe76Scherry {
37ba7cbe76Scherry 	uint64_t unwindstart, unwindend;
38ba7cbe76Scherry 	uint64_t unwindlen;
39ba7cbe76Scherry 	uint64_t region_len = 0;
4009c5f9ccSthorpej 	bool region_type = false; /* Prologue */
41ba7cbe76Scherry 
42ba7cbe76Scherry 	struct unwind_hdr_t {
43ba7cbe76Scherry 		uint64_t uwh;
44ba7cbe76Scherry 	} *uwhp = (void *) unwind_infop;
45ba7cbe76Scherry 
46ba7cbe76Scherry 	char *nextrecp, *recptr = (char *) unwind_infop + sizeof(uint64_t);
47ba7cbe76Scherry 
48ba7cbe76Scherry 	unwindstart = (uint64_t) recptr;
49ba7cbe76Scherry 
50ba7cbe76Scherry 	if (UNW_VER(uwhp->uwh) != 1) {
51ba7cbe76Scherry 		printf("Wrong unwind version! \n");
52ba7cbe76Scherry 		return;
53ba7cbe76Scherry 	}
54ba7cbe76Scherry 
55ba7cbe76Scherry 	unwindlen = UNW_LENGTH(uwhp->uwh) * sizeof(uint64_t);
56ba7cbe76Scherry 	unwindend = unwindstart + unwindlen;
57ba7cbe76Scherry 
58ba7cbe76Scherry #ifdef UNWIND_DIAGNOSTIC
59ba7cbe76Scherry 	printf("recptr = %p \n", recptr);
60ba7cbe76Scherry 	printf("unwindlen = %lx \n", unwindlen);
61ba7cbe76Scherry 	printf("unwindend = %lx \n", unwindend);
62ba7cbe76Scherry #endif
63ba7cbe76Scherry 
64ba7cbe76Scherry 	/* XXX: Ignore zero length records. */
65ba7cbe76Scherry 
66ba7cbe76Scherry 
67*e0ba28d7Sdholland 	for (rec_cnt = 0;
68*e0ba28d7Sdholland 	    rec_cnt < MAXSTATERECS && (uint64_t)recptr < unwindend;
69ba7cbe76Scherry 	    rec_cnt++) {
70*e0ba28d7Sdholland 		nextrecp = unwind_decode_R1(recptr, &strc[rec_cnt].udesc);
71*e0ba28d7Sdholland 		if (nextrecp) {
72ba7cbe76Scherry 			region_len = strc[rec_cnt].udesc.R1.rlen;
73ba7cbe76Scherry 			region_type = strc[rec_cnt].udesc.R1.r;
74ba7cbe76Scherry 			strc[rec_cnt].type = R1;
75ba7cbe76Scherry 			recptr = nextrecp;
76ba7cbe76Scherry 			continue;
77ba7cbe76Scherry 		}
78ba7cbe76Scherry 
79*e0ba28d7Sdholland 		nextrecp = unwind_decode_R2(recptr, &strc[rec_cnt].udesc);
80*e0ba28d7Sdholland 		if (nextrecp) {
81ba7cbe76Scherry 			region_len = strc[rec_cnt].udesc.R2.rlen;
82d6aeeea2Sdholland 			/* R2 regions are prologue regions */
83d6aeeea2Sdholland 			region_type = false;
84ba7cbe76Scherry 			strc[rec_cnt].type = R2;
85ba7cbe76Scherry 			recptr = nextrecp;
86ba7cbe76Scherry 			continue;
87ba7cbe76Scherry 		}
88ba7cbe76Scherry 
89*e0ba28d7Sdholland 		nextrecp = unwind_decode_R3(recptr, &strc[rec_cnt].udesc);
90*e0ba28d7Sdholland 		if (nextrecp) {
91ba7cbe76Scherry 			region_len = strc[rec_cnt].udesc.R3.rlen;
92ba7cbe76Scherry 			region_type = strc[rec_cnt].udesc.R3.r;
93ba7cbe76Scherry 			strc[rec_cnt].type = R3;
94ba7cbe76Scherry 			recptr = nextrecp;
95ba7cbe76Scherry 			continue;
96ba7cbe76Scherry 		}
97ba7cbe76Scherry 
98d6aeeea2Sdholland 		if (region_type == false) {
99d6aeeea2Sdholland 			/* Prologue Region */
100*e0ba28d7Sdholland 			nextrecp = unwind_decode_P1(recptr,
101*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
102*e0ba28d7Sdholland 			if (nextrecp) {
103ba7cbe76Scherry 				strc[rec_cnt].type = P1;
104ba7cbe76Scherry 				recptr = nextrecp;
105ba7cbe76Scherry 				continue;
106ba7cbe76Scherry 			}
107ba7cbe76Scherry 
108*e0ba28d7Sdholland 			nextrecp = unwind_decode_P2(recptr,
109*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
110*e0ba28d7Sdholland 			if (nextrecp) {
111ba7cbe76Scherry 				strc[rec_cnt].type = P2;
112ba7cbe76Scherry 				recptr = nextrecp;
113ba7cbe76Scherry 				continue;
114ba7cbe76Scherry 			}
115ba7cbe76Scherry 
116*e0ba28d7Sdholland 			nextrecp = unwind_decode_P3(recptr,
117*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
118*e0ba28d7Sdholland 			if (nextrecp) {
119ba7cbe76Scherry 				strc[rec_cnt].type = P3;
120ba7cbe76Scherry 				recptr = nextrecp;
121ba7cbe76Scherry 				continue;
122ba7cbe76Scherry 			}
123ba7cbe76Scherry 
124*e0ba28d7Sdholland 			nextrecp = unwind_decode_P4(recptr,
125*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc,
126*e0ba28d7Sdholland 						    region_len);
127*e0ba28d7Sdholland 			if (nextrecp) {
128ba7cbe76Scherry 				strc[rec_cnt].type = P4;
129ba7cbe76Scherry 				recptr = nextrecp;
130ba7cbe76Scherry 				break;
131ba7cbe76Scherry 			}
132ba7cbe76Scherry 
133*e0ba28d7Sdholland 			nextrecp = unwind_decode_P5(recptr,
134*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
135*e0ba28d7Sdholland 			if (nextrecp) {
136ba7cbe76Scherry 				strc[rec_cnt].type = P5;
137ba7cbe76Scherry 				recptr = nextrecp;
138ba7cbe76Scherry 				continue;
139ba7cbe76Scherry 			}
140ba7cbe76Scherry 
141*e0ba28d7Sdholland 			nextrecp = unwind_decode_P6(recptr,
142*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
143*e0ba28d7Sdholland 			if (nextrecp) {
144ba7cbe76Scherry 				strc[rec_cnt].type = P6;
145ba7cbe76Scherry 				recptr = nextrecp;
146ba7cbe76Scherry 				continue;
147ba7cbe76Scherry 			}
148ba7cbe76Scherry 
149*e0ba28d7Sdholland 			nextrecp = unwind_decode_P7(recptr,
150*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
151*e0ba28d7Sdholland 			if (nextrecp) {
152ba7cbe76Scherry 				strc[rec_cnt].type = P7;
153ba7cbe76Scherry 				recptr = nextrecp;
154ba7cbe76Scherry 				continue;
155ba7cbe76Scherry 			}
156ba7cbe76Scherry 
157*e0ba28d7Sdholland 			nextrecp = unwind_decode_P8(recptr,
158*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
159*e0ba28d7Sdholland 			if (nextrecp) {
160ba7cbe76Scherry 				strc[rec_cnt].type = P8;
161ba7cbe76Scherry 				recptr = nextrecp;
162ba7cbe76Scherry 				continue;
163ba7cbe76Scherry 			}
164ba7cbe76Scherry 
165*e0ba28d7Sdholland 			nextrecp = unwind_decode_P9(recptr,
166*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
167*e0ba28d7Sdholland 			if (nextrecp) {
168ba7cbe76Scherry 				strc[rec_cnt].type = P9;
169ba7cbe76Scherry 				recptr = nextrecp;
170ba7cbe76Scherry 				continue;
171ba7cbe76Scherry 			}
172ba7cbe76Scherry 
173*e0ba28d7Sdholland 			nextrecp = unwind_decode_P10(recptr,
174*e0ba28d7Sdholland 						     &strc[rec_cnt].udesc);
175*e0ba28d7Sdholland 			if (nextrecp) {
176ba7cbe76Scherry 				strc[rec_cnt].type = P10;
177ba7cbe76Scherry 				recptr = nextrecp;
178ba7cbe76Scherry 				continue;
179ba7cbe76Scherry 			}
180ba7cbe76Scherry 
181ba7cbe76Scherry 			printf("Skipping prologue desc slot :: %d \n", rec_cnt);
182*e0ba28d7Sdholland 		} else {
183ba7cbe76Scherry 
184*e0ba28d7Sdholland 			nextrecp = unwind_decode_B1(recptr,
185*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
186*e0ba28d7Sdholland 			if (nextrecp) {
187ba7cbe76Scherry 				strc[rec_cnt].type = B1;
188ba7cbe76Scherry 				recptr = nextrecp;
189ba7cbe76Scherry 				continue;
190ba7cbe76Scherry 			}
191ba7cbe76Scherry 
192*e0ba28d7Sdholland 			nextrecp = unwind_decode_B2(recptr,
193*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
194*e0ba28d7Sdholland 			if (nextrecp) {
195ba7cbe76Scherry 				strc[rec_cnt].type = B2;
196ba7cbe76Scherry 				recptr = nextrecp;
197ba7cbe76Scherry 				continue;
198ba7cbe76Scherry 			}
199ba7cbe76Scherry 
200*e0ba28d7Sdholland 			nextrecp = unwind_decode_B3(recptr,
201*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
202*e0ba28d7Sdholland 			if (nextrecp) {
203ba7cbe76Scherry 				strc[rec_cnt].type = B3;
204ba7cbe76Scherry 				recptr = nextrecp;
205ba7cbe76Scherry 				continue;
206ba7cbe76Scherry 			}
207ba7cbe76Scherry 
208*e0ba28d7Sdholland 			nextrecp = unwind_decode_B4(recptr,
209*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
210*e0ba28d7Sdholland 			if (nextrecp) {
211ba7cbe76Scherry 				strc[rec_cnt].type = B4;
212ba7cbe76Scherry 				recptr = nextrecp;
213ba7cbe76Scherry 				continue;
214ba7cbe76Scherry 			}
215ba7cbe76Scherry 
216*e0ba28d7Sdholland 			nextrecp = unwind_decode_X1(recptr,
217*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
218*e0ba28d7Sdholland 			if (nextrecp) {
219ba7cbe76Scherry 				strc[rec_cnt].type = X1;
220ba7cbe76Scherry 				recptr = nextrecp;
221ba7cbe76Scherry 				continue;
222ba7cbe76Scherry 			}
223ba7cbe76Scherry 
224*e0ba28d7Sdholland 			nextrecp = unwind_decode_X2(recptr,
225*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
226*e0ba28d7Sdholland 			if (nextrecp) {
227ba7cbe76Scherry 				strc[rec_cnt].type = X2;
228ba7cbe76Scherry 				recptr = nextrecp;
229ba7cbe76Scherry 				continue;
230ba7cbe76Scherry 			}
231ba7cbe76Scherry 
232ba7cbe76Scherry 
233*e0ba28d7Sdholland 			nextrecp = unwind_decode_X3(recptr,
234*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
235*e0ba28d7Sdholland 			if (nextrecp) {
236ba7cbe76Scherry 				strc[rec_cnt].type = X3;
237ba7cbe76Scherry 				recptr = nextrecp;
238ba7cbe76Scherry 				continue;
239ba7cbe76Scherry 			}
240ba7cbe76Scherry 
241*e0ba28d7Sdholland 			nextrecp = unwind_decode_X4(recptr,
242*e0ba28d7Sdholland 						    &strc[rec_cnt].udesc);
243*e0ba28d7Sdholland 			if (nextrecp) {
244ba7cbe76Scherry 				strc[rec_cnt].type = X4;
245ba7cbe76Scherry 				recptr = nextrecp;
246ba7cbe76Scherry 				continue;
247ba7cbe76Scherry 			}
248ba7cbe76Scherry 
249ba7cbe76Scherry 			printf("Skipping body desc slot :: %d \n", rec_cnt);
250ba7cbe76Scherry 		}
251ba7cbe76Scherry 	}
252ba7cbe76Scherry 
253ba7cbe76Scherry #ifdef UNWIND_DIAGNOSTIC
254ba7cbe76Scherry 	int i;
255ba7cbe76Scherry 	for(i = 0;i < rec_cnt;i++) {
256ba7cbe76Scherry 		dump_recordchain(&strc[i]);
257ba7cbe76Scherry 	}
258ba7cbe76Scherry 
259ba7cbe76Scherry #endif /* UNWIND_DIAGNOSTIC */
260ba7cbe76Scherry }
261ba7cbe76Scherry 
262ba7cbe76Scherry 
263ba7cbe76Scherry 
264ba7cbe76Scherry 
265d6aeeea2Sdholland /*
266d6aeeea2Sdholland  * Debug support: dump a record chain entry
267d6aeeea2Sdholland  */
268d6aeeea2Sdholland void
dump_recordchain(struct recordchain * rchain)269d6aeeea2Sdholland dump_recordchain(struct recordchain *rchain)
270ba7cbe76Scherry {
271ba7cbe76Scherry 
272ba7cbe76Scherry 	switch(rchain->type) {
273ba7cbe76Scherry 	case R1:
274ba7cbe76Scherry 		printf("\t R1:");
275ba7cbe76Scherry 		if(rchain->udesc.R1.r)
276ba7cbe76Scherry 			printf("body (");
277ba7cbe76Scherry 		else
278ba7cbe76Scherry 			printf("prologue (");
279ba7cbe76Scherry 		printf("rlen = %ld) \n", rchain->udesc.R1.rlen);
280ba7cbe76Scherry 		break;
281ba7cbe76Scherry 
282ba7cbe76Scherry 	case R2:
283ba7cbe76Scherry 		printf("\t R2:");
284ba7cbe76Scherry 		printf("prologue_gr (");
285ba7cbe76Scherry 		printf("mask = %x, ", rchain->udesc.R2.mask);
286ba7cbe76Scherry 		printf("grsave = %d, ", rchain->udesc.R2.grsave);
287ba7cbe76Scherry 		printf("rlen = %ld )\n", rchain->udesc.R2.rlen);
288ba7cbe76Scherry 		break;
289ba7cbe76Scherry 
290ba7cbe76Scherry 	case R3:
291ba7cbe76Scherry 		printf("\t R3:");
292ba7cbe76Scherry 		if(rchain->udesc.R3.r)
293ba7cbe76Scherry 			printf("body (");
294ba7cbe76Scherry 		else
295ba7cbe76Scherry 			printf("prologue (");
296ba7cbe76Scherry 		printf("rlen = %ld )\n", rchain->udesc.R3.rlen);
297ba7cbe76Scherry 		break;
298ba7cbe76Scherry 
299ba7cbe76Scherry 	case P1:
300ba7cbe76Scherry 		printf("\t\tP1:");
301ba7cbe76Scherry 		printf("br_mem (brmask = %x) \n", rchain->udesc.P1.brmask);
302ba7cbe76Scherry 		break;
303ba7cbe76Scherry 
304ba7cbe76Scherry 	case P2:
305ba7cbe76Scherry 		printf("\t\tP2:");
306ba7cbe76Scherry 		printf("br_gr(brmask = %x, ", rchain->udesc.P2.brmask);
307ba7cbe76Scherry 		printf("gr = %d ) \n", rchain->udesc.P2.gr);
308ba7cbe76Scherry 		break;
309ba7cbe76Scherry 
310ba7cbe76Scherry 	case P3:
311ba7cbe76Scherry 		printf("\t\tP3:");
312ba7cbe76Scherry 		switch(rchain->udesc.P3.r) {
313ba7cbe76Scherry 		case 0:
314ba7cbe76Scherry 			printf("psp_gr");
315ba7cbe76Scherry 			break;
316ba7cbe76Scherry 		case 1:
317ba7cbe76Scherry 			printf("rp_gr");
318ba7cbe76Scherry 			break;
319ba7cbe76Scherry 		case 2:
320ba7cbe76Scherry 			printf("pfs_gr");
321ba7cbe76Scherry 			break;
322ba7cbe76Scherry 		case 3:
323ba7cbe76Scherry 			printf("preds_gr");
324ba7cbe76Scherry 			break;
325ba7cbe76Scherry 		case 4:
326ba7cbe76Scherry 			printf("unat_gr");
327ba7cbe76Scherry 			break;
328ba7cbe76Scherry 		case 5:
329ba7cbe76Scherry 			printf("lc_gr");
330ba7cbe76Scherry 			break;
331ba7cbe76Scherry 		case 6:
332ba7cbe76Scherry 			printf("rp_br");
333ba7cbe76Scherry 			break;
334ba7cbe76Scherry 		case 7:
335ba7cbe76Scherry 			printf("rnat_gr");
336ba7cbe76Scherry 			break;
337ba7cbe76Scherry 		case 8:
338ba7cbe76Scherry 			printf("bsp_gr");
339ba7cbe76Scherry 			break;
340ba7cbe76Scherry 		case 9:
341ba7cbe76Scherry 			printf("bspstore_gr");
342ba7cbe76Scherry 			break;
343ba7cbe76Scherry 		case 10:
344ba7cbe76Scherry 			printf("fpsr_gr");
345ba7cbe76Scherry 			break;
346ba7cbe76Scherry 		case 11:
347ba7cbe76Scherry 			printf("priunat_gr");
348ba7cbe76Scherry 			break;
349ba7cbe76Scherry 		default:
350ba7cbe76Scherry 			printf("unknown desc: %d", rchain->udesc.P3.r);
351ba7cbe76Scherry 
352ba7cbe76Scherry 		}
353ba7cbe76Scherry 		printf("(gr/br = %d) \n", rchain->udesc.P3.grbr);
354ba7cbe76Scherry 
355ba7cbe76Scherry 		break;
356ba7cbe76Scherry 
357ba7cbe76Scherry 	case P4:
358ba7cbe76Scherry 		printf("P4: (unimplemented): \n");
359ba7cbe76Scherry 		break;
360ba7cbe76Scherry 
361ba7cbe76Scherry 	case P5:
362ba7cbe76Scherry 		printf("\t\tP5:");
363ba7cbe76Scherry 		printf("frgr_mem(grmask = %x, frmask = %x )\n",
364ba7cbe76Scherry 		       rchain->udesc.P5.grmask, rchain->udesc.P5.frmask);
365ba7cbe76Scherry 		break;
366ba7cbe76Scherry 
367ba7cbe76Scherry 	case P6:
368ba7cbe76Scherry 		printf("\t\tP6: ");
369ba7cbe76Scherry 		if(rchain->udesc.P6.r)
370ba7cbe76Scherry 			printf("gr_mem( ");
371ba7cbe76Scherry 		else
372ba7cbe76Scherry 			printf("fr_mem( ");
373ba7cbe76Scherry 		printf("rmask = %x) \n", rchain->udesc.P6.rmask);
374ba7cbe76Scherry 		break;
375ba7cbe76Scherry 
376ba7cbe76Scherry 	case P7:
377ba7cbe76Scherry 		printf("\t\tP7:");
378ba7cbe76Scherry 		switch(rchain->udesc.P7.r) {
379ba7cbe76Scherry 		case 0:
380ba7cbe76Scherry 			printf("memstack_f( ");
381ba7cbe76Scherry 			printf("t = %ld, ", rchain->udesc.P7.t);
382ba7cbe76Scherry 			printf("size = %ld) \n", rchain->udesc.P7.size);
383ba7cbe76Scherry 			break;
384ba7cbe76Scherry 		case 1:
385ba7cbe76Scherry 			printf("memstack_v( ");
386ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P7.t);
387ba7cbe76Scherry 			break;
388ba7cbe76Scherry 		case 2:
389ba7cbe76Scherry 			printf("spillbase( ");
390ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P7.t);
391ba7cbe76Scherry 			break;
392ba7cbe76Scherry 		case 3:
393ba7cbe76Scherry 			printf("psp_sprel( ");
394ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P7.t);
395ba7cbe76Scherry 			break;
396ba7cbe76Scherry 		case 4:
397ba7cbe76Scherry 			printf("rp_when( ");
398ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P7.t);
399ba7cbe76Scherry 			break;
400ba7cbe76Scherry 		case 5:
401ba7cbe76Scherry 			printf("rp_psprel( ");
402ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P7.t);
403ba7cbe76Scherry 			break;
404ba7cbe76Scherry 		case 6:
405ba7cbe76Scherry 			printf("pfs_when( ");
406ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P7.t);
407ba7cbe76Scherry 			break;
408ba7cbe76Scherry 		case 7:
409ba7cbe76Scherry 			printf("pfs_psprel( ");
410ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P7.t);
411ba7cbe76Scherry 			break;
412ba7cbe76Scherry 		case 8:
413ba7cbe76Scherry 			printf("preds_when( ");
414ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P7.t);
415ba7cbe76Scherry 			break;
416ba7cbe76Scherry 		case 9:
417ba7cbe76Scherry 			printf("preds_psprel( ");
418ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P7.t);
419ba7cbe76Scherry 			break;
420ba7cbe76Scherry 		case 10:
421ba7cbe76Scherry 			printf("lc_when( ");
422ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P7.t);
423ba7cbe76Scherry 			break;
424ba7cbe76Scherry 		case 11:
425ba7cbe76Scherry 			printf("lc_psprel( ");
426ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P7.t);
427ba7cbe76Scherry 			break;
428ba7cbe76Scherry 		case 12:
429ba7cbe76Scherry 			printf("unat_when( ");
430ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P7.t);
431ba7cbe76Scherry 			break;
432ba7cbe76Scherry 		case 13:
433ba7cbe76Scherry 			printf("unat_psprel( ");
434ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P7.t);
435ba7cbe76Scherry 			break;
436ba7cbe76Scherry 		case 14:
437ba7cbe76Scherry 			printf("fpsr_when( ");
438ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P7.t);
439ba7cbe76Scherry 			break;
440ba7cbe76Scherry 		case 15:
441ba7cbe76Scherry 			printf("fpsr_psprel( ");
442ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P7.t);
443ba7cbe76Scherry 			break;
444ba7cbe76Scherry 		default:
445ba7cbe76Scherry 			printf("unknown \n");
446ba7cbe76Scherry 		}
447ba7cbe76Scherry 
448ba7cbe76Scherry 		break;
449ba7cbe76Scherry 
450ba7cbe76Scherry 	case P8:
451ba7cbe76Scherry 		printf("\t\tP8:");
452ba7cbe76Scherry 		switch(rchain->udesc.P8.r) {
453ba7cbe76Scherry 		case 1:
454ba7cbe76Scherry 			printf("rp_sprel( ");
455ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
456ba7cbe76Scherry 			break;
457ba7cbe76Scherry 		case 2:
458ba7cbe76Scherry 			printf("pfs_sprel( ");
459ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
460ba7cbe76Scherry 			break;
461ba7cbe76Scherry 		case 3:
462ba7cbe76Scherry 			printf("preds_sprel( ");
463ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
464ba7cbe76Scherry 			break;
465ba7cbe76Scherry 		case 4:
466ba7cbe76Scherry 			printf("lc_sprel( ");
467ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
468ba7cbe76Scherry 			break;
469ba7cbe76Scherry 		case 5:
470ba7cbe76Scherry 			printf("unat_sprel( ");
471ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
472ba7cbe76Scherry 			break;
473ba7cbe76Scherry 		case 6:
474ba7cbe76Scherry 			printf("fpsr_sprel( ");
475ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
476ba7cbe76Scherry 			break;
477ba7cbe76Scherry 		case 7:
478ba7cbe76Scherry 			printf("bsp_when( ");
479ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P8.t);
480ba7cbe76Scherry 			break;
481ba7cbe76Scherry 		case 8:
482ba7cbe76Scherry 			printf("bsp_psprel( ");
483ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P8.t);
484ba7cbe76Scherry 			break;
485ba7cbe76Scherry 		case 9:
486ba7cbe76Scherry 			printf("bsp_sprel( ");
487ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
488ba7cbe76Scherry 			break;
489ba7cbe76Scherry 		case 10:
490ba7cbe76Scherry 			printf("bspstore_when( ");
491ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P8.t);
492ba7cbe76Scherry 			break;
493ba7cbe76Scherry 		case 11:
494ba7cbe76Scherry 			printf("bspstore_psprel( ");
495ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P8.t);
496ba7cbe76Scherry 			break;
497ba7cbe76Scherry 		case 12:
498ba7cbe76Scherry 			printf("bspstore_sprel( ");
499ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
500ba7cbe76Scherry 			break;
501ba7cbe76Scherry 		case 13:
502ba7cbe76Scherry 			printf("rnat_when( ");
503ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P8.t);
504ba7cbe76Scherry 			break;
505ba7cbe76Scherry 		case 14:
506ba7cbe76Scherry 			printf("rnat_psprel( ");
507ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P8.t);
508ba7cbe76Scherry 			break;
509ba7cbe76Scherry 		case 15:
510ba7cbe76Scherry 			printf("rnat_sprel( ");
511ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
512ba7cbe76Scherry 			break;
513ba7cbe76Scherry 		case 16:
514ba7cbe76Scherry 			printf("priunat_when_gr( ");
515ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P8.t);
516ba7cbe76Scherry 			break;
517ba7cbe76Scherry 		case 17:
518ba7cbe76Scherry 			printf("priunat_psprel( ");
519ba7cbe76Scherry 			printf("pspoff = %ld) \n", rchain->udesc.P8.t);
520ba7cbe76Scherry 			break;
521ba7cbe76Scherry 		case 18:
522ba7cbe76Scherry 			printf("priunat_sprel( ");
523ba7cbe76Scherry 			printf("spoff = %ld) \n", rchain->udesc.P8.t);
524ba7cbe76Scherry 			break;
525ba7cbe76Scherry 		case 19:
526ba7cbe76Scherry 			printf("priunat_when_mem( ");
527ba7cbe76Scherry 			printf("t = %ld) \n", rchain->udesc.P8.t);
528ba7cbe76Scherry 			break;
529ba7cbe76Scherry 
530ba7cbe76Scherry 		default:
531ba7cbe76Scherry 			printf("unknown \n");
532ba7cbe76Scherry 		}
533ba7cbe76Scherry 
534ba7cbe76Scherry 		break;
535ba7cbe76Scherry 
536ba7cbe76Scherry 	case P9:
537ba7cbe76Scherry 		printf("\t\tP9:");
538ba7cbe76Scherry 		printf("(grmask = %x, gr = %d) \n",
539ba7cbe76Scherry 		       rchain->udesc.P9.grmask, rchain->udesc.P9.gr);
540ba7cbe76Scherry 		break;
541ba7cbe76Scherry 
542ba7cbe76Scherry 	case P10:
543ba7cbe76Scherry 		printf("\t\tP10:");
544ba7cbe76Scherry 		printf("(abi: ");
545ba7cbe76Scherry 		switch(rchain->udesc.P10.abi) {
546ba7cbe76Scherry 		case 0:
547ba7cbe76Scherry 			printf("Unix SVR4) \n");
548ba7cbe76Scherry 			break;
549ba7cbe76Scherry 		case 1:
550ba7cbe76Scherry 			printf("HP-UX) \n");
551ba7cbe76Scherry 			break;
552ba7cbe76Scherry 		default:
553ba7cbe76Scherry 			printf("Other) \n");
554ba7cbe76Scherry 		}
555ba7cbe76Scherry 		break;
556ba7cbe76Scherry 
557ba7cbe76Scherry 	case B1:
558ba7cbe76Scherry 		printf("\t\tB1:");
559ba7cbe76Scherry 		if(rchain->udesc.B1.r)
560ba7cbe76Scherry 			printf("copy_state( ");
561ba7cbe76Scherry 		else
562ba7cbe76Scherry 			printf("label_state( ");
563ba7cbe76Scherry 		printf("label = %d) \n", rchain->udesc.B1.label);
564ba7cbe76Scherry 
565ba7cbe76Scherry 		break;
566ba7cbe76Scherry 
567ba7cbe76Scherry 	case B2:
568ba7cbe76Scherry 		printf("\t\tB2:");
569ba7cbe76Scherry 		printf("(ecount = %d, t = %ld)\n",
570ba7cbe76Scherry 		       rchain->udesc.B2.ecount, rchain->udesc.B2.t);
571ba7cbe76Scherry 
572ba7cbe76Scherry 		break;
573ba7cbe76Scherry 
574ba7cbe76Scherry 	case B3:
575ba7cbe76Scherry 		printf("\t\tB3:");
576ba7cbe76Scherry 		printf("(t = %ld, ecount = %ld) \n",
577ba7cbe76Scherry 		       rchain->udesc.B3.t, rchain->udesc.B3.ecount);
578ba7cbe76Scherry 
579ba7cbe76Scherry 		break;
580ba7cbe76Scherry 
581ba7cbe76Scherry 	case B4:
582ba7cbe76Scherry 		printf("\t\tB4:");
583ba7cbe76Scherry 		if(rchain->udesc.B4.r)
584ba7cbe76Scherry 			printf("copy_state( ");
585ba7cbe76Scherry 		else
586ba7cbe76Scherry 			printf("label_state( ");
587ba7cbe76Scherry 
588ba7cbe76Scherry 		printf("label = %ld) \n", rchain->udesc.B4.label);
589ba7cbe76Scherry 
590ba7cbe76Scherry 		break;
591ba7cbe76Scherry 
592ba7cbe76Scherry 
593ba7cbe76Scherry 	case X1:
594ba7cbe76Scherry 		printf("\tX1:\n ");
595ba7cbe76Scherry 		break;
596ba7cbe76Scherry 
597ba7cbe76Scherry 	case X2:
598ba7cbe76Scherry 		printf("\tX2:\n");
599ba7cbe76Scherry 		break;
600ba7cbe76Scherry 
601ba7cbe76Scherry 	case X3:
602ba7cbe76Scherry 		printf("\tX3:\n");
603ba7cbe76Scherry 		break;
604ba7cbe76Scherry 
605ba7cbe76Scherry 	case X4:
606ba7cbe76Scherry 		printf("\tX4:\n");
607ba7cbe76Scherry 		break;
608ba7cbe76Scherry 	default:
609ba7cbe76Scherry 		printf("\tunknow: \n");
610ba7cbe76Scherry 	}
611ba7cbe76Scherry 
612ba7cbe76Scherry }
613ba7cbe76Scherry 
614d6aeeea2Sdholland /*
615d6aeeea2Sdholland  * State record stuff..... based on section 11. and Appendix A. of the
616ba7cbe76Scherry  * "Itanium Software Conventions and Runtime Architecture Guide"
617ba7cbe76Scherry  */
618ba7cbe76Scherry 
619ba7cbe76Scherry 
620d6aeeea2Sdholland /*
621d6aeeea2Sdholland  * Global variables:
622ba7cbe76Scherry  * 1. Two arrays of staterecords: recordstack[], recordstackcopy[]
623ba7cbe76Scherry  *	XXX:	Since we don't use malloc, we have two arbitrary sized arrays
624ba7cbe76Scherry  *		providing guaranteed memory from the BSS. See the TODO file
625ba7cbe76Scherry  *		for more details.
626ba7cbe76Scherry  * 2. Two head variables to hold the member index: unwind_rsp,unwind_rscp
627ba7cbe76Scherry  */
628ba7cbe76Scherry 
629ba7cbe76Scherry struct staterecord recordstack[MAXSTATERECS];
630ba7cbe76Scherry struct staterecord recordstackcopy[MAXSTATERECS];
631ba7cbe76Scherry struct staterecord current_state;
632ba7cbe76Scherry struct staterecord *unwind_rsp, *unwind_rscp;
633ba7cbe76Scherry 
634ba7cbe76Scherry 
635d6aeeea2Sdholland /* Base of spill area in memory stack frame as a psp relative offset */
636d6aeeea2Sdholland uint64_t spill_base = 0;
637ba7cbe76Scherry 
638d6aeeea2Sdholland /*
639d6aeeea2Sdholland  * Initialises a staterecord from a given template,
640ba7cbe76Scherry  * with default values as described by the Runtime Spec.
641ba7cbe76Scherry  */
642ba7cbe76Scherry void
initrecord(struct staterecord * target)643ba7cbe76Scherry initrecord(struct staterecord *target)
644ba7cbe76Scherry {
645ba7cbe76Scherry 	target->bsp.where = UNSAVED;
646ba7cbe76Scherry 	target->bsp.when = 0;
647ba7cbe76Scherry 	target->bsp.offset = INVALID;
648ba7cbe76Scherry 	target->psp.where = UNSAVED;
649ba7cbe76Scherry 	target->psp.when = 0;
650ba7cbe76Scherry 	target->psp.offset = INVALID;
651ba7cbe76Scherry 	target->rp.where = UNSAVED;
652ba7cbe76Scherry 	target->rp.when = 0;
653ba7cbe76Scherry 	target->rp.offset = INVALID;
654ba7cbe76Scherry 	target->pfs.where = UNSAVED;
655ba7cbe76Scherry 	target->pfs.when = 0;
656ba7cbe76Scherry 	target->pfs.offset = INVALID;
657ba7cbe76Scherry }
658ba7cbe76Scherry 
659ba7cbe76Scherry 
660d6aeeea2Sdholland /*
661d6aeeea2Sdholland  * Modifies a staterecord structure by parsing
662ba7cbe76Scherry  * a single record chain structure.
663ba7cbe76Scherry  * regionoffset is the offset within a (prologue) region
664ba7cbe76Scherry  * where the stack unwinding began.
665ba7cbe76Scherry  */
666d6aeeea2Sdholland void
modifyrecord(struct staterecord * srec,struct recordchain * rchain,uint64_t regionoffset)667d6aeeea2Sdholland modifyrecord(struct staterecord *srec, struct recordchain *rchain,
668ba7cbe76Scherry 	uint64_t regionoffset)
669ba7cbe76Scherry {
670d6aeeea2Sdholland 	/*
671d6aeeea2Sdholland 	 * Default start save GR for prologue_save GRs.
672ba7cbe76Scherry 	 */
673d6aeeea2Sdholland 	uint64_t grno = 32;
674ba7cbe76Scherry 
675ba7cbe76Scherry 
676ba7cbe76Scherry 	switch (rchain->type) {
677ba7cbe76Scherry 
678ba7cbe76Scherry 	case R2:
679d6aeeea2Sdholland 		/*
680d6aeeea2Sdholland 		 * R2, prologue_gr is the only region encoding
681ba7cbe76Scherry 		 * with register save info.
682ba7cbe76Scherry 		 */
683ba7cbe76Scherry 
684ba7cbe76Scherry 		grno = rchain->udesc.R2.grsave;
685ba7cbe76Scherry 
686ba7cbe76Scherry 		if (rchain->udesc.R2.mask & R2MASKRP) {
687ba7cbe76Scherry 			srec->rp.when = 0;
688ba7cbe76Scherry 			srec->rp.where = GRREL;
689ba7cbe76Scherry 			srec->rp.offset = grno++;
690ba7cbe76Scherry 		}
691ba7cbe76Scherry 
692ba7cbe76Scherry 		if (rchain->udesc.R2.mask & R2MASKPFS) {
693ba7cbe76Scherry 			srec->pfs.when = 0;
694ba7cbe76Scherry 			srec->pfs.where = GRREL;
695ba7cbe76Scherry 			srec->pfs.offset = grno++;
696ba7cbe76Scherry 		}
697ba7cbe76Scherry 
698ba7cbe76Scherry 		if (rchain->udesc.R2.mask & R2MASKPSP) {
699ba7cbe76Scherry 			srec->psp.when = 0;
700ba7cbe76Scherry 			srec->psp.where = GRREL;
701ba7cbe76Scherry 			srec->psp.offset = grno++;
702ba7cbe76Scherry 		}
703ba7cbe76Scherry 		break;
704ba7cbe76Scherry 
705ba7cbe76Scherry 	case P3:
706ba7cbe76Scherry 		switch (rchain->udesc.P3.r) {
707ba7cbe76Scherry 		case 0: /* psp_gr */
708ba7cbe76Scherry 			if (srec->psp.when < regionoffset) {
709ba7cbe76Scherry 				srec->psp.where = GRREL;
710ba7cbe76Scherry 				srec->psp.offset = rchain->udesc.P3.grbr;
711ba7cbe76Scherry 			}
712ba7cbe76Scherry 			break;
713ba7cbe76Scherry 
714ba7cbe76Scherry 		case 1: /* rp_gr */
715ba7cbe76Scherry 			if (srec->rp.when < regionoffset) {
716ba7cbe76Scherry 				srec->rp.where = GRREL;
717ba7cbe76Scherry 				srec->rp.offset = rchain->udesc.P3.grbr;
718ba7cbe76Scherry 			}
719ba7cbe76Scherry 			break;
720ba7cbe76Scherry 
721ba7cbe76Scherry 		case 2: /* pfs_gr */
722ba7cbe76Scherry 			if (srec->pfs.when < regionoffset) {
723ba7cbe76Scherry 				srec->pfs.where = GRREL;
724ba7cbe76Scherry 				srec->pfs.offset = rchain->udesc.P3.grbr;
725ba7cbe76Scherry 			}
726ba7cbe76Scherry 			break;
727ba7cbe76Scherry 
728ba7cbe76Scherry 		}
729ba7cbe76Scherry 		break;
730ba7cbe76Scherry 
731ba7cbe76Scherry 
732d6aeeea2Sdholland 	/*
733d6aeeea2Sdholland 	 * XXX: P4 spill_mask and P7: spill_base are for GRs, FRs, and BRs.
734ba7cbe76Scherry 	 * We're not particularly worried about those right now.
735ba7cbe76Scherry 	 */
736ba7cbe76Scherry 
737ba7cbe76Scherry 	case P7:
738ba7cbe76Scherry 		switch (rchain->udesc.P7.r) {
739ba7cbe76Scherry 
740ba7cbe76Scherry 		case 0: /* mem_stack_f */
741*e0ba28d7Sdholland 			if (srec->psp.offset != INVALID) {
742*e0ba28d7Sdholland 				printf("!!!saw mem_stack_f more than once. \n");
743*e0ba28d7Sdholland 			}
744ba7cbe76Scherry 			srec->psp.when = rchain->udesc.P7.t;
745ba7cbe76Scherry 			if (srec->psp.when < regionoffset) {
746ba7cbe76Scherry 				srec->psp.where = IMMED;
747*e0ba28d7Sdholland 				/* spsz.offset is "overloaded" */
748*e0ba28d7Sdholland 				srec->psp.offset = rchain->udesc.P7.size;
749ba7cbe76Scherry 			}
750ba7cbe76Scherry 			break;
751ba7cbe76Scherry 
752ba7cbe76Scherry 		case 1: /* mem_stack_v */
753ba7cbe76Scherry 			srec->psp.when = rchain->udesc.P7.t;
754ba7cbe76Scherry 			break;
755ba7cbe76Scherry 
756ba7cbe76Scherry 		case 2: /* spill_base */
757ba7cbe76Scherry 			spill_base = rchain->udesc.P7.t;
758ba7cbe76Scherry 			break;
759ba7cbe76Scherry 
760ba7cbe76Scherry 		case 3: /* psp_sprel */
761ba7cbe76Scherry 			if (srec->psp.when < regionoffset) {
762ba7cbe76Scherry 				srec->psp.where = SPREL;
763ba7cbe76Scherry 				srec->psp.offset = rchain->udesc.P7.t;
764ba7cbe76Scherry 			}
765ba7cbe76Scherry 			break;
766ba7cbe76Scherry 
767ba7cbe76Scherry 		case 4: /* rp_when */
768ba7cbe76Scherry 			srec->rp.when = rchain->udesc.P7.t;
769*e0ba28d7Sdholland 			/*
770*e0ba28d7Sdholland 			 * XXX: Need to set to prologue_gr(grno) for
771*e0ba28d7Sdholland 			 *	the orphan case ie; _gr/_psprel/_sprel
772*e0ba28d7Sdholland 			 *	not set and therefore default to begin
773*e0ba28d7Sdholland 			 *	from the gr specified in prologue_gr.
774ba7cbe76Scherry 			 */
775ba7cbe76Scherry 			break;
776ba7cbe76Scherry 
777ba7cbe76Scherry 		case 5: /* rp_psprel */
778ba7cbe76Scherry 			if (srec->rp.when < regionoffset) {
779ba7cbe76Scherry 				srec->rp.where = PSPREL;
780ba7cbe76Scherry 				srec->rp.offset = rchain->udesc.P7.t;
781ba7cbe76Scherry 			}
782ba7cbe76Scherry 			break;
783ba7cbe76Scherry 
784ba7cbe76Scherry 		case 6: /* pfs_when */
785ba7cbe76Scherry 			srec->pfs.when = rchain->udesc.P7.t;
786*e0ba28d7Sdholland 			/*
787*e0ba28d7Sdholland 			 * XXX: Need to set to prologue_gr(grno) for
788*e0ba28d7Sdholland 			 *	the orphan case ie; _gr/_psprel/_sprel
789*e0ba28d7Sdholland 			 *	not set and therefore default to begin
790*e0ba28d7Sdholland 			 *	from the gr specified in prologue_gr.
791ba7cbe76Scherry 			 */
792ba7cbe76Scherry 			break;
793ba7cbe76Scherry 
794ba7cbe76Scherry 		case 7: /* pfs_psprel */
795ba7cbe76Scherry 			if (srec->pfs.when < regionoffset) {
796ba7cbe76Scherry 				srec->pfs.where = PSPREL;
797ba7cbe76Scherry 				srec->pfs.offset = rchain->udesc.P7.t;
798ba7cbe76Scherry 			}
799ba7cbe76Scherry 			break;
800ba7cbe76Scherry 
801ba7cbe76Scherry 		}
802ba7cbe76Scherry 		break;
803ba7cbe76Scherry 
804ba7cbe76Scherry 	case P8:
805ba7cbe76Scherry 		switch (rchain->udesc.P8.r) {
806ba7cbe76Scherry 		case 1: /* rp_sprel */
807ba7cbe76Scherry 			if (srec->rp.when < regionoffset) {
808ba7cbe76Scherry 				srec->rp.where = SPREL;
809ba7cbe76Scherry 				srec->rp.offset = rchain->udesc.P8.t;
810ba7cbe76Scherry 			}
811ba7cbe76Scherry 			break;
812ba7cbe76Scherry 		case 2: /* pfs_sprel */
813ba7cbe76Scherry 			if (srec->pfs.when < regionoffset) {
814ba7cbe76Scherry 				srec->pfs.where = SPREL;
815ba7cbe76Scherry 				srec->pfs.offset = rchain->udesc.P8.t;
816ba7cbe76Scherry 
817ba7cbe76Scherry 			}
818ba7cbe76Scherry 			break;
819ba7cbe76Scherry 		}
820ba7cbe76Scherry 		break;
821ba7cbe76Scherry 
822ba7cbe76Scherry 	case B1:
823ba7cbe76Scherry 
824ba7cbe76Scherry 		rchain->udesc.B1.r ? switchrecordstack(0) :
825ba7cbe76Scherry 			clonerecordstack(0);
826ba7cbe76Scherry 		break;
827ba7cbe76Scherry 
828ba7cbe76Scherry 	case B2:
829ba7cbe76Scherry 		if (regionoffset < rchain->udesc.B2.t) {
830ba7cbe76Scherry 		poprecord(&current_state, rchain->udesc.B2.ecount);
831ba7cbe76Scherry 		}
832ba7cbe76Scherry 		break;
833ba7cbe76Scherry 	case B3:
834ba7cbe76Scherry 		if (regionoffset < rchain->udesc.B3.t) {
835ba7cbe76Scherry 		poprecord(&current_state, rchain->udesc.B3.ecount);
836ba7cbe76Scherry 		}
837ba7cbe76Scherry 		break;
838ba7cbe76Scherry 	case B4:
839ba7cbe76Scherry 		rchain->udesc.B4.r ? switchrecordstack(0) :
840ba7cbe76Scherry 			clonerecordstack(0);
841ba7cbe76Scherry 		break;
842ba7cbe76Scherry 
843ba7cbe76Scherry 	case X1:
844ba7cbe76Scherry 	case X2:
845ba7cbe76Scherry 	case X3:
846ba7cbe76Scherry 		/* XXX: Todo */
847ba7cbe76Scherry 		break;
848ba7cbe76Scherry 
849ba7cbe76Scherry 
850ba7cbe76Scherry 	case R1:
851ba7cbe76Scherry 	case R3:
852ba7cbe76Scherry 	case P1:
853ba7cbe76Scherry 	case P2:
854ba7cbe76Scherry 	case P4:
855ba7cbe76Scherry 	case P5:
856ba7cbe76Scherry 	case P6:
857ba7cbe76Scherry 	case P9:
858ba7cbe76Scherry 	case P10:
859ba7cbe76Scherry 	default:
860ba7cbe76Scherry 		/* Ignore. */
861ba7cbe76Scherry 		printf("XXX: Ignored. \n");
862ba7cbe76Scherry 	}
863ba7cbe76Scherry 
864ba7cbe76Scherry 
865ba7cbe76Scherry }
866ba7cbe76Scherry 
867d6aeeea2Sdholland void
dump_staterecord(struct staterecord * srec)868d6aeeea2Sdholland dump_staterecord(struct staterecord *srec)
869ba7cbe76Scherry {
870ba7cbe76Scherry 	printf("rp.where: ");
871ba7cbe76Scherry 	switch(srec->rp.where) {
872ba7cbe76Scherry 	case UNSAVED:
873ba7cbe76Scherry 		printf("UNSAVED ");
874ba7cbe76Scherry 		break;
875ba7cbe76Scherry 	case BRREL:
876ba7cbe76Scherry 		printf("BRREL ");
877ba7cbe76Scherry 		break;
878ba7cbe76Scherry 	case GRREL:
879ba7cbe76Scherry 		printf("GRREL ");
880ba7cbe76Scherry 		break;
881ba7cbe76Scherry 	case SPREL:
882ba7cbe76Scherry 		printf("SPREL ");
883ba7cbe76Scherry 		break;
884ba7cbe76Scherry 	case PSPREL:
885ba7cbe76Scherry 		printf("PSPSREL ");
886ba7cbe76Scherry 		break;
887ba7cbe76Scherry 	default:
888ba7cbe76Scherry 		printf("unknown ");
889ba7cbe76Scherry 	}
890ba7cbe76Scherry 
891ba7cbe76Scherry 	printf(", rp.when = %lu, ", srec->rp.when);
892ba7cbe76Scherry 	printf("rp.offset = %lu \n", srec->rp.offset);
893ba7cbe76Scherry 
894ba7cbe76Scherry 
895ba7cbe76Scherry 	printf("pfs.where: ");
896ba7cbe76Scherry 	switch(srec->pfs.where) {
897ba7cbe76Scherry 	case UNSAVED:
898ba7cbe76Scherry 		printf("UNSAVED ");
899ba7cbe76Scherry 		break;
900ba7cbe76Scherry 	case BRREL:
901ba7cbe76Scherry 		printf("BRREL ");
902ba7cbe76Scherry 		break;
903ba7cbe76Scherry 	case GRREL:
904ba7cbe76Scherry 		printf("GRREL ");
905ba7cbe76Scherry 		break;
906ba7cbe76Scherry 	case SPREL:
907ba7cbe76Scherry 		printf("SPREL ");
908ba7cbe76Scherry 		break;
909ba7cbe76Scherry 	case PSPREL:
910ba7cbe76Scherry 		printf("PSPSREL ");
911ba7cbe76Scherry 		break;
912ba7cbe76Scherry 	default:
913ba7cbe76Scherry 		printf("unknown ");
914ba7cbe76Scherry 	}
915ba7cbe76Scherry 
916ba7cbe76Scherry 	printf(", pfs.when = %lu, ", srec->pfs.when);
917ba7cbe76Scherry 	printf("pfs.offset = %lu \n", srec->pfs.offset);
918ba7cbe76Scherry }
919ba7cbe76Scherry 
920ba7cbe76Scherry 
921d6aeeea2Sdholland /*
922d6aeeea2Sdholland  * Push a state record on the record stack.
923d6aeeea2Sdholland  */
924d6aeeea2Sdholland void
pushrecord(struct staterecord * srec)925d6aeeea2Sdholland pushrecord(struct staterecord *srec)
926ba7cbe76Scherry {
927ba7cbe76Scherry 	if(unwind_rsp >= recordstack + MAXSTATERECS) {
928ba7cbe76Scherry 		printf("Push exceeded array size!!! \n");
929ba7cbe76Scherry 		return;
930ba7cbe76Scherry 	}
931ba7cbe76Scherry 
932ba7cbe76Scherry 	memcpy(unwind_rsp, srec, sizeof(struct staterecord));
933ba7cbe76Scherry 	unwind_rsp++;
934ba7cbe76Scherry 
935ba7cbe76Scherry }
936ba7cbe76Scherry 
937d6aeeea2Sdholland /*
938d6aeeea2Sdholland  * Pop n state records off the record stack.
939d6aeeea2Sdholland  */
940d6aeeea2Sdholland void
poprecord(struct staterecord * srec,int n)941d6aeeea2Sdholland poprecord(struct staterecord *srec, int n)
942ba7cbe76Scherry {
943ba7cbe76Scherry 	if(unwind_rsp == recordstack) {
944ba7cbe76Scherry 		printf("Popped beyond end of Stack!!! \n");
945ba7cbe76Scherry 		return;
946ba7cbe76Scherry 	}
947ba7cbe76Scherry 	unwind_rsp -= n;
948ba7cbe76Scherry 	memcpy(srec, unwind_rsp, sizeof(struct staterecord));
949ba7cbe76Scherry #ifdef DEBUG
950c363a9cbScegger 	memset(unwind_rsp, 0, sizeof(struct staterecord) * n);
951ba7cbe76Scherry #endif
952ba7cbe76Scherry 
953ba7cbe76Scherry }
954ba7cbe76Scherry 
955d6aeeea2Sdholland /*
956d6aeeea2Sdholland  * Clone the whole record stack upto this one.
957d6aeeea2Sdholland  */
958d6aeeea2Sdholland void
clonerecordstack(u_int label)959d6aeeea2Sdholland clonerecordstack(u_int label)
960ba7cbe76Scherry {
961ba7cbe76Scherry 	memcpy(recordstackcopy, recordstack,
962ba7cbe76Scherry 	       (unwind_rsp - recordstack) * sizeof(struct staterecord));
963ba7cbe76Scherry 	unwind_rscp = unwind_rsp;
964ba7cbe76Scherry }
965ba7cbe76Scherry 
966d6aeeea2Sdholland /*
967d6aeeea2Sdholland  * Discard the current stack, and adopt a clone.
968d6aeeea2Sdholland  */
969d6aeeea2Sdholland void
switchrecordstack(u_int label)970d6aeeea2Sdholland switchrecordstack(u_int label)
971ba7cbe76Scherry {
972ba7cbe76Scherry 	memcpy((void *) recordstack, (void *) recordstackcopy,
973ba7cbe76Scherry 	       (unwind_rscp - recordstackcopy) * sizeof(struct staterecord));
974ba7cbe76Scherry 	unwind_rsp = unwind_rscp;
975ba7cbe76Scherry 
976ba7cbe76Scherry }
977ba7cbe76Scherry 
978d6aeeea2Sdholland /*
979d6aeeea2Sdholland  * In the context of a procedure:
980ba7cbe76Scherry  * Parses through a record chain, building, pushing and/or popping staterecords,
981ba7cbe76Scherry  * or cloning/destroying stacks of staterecords as required.
982ba7cbe76Scherry  * Parameters are:
983ba7cbe76Scherry  *	rchain: pointer to recordchain array.
984*e0ba28d7Sdholland  *	procoffset: offset of point of interest, in slots, within procedure
985*e0ba28d7Sdholland  *                  starting from slot 0
986ba7cbe76Scherry  * This routine obeys [1]
987ba7cbe76Scherry  */
988d6aeeea2Sdholland struct staterecord *
buildrecordstack(struct recordchain * rchain,uint64_t procoffset)989d6aeeea2Sdholland buildrecordstack(struct recordchain *rchain, uint64_t procoffset)
990ba7cbe76Scherry {
991*e0ba28d7Sdholland 	/* Current region length, defaults to zero if not specified */
992*e0ba28d7Sdholland 	uint64_t rlen = 0;
993*e0ba28d7Sdholland 	/* Accumulated region length */
994*e0ba28d7Sdholland 	uint64_t roffset = 0;
995*e0ba28d7Sdholland 	/* Offset within current region */
996*e0ba28d7Sdholland 	uint64_t rdepth = 0;
997*e0ba28d7Sdholland 
998712239e3Sthorpej 	bool rtype;
999ba7cbe76Scherry 	int i;
1000ba7cbe76Scherry 
1001d6aeeea2Sdholland 	/* Start with bottom of staterecord stack. */
1002d6aeeea2Sdholland 	unwind_rsp = recordstack;
1003d6aeeea2Sdholland 
1004d6aeeea2Sdholland 	initrecord(&current_state);
1005ba7cbe76Scherry 
1006ba7cbe76Scherry 	for (i = 0;i < rec_cnt;i++) {
1007ba7cbe76Scherry 
1008ba7cbe76Scherry 		switch (rchain[i].type) {
1009ba7cbe76Scherry 		case R1:
1010ba7cbe76Scherry 			rlen = rchain[i].udesc.R1.rlen;
1011d6aeeea2Sdholland 			if (procoffset < roffset) {
1012d6aeeea2Sdholland 				/*
1013d6aeeea2Sdholland 				 * Overshot Region containing
1014d6aeeea2Sdholland 				 * procoffset. Bail out.
1015d6aeeea2Sdholland 				 */
1016d6aeeea2Sdholland 				goto out;
1017d6aeeea2Sdholland 			}
1018ba7cbe76Scherry 			rdepth = procoffset - roffset;
1019ba7cbe76Scherry 			roffset += rlen;
1020ba7cbe76Scherry 			rtype = rchain[i].udesc.R1.r;
1021ba7cbe76Scherry 			if (!rtype) {
1022ba7cbe76Scherry 				pushrecord(&current_state);
1023ba7cbe76Scherry 			}
1024ba7cbe76Scherry 			break;
1025ba7cbe76Scherry 
1026ba7cbe76Scherry 		case R3:
1027ba7cbe76Scherry 			rlen = rchain[i].udesc.R3.rlen;
1028d6aeeea2Sdholland 			if (procoffset < roffset) {
1029d6aeeea2Sdholland 				/*
1030d6aeeea2Sdholland 				 * Overshot Region containing
1031d6aeeea2Sdholland 				 * procoffset. Bail out.
1032d6aeeea2Sdholland 				 */
1033d6aeeea2Sdholland 				goto out;
1034d6aeeea2Sdholland 			}
1035ba7cbe76Scherry 			rdepth = procoffset - roffset;
1036ba7cbe76Scherry 			roffset += rlen;
1037ba7cbe76Scherry 			rtype = rchain[i].udesc.R3.r;
1038ba7cbe76Scherry 			if (!rtype) {
1039ba7cbe76Scherry 				pushrecord(&current_state);
1040ba7cbe76Scherry 			}
1041ba7cbe76Scherry 			break;
1042ba7cbe76Scherry 
1043ba7cbe76Scherry 		case R2:
1044ba7cbe76Scherry 			rlen = rchain[i].udesc.R2.rlen;
1045d6aeeea2Sdholland 			if (procoffset < roffset) {
1046d6aeeea2Sdholland 				/*
1047d6aeeea2Sdholland 				 * Overshot Region containing
1048d6aeeea2Sdholland 				 * procoffset. Bail out.
1049d6aeeea2Sdholland 				 */
1050d6aeeea2Sdholland 				goto out;
1051d6aeeea2Sdholland 			}
1052ba7cbe76Scherry 			rdepth = procoffset - roffset;
1053ba7cbe76Scherry 			roffset += rlen;
105409c5f9ccSthorpej 			rtype = false; /* prologue region */
1055ba7cbe76Scherry 			pushrecord(&current_state);
1056ba7cbe76Scherry 
1057ba7cbe76Scherry 			/* R2 has save info. Continue down. */
1058d6aeeea2Sdholland 			/* FALLTHROUGH */
1059ba7cbe76Scherry 		case P1:
1060ba7cbe76Scherry 		case P2:
1061ba7cbe76Scherry 		case P3:
1062ba7cbe76Scherry 		case P4:
1063ba7cbe76Scherry 		case P5:
1064ba7cbe76Scherry 		case P6:
1065ba7cbe76Scherry 		case P7:
1066ba7cbe76Scherry 		case P8:
1067ba7cbe76Scherry 		case P9:
1068ba7cbe76Scherry 		case P10:
1069ba7cbe76Scherry 			modifyrecord(&current_state, &rchain[i], rdepth);
1070ba7cbe76Scherry 			break;
1071ba7cbe76Scherry 
1072ba7cbe76Scherry 		case B1:
1073ba7cbe76Scherry 		case B2:
1074ba7cbe76Scherry 		case B3:
1075ba7cbe76Scherry 		case B4:
1076*e0ba28d7Sdholland 			modifyrecord(&current_state, &rchain[i],
1077*e0ba28d7Sdholland 				     rlen - 1 - rdepth);
1078ba7cbe76Scherry 			break;
1079ba7cbe76Scherry 
1080ba7cbe76Scherry 		case X1:
1081ba7cbe76Scherry 		case X2:
1082ba7cbe76Scherry 		case X3:
1083ba7cbe76Scherry 		case X4:
1084ba7cbe76Scherry 		default:
1085ba7cbe76Scherry 			printf("Error: Unknown descriptor type!!! \n");
1086ba7cbe76Scherry 
1087ba7cbe76Scherry 		}
1088ba7cbe76Scherry 
1089ba7cbe76Scherry #if UNWIND_DIAGNOSTIC
1090ba7cbe76Scherry 		dump_staterecord(&current_state);
1091ba7cbe76Scherry #endif
1092ba7cbe76Scherry 
1093ba7cbe76Scherry 
1094ba7cbe76Scherry 	}
1095ba7cbe76Scherry 
1096ba7cbe76Scherry out:
1097ba7cbe76Scherry 
1098ba7cbe76Scherry 	return &current_state;
1099ba7cbe76Scherry }
1100ba7cbe76Scherry 
1101d6aeeea2Sdholland void
updateregs(struct unwind_frame * uwf,struct staterecord * srec,uint64_t procoffset)1102*e0ba28d7Sdholland updateregs(struct unwind_frame *uwf, struct staterecord *srec,
1103*e0ba28d7Sdholland 	uint64_t procoffset)
1104ba7cbe76Scherry {
1105ba7cbe76Scherry 	/* XXX: Update uwf for regs other than rp and pfs*/
1106ba7cbe76Scherry 	uint64_t roffset = 0;
1107ba7cbe76Scherry 
1108ba7cbe76Scherry 	/* Uses shadow arrays to update uwf from srec in a loop. */
1109ba7cbe76Scherry 	/* Count of number of regstate elements in struct staterecord */
1110ba7cbe76Scherry 	int statecount = sizeof(struct staterecord)/sizeof(struct regstate);
1111ba7cbe76Scherry 	/* Pointer to current regstate. */
1112ba7cbe76Scherry 	struct regstate *stptr = (void *) srec;
1113ba7cbe76Scherry 	/* Pointer to current unwind_frame element */
1114ba7cbe76Scherry 	uint64_t *gr = (void *) uwf;
1115ba7cbe76Scherry 
1116ba7cbe76Scherry 	int i;
1117ba7cbe76Scherry 
1118d6aeeea2Sdholland #ifdef UNWIND_DIAGNOSTIC
1119d6aeeea2Sdholland 	printf("updateregs(): \n");
1120d6aeeea2Sdholland 	printf("procoffset (slots) = %lu \n", procoffset);
1121d6aeeea2Sdholland #endif
1122d6aeeea2Sdholland 
1123ba7cbe76Scherry 	for(i = 0; i < statecount; i++) {
1124ba7cbe76Scherry 		switch (stptr[i].where) {
1125ba7cbe76Scherry 		case IMMED: /* currently only mem_stack_f */
1126ba7cbe76Scherry 			if (stptr[i].when >= procoffset) break;
1127ba7cbe76Scherry 			uwf->psp -= (stptr[i].offset << 4);
1128ba7cbe76Scherry 			break;
1129ba7cbe76Scherry 
1130ba7cbe76Scherry 		case GRREL:
1131ba7cbe76Scherry 			if (stptr[i].when >= procoffset) break;
1132ba7cbe76Scherry 
1133ba7cbe76Scherry 			roffset = stptr[i].offset;
1134ba7cbe76Scherry 			if (roffset == 0) {
1135ba7cbe76Scherry 				gr[i] = 0;
1136ba7cbe76Scherry 				break;
1137ba7cbe76Scherry 			}
1138ba7cbe76Scherry 
1139ba7cbe76Scherry 
1140ba7cbe76Scherry 			if (roffset < 32) {
1141*e0ba28d7Sdholland 				printf("GR%ld: static register save ??? \n",
1142*e0ba28d7Sdholland 				       roffset);
1143ba7cbe76Scherry 				break;
1144ba7cbe76Scherry 			}
1145ba7cbe76Scherry 
1146ba7cbe76Scherry 			/* Fetch from bsp + offset - 32 + Adjust for RNAT. */
1147ba7cbe76Scherry 			roffset -= 32;
1148ba7cbe76Scherry 			gr[i] = ia64_getrse_gr(uwf->bsp, roffset);
1149ba7cbe76Scherry 			break;
1150ba7cbe76Scherry 
1151ba7cbe76Scherry 		case SPREL:
1152ba7cbe76Scherry 			if (stptr[i].when >= procoffset) break;
1153ba7cbe76Scherry 
1154ba7cbe76Scherry 			/* Check if frame has been setup. */
1155ba7cbe76Scherry 			if (srec->psp.offset == INVALID) {
1156*e0ba28d7Sdholland 				printf("sprel used without setting up "
1157*e0ba28d7Sdholland 				       "stackframe!!! \n");
1158ba7cbe76Scherry 				break;
1159ba7cbe76Scherry 			}
1160ba7cbe76Scherry 
1161ba7cbe76Scherry 			roffset = stptr[i].offset;
1162ba7cbe76Scherry 
1163ba7cbe76Scherry 			/* Fetch from sp + offset */
1164*e0ba28d7Sdholland 			memcpy(&gr[i], (char *) uwf->sp + roffset * 4,
1165*e0ba28d7Sdholland 			       sizeof(uint64_t));
1166ba7cbe76Scherry 			break;
1167ba7cbe76Scherry 
1168ba7cbe76Scherry 
1169ba7cbe76Scherry 		case PSPREL:
1170ba7cbe76Scherry 			if (stptr[i].when >= procoffset) break;
1171ba7cbe76Scherry 
1172ba7cbe76Scherry 			/* Check if frame has been setup. */
1173ba7cbe76Scherry 			if (srec->psp.offset == INVALID) {
1174*e0ba28d7Sdholland 				printf("psprel used without setting up "
1175*e0ba28d7Sdholland 				       "stackframe!!! \n");
1176ba7cbe76Scherry 				break;
1177ba7cbe76Scherry 			}
1178ba7cbe76Scherry 
1179ba7cbe76Scherry 			roffset = stptr[i].offset;
1180ba7cbe76Scherry 
1181ba7cbe76Scherry 			/* Fetch from sp + offset */
1182*e0ba28d7Sdholland 			memcpy(&gr[i], (char *) uwf->psp + 16 - (roffset * 4),
1183*e0ba28d7Sdholland 			       sizeof(uint64_t));
1184ba7cbe76Scherry 			break;
1185ba7cbe76Scherry 
1186ba7cbe76Scherry 		case UNSAVED:
1187ba7cbe76Scherry 		case BRREL:
1188ba7cbe76Scherry 		default:
1189ba7cbe76Scherry #ifdef UNWIND_DIAGNOSTIC
1190ba7cbe76Scherry 			printf ("updateregs: reg[%d] is UNSAVED \n", i);
1191ba7cbe76Scherry #endif
1192ba7cbe76Scherry 			break;
1193ba7cbe76Scherry 			/* XXX: Not implemented yet. */
1194ba7cbe76Scherry 		}
1195ba7cbe76Scherry 
1196ba7cbe76Scherry 	}
1197ba7cbe76Scherry 
1198ba7cbe76Scherry }
1199ba7cbe76Scherry 
1200ba7cbe76Scherry 
1201d6aeeea2Sdholland /*
1202d6aeeea2Sdholland  * Locates unwind table entry, given unwind table entry info.
1203ba7cbe76Scherry  * Expects the variables ia64_unwindtab, and ia64_unwindtablen
1204ba7cbe76Scherry  * to be set appropriately.
1205ba7cbe76Scherry  */
1206ba7cbe76Scherry struct uwtable_ent *
get_unwind_table_entry(uint64_t iprel)1207ba7cbe76Scherry get_unwind_table_entry(uint64_t iprel)
1208ba7cbe76Scherry {
1209ba7cbe76Scherry 
1210ba7cbe76Scherry 	extern uint64_t ia64_unwindtab, ia64_unwindtablen;
1211ba7cbe76Scherry 
1212ba7cbe76Scherry 	struct uwtable_ent *uwt;
1213ba7cbe76Scherry 	int tabent;
1214ba7cbe76Scherry 
1215d6aeeea2Sdholland 
1216ba7cbe76Scherry 	for(uwt = (struct uwtable_ent *) ia64_unwindtab, tabent = 0;
1217ba7cbe76Scherry 	    /* The Runtime spec tells me the table entries are sorted. */
1218ba7cbe76Scherry 	    uwt->end <= iprel && tabent < ia64_unwindtablen;
1219ba7cbe76Scherry 	    uwt++, tabent += sizeof(struct uwtable_ent));
1220ba7cbe76Scherry 
1221ba7cbe76Scherry 
1222ba7cbe76Scherry 	if (!(uwt->start <= iprel && iprel < uwt->end)) {
1223ba7cbe76Scherry #ifdef UNWIND_DIAGNOSTIC
1224ba7cbe76Scherry 		printf("Entry not found \n");
1225ba7cbe76Scherry 		printf("iprel = %lx \n", iprel);
1226ba7cbe76Scherry 		printf("uwt->start = %lx \nuwt->end = %lx \n",
1227ba7cbe76Scherry 		       uwt->start, uwt->end);
1228ba7cbe76Scherry 		printf("tabent = %d \n", tabent);
1229ba7cbe76Scherry 		printf("ia64_unwindtablen = %ld \n",
1230ba7cbe76Scherry 		       ia64_unwindtablen);
1231ba7cbe76Scherry #endif
1232ba7cbe76Scherry 		return NULL;
1233ba7cbe76Scherry 	}
1234ba7cbe76Scherry 
1235ba7cbe76Scherry #ifdef UNWIND_DIAGNOSTIC
1236ba7cbe76Scherry 	printf("uwt->start = %lx \nuwt->end = %lx \n"
1237ba7cbe76Scherry 	       "uwt->infoptr = %p\n", uwt->start, uwt->end, uwt->infoptr);
1238ba7cbe76Scherry #endif
1239ba7cbe76Scherry 
1240ba7cbe76Scherry 	return uwt;
1241ba7cbe76Scherry }
1242ba7cbe76Scherry 
1243ba7cbe76Scherry 
1244ba7cbe76Scherry /*
1245ba7cbe76Scherry  * Reads unwind table info and updates register values.
1246ba7cbe76Scherry  */
1247ba7cbe76Scherry void
patchunwindframe(struct unwind_frame * uwf,uint64_t iprel,uint64_t relocoffset)1248ba7cbe76Scherry patchunwindframe(struct unwind_frame *uwf, uint64_t iprel, uint64_t relocoffset)
1249ba7cbe76Scherry {
1250ba7cbe76Scherry 
1251ba7cbe76Scherry 	extern struct recordchain strc[];
1252ba7cbe76Scherry 	struct staterecord *srec;
1253ba7cbe76Scherry 	struct uwtable_ent *uwt;
1254ba7cbe76Scherry 	uint64_t infoptr, procoffset, slotoffset;
1255ba7cbe76Scherry 
1256d31a64a0Sdholland #if 0 /* does not work - moved to assertion at the call site */
1257ba7cbe76Scherry 	if (iprel < 0) {
1258ba7cbe76Scherry 		panic("unwind ip out of range!!! \n");
1259ba7cbe76Scherry 		return;
1260ba7cbe76Scherry 	}
1261d31a64a0Sdholland #endif
1262ba7cbe76Scherry 
1263ba7cbe76Scherry 	uwt = get_unwind_table_entry(iprel);
1264ba7cbe76Scherry 
1265ba7cbe76Scherry 	if (uwt == NULL) return;
1266ba7cbe76Scherry 
1267ba7cbe76Scherry 	infoptr = (uint64_t) uwt->infoptr + relocoffset;
1268ba7cbe76Scherry 
1269ba7cbe76Scherry 	if (infoptr > relocoffset) {
1270ba7cbe76Scherry 		buildrecordchain(infoptr, NULL);
1271d6aeeea2Sdholland 	} else {
1272d6aeeea2Sdholland 		return;
1273ba7cbe76Scherry 	}
1274ba7cbe76Scherry 
1275ba7cbe76Scherry 	slotoffset = iprel & 3;
1276ba7cbe76Scherry 
1277ba7cbe76Scherry 	/* procoffset in Number of _slots_ , _not_ a byte offset. */
1278ba7cbe76Scherry 
1279*e0ba28d7Sdholland 	procoffset = (((iprel - slotoffset) - (uwt->start)) / 0x10 * 3)
1280*e0ba28d7Sdholland 		+ slotoffset;
1281ba7cbe76Scherry 	srec = buildrecordstack(strc, procoffset);
1282ba7cbe76Scherry 
1283ba7cbe76Scherry 	updateregs(uwf, srec, procoffset);
1284ba7cbe76Scherry }
1285