summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/mips64/include/mips_opcode.h209
-rw-r--r--sys/arch/mips64/mips64/db_disasm.c1070
2 files changed, 955 insertions, 324 deletions
diff --git a/sys/arch/mips64/include/mips_opcode.h b/sys/arch/mips64/include/mips_opcode.h
index 5cb7d074f45..6c324c10efa 100644
--- a/sys/arch/mips64/include/mips_opcode.h
+++ b/sys/arch/mips64/include/mips_opcode.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mips_opcode.h,v 1.4 2010/09/17 00:36:30 miod Exp $ */
+/* $OpenBSD: mips_opcode.h,v 1.5 2010/09/19 23:34:33 miod Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -35,7 +35,7 @@
*/
#ifndef _MIPS_MIPS_OPCODE_H_
-#define _MIPS_MIPS_OPCODE_H_
+#define _MIPS_MIPS_OPCODE_H_
/*
* Define the instruction formats and opcode values for the
@@ -137,29 +137,29 @@ typedef union {
/*
* Values for the 'op' field.
*/
-#define OP_SPECIAL 000
-#define OP_BCOND 001
-#define OP_J 002
+#define OP_SPECIAL 000
+#define OP_BCOND 001
+#define OP_J 002
#define OP_JAL 003
-#define OP_BEQ 004
-#define OP_BNE 005
-#define OP_BLEZ 006
-#define OP_BGTZ 007
-
-#define OP_ADDI 010
-#define OP_ADDIU 011
-#define OP_SLTI 012
-#define OP_SLTIU 013
-#define OP_ANDI 014
-#define OP_ORI 015
-#define OP_XORI 016
-#define OP_LUI 017
-
-#define OP_COP0 020
-#define OP_COP1 021
-#define OP_COP2 022
-#define OP_COP3 023
-#define OP_COP1X 023
+#define OP_BEQ 004
+#define OP_BNE 005
+#define OP_BLEZ 006
+#define OP_BGTZ 007
+
+#define OP_ADDI 010
+#define OP_ADDIU 011
+#define OP_SLTI 012
+#define OP_SLTIU 013
+#define OP_ANDI 014
+#define OP_ORI 015
+#define OP_XORI 016
+#define OP_LUI 017
+
+#define OP_COP0 020
+#define OP_COP1 021
+#define OP_COP2 022
+#define OP_COP3 023
+#define OP_COP1X 023
#define OP_BEQL 024
#define OP_BNEL 025
#define OP_BLEZL 026
@@ -172,88 +172,88 @@ typedef union {
#define OP_LB 040
#define OP_LH 041
-#define OP_LWL 042
-#define OP_LW 043
-#define OP_LBU 044
-#define OP_LHU 045
-#define OP_LWR 046
+#define OP_LWL 042
+#define OP_LW 043
+#define OP_LBU 044
+#define OP_LHU 045
+#define OP_LWR 046
#define OP_LWU 047
-#define OP_SB 050
-#define OP_SH 051
-#define OP_SWL 052
-#define OP_SW 053
+#define OP_SB 050
+#define OP_SH 051
+#define OP_SWL 052
+#define OP_SW 053
#define OP_SDL 054
#define OP_SDR 055
-#define OP_SWR 056
+#define OP_SWR 056
#define OP_CACHE 057
-#define OP_LL 060
-#define OP_LWC1 061
-#define OP_LWC2 062
-#define OP_LWC3 063
-#define OP_PREF 063
+#define OP_LL 060
+#define OP_LWC1 061
+#define OP_LWC2 062
+#define OP_LWC3 063
+#define OP_PREF 063
#define OP_LLD 064
#define OP_LDC1 065
#define OP_LDC2 066
#define OP_LD 067
-#define OP_SC 070
-#define OP_SWC1 071
-#define OP_SWC2 072
-#define OP_SWC3 073
+#define OP_SC 070
+#define OP_SWC1 071
+#define OP_SWC2 072
+#define OP_SWC3 073
#define OP_SCD 074
-#define OP_SDC1 075
-#define OP_SDC2 076
+#define OP_SDC1 075
+#define OP_SDC2 076
#define OP_SD 077
/*
* Values for the 'func' field when 'op' == OP_SPECIAL.
*/
-#define OP_SLL 000
+#define OP_SLL 000
#define OP_MOVCI 001
-#define OP_SRL 002
-#define OP_SRA 003
-#define OP_SLLV 004
-#define OP_SRLV 006
-#define OP_SRAV 007
-
-#define OP_JR 010
-#define OP_JALR 011
+#define OP_SRL 002
+#define OP_SRA 003
+#define OP_SLLV 004
+#define OP_SRLV 006
+#define OP_SRAV 007
+
+#define OP_JR 010
+#define OP_JALR 011
#define OP_MOVZ 012
#define OP_MOVN 013
-#define OP_SYSCALL 014
-#define OP_BREAK 015
+#define OP_SYSCALL 014
+#define OP_BREAK 015
#define OP_SYNC 017
-#define OP_MFHI 020
-#define OP_MTHI 021
-#define OP_MFLO 022
-#define OP_MTLO 023
+#define OP_MFHI 020
+#define OP_MTHI 021
+#define OP_MFLO 022
+#define OP_MTLO 023
#define OP_DSLLV 024
#define OP_DSRLV 026
#define OP_DSRAV 027
-#define OP_MULT 030
-#define OP_MULTU 031
-#define OP_DIV 032
-#define OP_DIVU 033
+#define OP_MULT 030
+#define OP_MULTU 031
+#define OP_DIV 032
+#define OP_DIVU 033
#define OP_DMULT 034
#define OP_DMULTU 035
#define OP_DDIV 036
#define OP_DDIVU 037
-#define OP_ADD 040
-#define OP_ADDU 041
-#define OP_SUB 042
-#define OP_SUBU 043
-#define OP_AND 044
-#define OP_OR 045
-#define OP_XOR 046
-#define OP_NOR 047
-
-#define OP_SLT 052
-#define OP_SLTU 053
+#define OP_ADD 040
+#define OP_ADDU 041
+#define OP_SUB 042
+#define OP_SUBU 043
+#define OP_AND 044
+#define OP_OR 045
+#define OP_XOR 046
+#define OP_NOR 047
+
+#define OP_SLT 052
+#define OP_SLTU 053
#define OP_DADD 054
#define OP_DADDU 055
#define OP_DSUB 056
@@ -276,8 +276,8 @@ typedef union {
/*
* Values for the 'func' field when 'op' == OP_BCOND.
*/
-#define OP_BLTZ 000
-#define OP_BGEZ 001
+#define OP_BLTZ 000
+#define OP_BGEZ 001
#define OP_BLTZL 002
#define OP_BGEZL 003
@@ -288,12 +288,38 @@ typedef union {
#define OP_TEQI 014
#define OP_TNEI 016
-#define OP_BLTZAL 020
-#define OP_BGEZAL 021
-#define OP_BLTZALL 022
+#define OP_BLTZAL 020
+#define OP_BGEZAL 021
+#define OP_BLTZALL 022
#define OP_BGEZALL 023
/*
+ * Values for the 'rs' field when 'op' == OP_COPz.
+ */
+#define OP_MF 000
+#define OP_DMF 001
+#define OP_CF 002
+#define OP_MFH 003
+#define OP_MT 004
+#define OP_DMT 005
+#define OP_CT 006
+#define OP_MTH 007
+#define OP_BC 010
+#define OP_C0MISC 020 /* cop0 only */
+
+/*
+ * Values for the 'rt' field when 'op' == OP_COPz.
+ */
+#define COPz_BC_TF_MASK 0x01
+#define COPz_BC_TRUE 0x01
+#define COPz_BC_FALSE 0x00
+#define COPz_BCL_TF_MASK 0x02
+#define COPz_BCL_TRUE 0x02
+#define COPz_BCL_FALSE 0x00
+#define COPz_BC_CC_MASK 0x1c
+#define COPz_BC_CC_SHIFT 2
+
+/*
* Values for the 'func' field when 'op' == OP_COP1X.
*/
#define OP_LWXC1 000
@@ -310,27 +336,4 @@ typedef union {
#define OP_NMADD 06
#define OP_NMSUB 07
-/*
- * Values for the 'rs' field when 'op' == OP_COPz.
- */
-#define OP_MF 000
-#define OP_DMF 001
-#define OP_CF 002
-#define OP_MT 004
-#define OP_DMT 005
-#define OP_CT 006
-#define OP_BC 010
-
-/*
- * Values for the 'rt' field when 'op' == OP_COPz.
- */
-#define COPz_BC_TF_MASK 0x01
-#define COPz_BC_TRUE 0x01
-#define COPz_BC_FALSE 0x00
-#define COPz_BCL_TF_MASK 0x02
-#define COPz_BCL_TRUE 0x02
-#define COPz_BCL_FALSE 0x00
-#define COPz_BC_CC_MASK 0x1c
-#define COPz_BC_CC_SHIFT 2
-
#endif /* !_MIPS_MIPS_OPCODE_H_ */
diff --git a/sys/arch/mips64/mips64/db_disasm.c b/sys/arch/mips64/mips64/db_disasm.c
index af7daa027e4..ecd9664eb36 100644
--- a/sys/arch/mips64/mips64/db_disasm.c
+++ b/sys/arch/mips64/mips64/db_disasm.c
@@ -1,4 +1,20 @@
-/* $OpenBSD: db_disasm.c,v 1.11 2010/09/17 00:30:09 miod Exp $ */
+/* $OpenBSD: db_disasm.c,v 1.12 2010/09/19 23:34:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -35,65 +51,370 @@
* SUCH DAMAGE.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
- * $Id: db_disasm.c,v 1.11 2010/09/17 00:30:09 miod Exp $
+ * $Id: db_disasm.c,v 1.12 2010/09/19 23:34:33 miod Exp $
*/
+#ifdef _KERNEL
#include <sys/param.h>
#include <sys/systm.h>
+#else
+#include <unistd.h>
+#include <stdio.h>
+#endif
-#include <machine/mips_opcode.h>
+#ifdef _KERNEL
#include <machine/db_machdep.h>
+#endif
+#include <machine/mips_opcode.h>
+#include <machine/regnum.h>
+
+#ifdef _KERNEL
#include <ddb/db_interface.h>
#include <ddb/db_output.h>
#include <ddb/db_sym.h>
+#else
+#define db_addr_t uint64_t
+#define db_printf printf
+#define db_printsym(addr,flags,fn) (fn)("%p",addr)
+#endif
static const char *op_name[64] = {
-/* 0 */ "spec", "bcond","j", "jal", "beq", "bne", "blez", "bgtz",
-/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
-/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
-/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
-/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
-/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
-/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld",
-/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd"
+ NULL, /* OP_SPECIAL */
+ NULL, /* OP_BCOND */
+ "j",
+ "jal",
+ "beq",
+ "bne",
+ "blez",
+ "bgtz",
+
+ "addi",
+ "addiu",
+ "slti",
+ "sltiu",
+ "andi",
+ "ori",
+ "xori",
+ "lui",
+
+ "cop0",
+ "cop1",
+ "cop2",
+ "cop1x",
+ "beql",
+ "bnel",
+ "blezl",
+ "bgtzl",
+
+ "daddi",
+ "daddiu",
+ "ldl",
+ "ldr",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ "lb",
+ "lh",
+ "lwl",
+ "lw",
+ "lbu",
+ "lhu",
+ "lwr",
+ "lwu",
+
+ "sb",
+ "sh",
+ "swl",
+ "sw",
+ "sdl",
+ "sdr",
+ "swr",
+ "cache",
+
+ "ll",
+ "lwc1",
+ "lwc2",
+ "pref",
+ "lld",
+ "ldc1",
+ "ldc2",
+ "ld",
+
+ "sc",
+ "swc1",
+ "swc2",
+ "swc3",
+ "scd",
+ "sdc1",
+ "sdc2",
+ "sd"
};
-static const char *spec_name[64] = {
-/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
-/* 8 */ "jr", "jalr", "spec12","spec13","syscall","break","spec16","sync",
-/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
-/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
-/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
-/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
-/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
-/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
+static const char *special_name[64] = {
+ "sll",
+ NULL,
+ "srl",
+ "sra",
+ "sllv",
+ NULL,
+ "srlv",
+ "srav",
+
+ "jr",
+ "jalr",
+ "movz",
+ "movn",
+ "syscall",
+ "break",
+ NULL,
+ "sync",
+
+ "mfhi",
+ "mthi",
+ "mflo",
+ "mtlo",
+ "dsllv",
+ NULL,
+ "dsrlv",
+ "dsrav",
+
+ "mult",
+ "multu",
+ "div",
+ "divu",
+ "dmult",
+ "dmultu",
+ "ddiv",
+ "ddivu",
+
+ "add",
+ "addu",
+ "sub",
+ "subu",
+ "and",
+ "or",
+ "xor",
+ "nor",
+
+ NULL,
+ NULL,
+ "slt",
+ "sltu",
+ "dadd",
+ "daddu",
+ "dsub",
+ "dsubu",
+
+ "tge",
+ "tgeu",
+ "tlt",
+ "tltu",
+ "teq",
+ NULL,
+ "tne",
+ NULL,
+
+ "dsll",
+ NULL,
+ "dsrl",
+ "dsra",
+ "dsll32",
+ NULL,
+ "dsrl32",
+ "dsra32"
};
static const char *bcond_name[32] = {
-/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
-/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
-/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
-/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
+ "bltz",
+ "bgez",
+ "bltzl",
+ "bgezl",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ "tgei",
+ "tgeiu",
+ "tlti",
+ "tltiu",
+ "teqi",
+ NULL,
+ "tnei",
+ NULL,
+
+ "bltzal",
+ "bgezal",
+ "bltzall",
+ "bgezall",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "synci"
+};
+
+static const char *cop_std[OP_MTH + 1] = {
+ "mfc",
+ "dmfc",
+ "cfc",
+ "mfhc",
+ "mtc",
+ "dmtc",
+ "ctc",
+ "mthc"
};
static const char *cop1_name[64] = {
-/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
-/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
-/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
-/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
-/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
-/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
-/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
- "fcmp.ole","fcmp.ule",
-/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
- "fcmp.le","fcmp.ngt"
+ "add",
+ "sub",
+ "mul",
+ "div",
+ "sqrt",
+ "abs",
+ "mov",
+ "neg",
+
+ "round.l",
+ "trunc.l",
+ "ceil.l",
+ "floor.l",
+ "round.w",
+ "trunc.w",
+ "ceil.w",
+ "floor.w",
+
+ NULL,
+ NULL, /* movf/movt */
+ "movz",
+ "movn",
+ NULL,
+ "recip",
+ "rsqrt",
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ "cvt.s",
+ "cvt.d",
+ NULL,
+ NULL,
+ "cvt.w",
+ "cvt.l",
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ "c.f",
+ "c.un",
+ "c.eq",
+ "c.ueq",
+ "c.olt",
+ "c.ult",
+ "c.ole",
+ "c.ule",
+
+ "c.sf",
+ "c.ngle",
+ "c.seq",
+ "c.ngl",
+ "c.lt",
+ "c.nge",
+ "c.le",
+ "c.ngt"
};
static const char *fmt_name[16] = {
- "s", "d", "e", "fmt3",
- "w", "fmt5", "fmt6", "fmt7",
- "fmt8", "fmt9", "fmta", "fmtb",
- "fmtc", "fmtd", "fmte", "fmtf"
+ "s",
+ "d",
+ NULL,
+ NULL,
+ "w",
+ "l",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const char *cop1x_op4[8] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "madd",
+ "msub",
+ "nmadd",
+ "nmsub"
+};
+
+static const char *cop1x_std[32] = {
+ "lwxc1",
+ "ldxc1",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ "swxc1",
+ "sdxc1",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "prefx",
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
static const char *reg_name[32] = {
@@ -103,63 +424,227 @@ static const char *reg_name[32] = {
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
-static const char *c0_opname[64] = {
- "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
- "tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
- "rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
- "eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
- "wait","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
- "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
- "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
- "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
+static const char *cop0_miscname[64] = {
+ NULL,
+ "tlbr",
+ "tlbwi",
+ NULL,
+ NULL,
+ NULL,
+ "tlbwr",
+ NULL,
+
+ "tlbp",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* rfe */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ "eret",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ "wait", /* RM5200 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
-static const char *c0_reg[32] = {
- "index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7",
- "badvaddr","count","tlbhi","c0r11","sr","cause","epc", "prid",
- "config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23",
- "c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31"
+static const char *cop0_reg0[32] = {
+ "Index",
+ "Random",
+ "EntryLo0",
+ "EntryLo1",
+ "Context",
+ "PageMask",
+ "Wired",
+ "Info", /* RM7000 */
+
+ "BadVAddr",
+ "Count",
+ "EntryHi",
+ "Compare",
+ "Status",
+ "Cause",
+ "EPC",
+ "PRId",
+
+ "Config",
+ "LLAddr",
+ "WatchLo", /* RM7000 Watch1 */
+ "WatchHi", /* RM7000 Watch2 */
+ "XContext",
+ NULL,
+ "PerfControl", /* RM7000 */
+ NULL,
+
+ "WatchMask", /* RM7000 */
+ "PerfCount", /* RM7000 */
+ "ECC",
+ "CacheErr",
+ "TagLo",
+ "TagHi",
+ "ErrorEPC",
+ NULL
};
-uint32_t kdbpeek(vaddr_t);
+static const char *cop0_reg1[32] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
-static int md_printins(uint32_t ins, db_addr_t mdbdot);
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
-db_addr_t
-db_disasm(db_addr_t loc, boolean_t altfmt)
-{
- if (md_printins(kdbpeek(loc), loc)) {
- loc += 4;
- db_printsym(loc, DB_STGY_ANY, db_printf);
- db_printf(":\t ");
- md_printins(kdbpeek(loc), loc);
- }
- loc += 4;
- return loc;
-}
+ NULL,
+ NULL,
+ "IPLLo",
+ "IPLHi",
+ "IntCtl",
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ "DErrAddr0",
+ "DErrAddr1",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static int md_printins(uint32_t ins, db_addr_t mdbdot);
-/* ARGSUSED */
static int
md_printins(uint32_t ins, db_addr_t mdbdot)
{
InstFmt i;
int delay = 0;
+ const char *insn, *descr;
i.word = ins;
+ insn = op_name[i.JType.op];
switch (i.JType.op) {
case OP_SPECIAL:
+ /* recognize nop/ssnop variants of sll early */
if (i.word == 0) {
db_printf("nop");
break;
+ } else if (i.word == 1 << 5) {
+ db_printf("ssnop");
+ break;
}
- if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
+
+ /* display `daddu' involving zero as `move' */
+ if (i.RType.func == OP_DADDU && i.RType.rt == 0) {
db_printf("move\t%s,%s",
- reg_name[i.RType.rd],
- reg_name[i.RType.rs]);
+ reg_name[i.RType.rd], reg_name[i.RType.rs]);
+ break;
+ }
+
+ if (i.RType.func == OP_MOVCI) {
+ db_printf("mov%c\t%s,%s,%d",
+ i.RType.rt & 1 ? 't' : 'f',
+ reg_name[i.RType.rd], reg_name[i.RType.rs],
+ i.RType.rt >> 2);
+ break;
+ }
+
+ /* fix ambiguous opcode memonics */
+ insn = special_name[i.RType.func];
+ switch (i.RType.func) {
+ case OP_SRL:
+ if (i.RType.rs != 0)
+ insn = "rotr";
+ break;
+ case OP_SRLV:
+ if (i.RType.shamt != 0)
+ insn = "rotrv";
+ break;
+ case OP_JR:
+ if (i.RType.shamt != 0)
+ insn = "jr.hb";
+ break;
+ case OP_JALR:
+ if (i.RType.shamt != 0)
+ insn = "jalr.hb";
+ break;
+ case OP_DSRL:
+ if (i.RType.rs != 0)
+ insn = "drotr";
+ break;
+ case OP_DSRLV:
+ if (i.RType.shamt != 0)
+ insn = "drotrv";
break;
}
- db_printf("%s", spec_name[i.RType.func]);
+
+ if (insn == NULL)
+ goto unknown;
+ db_printf("%s", insn);
+
switch (i.RType.func) {
case OP_SLL:
case OP_SRL:
@@ -171,252 +656,395 @@ md_printins(uint32_t ins, db_addr_t mdbdot)
case OP_DSRL32:
case OP_DSRA32:
db_printf("\t%s,%s,%d",
- reg_name[i.RType.rd],
- reg_name[i.RType.rt],
- i.RType.shamt);
+ reg_name[i.RType.rd], reg_name[i.RType.rt],
+ i.RType.shamt);
break;
-
case OP_SLLV:
case OP_SRLV:
case OP_SRAV:
+ case OP_MOVZ:
+ case OP_MOVN:
case OP_DSLLV:
case OP_DSRLV:
case OP_DSRAV:
db_printf("\t%s,%s,%s",
- reg_name[i.RType.rd],
- reg_name[i.RType.rt],
- reg_name[i.RType.rs]);
+ reg_name[i.RType.rd], reg_name[i.RType.rt],
+ reg_name[i.RType.rs]);
break;
-
case OP_MFHI:
case OP_MFLO:
db_printf("\t%s", reg_name[i.RType.rd]);
break;
-
- case OP_JR:
case OP_JALR:
delay = 1;
+ if (i.RType.rd != RA)
+ db_printf("\t%s,%s",
+ reg_name[i.RType.rd], reg_name[i.RType.rs]);
+ else
+ db_printf("\t%s", reg_name[i.RType.rs]);
+ break;
+ case OP_JR:
+ delay = 1;
/* FALLTHROUGH */
case OP_MTLO:
case OP_MTHI:
db_printf("\t%s", reg_name[i.RType.rs]);
break;
-
case OP_MULT:
case OP_MULTU:
- case OP_DMULT:
- case OP_DMULTU:
case OP_DIV:
case OP_DIVU:
+ case OP_DMULT:
+ case OP_DMULTU:
case OP_DDIV:
case OP_DDIVU:
+ case OP_TGE:
+ case OP_TGEU:
+ case OP_TLT:
+ case OP_TLTU:
+ case OP_TEQ:
+ case OP_TNE:
db_printf("\t%s,%s",
- reg_name[i.RType.rs],
- reg_name[i.RType.rt]);
+ reg_name[i.RType.rs], reg_name[i.RType.rt]);
break;
-
case OP_SYSCALL:
+ if ((ins >> 6) != 0)
+ db_printf("\t%d", ins >> 6);
+ break;
case OP_SYNC:
break;
-
case OP_BREAK:
- db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
+ db_printf("\t%d", ins >> 16);
break;
-
default:
db_printf("\t%s,%s,%s",
- reg_name[i.RType.rd],
- reg_name[i.RType.rs],
- reg_name[i.RType.rt]);
+ reg_name[i.RType.rd], reg_name[i.RType.rs],
+ reg_name[i.RType.rt]);
};
break;
case OP_BCOND:
- db_printf("%s\t%s,", bcond_name[i.IType.rt],
- reg_name[i.IType.rs]);
- goto pr_displ;
+ insn = bcond_name[i.IType.rt];
+ if (insn == NULL)
+ goto unknown;
+ if (i.IType.rt == 31) { /* synci */
+ db_printf("%s\t", insn);
+ goto loadstore;
+ }
+ db_printf("%s\t%s,", insn, reg_name[i.IType.rs]);
+ if ((i.IType.rt & 0x18) == 0x08) /* trap, not branch */
+ db_printf("%d", i.IType.imm);
+ else
+ goto pr_displ;
- case OP_BLEZ:
- case OP_BLEZL:
- case OP_BGTZ:
- case OP_BGTZL:
- db_printf("%s\t%s,", op_name[i.IType.op],
- reg_name[i.IType.rs]);
- goto pr_displ;
+ case OP_J:
+ case OP_JAL:
+ delay = 1;
+ db_printf("%s\t", insn);
+ db_printsym((mdbdot & ~0x0fffffffUL) |
+ (db_addr_t)(i.JType.target << 2), DB_STGY_PROC, db_printf);
+ break;
case OP_BEQ:
case OP_BEQL:
- if (i.IType.rs == 0 && i.IType.rt == 0) {
+ if (i.IType.rs == ZERO && i.IType.rt == ZERO) {
db_printf("b\t");
goto pr_displ;
}
/* FALLTHROUGH */
case OP_BNE:
case OP_BNEL:
- db_printf("%s\t%s,%s,", op_name[i.IType.op],
- reg_name[i.IType.rs],
- reg_name[i.IType.rt]);
- pr_displ:
+ if (i.IType.rt == ZERO) {
+ if (i.IType.op == OP_BEQL || i.IType.op == OP_BNEL) {
+ /* get the non-l opcode name */
+ insn = op_name[i.IType.op & 0x07];
+ db_printf("%szl\t%s,",
+ insn, reg_name[i.IType.rs]);
+ } else
+ db_printf("%sz\t%s,",
+ insn, reg_name[i.IType.rs]);
+ } else
+ db_printf("%s\t%s,%s,", insn,
+ reg_name[i.IType.rs], reg_name[i.IType.rt]);
+pr_displ:
delay = 1;
db_printsym(mdbdot + 4 + ((int16_t)i.IType.imm << 2),
DB_STGY_PROC, db_printf);
break;
- case OP_COP0:
- switch (i.RType.rs) {
- case OP_BC:
- db_printf("bc0%c%c\t",
- "ft"[i.RType.rt & COPz_BC_TF_MASK],
- i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' ');
- goto pr_displ;
+ case OP_BLEZ:
+ case OP_BGTZ:
+ case OP_BLEZL:
+ case OP_BGTZL:
+ db_printf("%s\t%s,", insn, reg_name[i.IType.rs]);
+ goto pr_displ;
- case OP_MT:
- db_printf("mtc0\t%s,%s",
- reg_name[i.RType.rt],
- c0_reg[i.RType.rd]);
+ case OP_ADDI:
+ case OP_ADDIU:
+ case OP_DADDI:
+ case OP_DADDIU:
+ if (i.IType.rs == 0) {
+ db_printf("li\t%s,%d",
+ reg_name[i.IType.rt], (int16_t)i.IType.imm);
break;
+ }
+ /* FALLTHROUGH */
+ case OP_SLTI:
+ case OP_SLTIU:
+ default:
+ if (insn != NULL)
+ db_printf("%s\t%s,%s,%d", insn,
+ reg_name[i.IType.rt], reg_name[i.IType.rs],
+ (int16_t)i.IType.imm);
+ else {
+unknown:
+ db_printf(".word\t%08x", ins);
+ }
+ break;
- case OP_DMT:
- db_printf("dmtc0\t%s,%s",
- reg_name[i.RType.rt],
- c0_reg[i.RType.rd]);
+ case OP_ORI:
+ case OP_XORI:
+ if (i.IType.rs == 0) {
+ db_printf("li\t%s,0x%x",
+ reg_name[i.IType.rt], i.IType.imm);
break;
+ }
+ /* FALLTHROUGH */
+ case OP_ANDI:
+ db_printf("%s\t%s,%s,0x%x", insn,
+ reg_name[i.IType.rt], reg_name[i.IType.rs], i.IType.imm);
+ break;
- case OP_MF:
- db_printf("mfc0\t%s,%s",
- reg_name[i.RType.rt],
- c0_reg[i.RType.rd]);
- break;
+ case OP_LUI:
+ db_printf("%s\t%s,0x%x", insn,
+ reg_name[i.IType.rt], i.IType.imm);
+ break;
+ case OP_COP0:
+ switch (i.RType.rs) {
+ case OP_MF:
case OP_DMF:
- db_printf("dmfc0\t%s,%s",
- reg_name[i.RType.rt],
- c0_reg[i.RType.rd]);
+ case OP_MT:
+ case OP_DMT:
+ case OP_CF:
+ case OP_CT:
+ insn = cop_std[i.RType.rs];
+ if (i.RType.rs == OP_CF || i.RType.rs == OP_CT)
+ descr = cop0_reg1[i.RType.rd];
+ else
+ descr = cop0_reg0[i.RType.rd];
+ if (descr != NULL)
+ db_printf("%s0\t%s,%d # %s", insn,
+ reg_name[i.RType.rt], i.RType.rd, descr);
+ else
+ db_printf("%s0\t%s,%d", insn,
+ reg_name[i.RType.rt], i.RType.rd);
break;
-
+ case OP_BC:
+ db_printf("bc0%c%c\t",
+ i.RType.rt & COPz_BC_TF_MASK ? 't' : 'f',
+ i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' ');
+ goto pr_displ;
+ case OP_C0MISC:
+ insn = cop0_miscname[i.FRType.func];
+ if (insn == NULL)
+ goto unknown;
+ else
+ db_printf("%s", insn);
default:
- db_printf("%s", c0_opname[i.FRType.func]);
+ goto unknown;
};
break;
case OP_COP1:
switch (i.RType.rs) {
+ case OP_MF:
+ case OP_DMF:
+ case OP_CF:
+ case OP_MFH:
+ case OP_MT:
+ case OP_DMT:
+ case OP_CT:
+ case OP_MTH:
+ insn = cop_std[i.RType.rs];
+ db_printf("%s1\t%s,f%d", insn,
+ reg_name[i.RType.rt], i.RType.rd);
+ break;
case OP_BC:
db_printf("bc1%c%c\t",
- "ft"[i.RType.rt & COPz_BC_TF_MASK],
- i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' ');
+ i.RType.rt & COPz_BC_TF_MASK ? 't' : 'f',
+ i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' ');
goto pr_displ;
+ default:
+ if (fmt_name[i.FRType.fmt] == NULL)
+ goto unknown;
+ if (i.FRType.func == 0x11) { /* movcf */
+ insn = i.FRType.ft & 1 ? "movt" : "movf";
+ db_printf("%s.%s\tf%d,f%d,%d",
+ insn, fmt_name[i.FRType.fmt],
+ i.FRType.fd, i.FRType.fs, i.FRType.ft >> 2);
+ break;
+ }
+ insn = cop1_name[i.FRType.func];
+ if (insn == NULL)
+ goto unknown;
+ db_printf("%s.%s\tf%d,f%d,f%d",
+ insn, fmt_name[i.FRType.fmt],
+ i.FRType.fd, i.FRType.fs, i.FRType.ft);
+ };
+ break;
- case OP_MT:
- db_printf("mtc1\t%s,f%d",
- reg_name[i.RType.rt],
- i.RType.rd);
- break;
-
+ case OP_COP2:
+ switch (i.RType.rs) {
case OP_MF:
- db_printf("mfc1\t%s,f%d",
- reg_name[i.RType.rt],
- i.RType.rd);
- break;
-
- case OP_CT:
- db_printf("ctc1\t%s,f%d",
- reg_name[i.RType.rt],
- i.RType.rd);
- break;
-
+ case OP_DMF:
case OP_CF:
- db_printf("cfc1\t%s,f%d",
- reg_name[i.RType.rt],
- i.RType.rd);
+ case OP_MFH:
+ case OP_MT:
+ case OP_DMT:
+ case OP_CT:
+ case OP_MTH:
+ insn = cop_std[i.RType.rs];
+ db_printf("%s2\t%s,f%d", insn,
+ reg_name[i.RType.rt], i.RType.rd);
break;
-
+ case OP_BC:
+ db_printf("bc2%c%c\t",
+ i.RType.rt & COPz_BC_TF_MASK ? 't' : 'f',
+ i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' ');
+ goto pr_displ;
default:
- db_printf("%s.%s\tf%d,f%d,f%d",
- cop1_name[i.FRType.func],
- fmt_name[i.FRType.fmt],
- i.FRType.fd, i.FRType.fs, i.FRType.ft);
+ goto unknown;
};
break;
- case OP_J:
- case OP_JAL:
- db_printf("%s\t", op_name[i.JType.op]);
- db_printsym((mdbdot & ~0x0fffffffUL) |
- (db_addr_t)(i.JType.target << 2), DB_STGY_PROC, db_printf);
- delay = 1;
+ case OP_COP1X:
+ switch (i.FQType.op4) {
+ case OP_MADD:
+ case OP_MSUB:
+ case OP_NMADD:
+ case OP_NMSUB:
+ if (fmt_name[i.FQType.fmt3] == NULL)
+ goto unknown;
+ insn = cop1x_op4[i.FQType.op4];
+ db_printf("%s.%s\tf%d,f%d,f%d,f%d",
+ insn, fmt_name[i.FQType.fmt3],
+ i.FQType.fd, i.FQType.fr,
+ i.FQType.fs, i.FQType.ft);
+ break;
+ default:
+ insn = cop1x_std[i.FRType.func];
+ switch (i.FRType.func) {
+ case OP_LWXC1:
+ case OP_LDXC1:
+ db_printf("%s\tf%d,%s(%s)", insn,
+ i.FQType.fd, reg_name[i.FQType.ft],
+ reg_name[i.FQType.fr]);
+ break;
+ case OP_SWXC1:
+ case OP_SDXC1:
+ db_printf("%s\tf%d,%s(%s)", insn,
+ i.FQType.fs, reg_name[i.FQType.ft],
+ reg_name[i.FQType.fr]);
+ break;
+ case OP_PREFX:
+ db_printf("%s\t%d,%s(%s)", insn,
+ i.FQType.fs, reg_name[i.FQType.ft],
+ reg_name[i.FQType.fr]);
+ break;
+ }
+ break;
+ }
break;
- case OP_LWC1:
- case OP_SWC1:
- db_printf("%s\tf%d,", op_name[i.IType.op],
- i.IType.rt);
- goto loadstore;
-
+ case OP_LDL:
+ case OP_LDR:
case OP_LB:
case OP_LH:
+ case OP_LWL:
case OP_LW:
- case OP_LD:
case OP_LBU:
case OP_LHU:
+ case OP_LWR:
case OP_LWU:
case OP_SB:
case OP_SH:
+ case OP_SWL:
case OP_SW:
+ case OP_SDL:
+ case OP_SDR:
+ case OP_SWR:
+ case OP_LL:
+ case OP_LLD:
+ case OP_LD:
+ case OP_SC:
+ case OP_SCD:
case OP_SD:
- db_printf("%s\t%s,", op_name[i.IType.op],
- reg_name[i.IType.rt]);
- loadstore:
- db_printf("%d(%s)", (int16_t)i.IType.imm,
- reg_name[i.IType.rs]);
- break;
-
- case OP_ORI:
- case OP_XORI:
- if (i.IType.rs == 0) {
- db_printf("li\t%s,0x%x",
- reg_name[i.IType.rt],
- i.IType.imm);
- break;
- }
- /* FALLTHROUGH */
- case OP_ANDI:
- db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
- reg_name[i.IType.rt],
- reg_name[i.IType.rs],
- i.IType.imm);
- break;
-
- case OP_LUI:
- db_printf("%s\t%s,0x%x", op_name[i.IType.op],
- reg_name[i.IType.rt],
- i.IType.imm);
+ db_printf("%s\t%s,", insn, reg_name[i.IType.rt]);
+loadstore:
+ db_printf("%d(%s)",
+ (int16_t)i.IType.imm, reg_name[i.IType.rs]);
break;
case OP_CACHE:
- db_printf("%s\t0x%x,%d(%s)", op_name[i.IType.op],
- i.IType.rt,
- (int16_t)i.IType.imm,
- reg_name[i.IType.rs]);
+ db_printf("%s\t0x%x,", insn, i.IType.rt);
+ goto loadstore;
break;
- case OP_ADDI:
- case OP_DADDI:
- case OP_ADDIU:
- case OP_DADDIU:
- if (i.IType.rs == 0) {
- db_printf("li\t%s,%d",
- reg_name[i.IType.rt],
- (int16_t)i.IType.imm);
- break;
- }
- /* FALLTHROUGH */
- default:
- db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
- reg_name[i.IType.rt],
- reg_name[i.IType.rs],
- (int16_t)i.IType.imm);
+ case OP_LWC1:
+ case OP_LWC2:
+ /* case OP_LWC3: superseded with OP_PREF */
+ case OP_LDC1:
+ case OP_LDC2:
+ case OP_SWC1:
+ case OP_SWC2:
+ case OP_SWC3:
+ case OP_SDC1:
+ case OP_SDC2:
+ db_printf("%s\tf%d,", insn, i.IType.rt);
+ goto loadstore;
+
+ case OP_PREF:
+ db_printf("%s\t%d,", insn, i.IType.rt);
+ goto loadstore;
}
db_printf("\n");
- return(delay);
+ return delay;
+}
+
+#ifdef _KERNEL
+db_addr_t
+db_disasm(db_addr_t loc, boolean_t altfmt)
+{
+ extern uint32_t kdbpeek(vaddr_t);
+
+ if (md_printins(kdbpeek(loc), loc)) {
+ loc += 4;
+ db_printsym(loc, DB_STGY_ANY, db_printf);
+ db_printf(":\t ");
+ md_printins(kdbpeek(loc), loc);
+ }
+ loc += 4;
+ return loc;
+}
+#else
+/*
+ * Simple userspace test program (to confirm the logic never tries to print
+ * NULL, to begin with...)
+ */
+int
+main()
+{
+ uint32_t insn = 0;
+
+ do {
+ printf("%08x\t", insn);
+ md_printins(insn, 0);
+ insn++;
+ if ((insn & 0x00ffffff) == 0)
+ fprintf(stderr, "%08x\n", insn);
+ } while (insn != 0);
+
+ return 0;
}
+#endif