1178172Simp/*	$OpenBSD: db_disasm.c,v 1.1 1998/03/16 09:03:24 pefo Exp $	*/
2178172Simp/*-
3178172Simp * Copyright (c) 1991, 1993
4178172Simp *	The Regents of the University of California.  All rights reserved.
5178172Simp *
6178172Simp * This code is derived from software contributed to Berkeley by
7178172Simp * Ralph Campbell.
8178172Simp *
9178172Simp * Redistribution and use in source and binary forms, with or without
10178172Simp * modification, are permitted provided that the following conditions
11178172Simp * are met:
12178172Simp * 1. Redistributions of source code must retain the above copyright
13178172Simp *    notice, this list of conditions and the following disclaimer.
14178172Simp * 2. Redistributions in binary form must reproduce the above copyright
15178172Simp *    notice, this list of conditions and the following disclaimer in the
16178172Simp *    documentation and/or other materials provided with the distribution.
17178172Simp * 3. All advertising materials mentioning features or use of this software
18178172Simp *    must display the following acknowledgement:
19178172Simp *	This product includes software developed by the University of
20178172Simp *	California, Berkeley and its contributors.
21178172Simp * 4. Neither the name of the University nor the names of its contributors
22178172Simp *    may be used to endorse or promote products derived from this software
23178172Simp *    without specific prior written permission.
24178172Simp *
25178172Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28178172Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35178172Simp * SUCH DAMAGE.
36178172Simp *
37178172Simp *	from: @(#)kadb.c	8.1 (Berkeley) 6/10/93
38178172Simp *	Id: db_disasm.c,v 1.1 1998/03/16 09:03:24 pefo Exp
39178172Simp *	JNPR: db_disasm.c,v 1.1 2006/08/07 05:38:57 katta
40178172Simp */
41178172Simp
42178172Simp#include <sys/cdefs.h>
43178172Simp__FBSDID("$FreeBSD$");
44178172Simp
45178172Simp#include <sys/param.h>
46178172Simp#include <vm/vm_param.h>
47178172Simp#include <vm/vm.h>
48178172Simp#include <vm/pmap.h>
49178172Simp#include <sys/systm.h>
50178172Simp
51178172Simp#include <machine/mips_opcode.h>
52178172Simp#include <machine/db_machdep.h>
53178172Simp#include <ddb/ddb.h>
54178172Simp#include <ddb/db_output.h>
55178172Simp
56178172Simpstatic char *op_name[64] = {
57178172Simp/* 0 */ "spec", "bcond","j",	"jal",	"beq",	"bne",	"blez",	"bgtz",
58178172Simp/* 8 */ "addi", "addiu","slti",	"sltiu","andi",	"ori",	"xori",	"lui",
59178172Simp/*16 */ "cop0", "cop1",	"cop2",	"cop3", "beql",	"bnel",	"blezl","bgtzl",
60178172Simp/*24 */ "daddi","daddiu","ldl",	"ldr",	"op34",	"op35",	"op36",	"op37",
61178172Simp/*32 */ "lb",	"lh",	"lwl",	"lw",	"lbu",	"lhu",	"lwr",	"lwu",
62178172Simp/*40 */ "sb",	"sh",	"swl",	"sw",	"sdl",	"sdr",	"swr",	"cache",
63178172Simp/*48 */ "ll",	"lwc1",	"lwc2",	"lwc3", "lld",	"ldc1",	"ldc2",	"ld",
64178172Simp/*56 */ "sc",	"swc1",	"swc2",	"swc3", "scd",	"sdc1",	"sdc2",	"sd"
65178172Simp};
66178172Simp
67178172Simpstatic char *spec_name[64] = {
68178172Simp/* 0 */ "sll",	"spec01","srl", "sra",	"sllv",	"spec05","srlv","srav",
69178172Simp/* 8 */ "jr",	"jalr",	"spec12","spec13","syscall","break","spec16","sync",
70178172Simp/*16 */ "mfhi",	"mthi",	"mflo", "mtlo",	"dsllv","spec25","dsrlv","dsrav",
71178172Simp/*24 */ "mult",	"multu","div",	"divu",	"dmult","dmultu","ddiv","ddivu",
72178172Simp/*32 */ "add",	"addu",	"sub",	"subu",	"and",	"or",	"xor",	"nor",
73178172Simp/*40 */ "spec50","spec51","slt","sltu",	"dadd","daddu","dsub","dsubu",
74178172Simp/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
75178172Simp/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
76178172Simp};
77178172Simp
78178172Simpstatic char *bcond_name[32] = {
79178172Simp/* 0 */ "bltz",	"bgez",	"bltzl", "bgezl", "?", "?", "?", "?",
80178172Simp/* 8 */ "tgei",	"tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
81178172Simp/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
82178172Simp/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
83178172Simp};
84178172Simp
85178172Simpstatic char *cop1_name[64] = {
86178172Simp/* 0 */ "fadd",	"fsub",	"fmpy",	"fdiv",	"fsqrt","fabs",	"fmov",	"fneg",
87178172Simp/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
88178172Simp/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
89178172Simp/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
90178172Simp/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
91178172Simp/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
92178172Simp/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
93178172Simp	"fcmp.ole","fcmp.ule",
94178172Simp/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
95178172Simp	"fcmp.le","fcmp.ngt"
96178172Simp};
97178172Simp
98178172Simpstatic char *fmt_name[16] = {
99178172Simp	"s",	"d",	"e",	"fmt3",
100178172Simp	"w",	"fmt5",	"fmt6",	"fmt7",
101178172Simp	"fmt8",	"fmt9",	"fmta",	"fmtb",
102178172Simp	"fmtc",	"fmtd",	"fmte",	"fmtf"
103178172Simp};
104178172Simp
105178172Simpstatic char *reg_name[32] = {
106178172Simp	"zero",	"at",	"v0",	"v1",	"a0",	"a1",	"a2",	"a3",
107178172Simp	"t0",	"t1",	"t2",	"t3",	"t4",	"t5",	"t6",	"t7",
108178172Simp	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",	"s7",
109178172Simp	"t8",	"t9",	"k0",	"k1",	"gp",	"sp",	"s8",	"ra"
110178172Simp};
111178172Simp
112178172Simpstatic char *c0_opname[64] = {
113178172Simp	"c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
114178172Simp	"tlbp",	"c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
115178172Simp	"rfe",	"c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
116178172Simp	"eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
117178172Simp	"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
118178172Simp	"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
119178172Simp	"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
120178172Simp	"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
121178172Simp};
122178172Simp
123178172Simpstatic char *c0_reg[32] = {
124178172Simp	"index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7",
125178172Simp	"badvaddr","count","tlbhi","c0r11","sr","cause","epc",	"prid",
126178172Simp	"config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23",
127178172Simp	"c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31"
128178172Simp};
129178172Simp
130178172Simpstatic int md_printins(int ins, int mdbdot);
131178172Simp
132178172Simpdb_addr_t
133178172Simpdb_disasm(db_addr_t loc, boolean_t altfmt)
134178172Simp
135178172Simp{
136178172Simp	int ins;
137178172Simp
138178172Simp	if (vtophys((vm_offset_t)loc)) {
139178172Simp		db_read_bytes((vm_offset_t)loc, (size_t)sizeof(int),
140178172Simp		    (char *)&ins);
141178172Simp		md_printins(ins, loc);
142178172Simp	}
143178172Simp
144178172Simp	return (loc + sizeof(int));
145178172Simp}
146178172Simp
147178172Simp/* ARGSUSED */
148178172Simpstatic int
149178172Simpmd_printins(int ins, int mdbdot)
150178172Simp{
151178172Simp	InstFmt i;
152178172Simp	int delay = 0;
153178172Simp
154178172Simp	i.word = ins;
155178172Simp
156178172Simp	switch (i.JType.op) {
157178172Simp	case OP_SPECIAL:
158178172Simp		if (i.word == 0) {
159178172Simp			db_printf("nop");
160178172Simp			break;
161178172Simp		}
162178172Simp		if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
163178172Simp			db_printf("move\t%s,%s",
164178172Simp			    reg_name[i.RType.rd], reg_name[i.RType.rs]);
165178172Simp			break;
166178172Simp		}
167178172Simp		db_printf("%s", spec_name[i.RType.func]);
168178172Simp		switch (i.RType.func) {
169178172Simp		case OP_SLL:
170178172Simp		case OP_SRL:
171178172Simp		case OP_SRA:
172178172Simp		case OP_DSLL:
173178172Simp		case OP_DSRL:
174178172Simp		case OP_DSRA:
175178172Simp		case OP_DSLL32:
176178172Simp		case OP_DSRL32:
177178172Simp		case OP_DSRA32:
178178172Simp			db_printf("\t%s,%s,%d", reg_name[i.RType.rd],
179178172Simp			    reg_name[i.RType.rt], i.RType.shamt);
180178172Simp			break;
181178172Simp
182178172Simp		case OP_SLLV:
183178172Simp		case OP_SRLV:
184178172Simp		case OP_SRAV:
185178172Simp		case OP_DSLLV:
186178172Simp		case OP_DSRLV:
187178172Simp		case OP_DSRAV:
188178172Simp			db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
189178172Simp			    reg_name[i.RType.rt], reg_name[i.RType.rs]);
190178172Simp			break;
191178172Simp
192178172Simp		case OP_MFHI:
193178172Simp		case OP_MFLO:
194178172Simp			db_printf("\t%s", reg_name[i.RType.rd]);
195178172Simp			break;
196178172Simp
197178172Simp		case OP_JR:
198178172Simp		case OP_JALR:
199178172Simp			delay = 1;
200178172Simp			/* FALLTHROUGH */
201178172Simp		case OP_MTLO:
202178172Simp		case OP_MTHI:
203178172Simp			db_printf("\t%s", reg_name[i.RType.rs]);
204178172Simp			break;
205178172Simp
206178172Simp		case OP_MULT:
207178172Simp		case OP_MULTU:
208178172Simp		case OP_DMULT:
209178172Simp		case OP_DMULTU:
210178172Simp		case OP_DIV:
211178172Simp		case OP_DIVU:
212178172Simp		case OP_DDIV:
213178172Simp		case OP_DDIVU:
214178172Simp			db_printf("\t%s,%s",
215178172Simp			    reg_name[i.RType.rs], reg_name[i.RType.rt]);
216178172Simp			break;
217178172Simp
218178172Simp		case OP_SYSCALL:
219178172Simp		case OP_SYNC:
220178172Simp			break;
221178172Simp
222178172Simp		case OP_BREAK:
223178172Simp			db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
224178172Simp			break;
225178172Simp
226178172Simp		default:
227178172Simp			db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
228178172Simp			    reg_name[i.RType.rs], reg_name[i.RType.rt]);
229178172Simp		};
230178172Simp		break;
231178172Simp
232178172Simp	case OP_BCOND:
233178172Simp		db_printf("%s\t%s,", bcond_name[i.IType.rt],
234178172Simp		    reg_name[i.IType.rs]);
235178172Simp		goto pr_displ;
236178172Simp
237178172Simp	case OP_BLEZ:
238178172Simp	case OP_BLEZL:
239178172Simp	case OP_BGTZ:
240178172Simp	case OP_BGTZL:
241178172Simp		db_printf("%s\t%s,", op_name[i.IType.op],
242178172Simp		    reg_name[i.IType.rs]);
243178172Simp		goto pr_displ;
244178172Simp
245178172Simp	case OP_BEQ:
246178172Simp	case OP_BEQL:
247178172Simp		if (i.IType.rs == 0 && i.IType.rt == 0) {
248178172Simp			db_printf("b\t");
249178172Simp			goto pr_displ;
250178172Simp		}
251178172Simp		/* FALLTHROUGH */
252178172Simp	case OP_BNE:
253178172Simp	case OP_BNEL:
254178172Simp		db_printf("%s\t%s,%s,", op_name[i.IType.op],
255178172Simp		    reg_name[i.IType.rs], reg_name[i.IType.rt]);
256178172Simp	pr_displ:
257178172Simp		delay = 1;
258178172Simp		db_printf("0x%08x", mdbdot + 4 + ((short)i.IType.imm << 2));
259178172Simp		break;
260178172Simp
261178172Simp	case OP_COP0:
262178172Simp		switch (i.RType.rs) {
263178172Simp		case OP_BCx:
264178172Simp		case OP_BCy:
265178172Simp			db_printf("bc0%c\t",
266178172Simp			    "ft"[i.RType.rt & COPz_BC_TF_MASK]);
267178172Simp			goto pr_displ;
268178172Simp
269178172Simp		case OP_MT:
270178172Simp			db_printf("mtc0\t%s,%s",
271178172Simp			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
272178172Simp			break;
273178172Simp
274178172Simp		case OP_DMT:
275178172Simp			db_printf("dmtc0\t%s,%s",
276178172Simp			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
277178172Simp			break;
278178172Simp
279178172Simp		case OP_MF:
280178172Simp			db_printf("mfc0\t%s,%s",
281178172Simp			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
282178172Simp			break;
283178172Simp
284178172Simp		case OP_DMF:
285178172Simp			db_printf("dmfc0\t%s,%s",
286178172Simp			    reg_name[i.RType.rt], c0_reg[i.RType.rd]);
287178172Simp			break;
288178172Simp
289178172Simp		default:
290178172Simp			db_printf("%s", c0_opname[i.FRType.func]);
291178172Simp		};
292178172Simp		break;
293178172Simp
294178172Simp	case OP_COP1:
295178172Simp		switch (i.RType.rs) {
296178172Simp		case OP_BCx:
297178172Simp		case OP_BCy:
298178172Simp			db_printf("bc1%c\t",
299178172Simp			    "ft"[i.RType.rt & COPz_BC_TF_MASK]);
300178172Simp			goto pr_displ;
301178172Simp
302178172Simp		case OP_MT:
303178172Simp			db_printf("mtc1\t%s,f%d",
304178172Simp			    reg_name[i.RType.rt], i.RType.rd);
305178172Simp			break;
306178172Simp
307178172Simp		case OP_MF:
308178172Simp			db_printf("mfc1\t%s,f%d",
309178172Simp			    reg_name[i.RType.rt], i.RType.rd);
310178172Simp			break;
311178172Simp
312178172Simp		case OP_CT:
313178172Simp			db_printf("ctc1\t%s,f%d",
314178172Simp			    reg_name[i.RType.rt], i.RType.rd);
315178172Simp			break;
316178172Simp
317178172Simp		case OP_CF:
318178172Simp			db_printf("cfc1\t%s,f%d",
319178172Simp			    reg_name[i.RType.rt], i.RType.rd);
320178172Simp			break;
321178172Simp
322178172Simp		default:
323178172Simp			db_printf("%s.%s\tf%d,f%d,f%d",
324178172Simp			    cop1_name[i.FRType.func], fmt_name[i.FRType.fmt],
325178172Simp			    i.FRType.fd, i.FRType.fs, i.FRType.ft);
326178172Simp		};
327178172Simp		break;
328178172Simp
329178172Simp	case OP_J:
330178172Simp	case OP_JAL:
331178172Simp		db_printf("%s\t", op_name[i.JType.op]);
332178172Simp		db_printf("0x%8x",(mdbdot & 0xF0000000) | (i.JType.target << 2));
333178172Simp		delay = 1;
334178172Simp		break;
335178172Simp
336178172Simp	case OP_LWC1:
337178172Simp	case OP_SWC1:
338178172Simp		db_printf("%s\tf%d,", op_name[i.IType.op], i.IType.rt);
339178172Simp		goto loadstore;
340178172Simp
341178172Simp	case OP_LB:
342178172Simp	case OP_LH:
343178172Simp	case OP_LW:
344178172Simp	case OP_LD:
345178172Simp	case OP_LBU:
346178172Simp	case OP_LHU:
347178172Simp	case OP_LWU:
348178172Simp	case OP_SB:
349178172Simp	case OP_SH:
350178172Simp	case OP_SW:
351178172Simp	case OP_SD:
352178172Simp		db_printf("%s\t%s,", op_name[i.IType.op],
353178172Simp		    reg_name[i.IType.rt]);
354178172Simp	loadstore:
355178172Simp		db_printf("%d(%s)", (short)i.IType.imm, reg_name[i.IType.rs]);
356178172Simp		break;
357178172Simp
358178172Simp	case OP_ORI:
359178172Simp	case OP_XORI:
360178172Simp		if (i.IType.rs == 0) {
361178172Simp			db_printf("li\t%s,0x%x",
362178172Simp			    reg_name[i.IType.rt], i.IType.imm);
363178172Simp			break;
364178172Simp		}
365178172Simp		/* FALLTHROUGH */
366178172Simp	case OP_ANDI:
367178172Simp		db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
368178172Simp		    reg_name[i.IType.rt], reg_name[i.IType.rs], i.IType.imm);
369178172Simp		break;
370178172Simp
371178172Simp	case OP_LUI:
372178172Simp		db_printf("%s\t%s,0x%x", op_name[i.IType.op],
373178172Simp		    reg_name[i.IType.rt], i.IType.imm);
374178172Simp		break;
375178172Simp
376178172Simp	case OP_ADDI:
377178172Simp	case OP_DADDI:
378178172Simp	case OP_ADDIU:
379178172Simp	case OP_DADDIU:
380178172Simp		if (i.IType.rs == 0) {
381178172Simp			db_printf("li\t%s,%d", reg_name[i.IType.rt],
382178172Simp			    (short)i.IType.imm);
383178172Simp			break;
384178172Simp		}
385178172Simp		/* FALLTHROUGH */
386178172Simp	default:
387178172Simp		db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
388178172Simp		    reg_name[i.IType.rt], reg_name[i.IType.rs],
389178172Simp		    (short)i.IType.imm);
390178172Simp	}
391178172Simp	return (delay);
392178172Simp}
393