xref: /original-bsd/sys/vax/vax/kdb_opset.c (revision 91abda3c)
1 /*
2  *	@(#)kdb_opset.c	7.4 (Berkeley) 5/1/89
3  */
4 
5 #include "../kdb/defs.h"
6 
7 #include "frame.h"
8 
9 ADDR	kdbcallpc;
10 ADDR	kdblastframe;
11 
12 /*
13  * Instruction printing.
14  */
15 REGLIST kdbreglist [] = {
16 	"p1lr",	&kdbpcb.pcb_p1lr,	"p1br",	(int *)&kdbpcb.pcb_p1br,
17 	"p0lr",	&kdbpcb.pcb_p0lr,	"p0br",	(int *)&kdbpcb.pcb_p0br,
18 	"ksp",	&kdbpcb.pcb_ksp,	"esp",	&kdbpcb.pcb_esp,
19 	"ssp",	&kdbpcb.pcb_ssp,	"psl",	&kdbpcb.pcb_psl,
20 	"pc",	&kdbpcb.pcb_pc,		"usp",	&kdbpcb.pcb_usp,
21 	"fp",	&kdbpcb.pcb_fp,		"ap",	&kdbpcb.pcb_ap,
22 	"r11",	&kdbpcb.pcb_r11,	"r10",	&kdbpcb.pcb_r10,
23 	"r9",	&kdbpcb.pcb_r9,		"r8",	&kdbpcb.pcb_r8,
24 	"r7",	&kdbpcb.pcb_r7,		"r6",	&kdbpcb.pcb_r6,
25 	"r5",	&kdbpcb.pcb_r5,		"r4",	&kdbpcb.pcb_r4,
26 	"r3",	&kdbpcb.pcb_r3,		"r2",	&kdbpcb.pcb_r2,
27 	"r1",	&kdbpcb.pcb_r1,		"r0",	&kdbpcb.pcb_r0,
28 	0
29 };
30 
31 /*
32  * Argument data types
33  *
34  * If you change these definitions, you must also change the tables
35  * in assizetab.c
36  */
37 #define	TYPB		000	/* byte integer */
38 #define	TYPW		001	/* word integer */
39 #define	TYPL		002	/* long integer */
40 #define	TYPQ		003	/* quad integer */
41 #define	TYPO		004	/* octa integer */
42 #define	TYPF		005	/* F float */
43 #define	TYPD		006	/* D float */
44 #define	TYPG		007	/* G float */
45 #define	TYPH		010	/* H float */
46 #define	TYPUNPACKED	011	/* when unpacked into mantissa & exponent */
47 #define	TYPNONE		012	/* when nothing */
48 #define	TYPLG		4	/* number of bits the above take up */
49 
50 #define	TYPMASK	((1<<TYPLG)-1)	/* the mask (assumes 2's comp arith) */
51 /*
52  * Constructors and extractors for argument access kinds and types
53  */
54 #define A_CONS(access, type)	((access) | (type))
55 #define	A_ACCEXT(consed)	((consed) & (TYPMASK << TYPLG))
56 #define	A_TYPEXT(consed)	((consed) & TYPMASK)
57 
58 /*
59  * Argument access types used to test validity of operands to operators
60  */
61 #define	ACCR	(1<<TYPLG)			/* read */
62 #define	ACCW	(2<<TYPLG)			/* write */
63 #define	ACCB	(4<<TYPLG)			/* branch displacement */
64 #define	ACCA	(8<<TYPLG)			/* address only */
65 #define	ACCV	(8<<TYPLG)			/* address only */
66 #define	ACCM	(ACCR | ACCW)			/* modify */
67 #define	ACCI	(ACCB | ACCR)			/* XFC code */
68 
69 #define ACCESSMASK	(ACCA | ACCR | ACCW | ACCB)	/* the mask */
70 
71 /*
72  * Construction of TYPX and ACCX, to make the instrs table
73  * easy to use and read.
74  */
75 /*
76  * For real memory address
77  */
78 #define	A_AB	A_CONS(ACCA, TYPB)
79 #define	A_AW	A_CONS(ACCA, TYPW)
80 #define	A_AL	A_CONS(ACCA, TYPL)
81 #define	A_AQ	A_CONS(ACCA, TYPQ)
82 #define	A_AO	A_CONS(ACCA, TYPO)
83 #define	A_AF	A_CONS(ACCA, TYPF)
84 #define	A_AD	A_CONS(ACCA, TYPD)
85 #define	A_AG	A_CONS(ACCA, TYPG)
86 #define	A_AH	A_CONS(ACCA, TYPH)
87 /*
88  * For real memory addresses, or register addresses [sic]
89  *
90  * CHEAT! we just call these read access, since
91  * registers are allowed. All field instruction, except insv,
92  * are are read access fields.
93  */
94 #define	A_VB	A_CONS(ACCR, TYPB)
95 #define	A_VW	A_CONS(ACCR, TYPW)
96 #define	A_VL	A_CONS(ACCR, TYPL)
97 #define	A_VQ	A_CONS(ACCR, TYPQ)
98 #define	A_VO	A_CONS(ACCR, TYPO)
99 #define	A_VF	A_CONS(ACCR, TYPF)
100 #define	A_VD	A_CONS(ACCR, TYPD)
101 #define	A_VG	A_CONS(ACCR, TYPG)
102 #define	A_VH	A_CONS(ACCR, TYPH)
103 /*
104  * For branch displacement
105  */
106 #define	A_BB	A_CONS(ACCB, TYPB)
107 #define	A_BW	A_CONS(ACCB, TYPW)
108 /*
109  * For modification
110  */
111 #define	A_MB	A_CONS(ACCM, TYPB)
112 #define	A_MW	A_CONS(ACCM, TYPW)
113 #define	A_ML	A_CONS(ACCM, TYPL)
114 #define	A_MF	A_CONS(ACCM, TYPF)
115 #define	A_MD	A_CONS(ACCM, TYPD)
116 #define	A_MG	A_CONS(ACCM, TYPG)
117 #define	A_MH	A_CONS(ACCM, TYPH)
118 /*
119  * For reading
120  */
121 #define	A_RB	A_CONS(ACCR, TYPB)
122 #define	A_RW	A_CONS(ACCR, TYPW)
123 #define	A_RL	A_CONS(ACCR, TYPL)
124 #define	A_RQ	A_CONS(ACCR, TYPQ)
125 #define	A_RO	A_CONS(ACCR, TYPO)
126 #define	A_RF	A_CONS(ACCR, TYPF)
127 #define	A_RD	A_CONS(ACCR, TYPD)
128 #define	A_RG	A_CONS(ACCR, TYPG)
129 #define	A_RH	A_CONS(ACCR, TYPH)
130 /*
131  * For writing
132  */
133 #define	A_WB	A_CONS(ACCW, TYPB)
134 #define	A_WW	A_CONS(ACCW, TYPW)
135 #define	A_WL	A_CONS(ACCW, TYPL)
136 #define	A_WQ	A_CONS(ACCW, TYPQ)
137 #define	A_WO	A_CONS(ACCW, TYPO)
138 #define	A_WF	A_CONS(ACCW, TYPF)
139 #define	A_WD	A_CONS(ACCW, TYPD)
140 #define	A_WG	A_CONS(ACCW, TYPG)
141 #define	A_WH	A_CONS(ACCW, TYPH)
142 
143 struct insttab {
144 	char	*iname;
145 	u_char	eopcode;
146 	u_char	popcode;
147 	char	nargs;
148 	u_char	argtype[6];
149 };
150 
151 #define OP(name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6) \
152 	{name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6}
153 /*
154  * Definitions for the escape bytes
155  */
156 #define	CORE	0
157 #define	NEW	1
158 #define	ESCD	0xfd
159 #define	ESCF	0xff
160 #define	mapescbyte(b)	((b) == ESCD ? 1 : (b) == ESCF ? 2 : 0)
161 
162 static	struct insttab insttab[] = {
163 #include "../vax/kdb_instrs"
164 0};
165 
166 /*
167  * Convert TYP[BWLQOFDGH] into {1 if relocation not OK}
168  */
169 int	ty_NORELOC[] = {
170 	0,	/* TYPB */
171 	0,	/* TYPW */
172 	0,	/* TYPL */
173 	1,	/* TYPQ */
174 	1,	/* TYPO */
175 	1,	/* TYPF */
176 	1,	/* TYPD */
177 	1,	/* TYPG */
178 	1,	/* TYPH */
179 	1	/* TYPNONE */
180 };
181 
182 /*
183  * Convert TYP[BWLQOFDGH] into {1 ... 16}
184  */
185 int	ty_nbyte[] = {
186 	1,	/* TYPB */
187 	2,	/* TYPW */
188 	4,	/* TYPL */
189 	8,	/* TYPQ */
190 	16,	/* TYPO */
191 	4,	/* TYPF */
192 	8,	/* TYPD */
193 	8,	/* TYPG */
194 	16,	/* TYPH */
195 	0	/* TYPNONE */
196 };
197 
198 static	char *regname[] = {
199 	"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
200 	"r8", "r9", "r10","r11","ap", "fp", "sp", "pc"
201 };
202 static	char *fltimm[] = {
203 "0.5", "0.5625", "0.625", "0.6875", "0.75", "0.8125", "0.875", "0.9375",
204 "1.0", "1.125", "1.25", "1.375", "1.5", "1.625", "1.75", "1.875",
205 "2.0", "2.25", "2.5", "2.75", "3.0", "3.25", "3.5", "3.75",
206 "4.0", "4.5", "5.0", "5.5", "6.0", "6.5", "7.0", "7.5",
207 "8.0", "9.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0",
208 "16.0", "18.0", "20.0", "22.0", "24.0", "26.0", "28.0", "30.0",
209 "32.0", "36.0", "40.0", "44.0", "48.0", "52.0", "56.0", "60.0",
210 "64.0", "72.0", "80.0", "88.0", "96.0", "104.0", "112.0", "120.0"
211 };
212 
213 static	int type, space, incp;
214 static	long insoutvar[36];
215 /*
216  * Definitions for registers and for operand classes
217  */
218 static	char *insregname();	/* how to print a register */
219 
220 #define	R_PC		0xF
221 
222 #define	OC_IMM0		0x0
223 #define	OC_IMM1		0x1
224 #define	OC_IMM2		0x2
225 #define	OC_IMM3		0x3
226 #define	OC_INDEX	0x4
227 #define	OC_REG		0x5
228 #define	OC_DREG		0x6
229 #define	OC_ADREG	0x7
230 #define	OC_AIREG	0x8
231 #define	OC_DAIREG	0x9
232 
233 #define	OC_BDISP	0xA
234 #define	OC_DBDISP	0xB
235 #define	OC_WDISP	0xC
236 #define	OC_DWDISP	0xD
237 #define	OC_LDISP	0xE
238 #define	OC_DLDISP	0xF
239 
240 #define	OC_SHIFT	4
241 #define	OC_CONS(oc,reg)	(((oc & 0xF) << OC_SHIFT) | (reg & 0xF))
242 #define	OC_AMEXT(x)	(((x) >> OC_SHIFT) & 0xF)
243 #define	OC_REGEXT(x)	((x) & 0xF)
244 
245 /*
246  * Definitions for large numbers
247  */
248 #include "asnumber.h"
249 typedef	struct	as_number	*numberp;
250 static	numberp snarf();
251 static	numberp snarfreloc();
252 /*
253  * Definitions for special instructions
254  */
255 #define	CASEB	0x8F
256 #define	CASEW	0xAF
257 #define	CASEL	0xCF
258 
259 /* two level 1-based index by opcode into insttab */
260 static	short ioptab[3][256];
261 
262 kdbsetup()
263 {
264 	register struct insttab *p;
265 		int	mapchar;
266 
267 	for(p = insttab; p->iname; p++){
268 		mapchar = mapescbyte(p->eopcode);
269 		if (ioptab[mapchar][p->popcode])
270 			continue;
271 		ioptab[mapchar][p->popcode] = (p - insttab) + 1;
272 	}
273 }
274 
275 static	u_char snarfuchar();
276 /*
277  * Global variables for communicating with the minions and printins
278  */
279 static	int	idsp;
280 static	short	argno;		/* which argument one is working on */
281 static	char	insoutfmt[2];	/* how to format the relocated symbols */
282 
283 static savevar(val)
284 	long	val;
285 {
286 	kdbvar[argno] = val;
287 	insoutvar[argno] = val;
288 }
289 
290 /* ARGSUSED */
291 kdbprintins(Idsp, ins)
292 	u_char	ins;
293 	int	Idsp;
294 {
295 		u_char	mode;		/* mode */
296 		u_char	ins2;
297 		char	*indexreg;	/* print of which register indexes */
298 		char	*indexed;	/* we indexed */
299 		char	*operandout();
300 	register u_char 	*ap;
301 	register struct insttab *ip;
302 		u_char	optype;
303 		int	mapchar;
304 
305 	idsp = Idsp;
306 	type = DSYM;
307 	space = idsp;
308 	insoutfmt[0] = 0;
309 
310 	incp = 1;
311 	if ((mapchar = mapescbyte(ins)) != 0){
312 		ins2 = snarfuchar();
313 		if (ioptab[mapchar][ins2] == 0){
314 			/*
315 			 *	Oops; not a defined instruction;
316 			 *	back over this escape byte.
317 			 */
318 			incp -= 1;
319 			mapchar = 0;
320 		} else {
321 			ins = ins2;
322 		}
323 	}
324 	if (ioptab[mapchar][ins] == 0){
325 		kdbprintf("<undefined operator byte>: %x", ins);
326 		goto ret;
327 	}
328 	ip = &insttab[ioptab[mapchar][ins] - 1];
329 	kdbprintf("%s\t", ip->iname);
330 
331 	for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) {
332 		savevar(0x80000000);	/* an illegal symbol */
333 		optype = *ap;
334 		if (argno != 0)
335 			kdbprintc(',');
336 		indexreg = 0;
337 		indexed = 0;
338 		do{
339 			if (A_ACCEXT(optype) & ACCB){
340 				switch(A_TYPEXT(optype)){
341 				case TYPB:
342 					mode = OC_CONS(OC_BDISP, R_PC);
343 					break;
344 				case TYPW:
345 					mode = OC_CONS(OC_WDISP, R_PC);
346 					break;
347 				}
348 			} else {
349 				mode = snarfuchar();
350 			}
351 			indexreg = operandout(mode, optype);
352 			if (indexed)
353 				kdbprintf("[%s]", indexed);
354 			indexed = indexreg;
355 		} while(indexed);
356 	}
357 	if (mapchar == 0){
358 		switch(ins){
359 		case CASEB:
360 		case CASEW:
361 		case CASEL:
362 			casebody(insoutvar[1], insoutvar[2]);
363 			break;
364 		default:
365 			break;
366 		}
367 	}
368    ret: ;
369 
370 	kdbdotinc = incp;
371 }
372 
373 casebody(base, limit)
374 	long	base;
375 	long	limit;
376 {
377 	int	i;
378 	u_int	baseincp;
379 	u_int	advincp;
380 	struct	as_number	*valuep;
381 #define	OSIZE (sizeof(short))
382 	argno = 0;
383 	baseincp = incp;
384 	for (i = 0; i <= limit; i++) {
385 		kdbprintc(EOR);
386 		kdbprintf("    %R:  ", i + base);
387 		valuep = snarfreloc(OSIZE, 0);
388 		advincp = incp;
389 		incp = baseincp;
390 		dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
391 		incp = advincp;
392 	}
393 }
394 
395 /*
396  * magic values to mung an offset to a register into
397  * something that psymoff can understand.. all magic
398  */
399 			      /* 0	1	2	3	4 */
400 static long magic_masks[5] =	{0,	0x80,	0x8000,	0,	0};
401 static long magic_compl[5] =	{0,	0x100,	0x10000,0,	0};
402 /*
403  * Snarf up some bytes, and put in the magic relocation flags
404  */
405 static numberp snarfreloc(nbytes)
406 	int	nbytes;
407 {
408 	numberp	back;
409 	back = snarf(nbytes);
410 	if (back->num_ulong[0] & magic_masks[nbytes])
411 		back->num_ulong[0] -= magic_compl[nbytes];
412 	return(back);
413 }
414 /*
415  * The following code is NOT portable from the PDP 11 to the VAX
416  * because of the byte ordering problem.
417  */
418 static numberp snarf(nbytes)
419 	int	nbytes;
420 {
421 	register	int	i;
422 
423 	static	struct	as_number	backnumber;
424 	static	struct	as_number	znumber;	/* init'ed to 0 */
425 
426 	backnumber = znumber;
427 	for (i = 0; i < nbytes; i++)
428 		backnumber.num_uchar[i] = snarfuchar();
429 	return(&backnumber);
430 }
431 
432 /*
433  * Read one single character, and advance the dot
434  */
435 static u_char
436 snarfuchar()
437 {
438 	u_char	back;
439 	/*
440 	 *	assert: bchkget and inkdot don't have side effects
441 	 */
442 	back = (u_char)kdbbchkget(kdbinkdot(incp), idsp);
443 	incp += 1;
444 	return(back);
445 }
446 
447 /*
448  * normal operand; return non zero pointer to register
449  * name if this is an index instruction.
450  */
451 char *operandout(mode, optype)
452 	u_char	mode;
453 	u_char	optype;
454 {
455 	char	*r;
456 	int	regnumber;
457 	int	nbytes;
458 
459 	regnumber = OC_REGEXT(mode);
460 	r = insregname(regnumber);
461 	switch (OC_AMEXT(mode)){
462 	case OC_IMM0:
463 	case OC_IMM1:
464 	case OC_IMM2:
465 	case OC_IMM3:
466 		shortliteral(mode, optype);
467 		return(0);
468 	case OC_INDEX:
469 		return(r);		/* will be printed later */
470 	case OC_REG:
471 		kdbprintf("%s", r);
472 		return(0);
473 	case OC_DREG:
474 		kdbprintf("(%s)", r);
475 		return(0);
476 	case OC_ADREG:
477 		kdbprintf("-(%s)", r);
478 		return(0);
479 	case OC_DAIREG:
480 		kdbprintc('*');
481 	case OC_AIREG:
482 		if (regnumber == R_PC){
483 			pcimmediate(mode, optype);
484 		} else {
485 			kdbprintf("(%s)+", r);
486 		}
487 		return(0);
488 	case OC_DBDISP:
489 		kdbprintc('*');
490 	case OC_BDISP:
491 		nbytes = 1;
492 		break;
493 	case OC_DWDISP:
494 		kdbprintc('*');
495 	case OC_WDISP:
496 		nbytes = 2;
497 		break;
498 	case OC_DLDISP:
499 		kdbprintc('*');
500 	case OC_LDISP:
501 		nbytes = 4;
502 		break;
503 	}
504 	dispaddress(snarfreloc(nbytes), mode);
505 	return(0);
506 }
507 
508 dispaddress(valuep, mode)
509 	numberp	valuep;
510 	u_char	mode;
511 {
512 	int	regnumber = OC_REGEXT(mode);
513 
514 	switch(OC_AMEXT(mode)){
515 	case OC_BDISP:
516 	case OC_DBDISP:
517 	case OC_WDISP:
518 	case OC_DWDISP:
519 	case OC_LDISP:
520 	case OC_DLDISP:
521 		if (regnumber == R_PC){
522 			/* PC offset addressing */
523 			valuep->num_ulong[0] += kdbinkdot(incp);
524 		}
525 	}
526 	if (regnumber == R_PC)
527 		kdbpsymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
528 	else {				/* } */
529 		kdbprintf(LPRMODE, valuep->num_ulong[0]);
530 		kdbprintf(insoutfmt);
531 		kdbprintf("(%s)", insregname(regnumber));
532 	}
533 	savevar((long)valuep->num_ulong[0]);
534 }
535 
536 /*
537  * get a register name
538  */
539 static char *
540 insregname(regnumber)
541 	int	regnumber;
542 {
543 	char	*r;
544 	r = regname[regnumber];
545 	return(r);
546 }
547 
548 /*
549  * print out a short literal
550  */
551 shortliteral(mode, optype)
552 	u_char	mode;
553 	u_char	optype;
554 {
555 	savevar((long)mode);
556 	switch(A_TYPEXT(optype)){
557 	case TYPF:
558 	case TYPD:
559 	case TYPG:
560 	case TYPH:
561 		kdbprintf("$%s", fltimm[mode]);
562 		break;
563 	default:
564 		kdbprintf("$%r", mode);
565 		break;
566 	}
567 }
568 
569 pcimmediate(mode, optype)
570 	u_char	mode;
571 	u_char	optype;
572 {
573 	int	nbytes;
574 
575 	kdbprintc('$');
576 	if (mode == OC_CONS(OC_DAIREG, R_PC)){	/* PC absolute, always 4 bytes*/
577 		dispaddress(snarfreloc(4), mode);
578 		return;
579 	}
580 	nbytes = ty_nbyte[A_TYPEXT(optype)];
581 	if (! ty_NORELOC[A_TYPEXT(optype)]){
582 		dispaddress(snarfreloc(nbytes), mode);
583 		return;
584 	}
585 	bignumprint(nbytes, optype);
586 }
587 
588 bignumprint(nbytes, optype)
589 	int	nbytes;
590 	u_char	optype;
591 {
592 	numberp	valuep;
593 	int	leading_zero = 1;
594 	register int	bindex;
595 	register int	nindex;
596 	register int	ch;
597 
598 	valuep = snarf(nbytes);
599 	switch(A_TYPEXT(optype)){
600 	case TYPF:
601 		kdbprintf("0f%f", valuep->num_num.numFf_float.Ff_value);
602 		break;
603 	case TYPD:
604 		kdbprintf("0d%f", valuep->num_num.numFd_float.Fd_value);
605 		break;
606 	case TYPG:
607 		kdbprintf("0g::"); goto qprint;
608 	case TYPH:
609 		kdbprintf("0h::"); goto qprint;
610 	case TYPQ:
611 	case TYPO:
612 	qprint:
613 		for (bindex = nbytes - 1; bindex >= 0; --bindex){
614 			for (nindex = 4; nindex >= 0; nindex -= 4){
615 				ch = (valuep->num_uchar[bindex] >> nindex);
616 				ch &= 0x0F;
617 				if ( ! (leading_zero &= (ch == 0) ) ){
618 					if (ch <= 0x09)
619 						kdbprintc(ch + '0');
620 					else
621 						kdbprintc(ch - 0x0A + 'a');
622 				}
623 			}
624 		}
625 		break;
626 	}
627 }
628 
629 kdbstacktrace(dolocals)
630 	int dolocals;
631 {
632 	register ADDR ap, fp;
633 	register int i, narg, tramp;
634 	struct frame fr;
635 
636 	if (kdbadrflg) {
637 		/*
638 		 * Can only find args if called via `calls' (not callg).
639 		 * The horrible expression below reads the second
640 		 * longword of the given frame address; this contains
641 		 * fr_s and fr_spa, plus the register save mask.  The
642 		 * memory layout is
643 		 *	fp+0x00: call frame structure
644 		 *	fp+0x14: saved registers
645 		 *	fp+0xMM: stack alignment bytes
646 		 *	fp+0xNN: arguments
647 		 */
648 		fp = kdbadrval;
649 		((int *)&fr)[1] = kdbget((off_t)fp + 4, DSP);
650 		if (fr.fr_s) {
651 			ap = fp + sizeof(fr) + fr.fr_spa;
652 			for (i = fr.fr_mask; i != 0; i >>= 1)
653 				if (i & 1)
654 					ap += 4;
655 		} else
656 			ap = 0;
657 		kdbcallpc = getprevpc(fp);
658 	} else {
659 		fp = kdbpcb.pcb_fp;
660 		ap = kdbpcb.pcb_ap;
661 		kdbcallpc = kdbpcb.pcb_pc;
662 	}
663 
664 	kdblastframe = NOFRAME;
665 	while (kdbcntval-- && fp != NOFRAME) {
666 		char *name;
667 
668 		kdbchkerr();
669 		/* check for pc in pcb (signal trampoline code) */
670 		if (issignalpc(kdbcallpc)) {
671 			tramp = 1;
672 			name = "sigtramp";
673 		} else {
674 			tramp = 0;
675 			(void) kdbfindsym((long)kdbcallpc, ISYM);
676 			if (kdbcursym)
677 				name = kdbcursym->n_un.n_name;
678 			else
679 				name = "?";
680 		}
681 		kdbprintf("%s(", name);
682 		if (ap) {
683 			/* byte at ap tells how many arguments */
684 			narg = kdbget((off_t)ap, DSP) & 0xff;
685 			for (i = narg > 10 ? 10 : narg; i;) {
686 				ap += 4;
687 				kdbprintf("%R", kdbget((off_t)ap, DSP));
688 				if (--i != 0)
689 					kdbprintc(',');
690 			}
691 		} else
692 			kdbprintc('?');
693 		kdbprintf(") at ");
694 		kdbpsymoff((long)kdbcallpc, ISYM, "\n");
695 
696 		if (dolocals) {
697 			register ADDR word;
698 
699 			while (kdblocalsym((long)fp)) {
700 				word = kdbget((off_t)kdblocalval, DSP);
701 				kdbprintf("%8t%s:%10t",
702 				    kdbcursym->n_un.n_name);
703 				if (kdberrflg) {
704 					kdbprintf("?\n");
705 					kdberrflg = 0;
706 				} else
707 					kdbprintf("%R\n", word);
708 			}
709 		}
710 		if (!tramp) {
711 			kdbcallpc = getprevpc(fp);
712 			kdblastframe = fp;
713 			/* 8 below == offsetof(struct frame, fr_savap) */
714 			ap = kdbget((off_t)fp + 8, DSP);
715 			fp = getprevframe(fp);
716 		} else {
717 			kdbcallpc = getsignalpc(kdblastframe);
718 			/* ??? WHAT ABOUT ap AND fp ??? */
719 		}
720 		if (!kdbadrflg && !INSTACK(fp))
721 			break;
722 	}
723 }
724