xref: /original-bsd/sys/pmax/pmax/kadb.c (revision c41723e9)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * 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	7.2 (Berkeley) 03/14/92
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;
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 &&
582 	    pc < (unsigned)MachUserIntr) {
583 		/* NOTE: the offsets depend on the code in locore.s */
584 		kdbprintf("interupt\n");
585 		a0 = kdbchkget(sp + 36, DSP);
586 		a1 = kdbchkget(sp + 40, DSP);
587 		a2 = kdbchkget(sp + 44, DSP);
588 		a3 = kdbchkget(sp + 48, DSP);
589 		pc = kdbchkget(sp + 20, DSP);
590 		ra = kdbchkget(sp + 92, DSP);
591 		sp = kdbchkget(sp + 100, DSP);
592 	}
593 
594 	/* check for current PC in the exception handler code */
595 	if (pc >= 0x80000000 &&
596 	    pc < (unsigned)setsoftclock) {
597 		ra = 0;
598 		goto done;
599 	}
600 	/*
601 	 * Find the beginning of the current subroutine by scanning backwards
602 	 * from the current PC for the end of the previous subroutine.
603 	 */
604 	va = pc - sizeof(int);
605 	while ((instr = kdbchkget(va, ISP)) != MIPS_JR_RA)
606 		va -= sizeof(int);
607 	va += 2 * sizeof(int);	/* skip back over branch & delay slot */
608 	/* skip over nulls which might separate .o files */
609 	while ((instr = kdbchkget(va, ISP)) == 0)
610 		va += sizeof(int);
611 	subr = va;
612 
613 	/* scan forwards to find stack size and any saved registers */
614 	stksize = 0;
615 	more = 3;
616 	for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) {
617 		instr = kdbchkget(va, ISP);
618 		i.word = instr;
619 		switch (i.JType.op) {
620 		case OP_SPECIAL:
621 			switch (i.RType.func) {
622 			case OP_JR:
623 			case OP_JALR:
624 				more = 2; /* stop after next instruction */
625 				break;
626 
627 			case OP_SYSCALL:
628 			case OP_BREAK:
629 				more = 1; /* stop now */
630 			};
631 			break;
632 
633 		case OP_BCOND:
634 		case OP_J:
635 		case OP_JAL:
636 		case OP_BEQ:
637 		case OP_BNE:
638 		case OP_BLEZ:
639 		case OP_BGTZ:
640 			more = 2; /* stop after next instruction */
641 			break;
642 
643 		case OP_COP0:
644 		case OP_COP1:
645 		case OP_COP2:
646 		case OP_COP3:
647 			switch (i.RType.rs) {
648 			case OP_BCx:
649 			case OP_BCy:
650 				more = 2; /* stop after next instruction */
651 			};
652 			break;
653 
654 		case OP_SW:
655 			/* look for saved registers on the stack */
656 			if (i.IType.rs != 29)
657 				break;
658 			switch (i.IType.rt) {
659 			case 4: /* a0 */
660 				a0 = kdbchkget(sp + (short)i.IType.imm, DSP);
661 				break;
662 
663 			case 5: /* a1 */
664 				a1 = kdbchkget(sp + (short)i.IType.imm, DSP);
665 				break;
666 
667 			case 6: /* a2 */
668 				a2 = kdbchkget(sp + (short)i.IType.imm, DSP);
669 				break;
670 
671 			case 7: /* a3 */
672 				a3 = kdbchkget(sp + (short)i.IType.imm, DSP);
673 				break;
674 
675 			case 31: /* ra */
676 				ra = kdbchkget(sp + (short)i.IType.imm, DSP);
677 			}
678 			break;
679 
680 		case OP_ADDI:
681 		case OP_ADDIU:
682 			/* look for stack pointer adjustment */
683 			if (i.IType.rs != 29 && i.IType.rt != 29)
684 				break;
685 			stksize = (short)i.IType.imm;
686 		}
687 	}
688 
689 done:
690 #if 0
691 	kdbpsymoff((long)pc, ISYM, "");
692 #else
693 	kdbprintf("%X+%X ", subr, pc - subr); /* XXX */
694 #endif
695 	kdbprintf("(%X,%X,%X,%X)\n", a0, a1, a2, a3);
696 
697 	if (ra) {
698 		pc = ra;
699 		sp -= stksize;
700 		goto loop;
701 	}
702 }
703 
704 /*
705  * Very simple memory allocator for kdb.
706  */
707 char *
708 kdbmalloc(size)
709 	int size;
710 {
711 	static char buffer[4096];
712 	static char *bufp = buffer;
713 	char *p;
714 
715 	/* round size up to sizeof(int) */
716 	size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
717 	p = bufp;
718 	bufp = p + size;
719 	return (p);
720 }
721 
722 /*
723  * Machine dependent printing '$'.
724  * Return zero if modif character not recognized.
725  */
726 kdbprintmachdep(modif)
727 {
728 	register int i, j;
729 	extern int tlbhi, tlblo;
730 
731 	switch (modif) {
732 	case 'p':
733 	case 'P': /* print TLB entries */
734 		if (kdbadrflg) {
735 			i = kdbadrval;
736 			if (i < 0 || i > VMMACH_NUM_TLB_ENTRIES) {
737 				extern char *kdbBADMOD;
738 
739 				kdberror(kdbBADMOD);
740 				break;
741 			}
742 			if (kdbcntflg == 0)
743 				j = i + 1;
744 			else {
745 				j = i + kdbcntval;
746 				if (j > VMMACH_NUM_TLB_ENTRIES)
747 					j = VMMACH_NUM_TLB_ENTRIES;
748 			}
749 		} else {
750 			i = 0;
751 			j = VMMACH_NUM_TLB_ENTRIES;
752 		}
753 		for (; i < j; i++) {
754 			MachTLBRead(i);
755 			if (modif == 'p' && !(tlblo & PG_V))
756 				continue;
757 			kdbprintf("TLB %2d: hi %8X low %8X\n", i, tlbhi, tlblo);
758 		}
759 		kdbprintf("TLB PID %x\n", MachTLBGetPID());
760 		break;
761 
762 	case 'f': /* find a TLB entry by virtaddr */
763 	case 'F': /* find a TLB entry by physaddr */
764 		j = kdbdot & PG_FRAME;
765 		for (i = 0; i < VMMACH_NUM_TLB_ENTRIES; i++) {
766 			MachTLBRead(i);
767 			if (modif == 'f') {
768 				if ((tlbhi & PG_FRAME) != j)
769 					continue;
770 			} else {
771 				if ((tlblo & PG_FRAME) != j)
772 					continue;
773 			}
774 			kdbprintf("TLB %2d: hi %8X low %8X\n", i, tlbhi, tlblo);
775 		}
776 		break;
777 
778 	default:
779 		return (0);
780 	}
781 	return (1);
782 }
783