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