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