svn commit: r337763 - head/sys/riscv/riscv

Ruslan Bukin br at FreeBSD.org
Tue Aug 14 16:03:05 UTC 2018


Author: br
Date: Tue Aug 14 16:03:03 2018
New Revision: 337763
URL: https://svnweb.freebsd.org/changeset/base/337763

Log:
  Rewrite RISC-V disassembler:
  - Use macroses from encoding.h generated by riscv-opcodes.
  - Add support for C-compressed ISA extension.
  
  Sponsored by:	DARPA, AFRL

Modified:
  head/sys/riscv/riscv/db_disasm.c

Modified: head/sys/riscv/riscv/db_disasm.c
==============================================================================
--- head/sys/riscv/riscv/db_disasm.c	Tue Aug 14 16:01:25 2018	(r337762)
+++ head/sys/riscv/riscv/db_disasm.c	Tue Aug 14 16:03:03 2018	(r337763)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2016 Ruslan Bukin <br at bsdpad.com>
+ * Copyright (c) 2016-2018 Ruslan Bukin <br at bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -41,232 +41,26 @@ __FBSDID("$FreeBSD$");
 #include <ddb/db_access.h>
 #include <ddb/db_sym.h>
 
-#include <machine/riscvreg.h>
-#include <machine/riscv_opcode.h>
+#include <machine/encoding.h>
 
-struct riscv_op {
-	char *name;
-	char *type;
-	char *fmt;
-	int opcode;
-	int funct3;
-	int funct7; /* Or imm, depending on type. */
-};
+#define	X_RA	1
+#define	X_SP	2
+#define	X_GP	3
+#define	X_TP	4
+#define	X_T0	5
+#define	X_T1	6
+#define	X_T2	7
+#define	X_T3	28
 
-/*
- * Keep sorted by opcode, funct3, funct7 so some instructions
- * aliases will be supported (e.g. "mv" instruction alias)
- * Use same print format as binutils do.
- */
-static struct riscv_op riscv_opcodes[] = {
-	{ "lb",		"I",	"d,o(s)",	3,   0, -1 },
-	{ "lh",		"I",	"d,o(s)",	3,   1, -1 },
-	{ "lw",		"I",	"d,o(s)",	3,   2, -1 },
-	{ "ld",		"I",	"d,o(s)",	3,   3, -1 },
-	{ "lbu",	"I",	"d,o(s)",	3,   4, -1 },
-	{ "lhu",	"I",	"d,o(s)",	3,   5, -1 },
-	{ "lwu",	"I",	"d,o(s)",	3,   6, -1 },
-	{ "ldu",	"I",	"d,o(s)",	3,   7, -1 },
-	{ "fence",	"I",	"",		15,  0, -1 },
-	{ "fence.i",	"I",	"",		15,  1, -1 },
-	{ "mv",		"I",	"d,s",		19,  0,  0 },
-	{ "addi",	"I",	"d,s,j",	19,  0, -1 },
-	{ "slli",	"R2",	"d,s,>",	19,  1,  0 },
-	{ "slti",	"I",	"d,s,j",	19,  2, -1 },
-	{ "sltiu",	"I",	"d,s,j",	19,  3, -1 },
-	{ "xori",	"I",	"d,s,j",	19,  4, -1 },
-	{ "srli",	"R2",	"d,s,>",	19,  5,  0 },
-	{ "srai",	"R2",	"d,s,>",	19,  5, 0b010000 },
-	{ "ori",	"I",	"d,s,j",	19,  6, -1 },
-	{ "andi",	"I",	"d,s,j",	19,  7, -1 },
-	{ "auipc",	"U",	"d,u",		23, -1, -1 },
-	{ "sext.w",	"I",	"d,s",		27,  0,  0 },
-	{ "addiw",	"I",	"d,s,j",	27,  0, -1 },
-	{ "slliw",	"R",	"d,s,<",	27,  1,  0 },
-	{ "srliw",	"R",	"d,s,<",	27,  5,  0 },
-	{ "sraiw",	"R",	"d,s,<",	27,  5, 0b0100000 },
-	{ "sb",		"S",	"t,q(s)",	35,  0, -1 },
-	{ "sh",		"S",	"t,q(s)",	35,  1, -1 },
-	{ "sw",		"S",	"t,q(s)",	35,  2, -1 },
-	{ "sd",		"S",	"t,q(s)",	35,  3, -1 },
-	{ "sbu",	"S",	"t,q(s)",	35,  4, -1 },
-	{ "shu",	"S",	"t,q(s)",	35,  5, -1 },
-	{ "swu",	"S",	"t,q(s)",	35,  6, -1 },
-	{ "sdu",	"S",	"t,q(s)",	35,  7, -1 },
-	{ "lr.w",	"R",	"d,t,0(s)",	47,  2, 0b0001000 },
-	{ "sc.w",	"R",	"d,t,0(s)",	47,  2, 0b0001100 },
-	{ "amoswap.w",	"R",	"d,t,0(s)",	47,  2, 0b0000100 },
-	{ "amoadd.w",	"R",	"d,t,0(s)",	47,  2, 0b0000000 },
-	{ "amoxor.w",	"R",	"d,t,0(s)",	47,  2, 0b0010000 },
-	{ "amoand.w",	"R",	"d,t,0(s)",	47,  2, 0b0110000 },
-	{ "amoor.w",	"R",	"d,t,0(s)",	47,  2, 0b0100000 },
-	{ "amomin.w",	"R",	"d,t,0(s)",	47,  2, 0b1000000 },
-	{ "amomax.w",	"R",	"d,t,0(s)",	47,  2, 0b1010000 },
-	{ "amominu.w",	"R",	"d,t,0(s)",	47,  2, 0b1100000 },
-	{ "amomaxu.w",	"R",	"d,t,0(s)",	47,  2, 0b1110000 },
-	{ "lr.w.aq",	"R",	"d,t,0(s)",	47,  2, 0b0001000 },
-	{ "sc.w.aq",	"R",	"d,t,0(s)",	47,  2, 0b0001100 },
-	{ "amoswap.w.aq","R",	"d,t,0(s)",	47,  2, 0b0000110 },
-	{ "amoadd.w.aq","R",	"d,t,0(s)",	47,  2, 0b0000010 },
-	{ "amoxor.w.aq","R",	"d,t,0(s)",	47,  2, 0b0010010 },
-	{ "amoand.w.aq","R",	"d,t,0(s)",	47,  2, 0b0110010 },
-	{ "amoor.w.aq",	"R",	"d,t,0(s)",	47,  2, 0b0100010 },
-	{ "amomin.w.aq","R",	"d,t,0(s)",	47,  2, 0b1000010 },
-	{ "amomax.w.aq","R",	"d,t,0(s)",	47,  2, 0b1010010 },
-	{ "amominu.w.aq","R",	"d,t,0(s)",	47,  2, 0b1100010 },
-	{ "amomaxu.w.aq","R",	"d,t,0(s)",	47,  2, 0b1110010 },
-	{ "amoswap.w.rl","R",	"d,t,0(s)",	47,  2, 0b0000110 },
-	{ "amoadd.w.rl","R",	"d,t,0(s)",	47,  2, 0b0000001 },
-	{ "amoxor.w.rl","R",	"d,t,0(s)",	47,  2, 0b0010001 },
-	{ "amoand.w.rl","R",	"d,t,0(s)",	47,  2, 0b0110001 },
-	{ "amoor.w.rl",	"R",	"d,t,0(s)",	47,  2, 0b0100001 },
-	{ "amomin.w.rl","R",	"d,t,0(s)",	47,  2, 0b1000001 },
-	{ "amomax.w.rl","R",	"d,t,0(s)",	47,  2, 0b1010001 },
-	{ "amominu.w.rl","R",	"d,t,0(s)",	47,  2, 0b1100001 },
-	{ "amomaxu.w.rl","R",	"d,t,0(s)",	47,  2, 0b1110001 },
-	{ "amoswap.d",	"R",	"d,t,0(s)",	47,  3, 0b0000100 },
-	{ "amoadd.d",	"R",	"d,t,0(s)",	47,  3, 0b0000000 },
-	{ "amoxor.d",	"R",	"d,t,0(s)",	47,  3, 0b0010000 },
-	{ "amoand.d",	"R",	"d,t,0(s)",	47,  3, 0b0110000 },
-	{ "amoor.d",	"R",	"d,t,0(s)",	47,  3, 0b0100000 },
-	{ "amomin.d",	"R",	"d,t,0(s)",	47,  3, 0b1000000 },
-	{ "amomax.d",	"R",	"d,t,0(s)",	47,  3, 0b1010000 },
-	{ "amominu.d",	"R",	"d,t,0(s)",	47,  3, 0b1100000 },
-	{ "amomaxu.d",	"R",	"d,t,0(s)",	47,  3, 0b1110000 },
-	{ "lr.d.aq",	"R",	"d,t,0(s)",	47,  3, 0b0001000 },
-	{ "sc.d.aq",	"R",	"d,t,0(s)",	47,  3, 0b0001100 },
-	{ "amoswap.d.aq","R",	"d,t,0(s)",	47,  3, 0b0000110 },
-	{ "amoadd.d.aq","R",	"d,t,0(s)",	47,  3, 0b0000010 },
-	{ "amoxor.d.aq","R",	"d,t,0(s)",	47,  3, 0b0010010 },
-	{ "amoand.d.aq","R",	"d,t,0(s)",	47,  3, 0b0110010 },
-	{ "amoor.d.aq",	"R",	"d,t,0(s)",	47,  3, 0b0100010 },
-	{ "amomin.d.aq","R",	"d,t,0(s)",	47,  3, 0b1000010 },
-	{ "amomax.d.aq","R",	"d,t,0(s)",	47,  3, 0b1010010 },
-	{ "amominu.d.aq","R",	"d,t,0(s)",	47,  3, 0b1100010 },
-	{ "amomaxu.d.aq","R",	"d,t,0(s)",	47,  3, 0b1110010 },
-	{ "amoswap.d.rl","R",	"d,t,0(s)",	47,  3, 0b0000110 },
-	{ "amoadd.d.rl","R",	"d,t,0(s)",	47,  3, 0b0000001 },
-	{ "amoxor.d.rl","R",	"d,t,0(s)",	47,  3, 0b0010001 },
-	{ "amoand.d.rl","R",	"d,t,0(s)",	47,  3, 0b0110001 },
-	{ "amoor.d.rl",	"R",	"d,t,0(s)",	47,  3, 0b0100001 },
-	{ "amomin.d.rl","R",	"d,t,0(s)",	47,  3, 0b1000001 },
-	{ "amomax.d.rl","R",	"d,t,0(s)",	47,  3, 0b1010001 },
-	{ "amominu.d.rl","R",	"d,t,0(s)",	47,  3, 0b1100001 },
-	{ "amomaxu.d.rl","R",	"d,t,0(s)",	47,  3, 0b1110001 },
-	{ "add",	"R",	"d,s,t",	51,  0,  0 },
-	{ "sub",	"R",	"d,s,t",	51,  0,  0b0100000 },
-	{ "mul",	"R",	"d,s,t",	51,  0,  0b0000001 },
-	{ "sll",	"R",	"d,s,t",	51,  1,  0 },
-	{ "slt",	"R",	"d,s,t",	51,  2,  0 },
-	{ "sltu",	"R",	"d,s,t",	51,  3,  0 },
-	{ "xor",	"R",	"d,s,t",	51,  4,  0 },
-	{ "srl",	"R",	"d,s,t",	51,  5,  0 },
-	{ "sra",	"R",	"d,s,t",	51,  5,  0b0100000 },
-	{ "or",		"R",	"d,s,t",	51,  6,  0 },
-	{ "and",	"R",	"d,s,t",	51,  7,  0 },
-	{ "lui",	"U",	"d,u",		55, -1, -1 },
-	{ "addw",	"R",	"d,s,t",	59,  0,  0 },
-	{ "subw",	"R",	"d,s,t",	59,  0,  0b0100000 },
-	{ "mulw",	"R",	"d,s,t",	59,  0,  1 },
-	{ "sllw",	"R",	"d,s,t",	59,  1,  0 },
-	{ "srlw",	"R",	"d,s,t",	59,  5,  0 },
-	{ "sraw",	"R",	"d,s,t",	59,  5,  0b0100000 },
-	{ "beq",	"SB",	"s,t,p",	99,  0,  -1 },
-	{ "bne",	"SB",	"s,t,p",	99,  1,  -1 },
-	{ "blt",	"SB",	"s,t,p",	99,  4,  -1 },
-	{ "bge",	"SB",	"s,t,p",	99,  5,  -1 },
-	{ "bltu",	"SB",	"s,t,p",	99,  6,  -1 },
-	{ "bgeu",	"SB",	"s,t,p",	99,  7,  -1 },
-	{ "jalr",	"I",	"d,s,j",	103,  0, -1 },
-	{ "jal",	"UJ",	"a",		111, -1, -1 },
-	{ "eret",	"I",	"",		115,  0, 0b000100000000 },
-	{ "sfence.vm",	"I",	"",		115,  0, 0b000100000001 },
-	{ "wfi",	"I",	"",		115,  0, 0b000100000010 },
-	{ "csrrw",	"I",	"d,E,s",	115,  1, -1},
-	{ "csrrs",	"I",	"d,E,s",	115,  2, -1},
-	{ "csrrc",	"I",	"d,E,s",	115,  3, -1},
-	{ "csrrwi",	"I",	"d,E,Z",	115,  5, -1},
-	{ "csrrsi",	"I",	"d,E,Z",	115,  6, -1},
-	{ "csrrci",	"I",	"d,E,Z",	115,  7, -1},
-	{ NULL, NULL, NULL, 0, 0, 0 }
-};
+#define	RD_SHIFT	7
+#define	RD_MASK		(0x1f << RD_SHIFT)
+#define	RS1_SHIFT	15
+#define	RS1_MASK	(0x1f << RS1_SHIFT)
+#define	RS2_SHIFT	20
+#define	RS2_MASK	(0x1f << RS2_SHIFT)
+#define	IMM_SHIFT	20
+#define	IMM_MASK	(0xfff << IMM_SHIFT)
 
-struct csr_op {
-	char *name;
-	int imm;
-};
-
-static struct csr_op csr_name[] = {
-	{ "fflags",		0x001 },
-	{ "frm",		0x002 },
-	{ "fcsr",		0x003 },
-	{ "cycle",		0xc00 },
-	{ "time",		0xc01 },
-	{ "instret",		0xc02 },
-	{ "stats",		0x0c0 },
-	{ "uarch0",		0xcc0 },
-	{ "uarch1",		0xcc1 },
-	{ "uarch2",		0xcc2 },
-	{ "uarch3",		0xcc3 },
-	{ "uarch4",		0xcc4 },
-	{ "uarch5",		0xcc5 },
-	{ "uarch6",		0xcc6 },
-	{ "uarch7",		0xcc7 },
-	{ "uarch8",		0xcc8 },
-	{ "uarch9",		0xcc9 },
-	{ "uarch10",		0xcca },
-	{ "uarch11",		0xccb },
-	{ "uarch12",		0xccc },
-	{ "uarch13",		0xccd },
-	{ "uarch14",		0xcce },
-	{ "uarch15",		0xccf },
-	{ "sstatus",		0x100 },
-	{ "stvec",		0x101 },
-	{ "sie",		0x104 },
-	{ "sscratch",		0x140 },
-	{ "sepc",		0x141 },
-	{ "sip",		0x144 },
-	{ "sptbr",		0x180 },
-	{ "sasid",		0x181 },
-	{ "cyclew",		0x900 },
-	{ "timew",		0x901 },
-	{ "instretw",		0x902 },
-	{ "stime",		0xd01 },
-	{ "scause",		0xd42 },
-	{ "sbadaddr",		0xd43 },
-	{ "stimew",		0xa01 },
-	{ "mstatus",		0x300 },
-	{ "mtvec",		0x301 },
-	{ "mtdeleg",		0x302 },
-	{ "mie",		0x304 },
-	{ "mtimecmp",		0x321 },
-	{ "mscratch",		0x340 },
-	{ "mepc",		0x341 },
-	{ "mcause",		0x342 },
-	{ "mbadaddr",		0x343 },
-	{ "mip",		0x344 },
-	{ "mtime",		0x701 },
-	{ "mcpuid",		0xf00 },
-	{ "mimpid",		0xf01 },
-	{ "mhartid",		0xf10 },
-	{ "mtohost",		0x780 },
-	{ "mfromhost",		0x781 },
-	{ "mreset",		0x782 },
-	{ "send_ipi",		0x783 },
-	{ "miobase",		0x784 },
-	{ "cycleh",		0xc80 },
-	{ "timeh",		0xc81 },
-	{ "instreth",		0xc82 },
-	{ "cyclehw",		0x980 },
-	{ "timehw",		0x981 },
-	{ "instrethw",		0x982 },
-	{ "stimeh",		0xd81 },
-	{ "stimehw",		0xa81 },
-	{ "mtimecmph",		0x361 },
-	{ "mtimeh",		0x741 },
-	{ NULL,	0 }
-};
-
 static char *reg_name[32] = {
 	"zero",	"ra",	"sp",	"gp",	"tp",	"t0",	"t1",	"t2",
 	"s0",	"s1",	"a0",	"a1",	"a2",	"a3",	"a4",	"a5",
@@ -274,202 +68,536 @@ static char *reg_name[32] = {
 	"s8",	"s9",	"s10",	"s11",	"t3",	"t4",	"t5",	"t6"
 };
 
-static int32_t
-get_imm(InstFmt i, char *type, uint32_t *val)
-{
-	int imm;
+static char *fp_reg_name[32] = {
+	"ft0", "ft1", "ft2",  "ft3",  "ft4", "ft5", "ft6",  "ft7",
+	"fs0", "fs1", "fa0",  "fa1",  "fa2", "fa3", "fa4",  "fa5",
+	"fa6", "fa7", "fs2",  "fs3",  "fs4", "fs5", "fs6",  "fs7",
+	"fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
+};
 
-	imm = 0;
+struct riscv_op {
+	char *name;
+	char *fmt;
+	int match;
+	int mask;
+	int (*match_func)(struct riscv_op *op, uint32_t insn);
+};
 
-	if (strcmp(type, "I") == 0) {
-		imm = i.IType.imm;
-		*val = imm;
-		if (imm & (1 << 11))
-			imm |= (0xfffff << 12);	/* sign extend */
+static int
+m_op(struct riscv_op *op, uint32_t insn)
+{
 
-	} else if (strcmp(type, "S") == 0) {
-		imm = i.SType.imm0_4;
-		imm |= (i.SType.imm5_11 << 5);
-		*val = imm;
-		if (imm & (1 << 11))
-			imm |= (0xfffff << 12);	/* sign extend */
+	if (((insn ^ op->match) & op->mask) == 0)
+		return (1);
 
-	} else if (strcmp(type, "U") == 0) {
-		imm = i.UType.imm12_31;
-		*val = imm;
+	return (0);
+}
 
-	} else if (strcmp(type, "UJ") == 0) {
-		imm = i.UJType.imm12_19 << 12;
-		imm |= i.UJType.imm11 << 11;
-		imm |= i.UJType.imm1_10 << 1;
-		imm |= i.UJType.imm20 << 20;
-		*val = imm;
-		if (imm & (1 << 20))
-			imm |= (0xfff << 21);	/* sign extend */
+static struct riscv_op riscv_opcodes[] = {
+	/* Aliases first */
+	{"ret","", MATCH_JALR | (X_RA << RS1_SHIFT),
+	    MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK, m_op },
 
-	} else if (strcmp(type, "SB") == 0) {
-		imm = i.SBType.imm11 << 11;
-		imm |= i.SBType.imm1_4 << 1;
-		imm |= i.SBType.imm5_10 << 5;
-		imm |= i.SBType.imm12 << 12;
-		*val = imm;
-		if (imm & (1 << 12))
-			imm |= (0xfffff << 12);	/* sign extend */
-	}
+	{ "beq",	"s,t,p", 	MATCH_BEQ, MASK_BEQ,		m_op },
+	{ "bne",	"s,t,p", 	MATCH_BNE, MASK_BNE,		m_op },
+	{ "blt",	"s,t,p", 	MATCH_BLT, MASK_BLT,		m_op },
+	{ "bge",	"s,t,p", 	MATCH_BGE, MASK_BGE,		m_op },
+	{ "bltu",	"s,t,p", 	MATCH_BLTU, MASK_BLTU,		m_op },
+	{ "bgeu",	"s,t,p", 	MATCH_BGEU, MASK_BGEU,		m_op },
+	{ "jalr",	"d,o(s)", 	MATCH_JALR, MASK_JALR,		m_op },
+	{ "jal",	"d,a", 		MATCH_JAL, MASK_JAL,		m_op },
+	{ "lui",	"d,u", 		MATCH_LUI, MASK_LUI,		m_op },
+	{ "auipc",	"d,u", 		MATCH_AUIPC, MASK_AUIPC,	m_op },
+	{ "addi",	"d,s,j", 	MATCH_ADDI, MASK_ADDI,		m_op },
+	{ "slli",	"d,s,>", 	MATCH_SLLI, MASK_SLLI,		m_op },
+	{ "slti",	"d,s,j", 	MATCH_SLTI, MASK_SLTI,		m_op },
+	{ "sltiu",	"d,s,j", 	MATCH_SLTIU, MASK_SLTIU,	m_op },
+	{ "xori",	"d,s,j", 	MATCH_XORI, MASK_XORI,		m_op },
+	{ "srli",	"d,s,>", 	MATCH_SRLI, MASK_SRLI,		m_op },
+	{ "srai",	"d,s,>", 	MATCH_SRAI, MASK_SRAI,		m_op },
+	{ "ori",	"d,s,j", 	MATCH_ORI, MASK_ORI,		m_op },
+	{ "andi",	"d,s,j", 	MATCH_ANDI, MASK_ANDI,		m_op },
+	{ "add",	"d,s,t", 	MATCH_ADD, MASK_ADD,		m_op },
+	{ "sub",	"d,s,t", 	MATCH_SUB, MASK_SUB,		m_op },
+	{ "sll",	"d,s,t", 	MATCH_SLL, MASK_SLL,		m_op },
+	{ "slt",	"d,s,t", 	MATCH_SLT, MASK_SLT,		m_op },
+	{ "sltu",	"d,s,t", 	MATCH_SLTU, MASK_SLTU,		m_op },
+	{ "xor",	"d,s,t", 	MATCH_XOR, MASK_XOR,		m_op },
+	{ "srl",	"d,s,t", 	MATCH_SRL, MASK_SRL,		m_op },
+	{ "sra",	"d,s,t", 	MATCH_SRA, MASK_SRA,		m_op },
+	{ "or",		"d,s,t", 	MATCH_OR, MASK_OR,		m_op },
+	{ "and",	"d,s,t", 	MATCH_AND, MASK_AND,		m_op },
+	{ "addiw",	"d,s,j", 	MATCH_ADDIW, MASK_ADDIW,	m_op },
+	{ "slliw",	"d,s,<", 	MATCH_SLLIW, MASK_SLLIW,	m_op },
+	{ "srliw",	"d,s,<", 	MATCH_SRLIW, MASK_SRLIW,	m_op },
+	{ "sraiw",	"d,s,<", 	MATCH_SRAIW, MASK_SRAIW,	m_op },
+	{ "addw",	"d,s,t", 	MATCH_ADDW, MASK_ADDW,		m_op },
+	{ "subw",	"d,s,t", 	MATCH_SUBW, MASK_SUBW,		m_op },
+	{ "sllw",	"d,s,t", 	MATCH_SLLW, MASK_SLLW,		m_op },
+	{ "srlw",	"d,s,t", 	MATCH_SRLW, MASK_SRLW,		m_op },
+	{ "sraw",	"d,s,t", 	MATCH_SRAW, MASK_SRAW,		m_op },
+	{ "lb",		"d,o(s)", 	MATCH_LB, MASK_LB,		m_op },
+	{ "lh",		"d,o(s)", 	MATCH_LH, MASK_LH,		m_op },
+	{ "lw",		"d,o(s)", 	MATCH_LW, MASK_LW,		m_op },
+	{ "ld",		"d,o(s)", 	MATCH_LD, MASK_LD,		m_op },
+	{ "lbu",	"d,o(s)", 	MATCH_LBU, MASK_LBU,		m_op },
+	{ "lhu",	"d,o(s)", 	MATCH_LHU, MASK_LHU,		m_op },
+	{ "lwu",	"d,o(s)", 	MATCH_LWU, MASK_LWU,		m_op },
+	{ "sb",		"t,q(s)", 	MATCH_SB, MASK_SB,		m_op },
+	{ "sh",		"t,q(s)", 	MATCH_SH, MASK_SH,		m_op },
+	{ "sw",		"t,q(s)", 	MATCH_SW, MASK_SW,		m_op },
+	{ "sd",		"t,q(s)", 	MATCH_SD, MASK_SD,		m_op },
+	{ "fence",	"P,Q",		MATCH_FENCE, MASK_FENCE,	m_op },
+	{ "fence.i",	"",		MATCH_FENCE_I, MASK_FENCE_I,	m_op },
+	{ "mul",	"d,s,t", 	MATCH_MUL, MASK_MUL,		m_op },
+	{ "mulh",	"d,s,t", 	MATCH_MULH, MASK_MULH,		m_op },
+	{ "mulhsu",	"d,s,t", 	MATCH_MULHSU, MASK_MULHSU,	m_op },
+	{ "mulhu",	"d,s,t", 	MATCH_MULHU, MASK_MULHU,	m_op },
+	{ "div",	"d,s,t", 	MATCH_DIV, MASK_DIV,		m_op },
+	{ "divu",	"d,s,t", 	MATCH_DIVU, MASK_DIVU,		m_op },
+	{ "rem",	"d,s,t", 	MATCH_REM, MASK_REM,		m_op },
+	{ "remu",	"d,s,t", 	MATCH_REMU, MASK_REMU,		m_op },
+	{ "mulw",	"d,s,t", 	MATCH_MULW, MASK_MULW,		m_op },
+	{ "divw",	"d,s,t", 	MATCH_DIVW, MASK_DIVW,		m_op },
+	{ "divuw",	"d,s,t", 	MATCH_DIVUW, MASK_DIVUW,	m_op },
+	{ "remw",	"d,s,t", 	MATCH_REMW, MASK_REMW,		m_op },
+	{ "remuw",	"d,s,t", 	MATCH_REMUW, MASK_REMUW,	m_op },
+	{ "amoadd.w",	"d,t,0(s)", 	MATCH_AMOADD_W, MASK_AMOADD_W,	m_op },
+	{ "amoxor.w",	"d,t,0(s)", 	MATCH_AMOXOR_W, MASK_AMOXOR_W,	m_op },
+	{ "amoor.w",	"d,t,0(s)", 	MATCH_AMOOR_W, MASK_AMOOR_W,	m_op },
+	{ "amoand.w",	"d,t,0(s)", 	MATCH_AMOAND_W, MASK_AMOAND_W,	m_op },
+	{ "amomin.w",	"d,t,0(s)", 	MATCH_AMOMIN_W, MASK_AMOMIN_W,	m_op },
+	{ "amomax.w",	"d,t,0(s)", 	MATCH_AMOMAX_W, MASK_AMOMAX_W,	m_op },
+	{ "amominu.w",	"d,t,0(s)", 	MATCH_AMOMINU_W, MASK_AMOMINU_W,m_op },
+	{ "amomaxu.w",	"d,t,0(s)", 	MATCH_AMOMAXU_W, MASK_AMOMAXU_W,m_op },
+	{ "amoswap.w",	"d,t,0(s)", 	MATCH_AMOSWAP_W, MASK_AMOSWAP_W,m_op },
+	{ "lr.w",	"d,0(s)", 	MATCH_LR_W, MASK_LR_W,		m_op },
+	{ "sc.w",	"d,t,0(s)", 	MATCH_SC_W, MASK_SC_W,		m_op },
+	{ "amoadd.d",	"d,t,0(s)", 	MATCH_AMOADD_D, MASK_AMOADD_D,	m_op },
+	{ "amoxor.d",	"d,t,0(s)", 	MATCH_AMOXOR_D, MASK_AMOXOR_D,	m_op },
+	{ "amoor.d",	"d,t,0(s)", 	MATCH_AMOOR_D, MASK_AMOOR_D,	m_op },
+	{ "amoand.d",	"d,t,0(s)", 	MATCH_AMOAND_D, MASK_AMOAND_D,	m_op },
+	{ "amomin.d",	"d,t,0(s)", 	MATCH_AMOMIN_D, MASK_AMOMIN_D,	m_op },
+	{ "amomax.d",	"d,t,0(s)", 	MATCH_AMOMAX_D, MASK_AMOMAX_D,	m_op },
+	{ "amominu.d",	"d,t,0(s)", 	MATCH_AMOMINU_D, MASK_AMOMINU_D,m_op },
+	{ "amomaxu.d",	"d,t,0(s)", 	MATCH_AMOMAXU_D, MASK_AMOMAXU_D,m_op },
+	{ "amoswap.d",	"d,t,0(s)", 	MATCH_AMOSWAP_D, MASK_AMOSWAP_D,m_op },
+	{ "lr.d",	"d,0(s)", 	MATCH_LR_D, MASK_LR_D,		m_op },
+	{ "sc.d",	"d,t,0(s)", 	MATCH_SC_D, MASK_SC_D,		m_op },
+	{ "ecall",	"", 		MATCH_ECALL, MASK_ECALL,	m_op },
+	{ "ebreak",	"", 		MATCH_EBREAK, MASK_EBREAK,	m_op },
+	{ "uret",	"", 		MATCH_URET, MASK_URET,		m_op },
+	{ "sret",	"", 		MATCH_SRET, MASK_SRET,		m_op },
+	{ "mret",	"", 		MATCH_MRET, MASK_MRET,		m_op },
+	{ "dret",	"", 		MATCH_DRET, MASK_DRET,		m_op },
+	{ "sfence.vma",	"", 	MATCH_SFENCE_VMA, MASK_SFENCE_VMA,	m_op },
+	{ "wfi",	"", 		MATCH_WFI, MASK_WFI,		m_op },
+	{ "csrrw",	"d,E,s", 	MATCH_CSRRW, MASK_CSRRW,	m_op },
+	{ "csrrs",	"d,E,s", 	MATCH_CSRRS, MASK_CSRRS,	m_op },
+	{ "csrrc",	"d,E,s", 	MATCH_CSRRC, MASK_CSRRC,	m_op },
+	{ "csrrwi",	"d,E,Z", 	MATCH_CSRRWI, MASK_CSRRWI,	m_op },
+	{ "csrrsi",	"d,E,Z", 	MATCH_CSRRSI, MASK_CSRRSI,	m_op },
+	{ "csrrci",	"d,E,Z", 	MATCH_CSRRCI, MASK_CSRRCI,	m_op },
+	{ "fadd.s",	"D,S,T", 	MATCH_FADD_S, MASK_FADD_S,	m_op },
+	{ "fsub.s",	"D,S,T", 	MATCH_FSUB_S, MASK_FSUB_S,	m_op },
+	{ "fmul.s",	"D,S,T", 	MATCH_FMUL_S, MASK_FMUL_S,	m_op },
+	{ "fdiv.s",	"D,S,T", 	MATCH_FDIV_S, MASK_FDIV_S,	m_op },
+	{ "fsgnj.s",	"D,S,T", 	MATCH_FSGNJ_S, MASK_FSGNJ_S,	m_op },
+	{ "fsgnjn.s",	"D,S,T", 	MATCH_FSGNJN_S, MASK_FSGNJN_S,	m_op },
+	{ "fsgnjx.s",	"D,S,T", 	MATCH_FSGNJX_S, MASK_FSGNJX_S,	m_op },
+	{ "fmin.s",	"D,S,T", 	MATCH_FMIN_S, MASK_FMIN_S,	m_op },
+	{ "fmax.s",	"D,S,T", 	MATCH_FMAX_S, MASK_FMAX_S,	m_op },
+	{ "fsqrt.s",	"D,S", 		MATCH_FSQRT_S, MASK_FSQRT_S,	m_op },
+	{ "fadd.d",	"D,S,T", 	MATCH_FADD_D, MASK_FADD_D,	m_op },
+	{ "fsub.d",	"D,S,T", 	MATCH_FSUB_D, MASK_FSUB_D,	m_op },
+	{ "fmul.d",	"D,S,T", 	MATCH_FMUL_D, MASK_FMUL_D,	m_op },
+	{ "fdiv.d",	"D,S,T", 	MATCH_FDIV_D, MASK_FDIV_D,	m_op },
+	{ "fsgnj.d",	"D,S,T", 	MATCH_FSGNJ_D, MASK_FSGNJ_D,	m_op },
+	{ "fsgnjn.d",	"D,S,T", 	MATCH_FSGNJN_D, MASK_FSGNJN_D,	m_op },
+	{ "fsgnjx.d",	"D,S,T", 	MATCH_FSGNJX_D, MASK_FSGNJX_D,	m_op },
+	{ "fmin.d",	"D,S,T", 	MATCH_FMIN_D, MASK_FMIN_D,	m_op },
+	{ "fmax.d",	"D,S,T", 	MATCH_FMAX_D, MASK_FMAX_D,	m_op },
+	{ "fcvt.s.d",	"D,S", 		MATCH_FCVT_S_D, MASK_FCVT_S_D,	m_op },
+	{ "fcvt.d.s",	"D,S", 		MATCH_FCVT_D_S, MASK_FCVT_D_S,	m_op },
+	{ "fsqrt.d",	"D,S", 		MATCH_FSQRT_D, MASK_FSQRT_D,	m_op },
+	{ "fadd.q",	"D,S,T", 	MATCH_FADD_Q, MASK_FADD_Q,	m_op },
+	{ "fsub.q",	"D,S,T", 	MATCH_FSUB_Q, MASK_FSUB_Q,	m_op },
+	{ "fmul.q",	"D,S,T", 	MATCH_FMUL_Q, MASK_FMUL_Q,	m_op },
+	{ "fdiv.q",	"D,S,T", 	MATCH_FDIV_Q, MASK_FDIV_Q,	m_op },
+	{ "fsgnj.q",	"D,S,T", 	MATCH_FSGNJ_Q, MASK_FSGNJ_Q,	m_op },
+	{ "fsgnjn.q",	"D,S,T", 	MATCH_FSGNJN_Q, MASK_FSGNJN_Q,	m_op },
+	{ "fsgnjx.q",	"D,S,T", 	MATCH_FSGNJX_Q, MASK_FSGNJX_Q,	m_op },
+	{ "fmin.q",	"D,S,T", 	MATCH_FMIN_Q, MASK_FMIN_Q,	m_op },
+	{ "fmax.q",	"D,S,T", 	MATCH_FMAX_Q, MASK_FMAX_Q,	m_op },
+	{ "fcvt.s.q",	"D,S", 		MATCH_FCVT_S_Q, MASK_FCVT_S_Q,	m_op },
+	{ "fcvt.q.s",	"D,S", 		MATCH_FCVT_Q_S, MASK_FCVT_Q_S,	m_op },
+	{ "fcvt.d.q",	"D,S", 		MATCH_FCVT_D_Q, MASK_FCVT_D_Q,	m_op },
+	{ "fcvt.q.d",	"D,S", 		MATCH_FCVT_Q_D, MASK_FCVT_Q_D,	m_op },
+	{ "fsqrt.q",	"D,S", 		MATCH_FSQRT_Q, MASK_FSQRT_Q,	m_op },
+	{ "fle.s",	"d,S,T", 	MATCH_FLE_S, MASK_FLE_S,	m_op },
+	{ "flt.s",	"d,S,T", 	MATCH_FLT_S, MASK_FLT_S,	m_op },
+	{ "feq.s",	"d,S,T", 	MATCH_FEQ_S, MASK_FEQ_S,	m_op },
+	{ "fle.d",	"d,S,T", 	MATCH_FLE_D, MASK_FLE_D,	m_op },
+	{ "flt.d",	"d,S,T", 	MATCH_FLT_D, MASK_FLT_D,	m_op },
+	{ "feq.d",	"d,S,T", 	MATCH_FEQ_D, MASK_FEQ_D,	m_op },
+	{ "fle.q",	"d,S,T", 	MATCH_FLE_Q, MASK_FLE_Q,	m_op },
+	{ "flt.q",	"d,S,T", 	MATCH_FLT_Q, MASK_FLT_Q,	m_op },
+	{ "feq.q",	"d,S,T", 	MATCH_FEQ_Q, MASK_FEQ_Q,	m_op },
+	{ "fcvt.w.s",	"d,S", 		MATCH_FCVT_W_S, MASK_FCVT_W_S,	m_op },
+	{ "fcvt.wu.s",	"d,S", 		MATCH_FCVT_WU_S, MASK_FCVT_WU_S,m_op },
+	{ "fcvt.l.s",	"d,S", 		MATCH_FCVT_L_S, MASK_FCVT_L_S,	m_op },
+	{ "fcvt.lu.s",	"d,S", 		MATCH_FCVT_LU_S, MASK_FCVT_LU_S,m_op },
+	{ "fmv.x.w",	"d,S", 		MATCH_FMV_X_W, MASK_FMV_X_W,	m_op },
+	{ "fclass.s",	"d,S", 		MATCH_FCLASS_S, MASK_FCLASS_S,	m_op },
+	{ "fcvt.w.d",	"d,S", 		MATCH_FCVT_W_D, MASK_FCVT_W_D,	m_op },
+	{ "fcvt.wu.d",	"d,S", 		MATCH_FCVT_WU_D, MASK_FCVT_WU_D,m_op },
+	{ "fcvt.l.d",	"d,S", 		MATCH_FCVT_L_D, MASK_FCVT_L_D,	m_op },
+	{ "fcvt.lu.d",	"d,S", 		MATCH_FCVT_LU_D, MASK_FCVT_LU_D,m_op },
+	{ "fmv.x.d",	"d,S", 		MATCH_FMV_X_D, MASK_FMV_X_D,	m_op },
+	{ "fclass.d",	"d,S", 		MATCH_FCLASS_D, MASK_FCLASS_D,	m_op },
+	{ "fcvt.w.q",	"d,S", 		MATCH_FCVT_W_Q, MASK_FCVT_W_Q,	m_op },
+	{ "fcvt.wu.q",	"d,S", 		MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q,m_op },
+	{ "fcvt.l.q",	"d,S", 		MATCH_FCVT_L_Q, MASK_FCVT_L_Q,	m_op },
+	{ "fcvt.lu.q",	"d,S", 		MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q,m_op },
+	{ "fmv.x.q",	"d,S", 		MATCH_FMV_X_Q, MASK_FMV_X_Q,	m_op },
+	{ "fclass.q",	"d,S", 		MATCH_FCLASS_Q, MASK_FCLASS_Q,	m_op },
+	{ "fcvt.s.w",	"D,s", 		MATCH_FCVT_S_W, MASK_FCVT_S_W,	m_op },
+	{ "fcvt.s.wu",	"D,s", 		MATCH_FCVT_S_WU, MASK_FCVT_S_WU,m_op },
+	{ "fcvt.s.l",	"D,s", 		MATCH_FCVT_S_L, MASK_FCVT_S_L,	m_op },
+	{ "fcvt.s.lu",	"D,s", 		MATCH_FCVT_S_LU, MASK_FCVT_S_LU,m_op },
+	{ "fmv.w.x",	"D,s", 		MATCH_FMV_W_X, MASK_FMV_W_X,	m_op },
+	{ "fcvt.d.w",	"D,s", 		MATCH_FCVT_D_W, MASK_FCVT_D_W,	m_op },
+	{ "fcvt.d.wu",	"D,s", 		MATCH_FCVT_D_WU, MASK_FCVT_D_WU,m_op },
+	{ "fcvt.d.l",	"D,s", 		MATCH_FCVT_D_L, MASK_FCVT_D_L,	m_op },
+	{ "fcvt.d.lu",	"D,s", 		MATCH_FCVT_D_LU, MASK_FCVT_D_LU,m_op },
+	{ "fmv.d.x",	"D,s", 		MATCH_FMV_D_X, MASK_FMV_D_X,	m_op },
+	{ "fcvt.q.w",	"D,s", 		MATCH_FCVT_Q_W, MASK_FCVT_Q_W,	m_op },
+	{ "fcvt.q.wu",	"D,s", 		MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU,m_op },
+	{ "fcvt.q.l",	"D,s", 		MATCH_FCVT_Q_L, MASK_FCVT_Q_L,	m_op },
+	{ "fcvt.q.lu",	"D,s", 		MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU,m_op },
+	{ "fmv.q.x",	"D,s", 		MATCH_FMV_Q_X, MASK_FMV_Q_X,	m_op },
+	{ "flw",	"D,o(s)", 	MATCH_FLW, MASK_FLW,		m_op },
+	{ "fld",	"D,o(s)", 	MATCH_FLD, MASK_FLD,		m_op },
+	{ "flq",	"D,o(s)", 	MATCH_FLQ, MASK_FLQ,		m_op },
+	{ "fsw",	"T,q(s)", 	MATCH_FSW, MASK_FSW,		m_op },
+	{ "fsd",	"T,q(s)", 	MATCH_FSD, MASK_FSD,		m_op },
+	{ "fsq",	"T,q(s)", 	MATCH_FSQ, MASK_FSQ,		m_op },
+	{ "fmadd.s",	"D,S,T,R", 	MATCH_FMADD_S, MASK_FMADD_S,	m_op },
+	{ "fmsub.s",	"D,S,T,R", 	MATCH_FMSUB_S, MASK_FMSUB_S,	m_op },
+	{ "fnmsub.s",	"D,S,T,R", 	MATCH_FNMSUB_S, MASK_FNMSUB_S,	m_op },
+	{ "fnmadd.s",	"D,S,T,R", 	MATCH_FNMADD_S, MASK_FNMADD_S,	m_op },
+	{ "fmadd.d",	"D,S,T,R", 	MATCH_FMADD_D, MASK_FMADD_D,	m_op },
+	{ "fmsub.d",	"D,S,T,R", 	MATCH_FMSUB_D, MASK_FMSUB_D,	m_op },
+	{ "fnmsub.d",	"D,S,T,R", 	MATCH_FNMSUB_D, MASK_FNMSUB_D,	m_op },
+	{ "fnmadd.d",	"D,S,T,R", 	MATCH_FNMADD_D, MASK_FNMADD_D,	m_op },
+	{ "fmadd.q",	"D,S,T,R", 	MATCH_FMADD_Q, MASK_FMADD_Q,	m_op },
+	{ "fmsub.q",	"D,S,T,R", 	MATCH_FMSUB_Q, MASK_FMSUB_Q,	m_op },
+	{ "fnmsub.q",	"D,S,T,R", 	MATCH_FNMSUB_Q, MASK_FNMSUB_Q,	m_op },
+	{ "fnmadd.q",	"D,S,T,R", 	MATCH_FNMADD_Q, MASK_FNMADD_Q,	m_op },
+	{ NULL, NULL, 0, 0, NULL },
+};
 
-	return (imm);
-}
+static struct riscv_op riscv_c_opcodes[] = {
+	/* Aliases first */
+	{ "ret","",MATCH_C_JR | (X_RA << RD_SHIFT), MASK_C_JR | RD_MASK, m_op},
 
+	/* C-Compressed ISA Extension Instructions */
+	{ "c.nop",	"", 		MATCH_C_NOP, MASK_C_NOP,	m_op },
+	{ "c.ebreak",	"", 		MATCH_C_EBREAK, MASK_C_EBREAK,	m_op },
+	{ "c.jr",	"d", 		MATCH_C_JR, MASK_C_JR,		m_op },
+	{ "c.jalr",	"d", 		MATCH_C_JALR, MASK_C_JALR,	m_op },
+	{ "c.jal",	"Ca", 		MATCH_C_JAL, MASK_C_JAL,	m_op },
+	{ "c.ld",	"Ct,Cl(Cs)", 	MATCH_C_LD, MASK_C_LD,		m_op },
+	{ "c.sd",	"Ct,Cl(Cs)", 	MATCH_C_SD, MASK_C_SD,		m_op },
+	{ "c.addiw",	"d,Co", 	MATCH_C_ADDIW, MASK_C_ADDIW,	m_op },
+	{ "c.ldsp",	"d,Cn(Cc)", 	MATCH_C_LDSP, MASK_C_LDSP,	m_op },
+	{ "c.sdsp",	"CV,CN(Cc)", 	MATCH_C_SDSP, MASK_C_SDSP,	m_op },
+	{ "c.addi4spn",	"", 	MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN,	m_op },
+	{ "c.addi16sp",	"", 	MATCH_C_ADDI16SP, MASK_C_ADDI16SP,	m_op },
+	{ "c.fld",	"CD,Cl(Cs)", 	MATCH_C_FLD, MASK_C_FLD,	m_op },
+	{ "c.lw",	"Ct,Ck(Cs)", 	MATCH_C_LW, MASK_C_LW,		m_op },
+	{ "c.flw",	"CD,Ck(Cs)", 	MATCH_C_FLW, MASK_C_FLW,	m_op },
+	{ "c.fsd",	"CD,Cl(Cs)", 	MATCH_C_FSD, MASK_C_FSD,	m_op },
+	{ "c.sw",	"Ct,Ck(Cs)", 	MATCH_C_SW, MASK_C_SW,		m_op },
+	{ "c.fsw",	"CD,Ck(Cs)", 	MATCH_C_FSW, MASK_C_FSW,	m_op },
+	{ "c.addi",	"d,Co", 	MATCH_C_ADDI, MASK_C_ADDI,	m_op },
+	{ "c.li",	"d,Co", 	MATCH_C_LI, MASK_C_LI,		m_op },
+	{ "c.lui",	"d,Cu", 	MATCH_C_LUI, MASK_C_LUI,	m_op },
+	{ "c.srli",	"Cs,C>", 	MATCH_C_SRLI, MASK_C_SRLI,	m_op },
+	{ "c.srai",	"Cs,C>", 	MATCH_C_SRAI, MASK_C_SRAI,	m_op },
+	{ "c.andi",	"Cs,Co", 	MATCH_C_ANDI, MASK_C_ANDI,	m_op },
+	{ "c.sub",	"Cs,Ct", 	MATCH_C_SUB, MASK_C_SUB,	m_op },
+	{ "c.xor",	"Cs,Ct", 	MATCH_C_XOR, MASK_C_XOR,	m_op },
+	{ "c.or",	"Cs,Ct", 	MATCH_C_OR, MASK_C_OR,		m_op },
+	{ "c.and",	"Cs,Ct", 	MATCH_C_AND, MASK_C_AND,	m_op },
+	{ "c.subw",	"Cs,Ct", 	MATCH_C_SUBW, MASK_C_SUBW,	m_op },
+	{ "c.addw",	"Cs,Ct", 	MATCH_C_ADDW, MASK_C_ADDW,	m_op },
+	{ "c.j",	"Ca", 		MATCH_C_J, MASK_C_J,		m_op },
+	{ "c.beqz",	"Cs,Cp", 	MATCH_C_BEQZ, MASK_C_BEQZ,	m_op },
+	{ "c.bnez",	"Cs,Cp", 	MATCH_C_BNEZ, MASK_C_BNEZ,	m_op },
+	{ "c.slli",	"d,C>", 	MATCH_C_SLLI, MASK_C_SLLI,	m_op },
+	{ "c.fldsp",	"D,Cn(Cc)", 	MATCH_C_FLDSP, MASK_C_FLDSP,	m_op },
+	{ "c.lwsp",	"d,Cm(Cc)", 	MATCH_C_LWSP, MASK_C_LWSP,	m_op },
+	{ "c.flwsp",	"D,Cm(Cc)", 	MATCH_C_FLWSP, MASK_C_FLWSP,	m_op },
+	{ "c.mv",	"d,CV", 	MATCH_C_MV, MASK_C_MV,		m_op },
+	{ "c.add",	"d,CV", 	MATCH_C_ADD, MASK_C_ADD,	m_op },
+	{ "c.fsdsp",	"CT,CN(Cc)", 	MATCH_C_FSDSP, MASK_C_FSDSP,	m_op },
+	{ "c.swsp",	"CV,CM(Cc)", 	MATCH_C_SWSP, MASK_C_SWSP,	m_op },
+	{ "c.fswsp",	"CT,CM(Cc)", 	MATCH_C_FSWSP, MASK_C_FSWSP,	m_op },
+	{ NULL, NULL, 0, 0, NULL },
+};
+
 static int
-oprint(struct riscv_op *op, vm_offset_t loc, int rd,
-    int rs1, int rs2, uint32_t val, vm_offset_t imm)
+oprint(struct riscv_op *op, vm_offset_t loc, int insn)
 {
+	uint32_t rd, rs1, rs2, rs3;
+	uint32_t val;
+	const char *csr_name;
+	int imm;
 	char *p;
-	int i;
 
 	p = op->fmt;
 
+	rd = (insn & RD_MASK) >> RD_SHIFT;
+	rs1 = (insn & RS1_MASK) >> RS1_SHIFT;
+	rs2 = (insn & RS2_MASK) >> RS2_SHIFT;
+
 	db_printf("%s\t", op->name);
 
 	while (*p) {
-		if (strncmp("d", p, 1) == 0)
+		switch (*p) {
+		case 'C':	/* C-Compressed ISA extension */
+			switch (*++p) {
+			case 't':
+				rd = (insn >> 2) & 0x7;
+				rd += 0x8;
+				db_printf("%s", reg_name[rd]);
+				break;
+			case 's':
+				rs2 = (insn >> 7) & 0x7;
+				rs2 += 0x8;
+				db_printf("%s", reg_name[rs2]);
+				break;
+			case 'l':
+				imm = ((insn >> 10) & 0x7) << 3;
+				imm |= ((insn >> 5) & 0x3) << 6;
+				if (imm & (1 << 8))
+					imm |= 0xffffff << 8;
+				db_printf("%d", imm);
+				break;
+			case 'k':
+				imm = ((insn >> 10) & 0x7) << 3;
+				imm |= ((insn >> 6) & 0x1) << 2;
+				imm |= ((insn >> 5) & 0x1) << 6;
+				if (imm & (1 << 8))
+					imm |= 0xffffff << 8;
+				db_printf("%d", imm);
+				break;
+			case 'c':
+				db_printf("sp");
+				break;
+			case 'n':
+				imm = ((insn >> 5) & 0x3) << 3;
+				imm |= ((insn >> 12) & 0x1) << 5;
+				imm |= ((insn >> 2) & 0x7) << 6;
+				if (imm & (1 << 8))
+					imm |= 0xffffff << 8;
+				db_printf("%d", imm);
+				break;
+			case 'N':
+				imm = ((insn >> 10) & 0x7) << 3;
+				imm |= ((insn >> 7) & 0x7) << 6;
+				if (imm & (1 << 8))
+					imm |= 0xffffff << 8;
+				db_printf("%d", imm);
+				break;
+			case 'u':
+				imm = ((insn >> 2) & 0x1f) << 0;
+				imm |= ((insn >> 12) & 0x1) << 5;
+				if (imm & (1 << 5))
+					imm |= (0x7ffffff << 5); /* sign ext */
+				db_printf("0x%lx", imm);
+				break;
+			case 'o':
+				imm = ((insn >> 2) & 0x1f) << 0;
+				imm |= ((insn >> 12) & 0x1) << 5;
+				if (imm & (1 << 5))
+					imm |= (0x7ffffff << 5); /* sign ext */
+				db_printf("%d", imm);
+				break;
+			case 'a':
+				/* imm[11|4|9:8|10|6|7|3:1|5] << 2 */
+				imm = ((insn >> 3) & 0x7) << 1;
+				imm |= ((insn >> 11) & 0x1) << 4;
+				imm |= ((insn >> 2) & 0x1) << 5;
+				imm |= ((insn >> 7) & 0x1) << 6;
+				imm |= ((insn >> 6) & 0x1) << 7;
+				imm |= ((insn >> 9) & 0x3) << 8;
+				imm |= ((insn >> 8) & 0x1) << 10;
+				imm |= ((insn >> 12) & 0x1) << 11;
+				if (imm & (1 << 11))
+					imm |= (0xfffff << 12);	/* sign ext */
+				db_printf("0x%lx", (loc + imm));
+				break;
+			case 'V':
+				rs2 = (insn >> 2) & 0x1f;
+				db_printf("%s", reg_name[rs2]);
+				break;
+			case '>':
+				imm = ((insn >> 2) & 0x1f) << 0;
+				imm |= ((insn >> 12) & 0x1) << 5;
+				db_printf("%d", imm);
+			};
+			break;
+		case 'd':
 			db_printf("%s", reg_name[rd]);
-
-		else if (strncmp("s", p, 1) == 0)
+			break;
+		case 'D':
+			db_printf("%s", fp_reg_name[rd]);
+			break;
+		case 's':
 			db_printf("%s", reg_name[rs1]);
-
-		else if (strncmp("t", p, 1) == 0)
+			break;
+		case 'S':
+			db_printf("%s", fp_reg_name[rs1]);
+			break;
+		case 't':
 			db_printf("%s", reg_name[rs2]);
-
-		else if (strncmp(">", p, 1) == 0)
-			db_printf("0x%x", rs2);
-
-		else if (strncmp("E", p, 1) == 0) {
-			for (i = 0; csr_name[i].name != NULL; i++)
-				if (csr_name[i].imm == val)
-					db_printf("%s",
-					    csr_name[i].name);
-		} else if (strncmp("Z", p, 1) == 0)
-			db_printf("%d", rs1);
-
-		else if (strncmp("<", p, 1) == 0)
-			db_printf("0x%x", rs2);
-
-		else if (strncmp("j", p, 1) == 0)
+			break;
+		case 'T':
+			db_printf("%s", fp_reg_name[rs2]);
+			break;
+		case 'R':
+			rs3 = (insn >> 27) & 0x1f;
+			db_printf("%s", fp_reg_name[rs3]);
+			break;
+		case 'Z':
+			imm = (insn >> 15) & 0x1f;
 			db_printf("%d", imm);
-
-		else if (strncmp("u", p, 1) == 0)
-			db_printf("0x%x", imm);
-
-		else if (strncmp("a", p, 1) == 0)
-			db_printf("0x%016lx", imm);
-
-		else if (strncmp("p", p, 1) == 0)
+			break;
+		case 'p':
+			imm = ((insn >> 8) & 0xf) << 1;
+			imm |= ((insn >> 25) & 0x3f) << 5;
+			imm |= ((insn >> 7) & 0x1) << 11;
+			imm |= ((insn >> 31) & 0x1) << 12;
+			if (imm & (1 << 12))
+				imm |= (0xfffff << 12);	/* sign extend */
 			db_printf("0x%016lx", (loc + imm));
-
-		else if (strlen(p) >= 4) {
-			if (strncmp("o(s)", p, 4) == 0)
-				db_printf("%d(%s)", imm, reg_name[rs1]);
-			else if (strncmp("q(s)", p, 4) == 0)
-				db_printf("%d(%s)", imm, reg_name[rs1]);
-			else if (strncmp("0(s)", p, 4) == 0)
-				db_printf("(%s)", reg_name[rs1]);
+			break;
+		case '(':
+		case ')':
+		case '[':
+		case ']':
+		case ',':
+			db_printf("%c", *p);
+			break;
+		case '0':
+			if (!p[1])
+				db_printf("%c", *p);
+			break;
+			
+		case 'o':
+			imm = (insn >> 20) & 0xfff;
+			if (imm & (1 << 11))
+				imm |= (0xfffff << 12);	/* sign extend */
+			db_printf("%d", imm);
+			break;
+		case 'q':
+			imm = (insn >> 7) & 0x1f;
+			imm |= ((insn >> 25) & 0x7f) << 5;
+			if (imm & (1 << 11))
+				imm |= (0xfffff << 12);	/* sign extend */
+			db_printf("%d", imm);
+			break;
+		case 'a':
+			/* imm[20|10:1|11|19:12] << 12 */
+			imm = ((insn >> 21) & 0x3ff) << 1;
+			imm |= ((insn >> 20) & 0x1) << 11;
+			imm |= ((insn >> 12) & 0xff) << 12;
+			imm |= ((insn >> 31) & 0x1) << 20;
+			if (imm & (1 << 20))
+				imm |= (0xfff << 20);	/* sign extend */
+			db_printf("0x%lx", (loc + imm));
+			break;
+		case 'u':
+			/* imm[31:12] << 12 */
+			imm = (insn >> 12) & 0xfffff;
+			if (imm & (1 << 20))
+				imm |= (0xfff << 20);	/* sign extend */
+			db_printf("0x%lx", imm);
+			break;
+		case 'j':
+			/* imm[11:0] << 20 */
+			imm = (insn >> 20) & 0xfff;
+			if (imm & (1 << 11))
+				imm |= (0xfffff << 12); /* sign extend */
+			db_printf("%d", imm);
+			break;
+		case '>':
+			val = (insn >> 20) & 0x3f;
+			db_printf("0x%x", val);
+			break;
+		case '<':
+			val = (insn >> 20) & 0x1f;
+			db_printf("0x%x", val);
+			break;
+		case 'E':
+			val = (insn >> 20) & 0xfff;
+			csr_name = NULL;
+			switch (val) {
+#define DECLARE_CSR(name, num) case num: csr_name = #name; break;
+#include "machine/encoding.h"
+#undef DECLARE_CSR
+			}
+			if (csr_name)
+				db_printf("%s", csr_name);
+			else
+				db_printf("0x%x", val);
+			break;
+		case 'P':
+			if (insn & (1 << 27)) db_printf("i");
+			if (insn & (1 << 26)) db_printf("o");
+			if (insn & (1 << 25)) db_printf("r");
+			if (insn & (1 << 24)) db_printf("w");
+			break;
+		case 'Q':
+			if (insn & (1 << 23)) db_printf("i");
+			if (insn & (1 << 22)) db_printf("o");
+			if (insn & (1 << 21)) db_printf("r");
+			if (insn & (1 << 20)) db_printf("w");
+			break;
 		}
 
-		while (*p && strncmp(p, ",", 1) != 0)
-			p++;
-
-		if (*p) {
-			db_printf(", ");
-			p++;
-		}
+		p++;
 	}
 
-
 	return (0);
 }
 
-static int
-match_type(InstFmt i, struct riscv_op *op, vm_offset_t loc)
-{
-	uint32_t val;
-	int found;
-	int imm;
-
-	val = 0;
-	imm = get_imm(i, op->type, &val);
-
-	if (strcmp(op->type, "U") == 0) {
-		oprint(op, loc, i.UType.rd, 0, 0, val, imm);
-		return (1);
-	}
-	if (strcmp(op->type, "UJ") == 0) {
-		oprint(op, loc, 0, 0, 0, val, (loc + imm));
-		return (1);
-	}
-	if ((strcmp(op->type, "I") == 0) && \
-	    (op->funct3 == i.IType.funct3)) {
-		found = 0;
-		if (op->funct7 != -1) {
-			if (op->funct7 == i.IType.imm)
-				found = 1;
-		} else
-			found = 1;
-
-		if (found) {
-			oprint(op, loc, i.IType.rd,
-			    i.IType.rs1, 0, val, imm);
-			return (1);
-		}
-	}
-	if ((strcmp(op->type, "S") == 0) && \
-	    (op->funct3 == i.SType.funct3)) {
-		oprint(op, loc, 0, i.SType.rs1, i.SType.rs2,
-		    val, imm);
-		return (1);
-	}
-	if ((strcmp(op->type, "SB") == 0) && \
-	    (op->funct3 == i.SBType.funct3)) {
-		oprint(op, loc, 0, i.SBType.rs1, i.SBType.rs2,
-		    val, imm);
-		return (1);
-	}
-	if ((strcmp(op->type, "R2") == 0) && \
-	    (op->funct3 == i.R2Type.funct3) && \
-	    (op->funct7 == i.R2Type.funct7)) {
-		oprint(op, loc, i.R2Type.rd, i.R2Type.rs1,
-		    i.R2Type.rs2, val, imm);
-		return (1);
-	}
-	if ((strcmp(op->type, "R") == 0) && \
-	    (op->funct3 == i.RType.funct3) && \
-	    (op->funct7 == i.RType.funct7)) {
-		oprint(op, loc, i.RType.rd, i.RType.rs1,
-		    val, i.RType.rs2, imm);
-		return (1);
-	}
-
-	return (0);
-}
-
 vm_offset_t
 db_disasm(vm_offset_t loc, bool altfmt)
 {
 	struct riscv_op *op;
-	InstFmt i;
+	uint32_t insn;
 	int j;
 
-	i.word = db_get_value(loc, INSN_SIZE, 0);
-
-	/* First match opcode */
+	insn = db_get_value(loc, 4, 0);
 	for (j = 0; riscv_opcodes[j].name != NULL; j++) {
 		op = &riscv_opcodes[j];
-		if (op->opcode == i.RType.opcode) {
-			if (match_type(i, op, loc))
-				break;
+		if (op->match_func(op, insn)) {
+			oprint(op, loc, insn);
+			return(loc + 4);
 		}
-	}
+	};
 
-	db_printf("\n");
-	return(loc + INSN_SIZE);
+	insn = db_get_value(loc, 2, 0);
+	for (j = 0; riscv_c_opcodes[j].name != NULL; j++) {
+		op = &riscv_c_opcodes[j];
+		if (op->match_func(op, insn)) {
+			oprint(op, loc, insn);
+			break;
+		}
+	};
+
+	return(loc + 2);
 }


More information about the svn-src-head mailing list