xref: /original-bsd/sys/pmax/pmax/kadb.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)kadb.c	8.1 (Berkeley) 06/10/93
11  */
12 
13 /*
14  * Define machine dependent primitives for kdb.
15  */
16 
17 #include <kdb/defs.h>
18 #undef SP
19 #include <machine/reg.h>
20 #include <machine/trap.h>
21 #include <machine/mips_opcode.h>
22 
23 REGLIST	kdbreglist[] = {
24 	/* register_name, address */
25 	"AT", &kdbpcb.pcb_regs[AST],
26 	"v0", &kdbpcb.pcb_regs[V0],
27 	"v1", &kdbpcb.pcb_regs[V1],
28 	"a0", &kdbpcb.pcb_regs[A0],
29 	"a1", &kdbpcb.pcb_regs[A1],
30 	"a2", &kdbpcb.pcb_regs[A2],
31 	"a3", &kdbpcb.pcb_regs[A3],
32 	"t0", &kdbpcb.pcb_regs[T0],
33 	"t1", &kdbpcb.pcb_regs[T1],
34 	"t2", &kdbpcb.pcb_regs[T2],
35 	"t3", &kdbpcb.pcb_regs[T3],
36 	"t4", &kdbpcb.pcb_regs[T4],
37 	"t5", &kdbpcb.pcb_regs[T5],
38 	"t6", &kdbpcb.pcb_regs[T6],
39 	"t7", &kdbpcb.pcb_regs[T7],
40 	"t8", &kdbpcb.pcb_regs[T8],
41 	"t9", &kdbpcb.pcb_regs[T9],
42 	"s0", &kdbpcb.pcb_regs[S0],
43 	"s1", &kdbpcb.pcb_regs[S1],
44 	"s2", &kdbpcb.pcb_regs[S2],
45 	"s3", &kdbpcb.pcb_regs[S3],
46 	"s4", &kdbpcb.pcb_regs[S4],
47 	"s5", &kdbpcb.pcb_regs[S5],
48 	"s6", &kdbpcb.pcb_regs[S6],
49 	"s7", &kdbpcb.pcb_regs[S7],
50 	"s8", &kdbpcb.pcb_regs[S8],
51 	"sp", &kdbpcb.pcb_regs[SP],
52 	"gp", &kdbpcb.pcb_regs[GP],
53 	"ra", &kdbpcb.pcb_regs[RA],
54 	"mullo", &kdbpcb.pcb_regs[MULLO],
55 	"mulhi", &kdbpcb.pcb_regs[MULHI],
56 	"SR", &kdbpcb.pcb_regs[SR],
57 	"pc", &kdbpcb.pcb_regs[PC],
58 	"f0", &kdbpcb.pcb_regs[F0],
59 	"f1", &kdbpcb.pcb_regs[F1],
60 	"f2", &kdbpcb.pcb_regs[F2],
61 	"f3", &kdbpcb.pcb_regs[F3],
62 	"f4", &kdbpcb.pcb_regs[F4],
63 	"f5", &kdbpcb.pcb_regs[F5],
64 	"f6", &kdbpcb.pcb_regs[F6],
65 	"f7", &kdbpcb.pcb_regs[F7],
66 	"f8", &kdbpcb.pcb_regs[F8],
67 	"f9", &kdbpcb.pcb_regs[F9],
68 	"f10", &kdbpcb.pcb_regs[F10],
69 	"f11", &kdbpcb.pcb_regs[F11],
70 	"f12", &kdbpcb.pcb_regs[F12],
71 	"f13", &kdbpcb.pcb_regs[F13],
72 	"f14", &kdbpcb.pcb_regs[F14],
73 	"f15", &kdbpcb.pcb_regs[F15],
74 	"f16", &kdbpcb.pcb_regs[F16],
75 	"f17", &kdbpcb.pcb_regs[F17],
76 	"f18", &kdbpcb.pcb_regs[F18],
77 	"f19", &kdbpcb.pcb_regs[F19],
78 	"f20", &kdbpcb.pcb_regs[F20],
79 	"f21", &kdbpcb.pcb_regs[F21],
80 	"f22", &kdbpcb.pcb_regs[F22],
81 	"f23", &kdbpcb.pcb_regs[F23],
82 	"f24", &kdbpcb.pcb_regs[F24],
83 	"f25", &kdbpcb.pcb_regs[F25],
84 	"f26", &kdbpcb.pcb_regs[F26],
85 	"f27", &kdbpcb.pcb_regs[F27],
86 	"f28", &kdbpcb.pcb_regs[F28],
87 	"f29", &kdbpcb.pcb_regs[F29],
88 	"f30", &kdbpcb.pcb_regs[F30],
89 	"f31", &kdbpcb.pcb_regs[F31],
90 	0, 0
91 };
92 
93 static char *op_name[64] = {
94 /* 0 */	"spec",	"bcond","j",	"jal",	"beq",	"bne",	"blez",	"bgtz",
95 /* 8 */	"addi",	"addiu","slti",	"sltiu","andi",	"ori",	"xori",	"lui",
96 /*16 */	"cop0",	"cop1",	"cop2",	"cop3",	"op24",	"op25",	"op26",	"op27",
97 /*24 */	"op30",	"op31",	"op32",	"op33",	"op34",	"op35",	"op36",	"op37",
98 /*32 */	"lb",	"lh",	"lwl",	"lw",	"lbu",	"lhu",	"lwr",	"ld",
99 /*40 */	"sb",	"sh",	"swl",	"sw",	"op54",	"op55",	"swr",	"sd",
100 /*48 */	"lwc0",	"lwc1",	"lwc2",	"lwc3",	"ldc0",	"ldc1",	"ldc2",	"ldc3",
101 /*56 */	"swc0",	"swc1",	"swc2",	"swc3",	"sdc0",	"sdc1",	"sdc2",	"sdc3"
102 };
103 
104 static char *spec_name[64] = {
105 /* 0 */	"sll",	"spec01","srl",	"sra",	"sllv",	"spec05","srlv","srav",
106 /* 8 */	"jr",	"jalr",	"spec12","spec13","syscall","break","spec16","tas",
107 /*16 */	"mfhi",	"mthi",	"mflo",	"mtlo",	"spec24","spec25","spec26","spec27",
108 /*24 */	"mult",	"multu","div",	"divu",	"spec34","spec35","spec36","spec37",
109 /*32 */	"add",	"addu",	"sub",	"subu",	"and",	"or",	"xor",	"nor",
110 /*40 */	"spec50","spec51","slt","sltu",	"spec54","spec55","spec56","spec57",
111 /*48 */	"spec60","spec61","spec62","spec63","spec64","spec65","spec66","spec67",
112 /*56 */	"spec70","spec71","spec72","spec73","spec74","spec75","spec76","spec77"
113 };
114 
115 static char *bcond_name[32] = {
116 /* 0 */	"bltz",	"bgez", "?", "?", "?", "?", "?", "?",
117 /* 8 */	"?", "?", "?", "?", "?", "?", "?", "?",
118 /*16 */	"bltzal", "bgezal", "?", "?", "?", "?", "?", "?",
119 /*24 */	"?", "?", "?", "?", "?", "?", "?", "?",
120 };
121 
122 static char *cop1_name[64] = {
123 /* 0 */	"fadd",	"fsub",	"fmpy",	"fdiv",	"fsqrt","fabs",	"fmov",	"fneg",
124 /* 8 */	"fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
125 /*16 */	"fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
126 /*24 */	"fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
127 /*32 */	"fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
128 /*40 */	"fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
129 /*48 */	"fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
130 	"fcmp.ole","fcmp.ule",
131 /*56 */	"fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
132 	"fcmp.le","fcmp.ngt"
133 };
134 
135 static char *fmt_name[16] = {
136 	"s",	"d",	"e",	"fmt3",
137 	"w",	"fmt5",	"fmt6",	"fmt7",
138 	"fmt8",	"fmt9",	"fmta",	"fmtb",
139 	"fmtc",	"fmtd",	"fmte",	"fmtf"
140 };
141 
142 static char *reg_name[32] = {
143 	"zero",	"at",	"v0",	"v1",	"a0",	"a1",	"a2",	"a3",
144 	"t0",	"t1",	"t2",	"t3",	"t4",	"t5",	"t6",	"t7",
145 	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",	"s7",
146 	"t8",	"t9",	"k0",	"k1",	"gp",	"sp",	"s8",	"ra"
147 };
148 
149 static char *c0_opname[64] = {
150 	"c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
151 	"tlbp",  "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
152 	"rfe",   "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
153 	"c0op30","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
154 	"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
155 	"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
156 	"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
157 	"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
158 };
159 
160 static char *c0_reg[32] = {
161 	"index","random","tlblo","c0r3","context","c0r5","c0r6","c0r7",
162 	"badvaddr","c0r9","tlbhi","c0r11","sr",	"cause","epc",	"c0r15",
163 	"c0r16","c0r17","c0r18","c0r19","c0r20","c0r21","c0r22","c0r23",
164 	"c0r24","c0r25","c0r26","c0r27","c0r28","c0r29","c0r30","c0r31"
165 };
166 
167 /*
168  * Print the cause of the trap to kdb.
169  */
170 void
171 kdbprinttrap(causeReg, vadr)
172 	unsigned causeReg, vadr;
173 {
174 	int type, pc;
175 	extern char *trap_type[];
176 
177 	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
178 
179 	/* check to see if we are entering kdb via kdbpanic() */
180 	pc = kdbpcb.pcb_regs[PC];
181 	if (type == T_BREAK && pc < 0) {
182 		if (kdbpeek(pc) == MACH_BREAK_KDB)
183 			kdbpcb.pcb_regs[PC] = pc + 4;
184 	}
185 
186 	kdbprintf("trap: %s\n", trap_type[type]);
187 }
188 
189 unsigned kdb_ss_addr;
190 unsigned kdb_ss_instr;
191 
192 void
193 kdbsetsstep()
194 {
195 	register unsigned va;
196 	register int *locr0 = kdbpcb.pcb_regs;
197 	int i;
198 
199 	/* compute next address after current location */
200 	va = MachEmulateBranch(locr0, locr0[PC], 0, 1);
201 	if (kdb_ss_addr) {
202 		kdbprintf("kdbsetsstep: breakpoint already set at %x (va %x)\n",
203 			kdb_ss_addr, va);
204 		return;
205 	}
206 	kdb_ss_addr = va;
207 
208 	if ((int)va < 0) {
209 		/* kernel address */
210 		kdb_ss_instr = kdbpeek(va);
211 		kdbpoke((caddr_t)va, MACH_BREAK_SSTEP);
212 		return;
213 	}
214 
215 	kdb_ss_instr = fuiword(va);
216 	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
217 	if (i < 0) {
218 		register struct proc *p = curproc;
219 		vm_offset_t sa, ea;
220 		int rv;
221 
222 		sa = trunc_page((vm_offset_t)va);
223 		ea = round_page((vm_offset_t)va+sizeof(int)-1);
224 		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
225 			VM_PROT_DEFAULT, FALSE);
226 		if (rv == KERN_SUCCESS) {
227 			i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
228 			(void) vm_map_protect(&p->p_vmspace->vm_map,
229 				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
230 		}
231 	}
232 	if (i < 0)
233 		return;
234 }
235 
236 void
237 kdbclrsstep()
238 {
239 	register unsigned cr, pc, va;
240 	unsigned instr;
241 	int i;
242 
243 	/* ignore this trap if it is not a break trap */
244 	cr = kdbvar[kdbvarchk('t')];
245 	if ((cr & MACH_CR_EXC_CODE) != (T_BREAK << MACH_CR_EXC_CODE_SHIFT))
246 		return;
247 
248 	/* fix pc if break instruction is in the delay slot */
249 	pc = kdbpcb.pcb_regs[PC];
250 	if ((int)cr < 0)
251 		pc += 4;
252 
253 	/* check to be sure its the one we are expecting */
254 	va = kdb_ss_addr;
255 	if (!va || va != pc)
256 		return;
257 
258 	/* read break instruction */
259 	instr = kdbpeek(va);
260 	if (instr != MACH_BREAK_SSTEP)
261 		return;
262 
263 	if ((int)va < 0) {
264 		/* kernel address */
265 		kdbpoke((caddr_t)va, kdb_ss_instr);
266 		kdb_ss_addr = 0;
267 		return;
268 	}
269 
270 	/* restore original instruction and clear BP */
271 	i = suiword((caddr_t)va, kdb_ss_instr);
272 	if (i < 0) {
273 		register struct proc *p = curproc;
274 		vm_offset_t sa, ea;
275 		int rv;
276 
277 		sa = trunc_page((vm_offset_t)va);
278 		ea = round_page((vm_offset_t)va+sizeof(int)-1);
279 		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
280 			VM_PROT_DEFAULT, FALSE);
281 		if (rv == KERN_SUCCESS) {
282 			i = suiword((caddr_t)va, p->p_md.md_ss_instr);
283 			(void) vm_map_protect(&p->p_vmspace->vm_map,
284 				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
285 				FALSE);
286 		}
287 	}
288 	if (i < 0)
289 		kdbprintf("can't clear break at %x\n", va);
290 	kdb_ss_addr = 0;
291 }
292 
293 void
294 kdbreadc(lp)
295 	char *lp;
296 {
297 	int c;
298 
299 	c = cngetc();
300 	if (c == '\r')
301 		c = '\n';
302 	*lp = c;
303 }
304 
305 void
306 kdbwrite(lp, len)
307 	char *lp;
308 	int len;
309 {
310 	while (len-- > 0)
311 		cnputc(*lp++);
312 }
313 
314 /* ARGSUSED */
315 void
316 kdbprintins(space, ins)
317 	int space;
318 	long ins;
319 {
320 	InstFmt i;
321 
322 	i.word = ins;
323 
324 	switch (i.JType.op) {
325 	case OP_SPECIAL:
326 		if (i.word == 0) {
327 			kdbprintf("nop");
328 			break;
329 		}
330 		if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
331 			kdbprintf("move\t%s,%s",
332 				reg_name[i.RType.rd],
333 				reg_name[i.RType.rs]);
334 			break;
335 		}
336 		kdbprintf("%s", spec_name[i.RType.func]);
337 		switch (i.RType.func) {
338 		case OP_SLL:
339 		case OP_SRL:
340 		case OP_SRA:
341 			kdbprintf("\t%s,%s,%d",
342 				reg_name[i.RType.rd],
343 				reg_name[i.RType.rt],
344 				i.RType.shamt);
345 			break;
346 
347 		case OP_SLLV:
348 		case OP_SRLV:
349 		case OP_SRAV:
350 			kdbprintf("\t%s,%s,%s",
351 				reg_name[i.RType.rd],
352 				reg_name[i.RType.rt],
353 				reg_name[i.RType.rs]);
354 			break;
355 
356 		case OP_MFHI:
357 		case OP_MFLO:
358 			kdbprintf("\t%s", reg_name[i.RType.rd]);
359 			break;
360 
361 		case OP_JR:
362 		case OP_JALR:
363 		case OP_MTLO:
364 		case OP_MTHI:
365 			kdbprintf("\t%s", reg_name[i.RType.rs]);
366 			break;
367 
368 		case OP_MULT:
369 		case OP_MULTU:
370 		case OP_DIV:
371 		case OP_DIVU:
372 			kdbprintf("\t%s,%s",
373 				reg_name[i.RType.rs],
374 				reg_name[i.RType.rt]);
375 			break;
376 
377 		case OP_SYSCALL:
378 			break;
379 
380 		case OP_BREAK:
381 			kdbprintf("\t%d", (i.RType.rs << 5) | i.RType.rt);
382 			break;
383 
384 		default:
385 			kdbprintf("\t%s,%s,%s",
386 				reg_name[i.RType.rd],
387 				reg_name[i.RType.rs],
388 				reg_name[i.RType.rt]);
389 		};
390 		break;
391 
392 	case OP_BCOND:
393 		kdbprintf("%s\t%s,", bcond_name[i.IType.rt],
394 			reg_name[i.IType.rs]);
395 		goto pr_displ;
396 
397 	case OP_BLEZ:
398 	case OP_BGTZ:
399 		kdbprintf("%s\t%s,", op_name[i.IType.op],
400 			reg_name[i.IType.rs]);
401 		goto pr_displ;
402 
403 	case OP_BEQ:
404 		if (i.IType.rs == 0 && i.IType.rt == 0) {
405 			kdbprintf("b\t");
406 			goto pr_displ;
407 		}
408 		/* FALLTHROUGH */
409 	case OP_BNE:
410 		kdbprintf("%s\t%s,%s,", op_name[i.IType.op],
411 			reg_name[i.IType.rs],
412 			reg_name[i.IType.rt]);
413 	pr_displ:
414 		kdbpsymoff(kdbdot + 4 + ((short)i.IType.imm << 2), ISYM, "");
415 		break;
416 
417 	case OP_COP0:
418 		switch (i.RType.rs) {
419 		case OP_BCx:
420 		case OP_BCy:
421 			kdbprintf("bc0%c\t",
422 				"ft"[i.RType.rt & COPz_BC_TF_MASK]);
423 			goto pr_displ;
424 
425 		case OP_MT:
426 			kdbprintf("mtc0\t%s,%s",
427 				reg_name[i.RType.rt],
428 				c0_reg[i.RType.rd]);
429 			break;
430 
431 		case OP_MF:
432 			kdbprintf("mfc0\t%s,%s",
433 				reg_name[i.RType.rt],
434 				c0_reg[i.RType.rd]);
435 			break;
436 
437 		default:
438 			kdbprintf("%s", c0_opname[i.FRType.func]);
439 		};
440 		break;
441 
442 	case OP_COP1:
443 		switch (i.RType.rs) {
444 		case OP_BCx:
445 		case OP_BCy:
446 			kdbprintf("bc1%c\t",
447 				"ft"[i.RType.rt & COPz_BC_TF_MASK]);
448 			goto pr_displ;
449 
450 		case OP_MT:
451 			kdbprintf("mtc1\t%s,f%d",
452 				reg_name[i.RType.rt],
453 				i.RType.rd);
454 			break;
455 
456 		case OP_MF:
457 			kdbprintf("mfc1\t%s,f%d",
458 				reg_name[i.RType.rt],
459 				i.RType.rd);
460 			break;
461 
462 		case OP_CT:
463 			kdbprintf("ctc1\t%s,f%d",
464 				reg_name[i.RType.rt],
465 				i.RType.rd);
466 			break;
467 
468 		case OP_CF:
469 			kdbprintf("cfc1\t%s,f%d",
470 				reg_name[i.RType.rt],
471 				i.RType.rd);
472 			break;
473 
474 		default:
475 			kdbprintf("%s.%s\tf%d,f%d,f%d",
476 				cop1_name[i.FRType.func],
477 				fmt_name[i.FRType.fmt],
478 				i.FRType.fd, i.FRType.fs, i.FRType.ft);
479 		};
480 		break;
481 
482 	case OP_J:
483 	case OP_JAL:
484 		kdbprintf("%s\t", op_name[i.JType.op]);
485 		kdbpsymoff((kdbdot & 0xF0000000) | (i.JType.target << 2),
486 			ISYM, "");
487 		break;
488 
489 	case OP_LWC1:
490 	case OP_SWC1:
491 		kdbprintf("%s\tf%d,", op_name[i.IType.op],
492 			i.IType.rt);
493 		goto loadstore;
494 
495 	case OP_LB:
496 	case OP_LH:
497 	case OP_LW:
498 	case OP_LBU:
499 	case OP_LHU:
500 	case OP_SB:
501 	case OP_SH:
502 	case OP_SW:
503 		kdbprintf("%s\t%s,", op_name[i.IType.op],
504 			reg_name[i.IType.rt]);
505 	loadstore:
506 		kdbprintf("%d(%s)", (short)i.IType.imm,
507 			reg_name[i.IType.rs]);
508 		break;
509 
510 	case OP_ORI:
511 	case OP_XORI:
512 		if (i.IType.rs == 0) {
513 			kdbprintf("li\t%s,0x%X",
514 				reg_name[i.IType.rt],
515 				i.IType.imm);
516 			break;
517 		}
518 		/* FALLTHROUGH */
519 	case OP_ANDI:
520 		kdbprintf("%s\t%s,%s,0x%X", op_name[i.IType.op],
521 			reg_name[i.IType.rt],
522 			reg_name[i.IType.rs],
523 			i.IType.imm);
524 		break;
525 
526 	case OP_LUI:
527 		kdbprintf("%s\t%s,0x%X", op_name[i.IType.op],
528 			reg_name[i.IType.rt],
529 			i.IType.imm);
530 		break;
531 
532 	case OP_ADDI:
533 	case OP_ADDIU:
534 		if (i.IType.rs == 0) {
535  			kdbprintf("li\t%s,%D",
536 				reg_name[i.IType.rt],
537 				(short)i.IType.imm);
538 			break;
539 		}
540 		/* FALLTHROUGH */
541 	default:
542 		kdbprintf("%s\t%s,%s,%D", op_name[i.IType.op],
543 			reg_name[i.IType.rt],
544 			reg_name[i.IType.rs],
545 			(short)i.IType.imm);
546 	}
547 	kdbdotinc = 4;
548 }
549 
550 #define MIPS_JR_RA	0x03e00008	/* instruction code for jr ra */
551 
552 /*
553  * Print a stack backtrace.
554  */
555 void
556 kdbstacktrace(printlocals)
557 	int printlocals;
558 {
559 	unsigned pc, sp, ra, va, subr;
560 	int a0, a1, a2, a3;
561 	unsigned instr, mask;
562 	InstFmt i;
563 	int more, stksize;
564 	extern MachKernGenException();
565 	extern MachUserGenException();
566 	extern MachKernIntr();
567 	extern MachUserIntr();
568 	extern setsoftclock();
569 
570 	/* get initial values from the exception frame */
571 	sp = kdbpcb.pcb_regs[SP];
572 	pc = kdbpcb.pcb_regs[PC];
573 	ra = kdbpcb.pcb_regs[RA];
574 	a0 = kdbpcb.pcb_regs[A0];
575 	a1 = kdbpcb.pcb_regs[A1];
576 	a2 = kdbpcb.pcb_regs[A2];
577 	a3 = kdbpcb.pcb_regs[A3];
578 
579 loop:
580 	/* check for current PC in the kernel interrupt handler code */
581 	if (pc >= (unsigned)MachKernIntr && pc < (unsigned)MachUserIntr) {
582 		/* NOTE: the offsets depend on the code in locore.s */
583 		kdbprintf("interupt\n");
584 		a0 = kdbchkget(sp + 36, DSP);
585 		a1 = kdbchkget(sp + 40, DSP);
586 		a2 = kdbchkget(sp + 44, DSP);
587 		a3 = kdbchkget(sp + 48, DSP);
588 		pc = kdbchkget(sp + 20, DSP);
589 		ra = kdbchkget(sp + 92, DSP);
590 		sp = kdbchkget(sp + 100, DSP);
591 	}
592 
593 	/* check for current PC in the exception handler code */
594 	if (pc >= 0x80000000 && pc < (unsigned)setsoftclock) {
595 		ra = 0;
596 		subr = 0;
597 		goto done;
598 	}
599 	/*
600 	 * Find the beginning of the current subroutine by scanning backwards
601 	 * from the current PC for the end of the previous subroutine.
602 	 */
603 	va = pc - sizeof(int);
604 	while ((instr = kdbchkget(va, ISP)) != MIPS_JR_RA)
605 		va -= sizeof(int);
606 	va += 2 * sizeof(int);	/* skip back over branch & delay slot */
607 	/* skip over nulls which might separate .o files */
608 	while ((instr = kdbchkget(va, ISP)) == 0)
609 		va += sizeof(int);
610 	subr = va;
611 
612 	/* scan forwards to find stack size and any saved registers */
613 	stksize = 0;
614 	more = 3;
615 	mask = 0;
616 	for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) {
617 		/* stop if hit our current position */
618 		if (va >= pc)
619 			break;
620 		instr = kdbchkget(va, ISP);
621 		i.word = instr;
622 		switch (i.JType.op) {
623 		case OP_SPECIAL:
624 			switch (i.RType.func) {
625 			case OP_JR:
626 			case OP_JALR:
627 				more = 2; /* stop after next instruction */
628 				break;
629 
630 			case OP_SYSCALL:
631 			case OP_BREAK:
632 				more = 1; /* stop now */
633 			};
634 			break;
635 
636 		case OP_BCOND:
637 		case OP_J:
638 		case OP_JAL:
639 		case OP_BEQ:
640 		case OP_BNE:
641 		case OP_BLEZ:
642 		case OP_BGTZ:
643 			more = 2; /* stop after next instruction */
644 			break;
645 
646 		case OP_COP0:
647 		case OP_COP1:
648 		case OP_COP2:
649 		case OP_COP3:
650 			switch (i.RType.rs) {
651 			case OP_BCx:
652 			case OP_BCy:
653 				more = 2; /* stop after next instruction */
654 			};
655 			break;
656 
657 		case OP_SW:
658 			/* look for saved registers on the stack */
659 			if (i.IType.rs != 29)
660 				break;
661 			/* only restore the first one */
662 			if (mask & (1 << i.IType.rt))
663 				break;
664 			mask |= 1 << i.IType.rt;
665 			switch (i.IType.rt) {
666 			case 4: /* a0 */
667 				a0 = kdbchkget(sp + (short)i.IType.imm, DSP);
668 				break;
669 
670 			case 5: /* a1 */
671 				a1 = kdbchkget(sp + (short)i.IType.imm, DSP);
672 				break;
673 
674 			case 6: /* a2 */
675 				a2 = kdbchkget(sp + (short)i.IType.imm, DSP);
676 				break;
677 
678 			case 7: /* a3 */
679 				a3 = kdbchkget(sp + (short)i.IType.imm, DSP);
680 				break;
681 
682 			case 31: /* ra */
683 				ra = kdbchkget(sp + (short)i.IType.imm, DSP);
684 			}
685 			break;
686 
687 		case OP_ADDI:
688 		case OP_ADDIU:
689 			/* look for stack pointer adjustment */
690 			if (i.IType.rs != 29 && i.IType.rt != 29)
691 				break;
692 			stksize = (short)i.IType.imm;
693 		}
694 	}
695 
696 done:
697 #if 0
698 	kdbpsymoff((long)pc, ISYM, "");
699 #else
700 	kdbprintf("%X+%X ", subr, pc - subr); /* XXX */
701 #endif
702 	kdbprintf("(%X,%X,%X,%X)\n", a0, a1, a2, a3);
703 
704 	if (ra) {
705 		pc = ra;
706 		sp -= stksize;
707 		goto loop;
708 	}
709 }
710 
711 /*
712  * Very simple memory allocator for kdb.
713  */
714 char *
715 kdbmalloc(size)
716 	int size;
717 {
718 	static char buffer[4096];
719 	static char *bufp = buffer;
720 	char *p;
721 
722 	/* round size up to sizeof(int) */
723 	size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
724 	p = bufp;
725 	bufp = p + size;
726 	return (p);
727 }
728 
729 /*
730  * Machine dependent printing '$'.
731  * Return zero if modif character not recognized.
732  */
733 kdbprintmachdep(modif)
734 {
735 	register int i, j;
736 	extern int tlbhi, tlblo;
737 
738 	switch (modif) {
739 	case 'p':
740 	case 'P': /* print TLB entries */
741 		if (kdbadrflg) {
742 			i = kdbadrval;
743 			if (i < 0 || i > VMMACH_NUM_TLB_ENTRIES) {
744 				extern char *kdbBADMOD;
745 
746 				kdberror(kdbBADMOD);
747 				break;
748 			}
749 			if (kdbcntflg == 0)
750 				j = i + 1;
751 			else {
752 				j = i + kdbcntval;
753 				if (j > VMMACH_NUM_TLB_ENTRIES)
754 					j = VMMACH_NUM_TLB_ENTRIES;
755 			}
756 		} else {
757 			i = 0;
758 			j = VMMACH_NUM_TLB_ENTRIES;
759 		}
760 		for (; i < j; i++) {
761 			MachTLBRead(i);
762 			if (modif == 'p' && !(tlblo & PG_V))
763 				continue;
764 			kdbprintf("TLB %2d: hi %8X low %8X\n", i, tlbhi, tlblo);
765 		}
766 		kdbprintf("TLB PID %x\n", MachTLBGetPID());
767 		break;
768 
769 	case 'f': /* find a TLB entry by virtaddr */
770 	case 'F': /* find a TLB entry by physaddr */
771 		j = kdbdot & PG_FRAME;
772 		for (i = 0; i < VMMACH_NUM_TLB_ENTRIES; i++) {
773 			MachTLBRead(i);
774 			if (modif == 'f') {
775 				if ((tlbhi & PG_FRAME) != j)
776 					continue;
777 			} else {
778 				if ((tlblo & PG_FRAME) != j)
779 					continue;
780 			}
781 			kdbprintf("TLB %2d: hi %8X low %8X\n", i, tlbhi, tlblo);
782 		}
783 		break;
784 
785 	default:
786 		return (0);
787 	}
788 	return (1);
789 }
790