xref: /plan9/sys/src/libmach/machdata.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
1219b2ee8SDavid du Colombier /*
2219b2ee8SDavid du Colombier  * Debugger utilities shared by at least two architectures
3219b2ee8SDavid du Colombier  */
4219b2ee8SDavid du Colombier 
5219b2ee8SDavid du Colombier #include <u.h>
6219b2ee8SDavid du Colombier #include <libc.h>
7219b2ee8SDavid du Colombier #include <bio.h>
8219b2ee8SDavid du Colombier #include <mach.h>
9219b2ee8SDavid du Colombier 
10219b2ee8SDavid du Colombier #define STARTSYM	"_main"
11219b2ee8SDavid du Colombier #define PROFSYM		"_mainp"
12219b2ee8SDavid du Colombier #define	FRAMENAME	".frame"
13219b2ee8SDavid du Colombier 
14219b2ee8SDavid du Colombier extern	Machdata	mipsmach;
15219b2ee8SDavid du Colombier 
16219b2ee8SDavid du Colombier int	asstype = AMIPS;		/* disassembler type */
17219b2ee8SDavid du Colombier Machdata *machdata;		/* machine-dependent functions */
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier int
localaddr(Map * map,char * fn,char * var,uvlong * r,Rgetter rget)20*4de34a7eSDavid du Colombier localaddr(Map *map, char *fn, char *var, uvlong *r, Rgetter rget)
21219b2ee8SDavid du Colombier {
22219b2ee8SDavid du Colombier 	Symbol s;
23*4de34a7eSDavid du Colombier 	uvlong fp, pc, sp, link;
24219b2ee8SDavid du Colombier 
25219b2ee8SDavid du Colombier 	if (!lookup(fn, 0, &s)) {
26219b2ee8SDavid du Colombier 		werrstr("function not found");
27219b2ee8SDavid du Colombier 		return -1;
28219b2ee8SDavid du Colombier 	}
29219b2ee8SDavid du Colombier 	pc = rget(map, mach->pc);
30219b2ee8SDavid du Colombier 	sp = rget(map, mach->sp);
31219b2ee8SDavid du Colombier 	if(mach->link)
32219b2ee8SDavid du Colombier 		link = rget(map, mach->link);
33219b2ee8SDavid du Colombier 	else
34219b2ee8SDavid du Colombier 		link = 0;
35219b2ee8SDavid du Colombier 	fp = machdata->findframe(map, s.value, pc, sp, link);
36219b2ee8SDavid du Colombier 	if (fp == 0) {
37219b2ee8SDavid du Colombier 		werrstr("stack frame not found");
38219b2ee8SDavid du Colombier 		return -1;
39219b2ee8SDavid du Colombier 	}
40219b2ee8SDavid du Colombier 
41219b2ee8SDavid du Colombier 	if (!var || !var[0]) {
42219b2ee8SDavid du Colombier 		*r = fp;
43219b2ee8SDavid du Colombier 		return 1;
44219b2ee8SDavid du Colombier 	}
45219b2ee8SDavid du Colombier 
46219b2ee8SDavid du Colombier 	if (findlocal(&s, var, &s) == 0) {
47219b2ee8SDavid du Colombier 		werrstr("local variable not found");
48219b2ee8SDavid du Colombier 		return -1;
49219b2ee8SDavid du Colombier 	}
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier 	switch (s.class) {
52219b2ee8SDavid du Colombier 	case CAUTO:
53219b2ee8SDavid du Colombier 		*r = fp - s.value;
54219b2ee8SDavid du Colombier 		break;
55219b2ee8SDavid du Colombier 	case CPARAM:		/* assume address size is stack width */
56219b2ee8SDavid du Colombier 		*r = fp + s.value + mach->szaddr;
57219b2ee8SDavid du Colombier 		break;
58219b2ee8SDavid du Colombier 	default:
59219b2ee8SDavid du Colombier 		werrstr("local variable not found: %d", s.class);
60219b2ee8SDavid du Colombier 		return -1;
61219b2ee8SDavid du Colombier 	}
62219b2ee8SDavid du Colombier 	return 1;
63219b2ee8SDavid du Colombier }
64219b2ee8SDavid du Colombier 
65219b2ee8SDavid du Colombier /*
66*4de34a7eSDavid du Colombier  * Print value v as s.name[+offset] if possible, or just v.
67219b2ee8SDavid du Colombier  */
68219b2ee8SDavid du Colombier int
symoff(char * buf,int n,uvlong v,int space)69*4de34a7eSDavid du Colombier symoff(char *buf, int n, uvlong v, int space)
70219b2ee8SDavid du Colombier {
71219b2ee8SDavid du Colombier 	Symbol s;
72219b2ee8SDavid du Colombier 	int r;
73219b2ee8SDavid du Colombier 	long delta;
74219b2ee8SDavid du Colombier 
75219b2ee8SDavid du Colombier 	r = delta = 0;		/* to shut compiler up */
76219b2ee8SDavid du Colombier 	if (v) {
77219b2ee8SDavid du Colombier 		r = findsym(v, space, &s);
78219b2ee8SDavid du Colombier 		if (r)
79219b2ee8SDavid du Colombier 			delta = v-s.value;
80219b2ee8SDavid du Colombier 		if (delta < 0)
81219b2ee8SDavid du Colombier 			delta = -delta;
82219b2ee8SDavid du Colombier 	}
83219b2ee8SDavid du Colombier 	if (v == 0 || r == 0)
84*4de34a7eSDavid du Colombier 		return snprint(buf, n, "%llux", v);
85219b2ee8SDavid du Colombier 	if (s.type != 't' && s.type != 'T' && delta >= 4096)
86*4de34a7eSDavid du Colombier 		return snprint(buf, n, "%llux", v);
87219b2ee8SDavid du Colombier 	else if (delta)
88219b2ee8SDavid du Colombier 		return snprint(buf, n, "%s+%lux", s.name, delta);
89219b2ee8SDavid du Colombier 	else
90219b2ee8SDavid du Colombier 		return snprint(buf, n, "%s", s.name);
91219b2ee8SDavid du Colombier }
92*4de34a7eSDavid du Colombier 
93219b2ee8SDavid du Colombier /*
94219b2ee8SDavid du Colombier  *	Format floating point registers
95219b2ee8SDavid du Colombier  *
96219b2ee8SDavid du Colombier  *	Register codes in format field:
97219b2ee8SDavid du Colombier  *	'X' - print as 32-bit hexadecimal value
98219b2ee8SDavid du Colombier  *	'F' - 64-bit double register when modif == 'F'; else 32-bit single reg
99219b2ee8SDavid du Colombier  *	'f' - 32-bit ieee float
100219b2ee8SDavid du Colombier  *	'8' - big endian 80-bit ieee extended float
101219b2ee8SDavid du Colombier  *	'3' - little endian 80-bit ieee extended float with hole in bytes 8&9
102219b2ee8SDavid du Colombier  */
103219b2ee8SDavid du Colombier int
fpformat(Map * map,Reglist * rp,char * buf,int n,int modif)104219b2ee8SDavid du Colombier fpformat(Map *map, Reglist *rp, char *buf, int n, int modif)
105219b2ee8SDavid du Colombier {
106219b2ee8SDavid du Colombier 	char reg[12];
107*4de34a7eSDavid du Colombier 	ulong r;
108219b2ee8SDavid du Colombier 
109219b2ee8SDavid du Colombier 	switch(rp->rformat)
110219b2ee8SDavid du Colombier 	{
111219b2ee8SDavid du Colombier 	case 'X':
1127dd7cddfSDavid du Colombier 		if (get4(map, rp->roffs, &r) < 0)
113219b2ee8SDavid du Colombier 			return -1;
1147dd7cddfSDavid du Colombier 		snprint(buf, n, "%lux", r);
115219b2ee8SDavid du Colombier 		break;
116219b2ee8SDavid du Colombier 	case 'F':	/* first reg of double reg pair */
117219b2ee8SDavid du Colombier 		if (modif == 'F')
1187dd7cddfSDavid du Colombier 		if ((rp->rformat=='F') || (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f')) {
1197dd7cddfSDavid du Colombier 			if (get1(map, rp->roffs, (uchar *)reg, 8) < 0)
120219b2ee8SDavid du Colombier 				return -1;
121219b2ee8SDavid du Colombier 			machdata->dftos(buf, n, reg);
1227dd7cddfSDavid du Colombier 			if (rp->rformat == 'F')
1237dd7cddfSDavid du Colombier 				return 1;
124219b2ee8SDavid du Colombier 			return 2;
125219b2ee8SDavid du Colombier 		}
126219b2ee8SDavid du Colombier 			/* treat it like 'f' */
1277dd7cddfSDavid du Colombier 		if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
128219b2ee8SDavid du Colombier 			return -1;
129219b2ee8SDavid du Colombier 		machdata->sftos(buf, n, reg);
130219b2ee8SDavid du Colombier 		break;
131219b2ee8SDavid du Colombier 	case 'f':	/* 32 bit float */
1327dd7cddfSDavid du Colombier 		if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
133219b2ee8SDavid du Colombier 			return -1;
134219b2ee8SDavid du Colombier 		machdata->sftos(buf, n, reg);
135219b2ee8SDavid du Colombier 		break;
136219b2ee8SDavid du Colombier 	case '3':	/* little endian ieee 80 with hole in bytes 8&9 */
1377dd7cddfSDavid du Colombier 		if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
138219b2ee8SDavid du Colombier 			return -1;
139219b2ee8SDavid du Colombier 		memmove(reg+10, reg+8, 2);	/* open hole */
140219b2ee8SDavid du Colombier 		memset(reg+8, 0, 2);		/* fill it */
141219b2ee8SDavid du Colombier 		leieee80ftos(buf, n, reg);
142219b2ee8SDavid du Colombier 		break;
143219b2ee8SDavid du Colombier 	case '8':	/* big-endian ieee 80 */
1447dd7cddfSDavid du Colombier 		if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
145219b2ee8SDavid du Colombier 			return -1;
146219b2ee8SDavid du Colombier 		beieee80ftos(buf, n, reg);
147219b2ee8SDavid du Colombier 		break;
148219b2ee8SDavid du Colombier 	default:	/* unknown */
149219b2ee8SDavid du Colombier 		break;
150219b2ee8SDavid du Colombier 	}
151219b2ee8SDavid du Colombier 	return 1;
152219b2ee8SDavid du Colombier }
153219b2ee8SDavid du Colombier 
154219b2ee8SDavid du Colombier char *
_hexify(char * buf,ulong p,int zeros)155219b2ee8SDavid du Colombier _hexify(char *buf, ulong p, int zeros)
156219b2ee8SDavid du Colombier {
157219b2ee8SDavid du Colombier 	ulong d;
158219b2ee8SDavid du Colombier 
159219b2ee8SDavid du Colombier 	d = p/16;
160219b2ee8SDavid du Colombier 	if(d)
161219b2ee8SDavid du Colombier 		buf = _hexify(buf, d, zeros-1);
162219b2ee8SDavid du Colombier 	else
163219b2ee8SDavid du Colombier 		while(zeros--)
164219b2ee8SDavid du Colombier 			*buf++ = '0';
165219b2ee8SDavid du Colombier 	*buf++ = "0123456789abcdef"[p&0x0f];
166219b2ee8SDavid du Colombier 	return buf;
167219b2ee8SDavid du Colombier }
168219b2ee8SDavid du Colombier 
169219b2ee8SDavid du Colombier /*
170219b2ee8SDavid du Colombier  * These routines assume that if the number is representable
171219b2ee8SDavid du Colombier  * in IEEE floating point, it will be representable in the native
172219b2ee8SDavid du Colombier  * double format.  Naive but workable, probably.
173219b2ee8SDavid du Colombier  */
174219b2ee8SDavid du Colombier int
ieeedftos(char * buf,int n,ulong h,ulong l)175219b2ee8SDavid du Colombier ieeedftos(char *buf, int n, ulong h, ulong l)
176219b2ee8SDavid du Colombier {
177219b2ee8SDavid du Colombier 	double fr;
178219b2ee8SDavid du Colombier 	int exp;
179219b2ee8SDavid du Colombier 
180219b2ee8SDavid du Colombier 	if (n <= 0)
181219b2ee8SDavid du Colombier 		return 0;
182219b2ee8SDavid du Colombier 
183219b2ee8SDavid du Colombier 
184219b2ee8SDavid du Colombier 	if(h & (1L<<31)){
185219b2ee8SDavid du Colombier 		*buf++ = '-';
186219b2ee8SDavid du Colombier 		h &= ~(1L<<31);
187219b2ee8SDavid du Colombier 	}else
188219b2ee8SDavid du Colombier 		*buf++ = ' ';
189219b2ee8SDavid du Colombier 	n--;
190219b2ee8SDavid du Colombier 	if(l == 0 && h == 0)
191219b2ee8SDavid du Colombier 		return snprint(buf, n, "0.");
192219b2ee8SDavid du Colombier 	exp = (h>>20) & ((1L<<11)-1L);
193219b2ee8SDavid du Colombier 	if(exp == 0)
194219b2ee8SDavid du Colombier 		return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
195219b2ee8SDavid du Colombier 	if(exp == ((1L<<11)-1L)){
196219b2ee8SDavid du Colombier 		if(l==0 && (h&((1L<<20)-1L)) == 0)
197219b2ee8SDavid du Colombier 			return snprint(buf, n, "Inf");
198219b2ee8SDavid du Colombier 		else
199219b2ee8SDavid du Colombier 			return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
200219b2ee8SDavid du Colombier 	}
201219b2ee8SDavid du Colombier 	exp -= (1L<<10) - 2L;
202219b2ee8SDavid du Colombier 	fr = l & ((1L<<16)-1L);
203219b2ee8SDavid du Colombier 	fr /= 1L<<16;
204219b2ee8SDavid du Colombier 	fr += (l>>16) & ((1L<<16)-1L);
205219b2ee8SDavid du Colombier 	fr /= 1L<<16;
206219b2ee8SDavid du Colombier 	fr += (h & (1L<<20)-1L) | (1L<<20);
207219b2ee8SDavid du Colombier 	fr /= 1L<<21;
208219b2ee8SDavid du Colombier 	fr = ldexp(fr, exp);
209219b2ee8SDavid du Colombier 	return snprint(buf, n, "%.18g", fr);
210219b2ee8SDavid du Colombier }
211219b2ee8SDavid du Colombier 
212219b2ee8SDavid du Colombier int
ieeesftos(char * buf,int n,ulong h)213219b2ee8SDavid du Colombier ieeesftos(char *buf, int n, ulong h)
214219b2ee8SDavid du Colombier {
215219b2ee8SDavid du Colombier 	double fr;
216219b2ee8SDavid du Colombier 	int exp;
217219b2ee8SDavid du Colombier 
218219b2ee8SDavid du Colombier 	if (n <= 0)
219219b2ee8SDavid du Colombier 		return 0;
220219b2ee8SDavid du Colombier 
221219b2ee8SDavid du Colombier 	if(h & (1L<<31)){
222219b2ee8SDavid du Colombier 		*buf++ = '-';
223219b2ee8SDavid du Colombier 		h &= ~(1L<<31);
224219b2ee8SDavid du Colombier 	}else
225219b2ee8SDavid du Colombier 		*buf++ = ' ';
226219b2ee8SDavid du Colombier 	n--;
227219b2ee8SDavid du Colombier 	if(h == 0)
228219b2ee8SDavid du Colombier 		return snprint(buf, n, "0.");
229219b2ee8SDavid du Colombier 	exp = (h>>23) & ((1L<<8)-1L);
230219b2ee8SDavid du Colombier 	if(exp == 0)
231219b2ee8SDavid du Colombier 		return snprint(buf, n, "DeN(%.8lux)", h);
232219b2ee8SDavid du Colombier 	if(exp == ((1L<<8)-1L)){
233219b2ee8SDavid du Colombier 		if((h&((1L<<23)-1L)) == 0)
234219b2ee8SDavid du Colombier 			return snprint(buf, n, "Inf");
235219b2ee8SDavid du Colombier 		else
236219b2ee8SDavid du Colombier 			return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
237219b2ee8SDavid du Colombier 	}
238219b2ee8SDavid du Colombier 	exp -= (1L<<7) - 2L;
239219b2ee8SDavid du Colombier 	fr = (h & ((1L<<23)-1L)) | (1L<<23);
240219b2ee8SDavid du Colombier 	fr /= 1L<<24;
241219b2ee8SDavid du Colombier 	fr = ldexp(fr, exp);
242219b2ee8SDavid du Colombier 	return snprint(buf, n, "%.9g", fr);
243219b2ee8SDavid du Colombier }
244219b2ee8SDavid du Colombier 
245219b2ee8SDavid du Colombier int
beieeesftos(char * buf,int n,void * s)246219b2ee8SDavid du Colombier beieeesftos(char *buf, int n, void *s)
247219b2ee8SDavid du Colombier {
248219b2ee8SDavid du Colombier 	return ieeesftos(buf, n, beswal(*(ulong*)s));
249219b2ee8SDavid du Colombier }
250219b2ee8SDavid du Colombier 
251219b2ee8SDavid du Colombier int
beieeedftos(char * buf,int n,void * s)252219b2ee8SDavid du Colombier beieeedftos(char *buf, int n, void *s)
253219b2ee8SDavid du Colombier {
254219b2ee8SDavid du Colombier 	return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1]));
255219b2ee8SDavid du Colombier }
256219b2ee8SDavid du Colombier 
257219b2ee8SDavid du Colombier int
leieeesftos(char * buf,int n,void * s)258219b2ee8SDavid du Colombier leieeesftos(char *buf, int n, void *s)
259219b2ee8SDavid du Colombier {
260219b2ee8SDavid du Colombier 	return ieeesftos(buf, n, leswal(*(ulong*)s));
261219b2ee8SDavid du Colombier }
262219b2ee8SDavid du Colombier 
263219b2ee8SDavid du Colombier int
leieeedftos(char * buf,int n,void * s)264219b2ee8SDavid du Colombier leieeedftos(char *buf, int n, void *s)
265219b2ee8SDavid du Colombier {
266219b2ee8SDavid du Colombier 	return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)s));
267219b2ee8SDavid du Colombier }
268219b2ee8SDavid du Colombier 
269219b2ee8SDavid du Colombier /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
270219b2ee8SDavid du Colombier int
beieee80ftos(char * buf,int n,void * s)271219b2ee8SDavid du Colombier beieee80ftos(char *buf, int n, void *s)
272219b2ee8SDavid du Colombier {
273219b2ee8SDavid du Colombier 	uchar *reg = (uchar*)s;
274219b2ee8SDavid du Colombier 	int i;
275219b2ee8SDavid du Colombier 	ulong x;
276219b2ee8SDavid du Colombier 	uchar ieee[8+8];	/* room for slop */
277219b2ee8SDavid du Colombier 	uchar *p, *q;
278219b2ee8SDavid du Colombier 
279219b2ee8SDavid du Colombier 	memset(ieee, 0, sizeof(ieee));
280219b2ee8SDavid du Colombier 	/* sign */
281219b2ee8SDavid du Colombier 	if(reg[0] & 0x80)
282219b2ee8SDavid du Colombier 		ieee[0] |= 0x80;
283219b2ee8SDavid du Colombier 
284219b2ee8SDavid du Colombier 	/* exponent */
285219b2ee8SDavid du Colombier 	x = ((reg[0]&0x7F)<<8) | reg[1];
286219b2ee8SDavid du Colombier 	if(x == 0)		/* number is ±0 */
287219b2ee8SDavid du Colombier 		goto done;
288219b2ee8SDavid du Colombier 	if(x == 0x7FFF){
289219b2ee8SDavid du Colombier 		if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
290219b2ee8SDavid du Colombier 			x = 2047;
291219b2ee8SDavid du Colombier 		}else{				/* NaN */
292219b2ee8SDavid du Colombier 			x = 2047;
293219b2ee8SDavid du Colombier 			ieee[7] = 0x1;		/* make sure */
294219b2ee8SDavid du Colombier 		}
295219b2ee8SDavid du Colombier 		ieee[0] |= x>>4;
296219b2ee8SDavid du Colombier 		ieee[1] |= (x&0xF)<<4;
297219b2ee8SDavid du Colombier 		goto done;
298219b2ee8SDavid du Colombier 	}
299219b2ee8SDavid du Colombier 	x -= 0x3FFF;		/* exponent bias */
300219b2ee8SDavid du Colombier 	x += 1023;
301219b2ee8SDavid du Colombier 	if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
302219b2ee8SDavid du Colombier 		return snprint(buf, n, "not in range");
303219b2ee8SDavid du Colombier 	ieee[0] |= x>>4;
304219b2ee8SDavid du Colombier 	ieee[1] |= (x&0xF)<<4;
305219b2ee8SDavid du Colombier 
306219b2ee8SDavid du Colombier 	/* mantissa */
307219b2ee8SDavid du Colombier 	p = reg+4;
308219b2ee8SDavid du Colombier 	q = ieee+1;
309219b2ee8SDavid du Colombier 	for(i=0; i<56; i+=8, p++, q++){	/* move one byte */
310219b2ee8SDavid du Colombier 		x = (p[0]&0x7F) << 1;
311219b2ee8SDavid du Colombier 		if(p[1] & 0x80)
312219b2ee8SDavid du Colombier 			x |= 1;
313219b2ee8SDavid du Colombier 		q[0] |= x>>4;
314219b2ee8SDavid du Colombier 		q[1] |= (x&0xF)<<4;
315219b2ee8SDavid du Colombier 	}
316219b2ee8SDavid du Colombier     done:
317219b2ee8SDavid du Colombier 	return beieeedftos(buf, n, (void*)ieee);
318219b2ee8SDavid du Colombier }
319219b2ee8SDavid du Colombier 
320219b2ee8SDavid du Colombier int
leieee80ftos(char * buf,int n,void * s)321219b2ee8SDavid du Colombier leieee80ftos(char *buf, int n, void *s)
322219b2ee8SDavid du Colombier {
323219b2ee8SDavid du Colombier 	int i;
324219b2ee8SDavid du Colombier 	char *cp;
325219b2ee8SDavid du Colombier 	char b[12];
326219b2ee8SDavid du Colombier 
327219b2ee8SDavid du Colombier 	cp = (char*) s;
328219b2ee8SDavid du Colombier 	for(i=0; i<12; i++)
329219b2ee8SDavid du Colombier 		b[11-i] = *cp++;
330219b2ee8SDavid du Colombier 	return beieee80ftos(buf, n, b);
331219b2ee8SDavid du Colombier }
332219b2ee8SDavid du Colombier 
333219b2ee8SDavid du Colombier int
cisctrace(Map * map,uvlong pc,uvlong sp,uvlong link,Tracer trace)334*4de34a7eSDavid du Colombier cisctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
335219b2ee8SDavid du Colombier {
336219b2ee8SDavid du Colombier 	Symbol s;
337*4de34a7eSDavid du Colombier 	int found, i;
338*4de34a7eSDavid du Colombier 	uvlong opc, moved;
339219b2ee8SDavid du Colombier 
340219b2ee8SDavid du Colombier 	USED(link);
341*4de34a7eSDavid du Colombier 	i = 0;
342219b2ee8SDavid du Colombier 	opc = 0;
343219b2ee8SDavid du Colombier 	while(pc && opc != pc) {
344219b2ee8SDavid du Colombier 		moved = pc2sp(pc);
345*4de34a7eSDavid du Colombier 		if (moved == ~0)
346219b2ee8SDavid du Colombier 			break;
347219b2ee8SDavid du Colombier 		found = findsym(pc, CTEXT, &s);
348219b2ee8SDavid du Colombier 		if (!found)
349219b2ee8SDavid du Colombier 			break;
350219b2ee8SDavid du Colombier 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
351219b2ee8SDavid du Colombier 			break;
352219b2ee8SDavid du Colombier 
353219b2ee8SDavid du Colombier 		sp += moved;
354219b2ee8SDavid du Colombier 		opc = pc;
355*4de34a7eSDavid du Colombier 		if (geta(map, sp, &pc) < 0)
356219b2ee8SDavid du Colombier 			break;
357219b2ee8SDavid du Colombier 		(*trace)(map, pc, sp, &s);
358219b2ee8SDavid du Colombier 		sp += mach->szaddr;	/*assumes address size = stack width*/
359*4de34a7eSDavid du Colombier 		if(++i > 40)
360219b2ee8SDavid du Colombier 			break;
361219b2ee8SDavid du Colombier 	}
362*4de34a7eSDavid du Colombier 	return i;
363219b2ee8SDavid du Colombier }
364219b2ee8SDavid du Colombier 
365219b2ee8SDavid du Colombier int
risctrace(Map * map,uvlong pc,uvlong sp,uvlong link,Tracer trace)366*4de34a7eSDavid du Colombier risctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
367219b2ee8SDavid du Colombier {
368219b2ee8SDavid du Colombier 	int i;
369219b2ee8SDavid du Colombier 	Symbol s, f;
370*4de34a7eSDavid du Colombier 	uvlong oldpc;
371219b2ee8SDavid du Colombier 
372219b2ee8SDavid du Colombier 	i = 0;
373219b2ee8SDavid du Colombier 	while(findsym(pc, CTEXT, &s)) {
374219b2ee8SDavid du Colombier 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
375219b2ee8SDavid du Colombier 			break;
376219b2ee8SDavid du Colombier 
377219b2ee8SDavid du Colombier 		if(pc == s.value)	/* at first instruction */
378219b2ee8SDavid du Colombier 			f.value = 0;
379219b2ee8SDavid du Colombier 		else if(findlocal(&s, FRAMENAME, &f) == 0)
380219b2ee8SDavid du Colombier 			break;
381219b2ee8SDavid du Colombier 
382219b2ee8SDavid du Colombier 		oldpc = pc;
383219b2ee8SDavid du Colombier 		if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant)
384219b2ee8SDavid du Colombier 			pc = link;
385219b2ee8SDavid du Colombier 		else
386*4de34a7eSDavid du Colombier 			if (geta(map, sp, &pc) < 0)
387219b2ee8SDavid du Colombier 				break;
388219b2ee8SDavid du Colombier 
389219b2ee8SDavid du Colombier 		if(pc == 0 || (pc == oldpc && f.value == 0))
390219b2ee8SDavid du Colombier 			break;
391219b2ee8SDavid du Colombier 
392219b2ee8SDavid du Colombier 		sp += f.value;
393219b2ee8SDavid du Colombier 		(*trace)(map, pc-8, sp, &s);
394219b2ee8SDavid du Colombier 
395219b2ee8SDavid du Colombier 		if(++i > 40)
396219b2ee8SDavid du Colombier 			break;
397219b2ee8SDavid du Colombier 	}
398219b2ee8SDavid du Colombier 	return i;
399219b2ee8SDavid du Colombier }
400219b2ee8SDavid du Colombier 
401*4de34a7eSDavid du Colombier uvlong
ciscframe(Map * map,uvlong addr,uvlong pc,uvlong sp,uvlong link)402*4de34a7eSDavid du Colombier ciscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
403219b2ee8SDavid du Colombier {
404219b2ee8SDavid du Colombier 	Symbol s;
405*4de34a7eSDavid du Colombier 	uvlong moved;
406219b2ee8SDavid du Colombier 
407219b2ee8SDavid du Colombier 	USED(link);
408219b2ee8SDavid du Colombier 	for(;;) {
409219b2ee8SDavid du Colombier 		moved = pc2sp(pc);
410*4de34a7eSDavid du Colombier 		if (moved  == ~0)
411219b2ee8SDavid du Colombier 			break;
412219b2ee8SDavid du Colombier 		sp += moved;
413219b2ee8SDavid du Colombier 		findsym(pc, CTEXT, &s);
414219b2ee8SDavid du Colombier 		if (addr == s.value)
415219b2ee8SDavid du Colombier 			return sp;
416*4de34a7eSDavid du Colombier 		if (geta(map, sp, &pc) < 0)
417219b2ee8SDavid du Colombier 			break;
418219b2ee8SDavid du Colombier 		sp += mach->szaddr;	/*assumes sizeof(addr) = stack width*/
419219b2ee8SDavid du Colombier 	}
420219b2ee8SDavid du Colombier 	return 0;
421219b2ee8SDavid du Colombier }
422219b2ee8SDavid du Colombier 
423*4de34a7eSDavid du Colombier uvlong
riscframe(Map * map,uvlong addr,uvlong pc,uvlong sp,uvlong link)424*4de34a7eSDavid du Colombier riscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
425219b2ee8SDavid du Colombier {
426219b2ee8SDavid du Colombier 	Symbol s, f;
427219b2ee8SDavid du Colombier 
428219b2ee8SDavid du Colombier 	while (findsym(pc, CTEXT, &s)) {
429219b2ee8SDavid du Colombier 		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
430219b2ee8SDavid du Colombier 			break;
431219b2ee8SDavid du Colombier 
432219b2ee8SDavid du Colombier 		if(pc == s.value)	/* at first instruction */
433219b2ee8SDavid du Colombier 			f.value = 0;
434219b2ee8SDavid du Colombier 		else
435219b2ee8SDavid du Colombier 		if(findlocal(&s, FRAMENAME, &f) == 0)
436219b2ee8SDavid du Colombier 			break;
437219b2ee8SDavid du Colombier 
438219b2ee8SDavid du Colombier 		sp += f.value;
439219b2ee8SDavid du Colombier 		if (s.value == addr)
440219b2ee8SDavid du Colombier 			return sp;
441219b2ee8SDavid du Colombier 
442219b2ee8SDavid du Colombier 		if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2)
443219b2ee8SDavid du Colombier 			pc = link;
444219b2ee8SDavid du Colombier 		else
445*4de34a7eSDavid du Colombier 		if (geta(map, sp-f.value, &pc) < 0)
446219b2ee8SDavid du Colombier 			break;
447219b2ee8SDavid du Colombier 	}
448219b2ee8SDavid du Colombier 	return 0;
449219b2ee8SDavid du Colombier }
450