xref: /NextBSD/sys/mips/mips/db_disasm.c (revision 287e3b14e9552995def1802ec9c5034f4adf28ec)
1 /*	$OpenBSD: db_disasm.c,v 1.1 1998/03/16 09:03:24 pefo Exp $	*/
2 /*-
3  * Copyright (c) 1991, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Ralph Campbell.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	from: @(#)kadb.c	8.1 (Berkeley) 6/10/93
38  *	Id: db_disasm.c,v 1.1 1998/03/16 09:03:24 pefo Exp
39  *	JNPR: db_disasm.c,v 1.1 2006/08/07 05:38:57 katta
40  */
41 
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44 
45 #include <sys/param.h>
46 #include <vm/vm_param.h>
47 #include <vm/vm.h>
48 #include <vm/pmap.h>
49 #include <sys/systm.h>
50 
51 #include <machine/mips_opcode.h>
52 #include <machine/db_machdep.h>
53 #include <ddb/ddb.h>
54 #include <ddb/db_output.h>
55 
56 static char *op_name[64] = {
57 /* 0 */ "spec", "bcond","j",	"jal",	"beq",	"bne",	"blez",	"bgtz",
58 /* 8 */ "addi", "addiu","slti",	"sltiu","andi",	"ori",	"xori",	"lui",
59 /*16 */ "cop0", "cop1",	"cop2",	"cop3", "beql",	"bnel",	"blezl","bgtzl",
60 /*24 */ "daddi","daddiu","ldl",	"ldr",	"op34",	"op35",	"op36",	"op37",
61 /*32 */ "lb",	"lh",	"lwl",	"lw",	"lbu",	"lhu",	"lwr",	"lwu",
62 /*40 */ "sb",	"sh",	"swl",	"sw",	"sdl",	"sdr",	"swr",	"cache",
63 /*48 */ "ll",	"lwc1",	"lwc2",	"lwc3", "lld",	"ldc1",	"ldc2",	"ld",
64 /*56 */ "sc",	"swc1",	"swc2",	"swc3", "scd",	"sdc1",	"sdc2",	"sd"
65 };
66 
67 static char *spec_name[64] = {
68 /* 0 */ "sll",	"spec01","srl", "sra",	"sllv",	"spec05","srlv","srav",
69 /* 8 */ "jr",	"jalr",	"spec12","spec13","syscall","break","spec16","sync",
70 /*16 */ "mfhi",	"mthi",	"mflo", "mtlo",	"dsllv","spec25","dsrlv","dsrav",
71 /*24 */ "mult",	"multu","div",	"divu",	"dmult","dmultu","ddiv","ddivu",
72 /*32 */ "add",	"addu",	"sub",	"subu",	"and",	"or",	"xor",	"nor",
73 /*40 */ "spec50","spec51","slt","sltu",	"dadd","daddu","dsub","dsubu",
74 /*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
75 /*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
76 };
77 
78 static char *bcond_name[32] = {
79 /* 0 */ "bltz",	"bgez",	"bltzl", "bgezl", "?", "?", "?", "?",
80 /* 8 */ "tgei",	"tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
81 /*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
82 /*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
83 };
84 
85 static char *cop1_name[64] = {
86 /* 0 */ "fadd",	"fsub",	"fmpy",	"fdiv",	"fsqrt","fabs",	"fmov",	"fneg",
87 /* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
88 /*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
89 /*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
90 /*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
91 /*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
92 /*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
93 	"fcmp.ole","fcmp.ule",
94 /*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
95 	"fcmp.le","fcmp.ngt"
96 };
97 
98 static char *fmt_name[16] = {
99 	"s",	"d",	"e",	"fmt3",
100 	"w",	"fmt5",	"fmt6",	"fmt7",
101 	"fmt8",	"fmt9",	"fmta",	"fmtb",
102 	"fmtc",	"fmtd",	"fmte",	"fmtf"
103 };
104 
105 static char *reg_name[32] = {
106 	"zero",	"at",	"v0",	"v1",	"a0",	"a1",	"a2",	"a3",
107 	"t0",	"t1",	"t2",	"t3",	"t4",	"t5",	"t6",	"t7",
108 	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",	"s7",
109 	"t8",	"t9",	"k0",	"k1",	"gp",	"sp",	"s8",	"ra"
110 };
111 
112 static char *c0_opname[64] = {
113 	"c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
114 	"tlbp",	"c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
115 	"rfe",	"c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
116 	"eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
117 	"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
118 	"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
119 	"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
120 	"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
121 };
122 
123 static char *c0_reg[32] = {
124 	"index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7",
125 	"badvaddr","count","tlbhi","c0r11","sr","cause","epc",	"prid",
126 	"config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23",
127 	"c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31"
128 };
129 
130 static int md_printins(int ins, int mdbdot);
131 
132 db_addr_t
db_disasm(db_addr_t loc,bool altfmt)133 db_disasm(db_addr_t loc, bool altfmt)
134 
135 {
136 	int ins;
137 
138 	if (vtophys((vm_offset_t)loc)) {
139 		db_read_bytes((vm_offset_t)loc, (size_t)sizeof(int),
140 		    (char *)&ins);
141 		md_printins(ins, loc);
142 	}
143 
144 	return (loc + sizeof(int));
145 }
146 
147 /* ARGSUSED */
148 static int
md_printins(int ins,int mdbdot)149 md_printins(int ins, int mdbdot)
150 {
151 	InstFmt i;
152 	int delay = 0;
153 
154 	i.word = ins;
155 
156 	switch (i.JType.op) {
157 	case OP_SPECIAL:
158 		if (i.word == 0) {
159 			db_printf("nop");
160 			break;
161 		}
162 		if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
163 			db_printf("move\t%s,%s",
164 			    reg_name[i.RType.rd], reg_name[i.RType.rs]);
165 			break;
166 		}
167 		db_printf("%s", spec_name[i.RType.func]);
168 		switch (i.RType.func) {
169 		case OP_SLL:
170 		case OP_SRL:
171 		case OP_SRA:
172 		case OP_DSLL:
173 		case OP_DSRL:
174 		case OP_DSRA:
175 		case OP_DSLL32:
176 		case OP_DSRL32:
177 		case OP_DSRA32:
178 			db_printf("\t%s,%s,%d", reg_name[i.RType.rd],
179 			    reg_name[i.RType.rt], i.RType.shamt);
180 			break;
181 
182 		case OP_SLLV:
183 		case OP_SRLV:
184 		case OP_SRAV:
185 		case OP_DSLLV:
186 		case OP_DSRLV:
187 		case OP_DSRAV:
188 			db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
189 			    reg_name[i.RType.rt], reg_name[i.RType.rs]);
190 			break;
191 
192 		case OP_MFHI:
193 		case OP_MFLO:
194 			db_printf("\t%s", reg_name[i.RType.rd]);
195 			break;
196 
197 		case OP_JR:
198 		case OP_JALR:
199 			delay = 1;
200 			/* FALLTHROUGH */
201 		case OP_MTLO:
202 		case OP_MTHI:
203 			db_printf("\t%s", reg_name[i.RType.rs]);
204 			break;
205 
206 		case OP_MULT:
207 		case OP_MULTU:
208 		case OP_DMULT:
209 		case OP_DMULTU:
210 		case OP_DIV:
211 		case OP_DIVU:
212 		case OP_DDIV:
213 		case OP_DDIVU:
214 			db_printf("\t%s,%s",
215 			    reg_name[i.RType.rs], reg_name[i.RType.rt]);
216 			break;
217 
218 		case OP_SYSCALL:
219 		case OP_SYNC:
220 			break;
221 
222 		case OP_BREAK:
223 			db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
224 			break;
225 
226 		default:
227 			db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
228 			    reg_name[i.RType.rs], reg_name[i.RType.rt]);
229 		};
230 		break;
231 
232 	case OP_BCOND:
233 		db_printf("%s\t%s,", bcond_name[i.IType.rt],
234 		    reg_name[i.IType.rs]);
235 		goto pr_displ;
236 
237 	case OP_BLEZ:
238 	case OP_BLEZL:
239 	case OP_BGTZ:
240 	case OP_BGTZL:
241 		db_printf("%s\t%s,", op_name[i.IType.op],
242 		    reg_name[i.IType.rs]);
243 		goto pr_displ;
244 
245 	case OP_BEQ:
246 	case OP_BEQL:
247 		if (i.IType.rs == 0 && i.IType.rt == 0) {
248 			db_printf("b\t");
249 			goto pr_displ;
250 		}
251 		/* FALLTHROUGH */
252 	case OP_BNE:
253 	case OP_BNEL:
254 		db_printf("%s\t%s,%s,", op_name[i.IType.op],
255 		    reg_name[i.IType.rs], reg_name[i.IType.rt]);
256 	pr_displ:
257 		delay = 1;
258 		db_printf("0x%08x", mdbdot + 4 + ((short)i.IType.imm << 2));
259 		break;
260 
261 	case OP_COP0:
262 		switch (i.RType.rs) {
263 		case OP_BCx:
264 		case OP_BCy:
265 			db_printf("bc0%c\t",
266 			    "ft"[i.RType.rt & COPz_BC_TF_MASK]);
267 			goto pr_displ;
268 
269 		case OP_MT:
270 			db_printf("mtc0\t%s,%s",
271 			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
272 			break;
273 
274 		case OP_DMT:
275 			db_printf("dmtc0\t%s,%s",
276 			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
277 			break;
278 
279 		case OP_MF:
280 			db_printf("mfc0\t%s,%s",
281 			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
282 			break;
283 
284 		case OP_DMF:
285 			db_printf("dmfc0\t%s,%s",
286 			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
287 			break;
288 
289 		default:
290 			db_printf("%s", c0_opname[i.FRType.func]);
291 		};
292 		break;
293 
294 	case OP_COP1:
295 		switch (i.RType.rs) {
296 		case OP_BCx:
297 		case OP_BCy:
298 			db_printf("bc1%c\t",
299 			    "ft"[i.RType.rt & COPz_BC_TF_MASK]);
300 			goto pr_displ;
301 
302 		case OP_MT:
303 			db_printf("mtc1\t%s,f%d",
304 			    reg_name[i.RType.rt], i.RType.rd);
305 			break;
306 
307 		case OP_MF:
308 			db_printf("mfc1\t%s,f%d",
309 			    reg_name[i.RType.rt], i.RType.rd);
310 			break;
311 
312 		case OP_CT:
313 			db_printf("ctc1\t%s,f%d",
314 			    reg_name[i.RType.rt], i.RType.rd);
315 			break;
316 
317 		case OP_CF:
318 			db_printf("cfc1\t%s,f%d",
319 			    reg_name[i.RType.rt], i.RType.rd);
320 			break;
321 
322 		default:
323 			db_printf("%s.%s\tf%d,f%d,f%d",
324 			    cop1_name[i.FRType.func], fmt_name[i.FRType.fmt],
325 			    i.FRType.fd, i.FRType.fs, i.FRType.ft);
326 		};
327 		break;
328 
329 	case OP_J:
330 	case OP_JAL:
331 		db_printf("%s\t", op_name[i.JType.op]);
332 		db_printf("0x%8x",(mdbdot & 0xF0000000) | (i.JType.target << 2));
333 		delay = 1;
334 		break;
335 
336 	case OP_LWC1:
337 	case OP_SWC1:
338 		db_printf("%s\tf%d,", op_name[i.IType.op], i.IType.rt);
339 		goto loadstore;
340 
341 	case OP_LB:
342 	case OP_LH:
343 	case OP_LW:
344 	case OP_LD:
345 	case OP_LBU:
346 	case OP_LHU:
347 	case OP_LWU:
348 	case OP_SB:
349 	case OP_SH:
350 	case OP_SW:
351 	case OP_SD:
352 		db_printf("%s\t%s,", op_name[i.IType.op],
353 		    reg_name[i.IType.rt]);
354 	loadstore:
355 		db_printf("%d(%s)", (short)i.IType.imm, reg_name[i.IType.rs]);
356 		break;
357 
358 	case OP_ORI:
359 	case OP_XORI:
360 		if (i.IType.rs == 0) {
361 			db_printf("li\t%s,0x%x",
362 			    reg_name[i.IType.rt], i.IType.imm);
363 			break;
364 		}
365 		/* FALLTHROUGH */
366 	case OP_ANDI:
367 		db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
368 		    reg_name[i.IType.rt], reg_name[i.IType.rs], i.IType.imm);
369 		break;
370 
371 	case OP_LUI:
372 		db_printf("%s\t%s,0x%x", op_name[i.IType.op],
373 		    reg_name[i.IType.rt], i.IType.imm);
374 		break;
375 
376 	case OP_ADDI:
377 	case OP_DADDI:
378 	case OP_ADDIU:
379 	case OP_DADDIU:
380 		if (i.IType.rs == 0) {
381 			db_printf("li\t%s,%d", reg_name[i.IType.rt],
382 			    (short)i.IType.imm);
383 			break;
384 		}
385 		/* FALLTHROUGH */
386 	default:
387 		db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
388 		    reg_name[i.IType.rt], reg_name[i.IType.rs],
389 		    (short)i.IType.imm);
390 	}
391 	db_printf("\n");
392 	return (delay);
393 }
394