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