xref: /netbsd/sys/arch/arc/arc/minidebug.c (revision 346d7152)
1*346d7152Ssoda /*	$NetBSD: minidebug.c,v 1.6 2000/01/23 20:09:15 soda Exp $	*/
2*346d7152Ssoda 
3*346d7152Ssoda /*-
4*346d7152Ssoda  * Copyright (c) 1991, 1993
5*346d7152Ssoda  *	The Regents of the University of California.  All rights reserved.
6*346d7152Ssoda  *
7*346d7152Ssoda  * This code is derived from software contributed to Berkeley by
8*346d7152Ssoda  * Ralph Campbell.
9*346d7152Ssoda  *
10*346d7152Ssoda  * Redistribution and use in source and binary forms, with or without
11*346d7152Ssoda  * modification, are permitted provided that the following conditions
12*346d7152Ssoda  * are met:
13*346d7152Ssoda  * 1. Redistributions of source code must retain the above copyright
14*346d7152Ssoda  *    notice, this list of conditions and the following disclaimer.
15*346d7152Ssoda  * 2. Redistributions in binary form must reproduce the above copyright
16*346d7152Ssoda  *    notice, this list of conditions and the following disclaimer in the
17*346d7152Ssoda  *    documentation and/or other materials provided with the distribution.
18*346d7152Ssoda  * 3. All advertising materials mentioning features or use of this software
19*346d7152Ssoda  *    must display the following acknowledgement:
20*346d7152Ssoda  *	This product includes software developed by the University of
21*346d7152Ssoda  *	California, Berkeley and its contributors.
22*346d7152Ssoda  * 4. Neither the name of the University nor the names of its contributors
23*346d7152Ssoda  *    may be used to endorse or promote products derived from this software
24*346d7152Ssoda  *    without specific prior written permission.
25*346d7152Ssoda  *
26*346d7152Ssoda  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27*346d7152Ssoda  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28*346d7152Ssoda  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29*346d7152Ssoda  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30*346d7152Ssoda  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31*346d7152Ssoda  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32*346d7152Ssoda  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33*346d7152Ssoda  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34*346d7152Ssoda  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35*346d7152Ssoda  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36*346d7152Ssoda  * SUCH DAMAGE.
37*346d7152Ssoda  *
38*346d7152Ssoda  *	from: @(#)kadb.c	8.1 (Berkeley) 6/10/93
39*346d7152Ssoda  */
40*346d7152Ssoda 
41*346d7152Ssoda /*
42*346d7152Ssoda  * Define machine dependent primitives for mdb.
43*346d7152Ssoda  */
44*346d7152Ssoda 
45*346d7152Ssoda #include <sys/types.h>
46*346d7152Ssoda #include <machine/pte.h>
47*346d7152Ssoda #include <vm/vm_prot.h>
48*346d7152Ssoda #undef SP
49*346d7152Ssoda #include <machine/machConst.h>
50*346d7152Ssoda #include <machine/reg.h>
51*346d7152Ssoda #include <machine/pcb.h>
52*346d7152Ssoda #include <machine/trap.h>
53*346d7152Ssoda #include <machine/mips_opcode.h>
54*346d7152Ssoda 
55*346d7152Ssoda #ifndef TRUE
56*346d7152Ssoda #define TRUE 1
57*346d7152Ssoda #define FALSE 0
58*346d7152Ssoda #endif
59*346d7152Ssoda 
60*346d7152Ssoda void pica_dump_tlb(int, int);
61*346d7152Ssoda 
62*346d7152Ssoda static char *op_name[64] = {
63*346d7152Ssoda /* 0 */	"spec",	"bcond","j",	"jal",	"beq",	"bne",	"blez",	"bgtz",
64*346d7152Ssoda /* 8 */	"addi",	"addiu","slti",	"sltiu","andi",	"ori",	"xori",	"lui",
65*346d7152Ssoda /*16 */	"cop0",	"cop1",	"cop2",	"cop3",	"beql",	"bnel",	"blezl","bgtzl",
66*346d7152Ssoda /*24 */	"daddi","daddiu","ldl",	"ldr",	"op34",	"op35",	"op36",	"op37",
67*346d7152Ssoda /*32 */	"lb",	"lh",	"lwl",	"lw",	"lbu",	"lhu",	"lwr",	"lwu",
68*346d7152Ssoda /*40 */	"sb",	"sh",	"swl",	"sw",	"sdl",	"sdr",	"swr",	"cache",
69*346d7152Ssoda /*48 */	"ll",	"lwc1",	"lwc2",	"lwc3",	"lld",	"ldc1",	"ldc2",	"ld",
70*346d7152Ssoda /*56 */	"sc",	"swc1",	"swc2",	"swc3",	"scd",	"sdc1",	"sdc2",	"sd"
71*346d7152Ssoda };
72*346d7152Ssoda 
73*346d7152Ssoda static char *spec_name[64] = {
74*346d7152Ssoda /* 0 */	"sll",	"spec01","srl",	"sra",	"sllv",	"spec05","srlv","srav",
75*346d7152Ssoda /* 8 */	"jr",	"jalr",	"spec12","spec13","syscall","break","spec16","sync",
76*346d7152Ssoda /*16 */	"mfhi",	"mthi",	"mflo",	"mtlo",	"dsllv","spec25","dsrlv","dsrav",
77*346d7152Ssoda /*24 */	"mult",	"multu","div",	"divu",	"dmult","dmultu","ddiv","ddivu",
78*346d7152Ssoda /*32 */	"add",	"addu",	"sub",	"subu",	"and",	"or",	"xor",	"nor",
79*346d7152Ssoda /*40 */	"spec50","spec51","slt","sltu",	"dadd","daddu","dsub","dsubu",
80*346d7152Ssoda /*48 */	"tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
81*346d7152Ssoda /*56 */	"dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
82*346d7152Ssoda };
83*346d7152Ssoda 
84*346d7152Ssoda static char *bcond_name[32] = {
85*346d7152Ssoda /* 0 */	"bltz",	"bgez", "bltzl", "bgezl", "?", "?", "?", "?",
86*346d7152Ssoda /* 8 */	"tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
87*346d7152Ssoda /*16 */	"bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
88*346d7152Ssoda /*24 */	"?", "?", "?", "?", "?", "?", "?", "?",
89*346d7152Ssoda };
90*346d7152Ssoda 
91*346d7152Ssoda static char *cop1_name[64] = {
92*346d7152Ssoda /* 0 */	"fadd",	"fsub",	"fmpy",	"fdiv",	"fsqrt","fabs",	"fmov",	"fneg",
93*346d7152Ssoda /* 8 */	"fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
94*346d7152Ssoda /*16 */	"fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
95*346d7152Ssoda /*24 */	"fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
96*346d7152Ssoda /*32 */	"fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
97*346d7152Ssoda /*40 */	"fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
98*346d7152Ssoda /*48 */	"fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
99*346d7152Ssoda 	"fcmp.ole","fcmp.ule",
100*346d7152Ssoda /*56 */	"fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
101*346d7152Ssoda 	"fcmp.le","fcmp.ngt"
102*346d7152Ssoda };
103*346d7152Ssoda 
104*346d7152Ssoda static char *fmt_name[16] = {
105*346d7152Ssoda 	"s",	"d",	"e",	"fmt3",
106*346d7152Ssoda 	"w",	"fmt5",	"fmt6",	"fmt7",
107*346d7152Ssoda 	"fmt8",	"fmt9",	"fmta",	"fmtb",
108*346d7152Ssoda 	"fmtc",	"fmtd",	"fmte",	"fmtf"
109*346d7152Ssoda };
110*346d7152Ssoda 
111*346d7152Ssoda static char *reg_name[32] = {
112*346d7152Ssoda 	"zero",	"at",	"v0",	"v1",	"a0",	"a1",	"a2",	"a3",
113*346d7152Ssoda 	"t0",	"t1",	"t2",	"t3",	"t4",	"t5",	"t6",	"t7",
114*346d7152Ssoda 	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",	"s7",
115*346d7152Ssoda 	"t8",	"t9",	"k0",	"k1",	"gp",	"sp",	"s8",	"ra"
116*346d7152Ssoda };
117*346d7152Ssoda 
118*346d7152Ssoda static char *c0_opname[64] = {
119*346d7152Ssoda 	"c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
120*346d7152Ssoda 	"tlbp",  "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
121*346d7152Ssoda 	"rfe",   "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
122*346d7152Ssoda 	"eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
123*346d7152Ssoda 	"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
124*346d7152Ssoda 	"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
125*346d7152Ssoda 	"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
126*346d7152Ssoda 	"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
127*346d7152Ssoda };
128*346d7152Ssoda 
129*346d7152Ssoda static char *c0_reg[32] = {
130*346d7152Ssoda 	"index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7",
131*346d7152Ssoda 	"badvaddr","count","tlbhi","c0r11","sr","cause","epc",	"prid",
132*346d7152Ssoda 	"config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23",
133*346d7152Ssoda 	"c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31"
134*346d7152Ssoda };
135*346d7152Ssoda 
136*346d7152Ssoda extern char *trap_type[];
137*346d7152Ssoda 
138*346d7152Ssoda struct pcb mdbpcb;
139*346d7152Ssoda int mdbmkfault;
140*346d7152Ssoda 
141*346d7152Ssoda #define MAXBRK 10
142*346d7152Ssoda struct brk {
143*346d7152Ssoda 	int	inst;
144*346d7152Ssoda 	int	addr;
145*346d7152Ssoda } brk_tab[MAXBRK];
146*346d7152Ssoda 
147*346d7152Ssoda /*
148*346d7152Ssoda  * Mini debugger for kernel.
149*346d7152Ssoda  */
150*346d7152Ssoda int gethex(u_int *val, u_int dotval)
151*346d7152Ssoda {
152*346d7152Ssoda 	u_int c;
153*346d7152Ssoda 
154*346d7152Ssoda 	*val = 0;
155*346d7152Ssoda 	while((c = cngetc()) != '\e' && c != '\n') {
156*346d7152Ssoda 		if(c >= '0' && c <= '9') {
157*346d7152Ssoda 			*val = (*val << 4) + c - '0';
158*346d7152Ssoda 			cnputc(c);
159*346d7152Ssoda 		}
160*346d7152Ssoda 		else if(c >= 'a' && c <= 'f') {
161*346d7152Ssoda 			*val = (*val << 4) + c - 'a' + 10;
162*346d7152Ssoda 			cnputc(c);
163*346d7152Ssoda 		}
164*346d7152Ssoda 		else if(c == '\b') {
165*346d7152Ssoda 			*val = *val >> 4;
166*346d7152Ssoda 			printf("\b \b");
167*346d7152Ssoda 		}
168*346d7152Ssoda 		else if(c == ',') {
169*346d7152Ssoda 			cnputc(c);
170*346d7152Ssoda 			return(c);
171*346d7152Ssoda 		}
172*346d7152Ssoda 		else if(c == '.') {
173*346d7152Ssoda 			*val = dotval;;
174*346d7152Ssoda 			cnputc(c);
175*346d7152Ssoda 		}
176*346d7152Ssoda 	}
177*346d7152Ssoda 	return(c);
178*346d7152Ssoda }
179*346d7152Ssoda 
180*346d7152Ssoda void dump(u_int *addr, u_int size)
181*346d7152Ssoda {
182*346d7152Ssoda 	int	cnt;
183*346d7152Ssoda 
184*346d7152Ssoda 	cnt = 0;
185*346d7152Ssoda 
186*346d7152Ssoda 	size = (size + 3) / 4;
187*346d7152Ssoda 	while(size--) {
188*346d7152Ssoda 		if((cnt++ & 3) == 0)
189*346d7152Ssoda 			printf("\n%08x: ",(int)addr);
190*346d7152Ssoda 		printf("%08x ",*addr++);
191*346d7152Ssoda 	}
192*346d7152Ssoda }
193*346d7152Ssoda 
194*346d7152Ssoda void print_regs()
195*346d7152Ssoda {
196*346d7152Ssoda 	printf("\n");
197*346d7152Ssoda 	printf("T0-7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
198*346d7152Ssoda 		mdbpcb.pcb_regs[T0],mdbpcb.pcb_regs[T1],
199*346d7152Ssoda 		mdbpcb.pcb_regs[T2],mdbpcb.pcb_regs[T3],
200*346d7152Ssoda 		mdbpcb.pcb_regs[T4],mdbpcb.pcb_regs[T5],
201*346d7152Ssoda 		mdbpcb.pcb_regs[T6],mdbpcb.pcb_regs[T7]);
202*346d7152Ssoda 	printf("T8-9 %08x %08x     A0-4 %08x %08x %08x %08x\n",
203*346d7152Ssoda 		mdbpcb.pcb_regs[T8],mdbpcb.pcb_regs[T9],
204*346d7152Ssoda 		mdbpcb.pcb_regs[A0],mdbpcb.pcb_regs[A1],
205*346d7152Ssoda 		mdbpcb.pcb_regs[A2],mdbpcb.pcb_regs[A3]);
206*346d7152Ssoda 	printf("S0-7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
207*346d7152Ssoda 		mdbpcb.pcb_regs[S0],mdbpcb.pcb_regs[S1],
208*346d7152Ssoda 		mdbpcb.pcb_regs[S2],mdbpcb.pcb_regs[S3],
209*346d7152Ssoda 		mdbpcb.pcb_regs[S4],mdbpcb.pcb_regs[S5],
210*346d7152Ssoda 		mdbpcb.pcb_regs[S6],mdbpcb.pcb_regs[S7]);
211*346d7152Ssoda 	printf("  S8 %08x     V0-1 %08x %08x       GP %08x       SP %08x\n",
212*346d7152Ssoda 		mdbpcb.pcb_regs[S8],mdbpcb.pcb_regs[V0],
213*346d7152Ssoda 		mdbpcb.pcb_regs[V1],mdbpcb.pcb_regs[GP],
214*346d7152Ssoda 		mdbpcb.pcb_regs[SP]);
215*346d7152Ssoda 	printf("  AT %08x       PC %08x       RA %08x       SR %08x",
216*346d7152Ssoda 		mdbpcb.pcb_regs[AST],mdbpcb.pcb_regs[PC],
217*346d7152Ssoda 		mdbpcb.pcb_regs[RA],mdbpcb.pcb_regs[SR]);
218*346d7152Ssoda }
219*346d7152Ssoda 
220*346d7152Ssoda set_break(va)
221*346d7152Ssoda {
222*346d7152Ssoda 	int i;
223*346d7152Ssoda 
224*346d7152Ssoda 	va = va & ~3;
225*346d7152Ssoda 	for(i = 0; i < MAXBRK; i++) {
226*346d7152Ssoda 		if(brk_tab[i].addr == 0) {
227*346d7152Ssoda 			brk_tab[i].addr = va;
228*346d7152Ssoda 			brk_tab[i].inst = *(u_int *)va;
229*346d7152Ssoda 			return;
230*346d7152Ssoda 		}
231*346d7152Ssoda 	}
232*346d7152Ssoda 	printf(" Break table full!!");
233*346d7152Ssoda }
234*346d7152Ssoda 
235*346d7152Ssoda del_break(va)
236*346d7152Ssoda {
237*346d7152Ssoda 	int i;
238*346d7152Ssoda 
239*346d7152Ssoda 	va = va & ~3;
240*346d7152Ssoda 	for(i = 0; i < MAXBRK; i++) {
241*346d7152Ssoda 		if(brk_tab[i].addr == va) {
242*346d7152Ssoda 			brk_tab[i].addr = 0;
243*346d7152Ssoda 			return;
244*346d7152Ssoda 		}
245*346d7152Ssoda 	}
246*346d7152Ssoda 	printf(" Break to remove not found!!");
247*346d7152Ssoda }
248*346d7152Ssoda 
249*346d7152Ssoda break_insert()
250*346d7152Ssoda {
251*346d7152Ssoda 	int i;
252*346d7152Ssoda 
253*346d7152Ssoda 	for(i = 0; i < MAXBRK; i++) {
254*346d7152Ssoda 		if(brk_tab[i].addr != 0) {
255*346d7152Ssoda 			brk_tab[i].inst = *(u_int *)brk_tab[i].addr;
256*346d7152Ssoda 			*(u_int *)brk_tab[i].addr = MIPS_BREAK_BRKPT;
257*346d7152Ssoda 			MachFlushDCache(brk_tab[i].addr,4);
258*346d7152Ssoda 			MachFlushICache(brk_tab[i].addr,4);
259*346d7152Ssoda 		}
260*346d7152Ssoda 	}
261*346d7152Ssoda }
262*346d7152Ssoda 
263*346d7152Ssoda break_restore()
264*346d7152Ssoda {
265*346d7152Ssoda 	int i;
266*346d7152Ssoda 
267*346d7152Ssoda 	for(i = 0; i < MAXBRK; i++) {
268*346d7152Ssoda 		if(brk_tab[i].addr != 0) {
269*346d7152Ssoda 			*(u_int *)brk_tab[i].addr = brk_tab[i].inst;
270*346d7152Ssoda 			MachFlushDCache(brk_tab[i].addr,4);
271*346d7152Ssoda 			MachFlushICache(brk_tab[i].addr,4);
272*346d7152Ssoda 		}
273*346d7152Ssoda 	}
274*346d7152Ssoda }
275*346d7152Ssoda 
276*346d7152Ssoda break_find(va)
277*346d7152Ssoda {
278*346d7152Ssoda 	int i;
279*346d7152Ssoda 
280*346d7152Ssoda 	for(i = 0; i < MAXBRK; i++) {
281*346d7152Ssoda 		if(brk_tab[i].addr == va) {
282*346d7152Ssoda 			return(i);
283*346d7152Ssoda 		}
284*346d7152Ssoda 	}
285*346d7152Ssoda 	return(-1);
286*346d7152Ssoda }
287*346d7152Ssoda 
288*346d7152Ssoda prt_break()
289*346d7152Ssoda {
290*346d7152Ssoda 	int i;
291*346d7152Ssoda 
292*346d7152Ssoda 	for(i = 0; i < MAXBRK; i++) {
293*346d7152Ssoda 		if(brk_tab[i].addr != 0) {
294*346d7152Ssoda 			printf("\n    %08x\t", brk_tab[i].addr);
295*346d7152Ssoda 			mdbprintins(brk_tab[i].inst, brk_tab[i].addr);
296*346d7152Ssoda 		}
297*346d7152Ssoda 	}
298*346d7152Ssoda }
299*346d7152Ssoda mdb(causeReg, vadr, p, kernelmode)
300*346d7152Ssoda {
301*346d7152Ssoda 	int c;
302*346d7152Ssoda 	int newaddr;
303*346d7152Ssoda 	int size;
304*346d7152Ssoda 	int cause;
305*346d7152Ssoda static int ssandrun;	/* Single step and run flag (when cont at brk) */
306*346d7152Ssoda 
307*346d7152Ssoda 	splhigh();
308*346d7152Ssoda 	cause = (causeReg & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
309*346d7152Ssoda 	newaddr = (int)(mdbpcb.pcb_regs[PC]);
310*346d7152Ssoda 	switch(cause) {
311*346d7152Ssoda 	case T_BREAK:
312*346d7152Ssoda 		if(*(int *)newaddr == MIPS_BREAK_SOVER) {
313*346d7152Ssoda 			break_restore();
314*346d7152Ssoda 			mdbpcb.pcb_regs[PC] += 4;
315*346d7152Ssoda 			printf("\nStop break (panic)\n# ");
316*346d7152Ssoda 			printf("    %08x\t",newaddr);
317*346d7152Ssoda 			mdbprintins(*(int *)newaddr, newaddr);
318*346d7152Ssoda 			printf("\n# ");
319*346d7152Ssoda 			break;
320*346d7152Ssoda 		}
321*346d7152Ssoda 		if(*(int *)newaddr == MIPS_BREAK_BRKPT) {
322*346d7152Ssoda 			break_restore();
323*346d7152Ssoda 			printf("\rBRK %08x\t",newaddr);
324*346d7152Ssoda 			if(mdbprintins(*(int *)newaddr, newaddr)) {
325*346d7152Ssoda 				newaddr += 4;
326*346d7152Ssoda 				printf("\n    %08x\t",newaddr);
327*346d7152Ssoda 				mdbprintins(*(int *)newaddr, newaddr);
328*346d7152Ssoda 			}
329*346d7152Ssoda 			printf("\n# ");
330*346d7152Ssoda 			break;
331*346d7152Ssoda 		}
332*346d7152Ssoda 		if(mdbclrsstep(causeReg)) {
333*346d7152Ssoda 			if(ssandrun) { /* Step over bp before free run */
334*346d7152Ssoda 				ssandrun = 0;
335*346d7152Ssoda 				break_insert();
336*346d7152Ssoda 				return(TRUE);
337*346d7152Ssoda 			}
338*346d7152Ssoda 			printf("\r    %08x\t",newaddr);
339*346d7152Ssoda 			if(mdbprintins(*(int *)newaddr, newaddr)) {
340*346d7152Ssoda 				newaddr += 4;
341*346d7152Ssoda 				printf("\n    %08x\t",newaddr);
342*346d7152Ssoda 				mdbprintins(*(int *)newaddr, newaddr);
343*346d7152Ssoda 			}
344*346d7152Ssoda 			printf("\n# ");
345*346d7152Ssoda 		}
346*346d7152Ssoda 		break;
347*346d7152Ssoda 
348*346d7152Ssoda 	default:
349*346d7152Ssoda 		printf("\n-- %s --\n# ",trap_type[cause]);
350*346d7152Ssoda 	}
351*346d7152Ssoda 	ssandrun = 0;
352*346d7152Ssoda 	break_restore();
353*346d7152Ssoda 
354*346d7152Ssoda 	while(c = cngetc()) {
355*346d7152Ssoda 		switch(c) {
356*346d7152Ssoda 		case 'T':
357*346d7152Ssoda 			trapDump("Debugger");
358*346d7152Ssoda 			break;
359*346d7152Ssoda 		case 'b':
360*346d7152Ssoda 			printf("break-");
361*346d7152Ssoda 			c = cngetc();
362*346d7152Ssoda 			switch(c) {
363*346d7152Ssoda 			case 's':
364*346d7152Ssoda 				printf("set at ");
365*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
366*346d7152Ssoda 				if(c != '\e') {
367*346d7152Ssoda 					set_break(newaddr);
368*346d7152Ssoda 				}
369*346d7152Ssoda 				break;
370*346d7152Ssoda 
371*346d7152Ssoda 			case 'd':
372*346d7152Ssoda 				printf("delete at ");
373*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
374*346d7152Ssoda 				if(c != '\e') {
375*346d7152Ssoda 					del_break(newaddr);
376*346d7152Ssoda 				}
377*346d7152Ssoda 				break;
378*346d7152Ssoda 
379*346d7152Ssoda 			case 'p':
380*346d7152Ssoda 				printf("print");
381*346d7152Ssoda 				prt_break();
382*346d7152Ssoda 				break;
383*346d7152Ssoda 			}
384*346d7152Ssoda 			break;
385*346d7152Ssoda 
386*346d7152Ssoda 		case 'r':
387*346d7152Ssoda 			print_regs();
388*346d7152Ssoda 			break;
389*346d7152Ssoda 
390*346d7152Ssoda 		case 'I':
391*346d7152Ssoda 			printf("Instruction at ");
392*346d7152Ssoda 			c = gethex(&newaddr, newaddr);
393*346d7152Ssoda 			while(c != '\e') {
394*346d7152Ssoda 				printf("\n    %08x\t",newaddr);
395*346d7152Ssoda 				mdbprintins(*(int *)newaddr, newaddr);
396*346d7152Ssoda 				newaddr += 4;
397*346d7152Ssoda 				c = cngetc();
398*346d7152Ssoda 			}
399*346d7152Ssoda 			break;
400*346d7152Ssoda 
401*346d7152Ssoda 		case 'c':
402*346d7152Ssoda 			printf("continue");
403*346d7152Ssoda 			if(break_find((int)(mdbpcb.pcb_regs[PC])) >= 0) {
404*346d7152Ssoda 				ssandrun = 1;
405*346d7152Ssoda 				mdbsetsstep();
406*346d7152Ssoda 			}
407*346d7152Ssoda 			else {
408*346d7152Ssoda 				break_insert();
409*346d7152Ssoda 			}
410*346d7152Ssoda 			return(TRUE);
411*346d7152Ssoda 
412*346d7152Ssoda 		case 's':
413*346d7152Ssoda 			set_break(mdbpcb.pcb_regs[PC] + 8);
414*346d7152Ssoda 			return(TRUE);
415*346d7152Ssoda 		case ' ':
416*346d7152Ssoda 			mdbsetsstep();
417*346d7152Ssoda 			return(TRUE);
418*346d7152Ssoda 
419*346d7152Ssoda 		case 'd':
420*346d7152Ssoda 			printf("dump ");
421*346d7152Ssoda 			c = gethex(&newaddr, newaddr);
422*346d7152Ssoda 			if(c == ',') {
423*346d7152Ssoda 				c = gethex(&size,256);
424*346d7152Ssoda 			}
425*346d7152Ssoda 			else {
426*346d7152Ssoda 				size = 16;
427*346d7152Ssoda 			}
428*346d7152Ssoda 			if(c == '\n' && newaddr != 0) {
429*346d7152Ssoda 				dump((u_int *)newaddr, size);
430*346d7152Ssoda 				newaddr += size;
431*346d7152Ssoda 			}
432*346d7152Ssoda 			break;
433*346d7152Ssoda 
434*346d7152Ssoda 		case 'm':
435*346d7152Ssoda 			printf("mod ");
436*346d7152Ssoda 			c = gethex(&newaddr, newaddr);
437*346d7152Ssoda 			while(c == ',') {
438*346d7152Ssoda 				c = gethex(&size, 0);
439*346d7152Ssoda 				if(c != '\e')
440*346d7152Ssoda 					*((u_int *)newaddr)++ = size;
441*346d7152Ssoda 			}
442*346d7152Ssoda 			break;
443*346d7152Ssoda 
444*346d7152Ssoda 		case 'i':
445*346d7152Ssoda 			printf("in-");
446*346d7152Ssoda 			c = cngetc();
447*346d7152Ssoda 			switch(c) {
448*346d7152Ssoda 			case 'b':
449*346d7152Ssoda 				printf("byte ");
450*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
451*346d7152Ssoda 				if(c == '\n') {
452*346d7152Ssoda 					printf("= %02x",
453*346d7152Ssoda 						*(u_char *)newaddr);
454*346d7152Ssoda 				}
455*346d7152Ssoda 				break;
456*346d7152Ssoda 			case 'h':
457*346d7152Ssoda 				printf("halfword ");
458*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
459*346d7152Ssoda 				if(c == '\n') {
460*346d7152Ssoda 					printf("= %04x",
461*346d7152Ssoda 						*(u_short *)newaddr);
462*346d7152Ssoda 				}
463*346d7152Ssoda 				break;
464*346d7152Ssoda 			case 'w':
465*346d7152Ssoda 				printf("word ");
466*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
467*346d7152Ssoda 				if(c == '\n') {
468*346d7152Ssoda 					printf("= %08x",
469*346d7152Ssoda 						*(u_int *)newaddr);
470*346d7152Ssoda 				}
471*346d7152Ssoda 				break;
472*346d7152Ssoda 			}
473*346d7152Ssoda 			break;
474*346d7152Ssoda 
475*346d7152Ssoda 		case 'o':
476*346d7152Ssoda 			printf("out-");
477*346d7152Ssoda 			c = cngetc();
478*346d7152Ssoda 			switch(c) {
479*346d7152Ssoda 			case 'b':
480*346d7152Ssoda 				printf("byte ");
481*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
482*346d7152Ssoda 				if(c == ',') {
483*346d7152Ssoda 					c = gethex(&size, 0);
484*346d7152Ssoda 					if(c == '\n') {
485*346d7152Ssoda 						*(u_char *)newaddr = size;
486*346d7152Ssoda 					}
487*346d7152Ssoda 				}
488*346d7152Ssoda 				break;
489*346d7152Ssoda 			case 'h':
490*346d7152Ssoda 				printf("halfword ");
491*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
492*346d7152Ssoda 				if(c == ',') {
493*346d7152Ssoda 					c = gethex(&size, 0);
494*346d7152Ssoda 					if(c == '\n') {
495*346d7152Ssoda 						*(u_short *)newaddr = size;
496*346d7152Ssoda 					}
497*346d7152Ssoda 				}
498*346d7152Ssoda 				break;
499*346d7152Ssoda 			case 'w':
500*346d7152Ssoda 				printf("word ");
501*346d7152Ssoda 				c = gethex(&newaddr, newaddr);
502*346d7152Ssoda 				if(c == ',') {
503*346d7152Ssoda 					c = gethex(&size, 0);
504*346d7152Ssoda 					if(c == '\n') {
505*346d7152Ssoda 						*(u_int *)newaddr = size;
506*346d7152Ssoda 					}
507*346d7152Ssoda 				}
508*346d7152Ssoda 				break;
509*346d7152Ssoda 			}
510*346d7152Ssoda 			break;
511*346d7152Ssoda 
512*346d7152Ssoda 		case 't':
513*346d7152Ssoda 			printf("tlb-dump\n");
514*346d7152Ssoda 			pica_dump_tlb(0,23);
515*346d7152Ssoda 			(void)cngetc();
516*346d7152Ssoda 			pica_dump_tlb(24,47);
517*346d7152Ssoda 			break;
518*346d7152Ssoda 
519*346d7152Ssoda 		case 'f':
520*346d7152Ssoda 			printf("flush-");
521*346d7152Ssoda 			c = cngetc();
522*346d7152Ssoda 			switch(c) {
523*346d7152Ssoda 			case 't':
524*346d7152Ssoda 				printf("tlb");
525*346d7152Ssoda 				MachTLBFlush();
526*346d7152Ssoda 				break;
527*346d7152Ssoda 
528*346d7152Ssoda 			case 'c':
529*346d7152Ssoda 				printf("cache");
530*346d7152Ssoda 				MachFlushCache();
531*346d7152Ssoda 				break;
532*346d7152Ssoda 			}
533*346d7152Ssoda 			break;
534*346d7152Ssoda 
535*346d7152Ssoda 		default:
536*346d7152Ssoda 			cnputc('\a');
537*346d7152Ssoda 			break;
538*346d7152Ssoda 		}
539*346d7152Ssoda 		printf("\n# ");
540*346d7152Ssoda 	}
541*346d7152Ssoda }
542*346d7152Ssoda 
543*346d7152Ssoda u_int mdb_ss_addr;
544*346d7152Ssoda u_int mdb_ss_instr;
545*346d7152Ssoda 
546*346d7152Ssoda mdbsetsstep()
547*346d7152Ssoda {
548*346d7152Ssoda 	register u_int va;
549*346d7152Ssoda 	register int *locr0 = mdbpcb.pcb_regs;
550*346d7152Ssoda 	int i;
551*346d7152Ssoda 
552*346d7152Ssoda 	/* compute next address after current location */
553*346d7152Ssoda 	if(mdbpeek(locr0[PC]) != 0) {
554*346d7152Ssoda 		va = MachEmulateBranch(locr0, locr0[PC], 0, mdbpeek(locr0[PC]));
555*346d7152Ssoda 	}
556*346d7152Ssoda 	else {
557*346d7152Ssoda 		va = locr0[PC] + 4;
558*346d7152Ssoda 	}
559*346d7152Ssoda 	if (mdb_ss_addr) {
560*346d7152Ssoda 		printf("mdbsetsstep: breakpoint already set at %x (va %x)\n",
561*346d7152Ssoda 			mdb_ss_addr, va);
562*346d7152Ssoda 		return;
563*346d7152Ssoda 	}
564*346d7152Ssoda 	mdb_ss_addr = va;
565*346d7152Ssoda 
566*346d7152Ssoda 	if ((int)va < 0) {
567*346d7152Ssoda 		/* kernel address */
568*346d7152Ssoda 		mdb_ss_instr = mdbpeek(va);
569*346d7152Ssoda 		mdbpoke((caddr_t)va, MIPS_BREAK_SSTEP);
570*346d7152Ssoda 		MachFlushDCache(va,4);
571*346d7152Ssoda 		MachFlushICache(va,4);
572*346d7152Ssoda 		return;
573*346d7152Ssoda 	}
574*346d7152Ssoda }
575*346d7152Ssoda 
576*346d7152Ssoda mdbclrsstep(cr)
577*346d7152Ssoda 	int cr;
578*346d7152Ssoda {
579*346d7152Ssoda 	register u_int pc, va;
580*346d7152Ssoda 	u_int instr;
581*346d7152Ssoda 
582*346d7152Ssoda 	/* fix pc if break instruction is in the delay slot */
583*346d7152Ssoda 	pc = mdbpcb.pcb_regs[PC];
584*346d7152Ssoda 	if (cr < 0)
585*346d7152Ssoda 		pc += 4;
586*346d7152Ssoda 
587*346d7152Ssoda 	/* check to be sure its the one we are expecting */
588*346d7152Ssoda 	va = mdb_ss_addr;
589*346d7152Ssoda 	if (!va || va != pc)
590*346d7152Ssoda 		return(FALSE);
591*346d7152Ssoda 
592*346d7152Ssoda 	/* read break instruction */
593*346d7152Ssoda 	instr = mdbpeek(va);
594*346d7152Ssoda 	if (instr != MIPS_BREAK_SSTEP)
595*346d7152Ssoda 		return(FALSE);
596*346d7152Ssoda 
597*346d7152Ssoda 	if ((int)va < 0) {
598*346d7152Ssoda 		/* kernel address */
599*346d7152Ssoda 		mdbpoke((caddr_t)va, mdb_ss_instr);
600*346d7152Ssoda 		MachFlushDCache(va,4);
601*346d7152Ssoda 		MachFlushICache(va,4);
602*346d7152Ssoda 		mdb_ss_addr = 0;
603*346d7152Ssoda 		return(TRUE);
604*346d7152Ssoda 	}
605*346d7152Ssoda 
606*346d7152Ssoda 	printf("can't clear break at %x\n", va);
607*346d7152Ssoda 	mdb_ss_addr = 0;
608*346d7152Ssoda 	return(FALSE);
609*346d7152Ssoda }
610*346d7152Ssoda 
611*346d7152Ssoda void
612*346d7152Ssoda mdbreadc(lp)
613*346d7152Ssoda 	char *lp;
614*346d7152Ssoda {
615*346d7152Ssoda 	int c;
616*346d7152Ssoda 
617*346d7152Ssoda 	c = cngetc();
618*346d7152Ssoda 	if (c == '\r')
619*346d7152Ssoda 		c = '\n';
620*346d7152Ssoda 	*lp = c;
621*346d7152Ssoda }
622*346d7152Ssoda 
623*346d7152Ssoda void
624*346d7152Ssoda mdbwrite(lp, len)
625*346d7152Ssoda 	char *lp;
626*346d7152Ssoda 	int len;
627*346d7152Ssoda {
628*346d7152Ssoda 	while (len-- > 0)
629*346d7152Ssoda 		cnputc(*lp++);
630*346d7152Ssoda }
631*346d7152Ssoda 
632*346d7152Ssoda /* ARGSUSED */
633*346d7152Ssoda mdbprintins(ins, mdbdot)
634*346d7152Ssoda {
635*346d7152Ssoda 	InstFmt i;
636*346d7152Ssoda 	int delay = 0;
637*346d7152Ssoda 
638*346d7152Ssoda 	i.word = ins;
639*346d7152Ssoda 
640*346d7152Ssoda 	switch (i.JType.op) {
641*346d7152Ssoda 	case OP_SPECIAL:
642*346d7152Ssoda 		if (i.word == 0) {
643*346d7152Ssoda 			printf("nop");
644*346d7152Ssoda 			break;
645*346d7152Ssoda 		}
646*346d7152Ssoda 		if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
647*346d7152Ssoda 			printf("move\t%s,%s",
648*346d7152Ssoda 				reg_name[i.RType.rd],
649*346d7152Ssoda 				reg_name[i.RType.rs]);
650*346d7152Ssoda 			break;
651*346d7152Ssoda 		}
652*346d7152Ssoda 		printf("%s", spec_name[i.RType.func]);
653*346d7152Ssoda 		switch (i.RType.func) {
654*346d7152Ssoda 		case OP_SLL:
655*346d7152Ssoda 		case OP_SRL:
656*346d7152Ssoda 		case OP_SRA:
657*346d7152Ssoda 		case OP_DSLL:
658*346d7152Ssoda 		case OP_DSRL:
659*346d7152Ssoda 		case OP_DSRA:
660*346d7152Ssoda 		case OP_DSLL32:
661*346d7152Ssoda 		case OP_DSRL32:
662*346d7152Ssoda 		case OP_DSRA32:
663*346d7152Ssoda 			printf("\t%s,%s,%d",
664*346d7152Ssoda 				reg_name[i.RType.rd],
665*346d7152Ssoda 				reg_name[i.RType.rt],
666*346d7152Ssoda 				i.RType.shamt);
667*346d7152Ssoda 			break;
668*346d7152Ssoda 
669*346d7152Ssoda 		case OP_SLLV:
670*346d7152Ssoda 		case OP_SRLV:
671*346d7152Ssoda 		case OP_SRAV:
672*346d7152Ssoda 		case OP_DSLLV:
673*346d7152Ssoda 		case OP_DSRLV:
674*346d7152Ssoda 		case OP_DSRAV:
675*346d7152Ssoda 			printf("\t%s,%s,%s",
676*346d7152Ssoda 				reg_name[i.RType.rd],
677*346d7152Ssoda 				reg_name[i.RType.rt],
678*346d7152Ssoda 				reg_name[i.RType.rs]);
679*346d7152Ssoda 			break;
680*346d7152Ssoda 
681*346d7152Ssoda 		case OP_MFHI:
682*346d7152Ssoda 		case OP_MFLO:
683*346d7152Ssoda 			printf("\t%s", reg_name[i.RType.rd]);
684*346d7152Ssoda 			break;
685*346d7152Ssoda 
686*346d7152Ssoda 		case OP_JR:
687*346d7152Ssoda 		case OP_JALR:
688*346d7152Ssoda 			delay = 1;
689*346d7152Ssoda 			/* FALLTHROUGH */
690*346d7152Ssoda 		case OP_MTLO:
691*346d7152Ssoda 		case OP_MTHI:
692*346d7152Ssoda 			printf("\t%s", reg_name[i.RType.rs]);
693*346d7152Ssoda 			break;
694*346d7152Ssoda 
695*346d7152Ssoda 		case OP_MULT:
696*346d7152Ssoda 		case OP_MULTU:
697*346d7152Ssoda 		case OP_DMULT:
698*346d7152Ssoda 		case OP_DMULTU:
699*346d7152Ssoda 		case OP_DIV:
700*346d7152Ssoda 		case OP_DIVU:
701*346d7152Ssoda 		case OP_DDIV:
702*346d7152Ssoda 		case OP_DDIVU:
703*346d7152Ssoda 			printf("\t%s,%s",
704*346d7152Ssoda 				reg_name[i.RType.rs],
705*346d7152Ssoda 				reg_name[i.RType.rt]);
706*346d7152Ssoda 			break;
707*346d7152Ssoda 
708*346d7152Ssoda 		case OP_SYSCALL:
709*346d7152Ssoda 		case OP_SYNC:
710*346d7152Ssoda 			break;
711*346d7152Ssoda 
712*346d7152Ssoda 		case OP_BREAK:
713*346d7152Ssoda 			printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
714*346d7152Ssoda 			break;
715*346d7152Ssoda 
716*346d7152Ssoda 		default:
717*346d7152Ssoda 			printf("\t%s,%s,%s",
718*346d7152Ssoda 				reg_name[i.RType.rd],
719*346d7152Ssoda 				reg_name[i.RType.rs],
720*346d7152Ssoda 				reg_name[i.RType.rt]);
721*346d7152Ssoda 		};
722*346d7152Ssoda 		break;
723*346d7152Ssoda 
724*346d7152Ssoda 	case OP_BCOND:
725*346d7152Ssoda 		printf("%s\t%s,", bcond_name[i.IType.rt],
726*346d7152Ssoda 			reg_name[i.IType.rs]);
727*346d7152Ssoda 		goto pr_displ;
728*346d7152Ssoda 
729*346d7152Ssoda 	case OP_BLEZ:
730*346d7152Ssoda 	case OP_BLEZL:
731*346d7152Ssoda 	case OP_BGTZ:
732*346d7152Ssoda 	case OP_BGTZL:
733*346d7152Ssoda 		printf("%s\t%s,", op_name[i.IType.op],
734*346d7152Ssoda 			reg_name[i.IType.rs]);
735*346d7152Ssoda 		goto pr_displ;
736*346d7152Ssoda 
737*346d7152Ssoda 	case OP_BEQ:
738*346d7152Ssoda 	case OP_BEQL:
739*346d7152Ssoda 		if (i.IType.rs == 0 && i.IType.rt == 0) {
740*346d7152Ssoda 			printf("b\t");
741*346d7152Ssoda 			goto pr_displ;
742*346d7152Ssoda 		}
743*346d7152Ssoda 		/* FALLTHROUGH */
744*346d7152Ssoda 	case OP_BNE:
745*346d7152Ssoda 	case OP_BNEL:
746*346d7152Ssoda 		printf("%s\t%s,%s,", op_name[i.IType.op],
747*346d7152Ssoda 			reg_name[i.IType.rs],
748*346d7152Ssoda 			reg_name[i.IType.rt]);
749*346d7152Ssoda 	pr_displ:
750*346d7152Ssoda 		delay = 1;
751*346d7152Ssoda 		printf("0x%08x", mdbdot + 4 + ((short)i.IType.imm << 2));
752*346d7152Ssoda 		break;
753*346d7152Ssoda 
754*346d7152Ssoda 	case OP_COP0:
755*346d7152Ssoda 		switch (i.RType.rs) {
756*346d7152Ssoda 		case OP_BCx:
757*346d7152Ssoda 		case OP_BCy:
758*346d7152Ssoda 			printf("bc0%c\t",
759*346d7152Ssoda 				"ft"[i.RType.rt & COPz_BC_TF_MASK]);
760*346d7152Ssoda 			goto pr_displ;
761*346d7152Ssoda 
762*346d7152Ssoda 		case OP_MT:
763*346d7152Ssoda 			printf("mtc0\t%s,%s",
764*346d7152Ssoda 				reg_name[i.RType.rt],
765*346d7152Ssoda 				c0_reg[i.RType.rd]);
766*346d7152Ssoda 			break;
767*346d7152Ssoda 
768*346d7152Ssoda 		case OP_DMT:
769*346d7152Ssoda 			printf("dmtc0\t%s,%s",
770*346d7152Ssoda 				reg_name[i.RType.rt],
771*346d7152Ssoda 				c0_reg[i.RType.rd]);
772*346d7152Ssoda 			break;
773*346d7152Ssoda 
774*346d7152Ssoda 		case OP_MF:
775*346d7152Ssoda 			printf("mfc0\t%s,%s",
776*346d7152Ssoda 				reg_name[i.RType.rt],
777*346d7152Ssoda 				c0_reg[i.RType.rd]);
778*346d7152Ssoda 			break;
779*346d7152Ssoda 
780*346d7152Ssoda 		case OP_DMF:
781*346d7152Ssoda 			printf("dmfc0\t%s,%s",
782*346d7152Ssoda 				reg_name[i.RType.rt],
783*346d7152Ssoda 				c0_reg[i.RType.rd]);
784*346d7152Ssoda 			break;
785*346d7152Ssoda 
786*346d7152Ssoda 		default:
787*346d7152Ssoda 			printf("%s", c0_opname[i.FRType.func]);
788*346d7152Ssoda 		};
789*346d7152Ssoda 		break;
790*346d7152Ssoda 
791*346d7152Ssoda 	case OP_COP1:
792*346d7152Ssoda 		switch (i.RType.rs) {
793*346d7152Ssoda 		case OP_BCx:
794*346d7152Ssoda 		case OP_BCy:
795*346d7152Ssoda 			printf("bc1%c\t",
796*346d7152Ssoda 				"ft"[i.RType.rt & COPz_BC_TF_MASK]);
797*346d7152Ssoda 			goto pr_displ;
798*346d7152Ssoda 
799*346d7152Ssoda 		case OP_MT:
800*346d7152Ssoda 			printf("mtc1\t%s,f%d",
801*346d7152Ssoda 				reg_name[i.RType.rt],
802*346d7152Ssoda 				i.RType.rd);
803*346d7152Ssoda 			break;
804*346d7152Ssoda 
805*346d7152Ssoda 		case OP_MF:
806*346d7152Ssoda 			printf("mfc1\t%s,f%d",
807*346d7152Ssoda 				reg_name[i.RType.rt],
808*346d7152Ssoda 				i.RType.rd);
809*346d7152Ssoda 			break;
810*346d7152Ssoda 
811*346d7152Ssoda 		case OP_CT:
812*346d7152Ssoda 			printf("ctc1\t%s,f%d",
813*346d7152Ssoda 				reg_name[i.RType.rt],
814*346d7152Ssoda 				i.RType.rd);
815*346d7152Ssoda 			break;
816*346d7152Ssoda 
817*346d7152Ssoda 		case OP_CF:
818*346d7152Ssoda 			printf("cfc1\t%s,f%d",
819*346d7152Ssoda 				reg_name[i.RType.rt],
820*346d7152Ssoda 				i.RType.rd);
821*346d7152Ssoda 			break;
822*346d7152Ssoda 
823*346d7152Ssoda 		default:
824*346d7152Ssoda 			printf("%s.%s\tf%d,f%d,f%d",
825*346d7152Ssoda 				cop1_name[i.FRType.func],
826*346d7152Ssoda 				fmt_name[i.FRType.fmt],
827*346d7152Ssoda 				i.FRType.fd, i.FRType.fs, i.FRType.ft);
828*346d7152Ssoda 		};
829*346d7152Ssoda 		break;
830*346d7152Ssoda 
831*346d7152Ssoda 	case OP_J:
832*346d7152Ssoda 	case OP_JAL:
833*346d7152Ssoda 		printf("%s\t", op_name[i.JType.op]);
834*346d7152Ssoda 		printf("0x%8x",(mdbdot & 0xF0000000) | (i.JType.target << 2));
835*346d7152Ssoda 		delay = 1;
836*346d7152Ssoda 		break;
837*346d7152Ssoda 
838*346d7152Ssoda 	case OP_LWC1:
839*346d7152Ssoda 	case OP_SWC1:
840*346d7152Ssoda 		printf("%s\tf%d,", op_name[i.IType.op],
841*346d7152Ssoda 			i.IType.rt);
842*346d7152Ssoda 		goto loadstore;
843*346d7152Ssoda 
844*346d7152Ssoda 	case OP_LB:
845*346d7152Ssoda 	case OP_LH:
846*346d7152Ssoda 	case OP_LW:
847*346d7152Ssoda 	case OP_LD:
848*346d7152Ssoda 	case OP_LBU:
849*346d7152Ssoda 	case OP_LHU:
850*346d7152Ssoda 	case OP_LWU:
851*346d7152Ssoda 	case OP_SB:
852*346d7152Ssoda 	case OP_SH:
853*346d7152Ssoda 	case OP_SW:
854*346d7152Ssoda 	case OP_SD:
855*346d7152Ssoda 		printf("%s\t%s,", op_name[i.IType.op],
856*346d7152Ssoda 			reg_name[i.IType.rt]);
857*346d7152Ssoda 	loadstore:
858*346d7152Ssoda 		printf("%d(%s)", (short)i.IType.imm,
859*346d7152Ssoda 			reg_name[i.IType.rs]);
860*346d7152Ssoda 		break;
861*346d7152Ssoda 
862*346d7152Ssoda 	case OP_ORI:
863*346d7152Ssoda 	case OP_XORI:
864*346d7152Ssoda 		if (i.IType.rs == 0) {
865*346d7152Ssoda 			printf("li\t%s,0x%x",
866*346d7152Ssoda 				reg_name[i.IType.rt],
867*346d7152Ssoda 				i.IType.imm);
868*346d7152Ssoda 			break;
869*346d7152Ssoda 		}
870*346d7152Ssoda 		/* FALLTHROUGH */
871*346d7152Ssoda 	case OP_ANDI:
872*346d7152Ssoda 		printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
873*346d7152Ssoda 			reg_name[i.IType.rt],
874*346d7152Ssoda 			reg_name[i.IType.rs],
875*346d7152Ssoda 			i.IType.imm);
876*346d7152Ssoda 		break;
877*346d7152Ssoda 
878*346d7152Ssoda 	case OP_LUI:
879*346d7152Ssoda 		printf("%s\t%s,0x%x", op_name[i.IType.op],
880*346d7152Ssoda 			reg_name[i.IType.rt],
881*346d7152Ssoda 			i.IType.imm);
882*346d7152Ssoda 		break;
883*346d7152Ssoda 
884*346d7152Ssoda 	case OP_ADDI:
885*346d7152Ssoda 	case OP_DADDI:
886*346d7152Ssoda 	case OP_ADDIU:
887*346d7152Ssoda 	case OP_DADDIU:
888*346d7152Ssoda 		if (i.IType.rs == 0) {
889*346d7152Ssoda  			printf("li\t%s,%d",
890*346d7152Ssoda 				reg_name[i.IType.rt],
891*346d7152Ssoda 				(short)i.IType.imm);
892*346d7152Ssoda 			break;
893*346d7152Ssoda 		}
894*346d7152Ssoda 		/* FALLTHROUGH */
895*346d7152Ssoda 	default:
896*346d7152Ssoda 		printf("%s\t%s,%s,%d", op_name[i.IType.op],
897*346d7152Ssoda 			reg_name[i.IType.rt],
898*346d7152Ssoda 			reg_name[i.IType.rs],
899*346d7152Ssoda 			(short)i.IType.imm);
900*346d7152Ssoda 	}
901*346d7152Ssoda 	return(delay);
902*346d7152Ssoda }
903*346d7152Ssoda 
904*346d7152Ssoda #define MIPS_JR_RA	0x03e00008	/* instruction code for jr ra */
905*346d7152Ssoda 
906*346d7152Ssoda #if 0
907*346d7152Ssoda /*
908*346d7152Ssoda  * Print a stack backtrace.
909*346d7152Ssoda  */
910*346d7152Ssoda void
911*346d7152Ssoda mdbstacktrace(printlocals)
912*346d7152Ssoda 	int printlocals;
913*346d7152Ssoda {
914*346d7152Ssoda 	u_int pc, sp, ra, va, subr;
915*346d7152Ssoda 	int a0, a1, a2, a3;
916*346d7152Ssoda 	u_int instr, mask;
917*346d7152Ssoda 	InstFmt i;
918*346d7152Ssoda 	int more, stksize;
919*346d7152Ssoda 	extern MachKernGenException();
920*346d7152Ssoda 	extern MachUserGenException();
921*346d7152Ssoda 	extern MachKernIntr();
922*346d7152Ssoda 	extern MachUserIntr();
923*346d7152Ssoda 	extern setsoftclock();
924*346d7152Ssoda 
925*346d7152Ssoda 	/* get initial values from the exception frame */
926*346d7152Ssoda 	sp = mdbpcb.pcb_regs[SP];
927*346d7152Ssoda 	pc = mdbpcb.pcb_regs[PC];
928*346d7152Ssoda 	ra = mdbpcb.pcb_regs[RA];
929*346d7152Ssoda 	a0 = mdbpcb.pcb_regs[A0];
930*346d7152Ssoda 	a1 = mdbpcb.pcb_regs[A1];
931*346d7152Ssoda 	a2 = mdbpcb.pcb_regs[A2];
932*346d7152Ssoda 	a3 = mdbpcb.pcb_regs[A3];
933*346d7152Ssoda 
934*346d7152Ssoda loop:
935*346d7152Ssoda 	/* check for current PC in the kernel interrupt handler code */
936*346d7152Ssoda 	if (pc >= (u_int)MachKernIntr && pc < (u_int)MachUserIntr) {
937*346d7152Ssoda 		/* NOTE: the offsets depend on the code in locore.s */
938*346d7152Ssoda 		printf("interupt\n");
939*346d7152Ssoda 		a0 = mdbchkget(sp + 36, DSP);
940*346d7152Ssoda 		a1 = mdbchkget(sp + 40, DSP);
941*346d7152Ssoda 		a2 = mdbchkget(sp + 44, DSP);
942*346d7152Ssoda 		a3 = mdbchkget(sp + 48, DSP);
943*346d7152Ssoda 		pc = mdbchkget(sp + 20, DSP);
944*346d7152Ssoda 		ra = mdbchkget(sp + 92, DSP);
945*346d7152Ssoda 		sp = mdbchkget(sp + 100, DSP);
946*346d7152Ssoda 	}
947*346d7152Ssoda 
948*346d7152Ssoda 	/* check for current PC in the exception handler code */
949*346d7152Ssoda 	if (pc >= 0x80000000 && pc < (u_int)setsoftclock) {
950*346d7152Ssoda 		ra = 0;
951*346d7152Ssoda 		subr = 0;
952*346d7152Ssoda 		goto done;
953*346d7152Ssoda 	}
954*346d7152Ssoda 	/*
955*346d7152Ssoda 	 * Find the beginning of the current subroutine by scanning backwards
956*346d7152Ssoda 	 * from the current PC for the end of the previous subroutine.
957*346d7152Ssoda 	 */
958*346d7152Ssoda 	va = pc - sizeof(int);
959*346d7152Ssoda 	while ((instr = mdbchkget(va, ISP)) != MIPS_JR_RA)
960*346d7152Ssoda 		va -= sizeof(int);
961*346d7152Ssoda 	va += 2 * sizeof(int);	/* skip back over branch & delay slot */
962*346d7152Ssoda 	/* skip over nulls which might separate .o files */
963*346d7152Ssoda 	while ((instr = mdbchkget(va, ISP)) == 0)
964*346d7152Ssoda 		va += sizeof(int);
965*346d7152Ssoda 	subr = va;
966*346d7152Ssoda 
967*346d7152Ssoda 	/* scan forwards to find stack size and any saved registers */
968*346d7152Ssoda 	stksize = 0;
969*346d7152Ssoda 	more = 3;
970*346d7152Ssoda 	mask = 0;
971*346d7152Ssoda 	for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) {
972*346d7152Ssoda 		/* stop if hit our current position */
973*346d7152Ssoda 		if (va >= pc)
974*346d7152Ssoda 			break;
975*346d7152Ssoda 		instr = mdbchkget(va, ISP);
976*346d7152Ssoda 		i.word = instr;
977*346d7152Ssoda 		switch (i.JType.op) {
978*346d7152Ssoda 		case OP_SPECIAL:
979*346d7152Ssoda 			switch (i.RType.func) {
980*346d7152Ssoda 			case OP_JR:
981*346d7152Ssoda 			case OP_JALR:
982*346d7152Ssoda 				more = 2; /* stop after next instruction */
983*346d7152Ssoda 				break;
984*346d7152Ssoda 
985*346d7152Ssoda 			case OP_SYSCALL:
986*346d7152Ssoda 			case OP_BREAK:
987*346d7152Ssoda 				more = 1; /* stop now */
988*346d7152Ssoda 			};
989*346d7152Ssoda 			break;
990*346d7152Ssoda 
991*346d7152Ssoda 		case OP_BCOND:
992*346d7152Ssoda 		case OP_J:
993*346d7152Ssoda 		case OP_JAL:
994*346d7152Ssoda 		case OP_BEQ:
995*346d7152Ssoda 		case OP_BNE:
996*346d7152Ssoda 		case OP_BLEZ:
997*346d7152Ssoda 		case OP_BGTZ:
998*346d7152Ssoda 			more = 2; /* stop after next instruction */
999*346d7152Ssoda 			break;
1000*346d7152Ssoda 
1001*346d7152Ssoda 		case OP_COP0:
1002*346d7152Ssoda 		case OP_COP1:
1003*346d7152Ssoda 		case OP_COP2:
1004*346d7152Ssoda 		case OP_COP3:
1005*346d7152Ssoda 			switch (i.RType.rs) {
1006*346d7152Ssoda 			case OP_BCx:
1007*346d7152Ssoda 			case OP_BCy:
1008*346d7152Ssoda 				more = 2; /* stop after next instruction */
1009*346d7152Ssoda 			};
1010*346d7152Ssoda 			break;
1011*346d7152Ssoda 
1012*346d7152Ssoda 		case OP_SW:
1013*346d7152Ssoda 			/* look for saved registers on the stack */
1014*346d7152Ssoda 			if (i.IType.rs != 29)
1015*346d7152Ssoda 				break;
1016*346d7152Ssoda 			/* only restore the first one */
1017*346d7152Ssoda 			if (mask & (1 << i.IType.rt))
1018*346d7152Ssoda 				break;
1019*346d7152Ssoda 			mask |= 1 << i.IType.rt;
1020*346d7152Ssoda 			switch (i.IType.rt) {
1021*346d7152Ssoda 			case 4: /* a0 */
1022*346d7152Ssoda 				a0 = mdbchkget(sp + (short)i.IType.imm, DSP);
1023*346d7152Ssoda 				break;
1024*346d7152Ssoda 
1025*346d7152Ssoda 			case 5: /* a1 */
1026*346d7152Ssoda 				a1 = mdbchkget(sp + (short)i.IType.imm, DSP);
1027*346d7152Ssoda 				break;
1028*346d7152Ssoda 
1029*346d7152Ssoda 			case 6: /* a2 */
1030*346d7152Ssoda 				a2 = mdbchkget(sp + (short)i.IType.imm, DSP);
1031*346d7152Ssoda 				break;
1032*346d7152Ssoda 
1033*346d7152Ssoda 			case 7: /* a3 */
1034*346d7152Ssoda 				a3 = mdbchkget(sp + (short)i.IType.imm, DSP);
1035*346d7152Ssoda 				break;
1036*346d7152Ssoda 
1037*346d7152Ssoda 			case 31: /* ra */
1038*346d7152Ssoda 				ra = mdbchkget(sp + (short)i.IType.imm, DSP);
1039*346d7152Ssoda 			}
1040*346d7152Ssoda 			break;
1041*346d7152Ssoda 
1042*346d7152Ssoda 		case OP_ADDI:
1043*346d7152Ssoda 		case OP_ADDIU:
1044*346d7152Ssoda 			/* look for stack pointer adjustment */
1045*346d7152Ssoda 			if (i.IType.rs != 29 && i.IType.rt != 29)
1046*346d7152Ssoda 				break;
1047*346d7152Ssoda 			stksize = (short)i.IType.imm;
1048*346d7152Ssoda 		}
1049*346d7152Ssoda 	}
1050*346d7152Ssoda 
1051*346d7152Ssoda done:
1052*346d7152Ssoda 	printf("%x+%x ", subr, pc - subr); /* XXX */
1053*346d7152Ssoda 	printf("(%x,%x,%x,%x)\n", a0, a1, a2, a3);
1054*346d7152Ssoda 
1055*346d7152Ssoda 	if (ra) {
1056*346d7152Ssoda 		pc = ra;
1057*346d7152Ssoda 		sp -= stksize;
1058*346d7152Ssoda 		goto loop;
1059*346d7152Ssoda 	}
1060*346d7152Ssoda }
1061*346d7152Ssoda #endif
1062*346d7152Ssoda 
1063*346d7152Ssoda /*
1064*346d7152Ssoda  * Very simple memory allocator for mdb.
1065*346d7152Ssoda  */
1066*346d7152Ssoda char *
1067*346d7152Ssoda mdbmalloc(size)
1068*346d7152Ssoda 	int size;
1069*346d7152Ssoda {
1070*346d7152Ssoda 	static char buffer[4096];
1071*346d7152Ssoda 	static char *bufp = buffer;
1072*346d7152Ssoda 	char *p;
1073*346d7152Ssoda 
1074*346d7152Ssoda 	/* round size up to sizeof(int) */
1075*346d7152Ssoda 	size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
1076*346d7152Ssoda 	p = bufp;
1077*346d7152Ssoda 	bufp = p + size;
1078*346d7152Ssoda 	return (p);
1079*346d7152Ssoda }
1080*346d7152Ssoda 
1081*346d7152Ssoda /*
1082*346d7152Ssoda  *	Dump TLB contents.
1083*346d7152Ssoda  */
1084*346d7152Ssoda void pica_dump_tlb(int first,int last)
1085*346d7152Ssoda {
1086*346d7152Ssoda 	int tlbno;
1087*346d7152Ssoda 	struct tlb tlb;
1088*346d7152Ssoda 
1089*346d7152Ssoda 	tlbno = first;
1090*346d7152Ssoda 
1091*346d7152Ssoda 	while(tlbno <= last) {
1092*346d7152Ssoda 		MachTLBRead(tlbno, &tlb);
1093*346d7152Ssoda 		if(tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V) {
1094*346d7152Ssoda 			printf("TLB %2d vad 0x%08x ", tlbno, tlb.tlb_hi);
1095*346d7152Ssoda 		}
1096*346d7152Ssoda 		else {
1097*346d7152Ssoda 			printf("TLB*%2d vad 0x%08x ", tlbno, tlb.tlb_hi);
1098*346d7152Ssoda 		}
1099*346d7152Ssoda 		printf("0=0x%08x ", pfn_to_vad(tlb.tlb_lo0));
1100*346d7152Ssoda 		printf("%c", tlb.tlb_lo0 & PG_M ? 'M' : ' ');
1101*346d7152Ssoda 		printf("%c", tlb.tlb_lo0 & PG_G ? 'G' : ' ');
1102*346d7152Ssoda 		printf(" atr %x ", (tlb.tlb_lo0 >> 3) & 7);
1103*346d7152Ssoda 		printf("1=0x%08x ", pfn_to_vad(tlb.tlb_lo1));
1104*346d7152Ssoda 		printf("%c", tlb.tlb_lo1 & PG_M ? 'M' : ' ');
1105*346d7152Ssoda 		printf("%c", tlb.tlb_lo1 & PG_G ? 'G' : ' ');
1106*346d7152Ssoda 		printf(" atr %x ", (tlb.tlb_lo1 >> 3) & 7);
1107*346d7152Ssoda 		printf(" sz=%x\n", tlb.tlb_mask);
1108*346d7152Ssoda 
1109*346d7152Ssoda 		tlbno++;
1110*346d7152Ssoda 	}
1111*346d7152Ssoda }
1112