xref: /netbsd-src/sys/arch/mips/mips/db_disasm.c (revision 6949431564948da7c59bba027af2559a4a772baa)
1 /*	$NetBSD: db_disasm.c,v 1.43 2021/05/23 23:22:55 dholland Exp $	*/
2 
3 /*-
4  * Copyright (c) 1991, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Ralph Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	from: @(#)kadb.c	8.1 (Berkeley) 6/10/93
35  */
36 
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.43 2021/05/23 23:22:55 dholland Exp $");
39 
40 #include <sys/param.h>
41 #include <sys/cpu.h>
42 #include <sys/systm.h>
43 
44 #include <mips/locore.h>
45 #include <mips/mips_opcode.h>
46 #include <mips/reg.h>
47 
48 #include <machine/db_machdep.h>
49 
50 #include <ddb/db_access.h>
51 #include <ddb/db_user.h>
52 #include <ddb/db_interface.h>
53 #include <ddb/db_output.h>
54 #include <ddb/db_extern.h>
55 #include <ddb/db_sym.h>
56 
57 static const char * const op_name[64] = {
58 /* 0 */ "spec", "regimm","j",	"jal",	"beq",	"bne",	"blez", "bgtz",
59 /* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori",	"xori", "lui",
60 /*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
61 /*24 */ "daddi","daddiu","ldl", "ldr",	"op34", "op35", "op36", "op37",
62 /*32 */ "lb",	"lh",	"lwl",	"lw",	"lbu",	"lhu",	"lwr",	"lwu",
63 /*40 */ "sb",	"sh",	"swl",	"sw",	"sdl",	"sdr",	"swr",	"cache",
64 #ifdef __OCTEON__
65 /*48 */ "ll",	"lwc1", "bbit0", "lwc3", "lld",	"ldc1", "bbit032", "ld",
66 /*56 */ "sc",	"swc1", "bbit1", "swc3", "scd",	"sdc1", "bbit132", "sd"
67 #else
68 /*48 */ "ll",	"lwc1", "lwc2", "lwc3", "lld",	"ldc1", "ldc2", "ld",
69 /*56 */ "sc",	"swc1", "swc2", "swc3", "scd",	"sdc1", "sdc2", "sd"
70 #endif
71 };
72 
73 static const char * const spec_name[64] = {
74 /* 0 */ "sll",	"movc1","srl", "sra",	"sllv", "spec05","srlv","srav",
75 /* 8 */ "jr",	"jalr", "movz","movn","syscall","break","spec16","sync",
76 /*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
77 /*24 */ "mult", "multu","div",	"divu", "dmult","dmultu","ddiv","ddivu",
78 /*32 */ "add",	"addu", "sub",	"subu", "and",	"or",	"xor",	"nor",
79 /*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
80 /*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
81 /*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
82 };
83 
84 static const char * const spec2_name[64] = {	/* QED, MIPS32/64, etc. */
85 	[OP_MADD] = "madd",
86 	[OP_MADDU] = "maddu",
87 	[OP_MUL] = "mul",
88 #ifdef __OCTEON__
89 	[OP_CVM_DMUL] = "dmul",
90 #endif
91 	[OP_MSUB] = "msub",
92 	[OP_MSUBU] = "msubu",
93 	[OP_CLZ] = "clz",
94 	[OP_CLO] = "clo",
95 	[OP_DCLZ] = "dclz",
96 	[OP_DCLO] = "dclo",
97 #ifdef __OCTEON__
98 	[OP_CVM_BADDU] = "baddu",
99 	[OP_CVM_POP] = "pop",
100 	[OP_CVM_DPOP] = "dpop",
101 	[OP_CVM_CINS] = "cins",
102 	[OP_CVM_CINS32] = "cins32",
103 	[OP_CVM_EXTS] = "exts",
104 	[OP_CVM_EXTS32] = "exts32",
105 	[OP_CVM_SEQ] = "seq",
106 	[OP_CVM_SEQI] = "seqi",
107 	[OP_CVM_SNE] = "sne",
108 	[OP_CVM_SNEI] = "snei",
109 	[OP_CVM_SAA] = "saa",
110 	[OP_CVM_SAAD] = "saad",
111 #endif
112 	[OP_SDBBP] = "sdbbp",
113 };
114 
115 static const char * const spec3_name[64] = {
116 	[OP_EXT] = "ext",
117 	[OP_DEXTM] = "dextm",
118 	[OP_DEXTU] = "dextu",
119 	[OP_DEXT] = "dext",
120 	[OP_INS] = "ins",
121 	[OP_DINSM] = "dinsm",
122 	[OP_DINSU] = "dinsu",
123 	[OP_DINS] = "dins",
124 	[OP_LWLE] = "lwle",
125 	[OP_LWRE] = "lwre",
126 	[OP_CACHEE] = "cachee",
127 	[OP_SBE] = "sbe",
128 	[OP_SHE] = "she",
129 	[OP_SCE] = "sce",
130 	[OP_SWE] = "swe",
131 	[OP_BSHFL] = "bshfl",
132 	[OP_SWLE] = "swle",
133 	[OP_SWRE] = "swre",
134 	[OP_PREFE] = "prefe",
135 	[OP_DBSHFL] = "dbshfl",
136 	[OP_CACHE_R6] = "cache",
137 	[OP_LBUE] = "lbue",
138 	[OP_LHUE] = "lhue",
139 	[OP_LBE] = "lbe",
140 	[OP_LHE] = "lhe",
141 	[OP_LLE] = "lle",
142 	[OP_LWE] = "lwe",
143 	[OP_RDHWR] = "rdhwr",
144 };
145 
146 static const char * const regimm_name[32] = {
147 /* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
148 /* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
149 /*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
150 /*24 */ "?", "?", "?", "?", "bposge32", "?", "?", "?",
151 };
152 
153 static const char * const cop1_name[64] = {
154 /* 0 */ "fadd",  "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
155 /* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
156 /*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
157 /*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
158 /*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
159 /*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
160 /*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
161 	"fcmp.ole","fcmp.ule",
162 /*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
163 	"fcmp.le","fcmp.ngt"
164 };
165 
166 static const char * const fmt_name[16] = {
167 	"s",	"d",	"e",	"fmt3",
168 	"w",	"fmt5", "fmt6", "fmt7",
169 	"fmt8", "fmt9", "fmta", "fmtb",
170 	"fmtc", "fmtd", "fmte", "fmtf"
171 };
172 
173 #if defined(__mips_n32) || defined(__mips_n64)
174 static const char * const reg_name[32] = {
175 	"zero", "at",	"v0",	"v1",	"a0",	"a1",	"a2",	"a3",
176 	"a4",	"a5",	"a6",	"a7",	"t0",	"t1",	"t2",	"t3",
177 	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",	"s7",
178 	"t8",	"t9",	"k0",	"k1",	"gp",	"sp",	"s8",	"ra"
179 };
180 #else
181 static const char * const reg_name[32] = {
182 	"zero", "at",	"v0",	"v1",	"a0",	"a1",	"a2",	"a3",
183 	"t0",	"t1",	"t2",	"t3",	"t4",	"t5",	"t6",	"t7",
184 	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",	"s7",
185 	"t8",	"t9",	"k0",	"k1",	"gp",	"sp",	"s8",	"ra"
186 };
187 #endif /* __mips_n32 || __mips_n64 */
188 
189 static const char * const c0_opname[64] = {
190 	"c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
191 	"tlbp",	 "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
192 	"rfe",	 "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
193 	"eret",  "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
194 	"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
195 	"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
196 	"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
197 	"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
198 };
199 
200 static const char * const c0_reg[32] = {
201 	"index",    "random",   "tlblo0",  "tlblo1",
202 	"context",  "pagemask", "wired",   "hwrena",
203 	"badvaddr", "count",    "tlbhi",   "compare",
204 	"status",   "cause",    "epc",     "prid",
205 	"config",   "lladdr",   "watchlo", "watchhi",
206 	"xcontext", "cp0r21",   "osscratch",  "debug",
207 	"depc",     "perfcnt",  "ecc",     "cacheerr",
208 	"taglo",    "taghi",    "errepc",  "desave"
209 };
210 
211 static void print_addr(db_addr_t);
212 
213 /*
214  * Disassemble instruction at 'loc'.  'altfmt' specifies an
215  * (optional) alternate format (altfmt for vax: don't assume
216  * that each external label is a procedure entry mask).
217  * Return address of start of next instruction.
218  * Since this function is used by 'examine' and by 'step'
219  * "next instruction" does NOT mean the next instruction to
220  * be executed but the 'linear' next instruction.
221  */
222 db_addr_t
db_disasm(db_addr_t loc,bool altfmt)223 db_disasm(db_addr_t loc, bool altfmt)
224 {
225 	uint32_t instr;
226 
227 	/*
228 	 * Take some care with addresses to not UTLB here as it
229 	 * loses the current debugging context.  KSEG2 and XKSEG
230 	 * are not checked.
231 	 * Update: db_read_bytes is supposed to do that, and now
232 	 * does, so we can use that.
233 	 *
234 	 * XXX db_read_bytes_can't return failure but instead zeros
235 	 * the output. That's ok here, but if ever improved the
236 	 * proper thing here on error is to return the original loc.
237 	 */
238 	db_read_bytes(loc, sizeof(instr), (void *)&instr);
239 
240 	return (db_disasm_insn(instr, loc, altfmt));
241 }
242 
243 
244 /*
245  * Disassemble instruction 'insn' nominally at 'loc'.
246  * 'loc' may in fact contain a breakpoint instruction.
247  */
248 db_addr_t
db_disasm_insn(int insn,db_addr_t loc,bool altfmt)249 db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
250 {
251 	bool bdslot = false;
252 	InstFmt i;
253 
254 	i.word = insn;
255 
256 	switch (i.JType.op) {
257 	case OP_SPECIAL: {
258 		const char *name = spec_name[i.RType.func];
259 
260 		/* Handle varations of NOPs */
261 		if ((i.RType.func == OP_SLL) &&
262 		    (i.RType.rs == 0) &&
263 		    (i.RType.rt == 0) &&
264 		    (i.RType.rd == 0)) {
265 			switch (i.RType.shamt) {
266 			case OP_SLL_NOP:
267 				db_printf("nop");
268 				break;
269 			case OP_SLL_SSNOP:
270 				db_printf("ssnop");
271 				break;
272 			case OP_SLL_EHB:
273 				db_printf("ehb");
274 				break;
275 			case OP_SLL_PAUSE:
276 				db_printf("pause");
277 				break;
278 			default:
279 				db_printf("nop *");	/* "undefined" NOP */
280 				break;
281 			}
282 			break;
283 		}
284 
285 		/*
286 		 * The following are equivalents of a "move dst,src":
287 		 *	addu	dst,src,zero	(in 32-bit mode)
288 		 *	daddu	dst,src,zero	(in 64-bit mode)
289 		 *	or	dst,src,zero	(in 32- and 64-bit modes)
290 		 */
291 #ifdef __mips_o32
292 #define	OP_MOVE_ADDU	OP_ADDU
293 #else
294 #define	OP_MOVE_ADDU	OP_DADDU
295 #endif
296 		if (true &&
297 		    ((i.RType.func == OP_OR) || (i.RType.func == OP_MOVE_ADDU))
298 		    && i.RType.rt == 0) {
299 			db_printf("move\t%s,%s",
300 			    reg_name[i.RType.rd],
301 			    reg_name[i.RType.rs]);
302 			break;
303 		}
304 
305 		if ((i.RType.func == OP_SRL || i.RType.func == OP_SRLV)
306 		    && i.RType.rs == 1) {
307 			name = (i.RType.func == OP_SRL) ? "rotr" : "rotrv";
308 		} else if ((i.RType.func == OP_DSRL || i.RType.func == OP_DSRLV)
309 		    && i.RType.shamt == 1) {
310 			name = (i.RType.func == OP_DSRL) ? "drotr" : "drotrv";
311 		}
312 
313 		db_printf("%s", name);
314 		switch (i.RType.func) {
315 		case OP_SLL:
316 		case OP_SRL:
317 		case OP_SRA:
318 		case OP_DSLL:
319 		case OP_DSRL:
320 		case OP_DSRA:
321 		case OP_DSLL32:
322 		case OP_DSRL32:
323 		case OP_DSRA32:
324 			db_printf("\t%s,%s,%d",
325 			    reg_name[i.RType.rd],
326 			    reg_name[i.RType.rt],
327 			    i.RType.shamt);
328 			break;
329 
330 		case OP_SLLV:
331 		case OP_SRLV:
332 		case OP_SRAV:
333 		case OP_DSLLV:
334 		case OP_DSRLV:
335 		case OP_DSRAV:
336 			db_printf("\t%s,%s,%s",
337 			    reg_name[i.RType.rd],
338 			    reg_name[i.RType.rt],
339 			    reg_name[i.RType.rs]);
340 			break;
341 
342 		case OP_MFHI:
343 		case OP_MFLO:
344 			db_printf("\t%s", reg_name[i.RType.rd]);
345 			break;
346 
347 		case OP_JR:
348 		case OP_JALR:
349 			db_printf("\t%s%s", reg_name[i.RType.rs],
350 			    (insn & __BIT(10)) ? ".hb" : "");
351 			bdslot = true;
352 			break;
353 		case OP_MTLO:
354 		case OP_MTHI:
355 			db_printf("\t%s", reg_name[i.RType.rs]);
356 			break;
357 
358 		case OP_MULT:
359 		case OP_MULTU:
360 		case OP_DMULT:
361 		case OP_DMULTU:
362 		case OP_DIV:
363 		case OP_DIVU:
364 		case OP_DDIV:
365 		case OP_DDIVU:
366 			db_printf("\t%s,%s",
367 			    reg_name[i.RType.rs],
368 			    reg_name[i.RType.rt]);
369 			break;
370 
371 
372 		case OP_SYSCALL:
373 			break;
374 		case OP_SYNC:
375 			if (i.RType.shamt != 0)
376 				db_printf("\t%d", i.RType.shamt);
377 			break;
378 
379 		case OP_BREAK:
380 			db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
381 			break;
382 
383 		case OP_TEQ:
384 			db_printf("\t%s,%s,%#x",
385 			    reg_name[i.RType.rs],
386 			    reg_name[i.RType.rt],
387 			    (i.RType.rd << 5) | i.RType.shamt);
388 			break;
389 
390 		default:
391 			db_printf("\t%s,%s,%s",
392 			    reg_name[i.RType.rd],
393 			    reg_name[i.RType.rs],
394 			    reg_name[i.RType.rt]);
395 		}
396 		break;
397 	}
398 
399 	case OP_SPECIAL2:
400 		if (spec_name[i.RType.func] == NULL) {
401 			db_printf("spec2#%03o\t%s,%s",
402 				i.RType.func,
403 		    		reg_name[i.RType.rs],
404 		    		reg_name[i.RType.rt]);
405 			break;
406 		}
407 		if (i.RType.func == OP_MUL
408 #ifdef __OCTEON__
409 		    || i.RType.func == OP_CVM_DMUL
410 		    || i.RType.func == OP_CVM_SEQ
411 		    || i.RType.func == OP_CVM_SNE
412 #endif
413 		    || false) {
414 			db_printf("%s\t%s,%s,%s",
415 				spec2_name[i.RType.func],
416 		    		reg_name[i.RType.rd],
417 		    		reg_name[i.RType.rs],
418 		    		reg_name[i.RType.rt]);
419 			break;
420 		}
421 #ifdef __OCTEON__
422 		if (i.RType.func == OP_CVM_CINS
423 		    || i.RType.func == OP_CVM_CINS32
424 		    || i.RType.func == OP_CVM_EXTS
425 		    || i.RType.func == OP_CVM_EXTS32) {
426 			db_printf("%s\t%s,%s,%d,%d",
427 				spec2_name[i.RType.func],
428 		    		reg_name[i.RType.rt],
429 		    		reg_name[i.RType.rs],
430 				i.RType.shamt,
431 				i.RType.rd);
432 			break;
433 		}
434 		if (i.RType.func == OP_CVM_SEQI
435 		    || i.RType.func == OP_CVM_SNEI) {
436 			db_printf("%s\t%s,%s,%d",
437 				spec2_name[i.RType.func],
438 		    		reg_name[i.RType.rs],
439 		    		reg_name[i.RType.rt],
440 				(short)i.IType.imm >> 6);
441 			break;
442 		}
443 		if (i.RType.func == OP_CVM_SAA
444 		    || i.RType.func == OP_CVM_SAAD) {
445 			db_printf("%s\t%s,(%s)",
446 				spec2_name[i.RType.func],
447 		    		reg_name[i.RType.rt],
448 		    		reg_name[i.RType.rs]);
449 			break;
450 		}
451 #endif
452 		if (i.RType.func == OP_CLO
453 		    || i.RType.func == OP_DCLO
454 #ifdef __OCTEON__
455 		    || i.RType.func == OP_CVM_POP
456 		    || i.RType.func == OP_CVM_DPOP
457 #endif
458 		    || i.RType.func == OP_CLZ
459 		    || i.RType.func == OP_DCLZ) {
460 			db_printf("%s\t%s,%s",
461 				spec2_name[i.RType.func],
462 		    		reg_name[i.RType.rs],
463 		    		reg_name[i.RType.rd]);
464 			break;
465 		}
466 		db_printf("%s\t%s,%s",
467 			spec2_name[i.RType.func],
468 	    		reg_name[i.RType.rs],
469 	    		reg_name[i.RType.rt]);
470 		break;
471 
472 	case OP_SPECIAL3:
473 		if (spec3_name[i.RType.func] == NULL) {
474 			db_printf("spec3#%03o\t%s,%s",
475 				i.RType.func,
476 		    		reg_name[i.RType.rs],
477 		    		reg_name[i.RType.rt]);
478 			break;
479 		}
480 		if (i.RType.func <= OP_DINS) {
481 			int pos = i.RType.shamt;
482 			int size = i.RType.rd - pos + 1;
483 			size += (((i.RType.func & 3) == 1) ? 32 : 0);
484 			pos  += (((i.RType.func & 3) == 2) ? 32 : 0);
485 
486 			db_printf("%s\t%s,%s,%d,%d",
487 				spec3_name[i.RType.func],
488 				reg_name[i.RType.rt],
489 				reg_name[i.RType.rs],
490 				pos, size);
491 			break;
492 		}
493 		if (i.RType.func == OP_RDHWR) {
494 			db_printf("%s\t%s,$%d",
495 				spec3_name[i.RType.func],
496 				reg_name[i.RType.rt],
497 				i.RType.rd);
498 			break;
499 		}
500 		if (i.RType.func == OP_BSHFL) {
501 			if (i.RType.shamt == OP_BSHFL_SBH) {
502 				db_printf("wsbh\t%s,%s",
503 					reg_name[i.RType.rd],
504 					reg_name[i.RType.rt]);
505 			} else if (i.RType.shamt == OP_BSHFL_SEB) {
506 				db_printf("seb\t%s,%s",
507 					reg_name[i.RType.rd],
508 					reg_name[i.RType.rt]);
509 			} else if (i.RType.shamt == OP_BSHFL_SEH) {
510 				db_printf("seh\t%s,%s",
511 					reg_name[i.RType.rd],
512 					reg_name[i.RType.rt]);
513 			} else {
514 				db_printf("bshfl\t%s,%s,%d",
515 					reg_name[i.RType.rd],
516 					reg_name[i.RType.rt],
517 					i.RType.shamt);
518 			}
519 			break;
520 		}
521 		if (i.RType.func == OP_DBSHFL) {
522 			if (i.RType.shamt == OP_BSHFL_SBH) {
523 				db_printf("dsbh\t%s,%s",
524 					reg_name[i.RType.rd],
525 					reg_name[i.RType.rt]);
526 			} else if (i.RType.shamt == OP_BSHFL_SHD) {
527 				db_printf("dshd\t%s,%s",
528 					reg_name[i.RType.rd],
529 					reg_name[i.RType.rt]);
530 			} else {
531 				db_printf("dbshfl\t%s,%s,%d",
532 					reg_name[i.RType.rd],
533 					reg_name[i.RType.rt],
534 					i.RType.shamt);
535 			}
536 			break;
537 		}
538 		switch (i.RType.func) {
539 		case OP_LWLE:
540 		case OP_LWRE:
541 		case OP_CACHEE:
542 		case OP_SBE:
543 		case OP_SHE:
544 		case OP_SCE:
545 		case OP_SWE:
546 		case OP_SWLE:
547 		case OP_SWRE:
548 		case OP_PREFE:
549 		case OP_CACHE_R6:
550 		case OP_LBUE:
551 		case OP_LHUE:
552 		case OP_LBE:
553 		case OP_LHE:
554 		case OP_LLE:
555 		case OP_LWE:
556 			db_printf("%s\t%s,%d(%s)",
557 				spec3_name[i.RType.func],
558 				reg_name[i.RType.rs],
559 				i.S3OType.offset > 255 ?
560 				  -i.S3OType.offset : i.S3OType.offset,
561 				reg_name[i.RType.rt]);
562 			break;
563 		default:
564 			db_printf("%s\t%s,%s",
565 				spec3_name[i.RType.func],
566 				reg_name[i.RType.rs],
567 				reg_name[i.RType.rt]);
568 		}
569 		break;
570 
571 	case OP_REGIMM:
572 		db_printf("%s\t%s,", regimm_name[i.IType.rt],
573 		    reg_name[i.IType.rs]);
574 		if (i.IType.rt >= OP_TGEI && i.IType.rt <= OP_TNEI) {
575 			db_printf("%d",(int16_t)i.IType.imm);
576 			break;
577 		}
578 		goto pr_displ;
579 
580 	case OP_BLEZ:
581 	case OP_BLEZL:
582 	case OP_BGTZ:
583 	case OP_BGTZL:
584 		db_printf("%s\t%s,", op_name[i.IType.op],
585 		    reg_name[i.IType.rs]);
586 		goto pr_displ;
587 
588 	case OP_BEQ:
589 	case OP_BEQL:
590 		if (i.IType.rs == 0 && i.IType.rt == 0) {
591 			db_printf("b\t");
592 			goto pr_displ;
593 		}
594 		/* FALLTHROUGH */
595 	case OP_BNE:
596 	case OP_BNEL:
597 		db_printf("%s\t%s,%s,", op_name[i.IType.op],
598 		    reg_name[i.IType.rs],
599 		    reg_name[i.IType.rt]);
600 	pr_displ:
601 		print_addr(loc + 4 + ((short)i.IType.imm << 2));
602 		bdslot = true;
603 		break;
604 
605 	case OP_COP0:
606 		switch (i.RType.rs) {
607 		case OP_BCx:
608 		case OP_BCy:
609 
610 			db_printf("bc0%c\t",
611 			    "ft"[i.RType.rt & COPz_BC_TRUE]);
612 			goto pr_displ;
613 
614 		case OP_MT:
615 			db_printf("mtc0\t%s,%s",
616 			    reg_name[i.RType.rt],
617 			    c0_reg[i.RType.rd]);
618 			break;
619 
620 		case OP_DMT:
621 			db_printf("dmtc0\t%s,%s",
622 			    reg_name[i.RType.rt],
623 			    c0_reg[i.RType.rd]);
624 			break;
625 
626 		case OP_MF:
627 			db_printf("mfc0\t%s,%s",
628 			    reg_name[i.RType.rt],
629 			    c0_reg[i.RType.rd]);
630 			break;
631 
632 		case OP_DMF:
633 			db_printf("dmfc0\t%s,%s",
634 			    reg_name[i.RType.rt],
635 			    c0_reg[i.RType.rd]);
636 			break;
637 
638 		case OP_MFM:
639 			if (i.RType.rd == MIPS_COP_0_STATUS
640 			    && i.RType.shamt == 0
641 			    && (i.RType.func & 31) == 0) {
642 				db_printf("%s",
643 				    i.RType.func & 16 ? "ei" : "di");
644 				if (i.RType.rt != 0) {
645 					db_printf("\t%s",
646 					    reg_name[i.RType.rt]);
647 				}
648 				break;
649 			}
650 			/* FALLTHROUGH */
651 
652 		default:
653 			db_printf("%s", c0_opname[i.FRType.func]);
654 		}
655 		break;
656 
657 	case OP_COP1:
658 		switch (i.RType.rs) {
659 		case OP_BCx:
660 		case OP_BCy:
661 			db_printf("bc1%c\t",
662 			    "ft"[i.RType.rt & COPz_BC_TRUE]);
663 			goto pr_displ;
664 
665 		case OP_MT:
666 			db_printf("mtc1\t%s,f%d",
667 			    reg_name[i.RType.rt],
668 			    i.RType.rd);
669 			break;
670 
671 		case OP_MF:
672 			db_printf("mfc1\t%s,f%d",
673 			    reg_name[i.RType.rt],
674 			    i.RType.rd);
675 			break;
676 
677 		case OP_CT:
678 			db_printf("ctc1\t%s,%d",
679 			    reg_name[i.RType.rt],
680 			    i.RType.rd);
681 			break;
682 
683 		case OP_CF:
684 			db_printf("cfc1\t%s,%d",
685 			    reg_name[i.RType.rt],
686 			    i.RType.rd);
687 			break;
688 
689 		case OP_DMT:
690 			db_printf("dmtc1\t%s,f%d",
691 			    reg_name[i.RType.rt],
692 			    i.RType.rd);
693 			break;
694 
695 		case OP_DMF:
696 			db_printf("dmfc1\t%s,f%d",
697 			    reg_name[i.RType.rt],
698 			    i.RType.rd);
699 			break;
700 
701 		case OP_MTH:
702 			db_printf("mthc1\t%s,f%d",
703 			    reg_name[i.RType.rt],
704 			    i.RType.rd);
705 			break;
706 
707 		case OP_MFH:
708 			db_printf("mfhc1\t%s,f%d",
709 			    reg_name[i.RType.rt],
710 			    i.RType.rd);
711 			break;
712 
713 		default:
714 			db_printf("%s.%s\tf%d,f%d,f%d",
715 			    cop1_name[i.FRType.func],
716 			    fmt_name[i.FRType.fmt],
717 			    i.FRType.fd, i.FRType.fs, i.FRType.ft);
718 		}
719 		break;
720 
721 	case OP_COP2:
722 		switch (i.RType.rs) {
723 		case OP_BCx:
724 		case OP_BCy:
725 			db_printf("bc2%c\t",
726 			    "ft"[i.RType.rt & COPz_BC_TRUE]);
727 			goto pr_displ;
728 
729 		case OP_MT:
730 			db_printf("mtc2\t%s,f%d",
731 			    reg_name[i.RType.rt],
732 			    i.RType.rd);
733 			break;
734 
735 		case OP_MF:
736 			db_printf("mfc2\t%s,f%d",
737 			    reg_name[i.RType.rt],
738 			    i.RType.rd);
739 			break;
740 
741 		case OP_CT:
742 			db_printf("ctc2\t%s,f%d",
743 			    reg_name[i.RType.rt],
744 			    i.RType.rd);
745 			break;
746 
747 		case OP_CF:
748 			db_printf("cfc2\t%s,f%d",
749 			    reg_name[i.RType.rt],
750 			    i.RType.rd);
751 			break;
752 
753 		case OP_DMT:
754 			db_printf("dmtc2\t%s,f%d",
755 			    reg_name[i.RType.rt],
756 			    i.RType.rd);
757 			break;
758 
759 		case OP_DMF:
760 			db_printf("dmfc2\t%s,f%d",
761 			    reg_name[i.RType.rt],
762 			    i.RType.rd);
763 			break;
764 
765 		case OP_MTH:
766 			db_printf("mthc2\t%s,f%d",
767 			    reg_name[i.RType.rt],
768 			    i.RType.rd);
769 			break;
770 
771 		case OP_MFH:
772 			db_printf("mfhc2\t%s,f%d",
773 			    reg_name[i.RType.rt],
774 			    i.RType.rd);
775 			break;
776 
777 		default:
778 			db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
779 			    reg_name[i.IType.rt],
780 			    reg_name[i.IType.rs],
781 			    (short)i.IType.imm);
782 		}
783 		break;
784 
785 	case OP_J:
786 	case OP_JAL:
787 	case OP_JALX:
788 		db_printf("%s\t", op_name[i.JType.op]);
789 		print_addr((loc & ~0x0FFFFFFFL) | (i.JType.target << 2));
790 		bdslot = true;
791 		break;
792 
793 #ifdef __OCTEON__
794 	case OP_CVM_BBIT0:
795 	case OP_CVM_BBIT032:
796 	case OP_CVM_BBIT1:
797 	case OP_CVM_BBIT132:
798 			db_printf("%s\t%s,%d,",
799 			    op_name[i.IType.op],
800 			    reg_name[i.IType.rs],
801 			    i.IType.rt);
802 			goto pr_displ;
803 #else
804 	case OP_LWC2:
805 	case OP_LDC2:
806 	case OP_SWC2:
807 	case OP_SDC2:
808 #endif
809 
810 	case OP_LWC1:
811 	case OP_SWC1:
812 	case OP_LDC1:
813 	case OP_SDC1:
814 		db_printf("%s\tf%d,", op_name[i.IType.op],
815 		    i.IType.rt);
816 		goto loadstore;
817 
818 	case OP_LB:
819 	case OP_LH:
820 	case OP_LW:
821 	case OP_LD:
822 	case OP_LBU:
823 	case OP_LHU:
824 	case OP_LWU:
825 	case OP_SB:
826 	case OP_SH:
827 	case OP_SW:
828 	case OP_SD:
829 		db_printf("%s\t%s,", op_name[i.IType.op],
830 		    reg_name[i.IType.rt]);
831 	loadstore:
832 		db_printf("%d(%s)", (short)i.IType.imm,
833 		    reg_name[i.IType.rs]);
834 		break;
835 
836 	case OP_ORI:
837 	case OP_XORI:
838 		if (i.IType.rs == 0) {
839 			db_printf("li\t%s,0x%x",
840 			    reg_name[i.IType.rt],
841 			    i.IType.imm);
842 			break;
843 		}
844 		/* FALLTHROUGH */
845 	case OP_ANDI:
846 		db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
847 		    reg_name[i.IType.rt],
848 		    reg_name[i.IType.rs],
849 		    i.IType.imm);
850 		break;
851 
852 	case OP_LUI:
853 		db_printf("%s\t%s,0x%x", op_name[i.IType.op],
854 		    reg_name[i.IType.rt],
855 		    i.IType.imm);
856 		break;
857 
858 	case OP_CACHE:
859 		db_printf("%s\t0x%x,0x%x(%s)",
860 		    op_name[i.IType.op],
861 		    i.IType.rt,
862 		    i.IType.imm,
863 		    reg_name[i.IType.rs]);
864 		break;
865 
866 	case OP_ADDI:
867 	case OP_DADDI:
868 	case OP_ADDIU:
869 	case OP_DADDIU:
870 		if (i.IType.rs == 0) {
871 			db_printf("li\t%s,%d",
872 			    reg_name[i.IType.rt],
873 			    (short)i.IType.imm);
874 			break;
875 		}
876 		/* FALLTHROUGH */
877 	default:
878 		db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
879 		    reg_name[i.IType.rt],
880 		    reg_name[i.IType.rs],
881 		    (short)i.IType.imm);
882 	}
883 	db_printf("\n");
884 	if (bdslot) {
885 		db_printf("\t\tbdslot:\t");
886 		db_disasm(loc+4, false);
887 		return (loc + 8);
888 	}
889 	return (loc + 4);
890 }
891 
892 static void
print_addr(db_addr_t loc)893 print_addr(db_addr_t loc)
894 {
895 	db_expr_t diff;
896 	db_sym_t sym;
897 	const char *symname;
898 
899 	diff = INT_MAX;
900 	symname = NULL;
901 	sym = db_search_symbol(loc, DB_STGY_ANY, &diff);
902 	db_symbol_values(sym, &symname, 0);
903 
904 	db_printf("%#"PRIxVADDR, loc);
905 	if (symname) {
906 		db_printf(" <%s", symname);
907 		if (diff != 0)
908 			db_printf("+%#"DDB_EXPR_FMT"x", diff);
909 		db_printf(">");
910 	}
911 }
912