adapt ruslan@freebsd's disasm to our world, and replace the incomplete decoder.
authorderaadt <deraadt@openbsd.org>
Sat, 8 May 2021 18:10:03 +0000 (18:10 +0000)
committerderaadt <deraadt@openbsd.org>
Sat, 8 May 2021 18:10:03 +0000 (18:10 +0000)
ok jsg kettenis

sys/arch/riscv64/riscv64/db_disasm.c

index fbdcd08..31f6f0f 100644 (file)
@@ -1,17 +1,37 @@
-/*
- * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
+/*     $OpenBSD: db_disasm.c,v 1.3 2021/05/08 18:10:03 deraadt Exp $   */
+
+/*-
+ * Copyright (c) 2016-2018 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
  *
- * 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * 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.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #include <sys/param.h>
 #include <ddb/db_output.h>
 #include <ddb/db_access.h>
 
-#define RV64_MASK0 0xFC00707F  /* 11111100000000000111000001111111 */
-#define RV64_MASK1 0x0600007F  /* 00000110000000000000000001111111 */
-#define RV64_MASK2 0xFFF0707F  /* 11111111111100000111000001111111 */
-#define RV64_MASK3 0xFFF0007F  /* 11111111111100000000000001111111 */
-#define RV64_MASK4 0xFE00007F  /* 11111110000000000000000001111111 */
-#define RV64_MASK5 0x0C00007F  /* 00001100000000000000000001111111 */
-#define RV64_MASK6 0xF800707F  /* 11111000000000000111000001111111 */
-#define RV64_MASK7 0xF9F0707F  /* 11111001111100000111000001111111 */
-#define RV64_MASK8 0xFE007FFF  /* 11111110000000000111111111111111 */
-#define RV64_MASK9 0xFFFFFFFF  /* 11111111111111111111111111111111 */
-#define RV64_MASK10 0xF01FFFFF /* 11110000000111111111111111111111 */
-#define RV64_MASK11 0xFE00707F /* 11111110000000000111000001111111 */
-#define RV64_MASK12 0x0000707F /* 00000000000000000111000001111111 */
-#define RV64_MASK13 0x0000007F /* 00000000000000000000000001111111 */
+#include <riscv64/riscv64/db_instruction.h>
 
-#define RV64I_LUI_OPCODE       0x00000037      /* lui */
-#define RV64I_AUIPC_OPCODE     0x00000017      /* auipc */
-#define RV64I_JAL_OPCODE       0x0000006F      /* jal */
-#define RV64I_JALR_OPCODE      0x00000067      /* jalr */
-#define RV64I_BEQ_OPCODE       0x00000063      /* beq */
-#define RV64I_BNE_OPCODE       0x00001063      /* bne */
-#define RV64I_BLT_OPCODE       0x00004063      /* blt */
-#define RV64I_BGE_OPCODE       0x00005063      /* bge */
-#define RV64I_BLTU_OPCODE      0x00006063      /* bltu */
-#define RV64I_BGEU_OPCODE      0x00007063      /* bgeu */
-#define RV64I_LB_OPCODE        0x00000003      /* lb */
-#define RV64I_LH_OPCODE        0x00001003      /* lh */
-#define RV64I_LHU_OPCODE       0x00005003      /* lhu */
-#define RV64I_LW_OPCODE        0x00002003      /* lw */
-#define RV64I_LBU_OPCODE       0x00004003      /* lbu */
-#define RV64I_SB_OPCODE        0x00000023      /* sb */
-#define RV64I_SH_OPCODE        0x00001023      /* sh */
-#define RV64I_SW_OPCODE        0x00002023      /* sw */
-#define RV64I_ADDI_OPCODE      0x00000013      /* addi */
-#define RV64I_SLTI_OPCODE      0x00002013      /* slti */
-#define RV64I_SLTIU_OPCODE     0x00003013      /* sltiu */
-#define RV64I_XORI_OPCODE      0x00004013      /* xori */
-#define RV64I_ORI_OPCODE       0x00006013      /* ori */
-#define RV64I_ANDI_OPCODE      0x00007013      /* andi */
-#define RV64I_ADD_OPCODE       0x00000033      /* add */
-#define RV64I_SUB_OPCODE       0x40000033      /* sub */
-#define RV64I_SLL_OPCODE       0x00001033      /* sll */
-#define RV64I_SLT_OPCODE       0x00002033      /* slt */
-#define RV64I_SLTU_OPCODE      0x00003033      /* sltu */
-#define RV64I_XOR_OPCODE       0x00004033      /* xor */
-#define RV64I_SRL_OPCODE       0x00005033      /* srl */
-#define RV64I_SRA_OPCODE       0x40005033      /* sra */
-#define RV64I_OR_OPCODE        0x00006033      /* or */
-#define RV64I_AND_OPCODE       0x00007033      /* and */
-#define RV64I_FENCE_OPCODE     0x0000000F      /* fence */
-#define RV64I_FENCE_I_OPCODE   0x0000100F      /* fence.i */
-#define RV64I_WFI_OPCODE       0x10500073      /* wfi */
-#define RV64I_SFENCE_VMA_OPCODE        0x120000E7      /* sfence.vma */
-#define RV64I_ECALL_OPCODE     0x00000073      /* ecall */
-#define RV64I_EBREAK_OPCODE    0x00100073      /* ebreak */
-#define RV64I_CSRRW_OPCODE     0x00001073      /* csrrw */
-#define RV64I_CSRRS_OPCODE     0x00002073      /* csrrs */
-#define RV64I_CSRRC_OPCODE     0x00003073      /* csrrc */
-#define RV64I_CSRRWI_OPCODE    0x00005073      /* csrrwi */
-#define RV64I_CSRRSI_OPCODE    0x00006073      /* csrrsi */
-#define RV64I_CSRRCI_OPCODE    0x00007073      /* csrrci */
-#define RV64I_SRET_OPCODE      0x10200073      /* sret */
-#define RV64I_MRET_OPCODE      0x30200073      /* mret */
-#define RV64M_MUL_OPCODE       0x02000033      /* mul */
-#define RV64M_MULH_OPCODE      0x02001033      /* mulh */
-#define RV64M_MULHSU_OPCODE    0x02002033      /* mulhsu */
-#define RV64M_MULHU_OPCODE     0x02003033      /* mulhu */
-#define RV64M_DIV_OPCODE       0x02004033      /* div */
-#define RV64M_DIVU_OPCODE      0x02005033      /* divu */
-#define RV64M_REM_OPCODE       0x02006033      /* rem */
-#define RV64M_REMU_OPCODE      0x02007033      /* remu */
-#define RV64A_LR_W_OPCODE      0x1000202F      /* lr.w */
-#define RV64A_SC_W_OPCODE      0x1800202F      /* sc.w */
-#define RV64A_AMOSWAP_W_OPCODE 0x0800202F      /* amoswap.w */
-#define RV64A_AMOADD_W_OPCODE  0x0000202F      /* amoadd.w */
-#define RV64A_AMOXOR_W_OPCODE  0x2000202F      /* amoxor.w */
-#define RV64A_AMOAND_W_OPCODE  0x6000202F      /* amoand.w */
-#define RV64A_AMOOR_W_OPCODE   0x4000202F      /* amoor.w */
-#define RV64A_AMOMIN_W_OPCODE  0x8000202F      /* amomin.w */
-#define RV64A_AMOMAX_W_OPCODE  0xA000202F      /* amomax.w */
-#define RV64A_AMOMINU_W_OPCODE 0xC000202F      /* amominu.w */
-#define RV64A_AMOMAXU_W_OPCODE 0xE000202F      /* amomaxu.w */
-#define RV64F_FLW_OPCODE       0x00002007      /* flw */
-#define RV64F_FSW_OPCODE       0x00002027      /* fsw */
-#define RV64F_FMADD_S_OPCODE   0x00000043      /* fmadd.s */
-#define RV64F_FMSUB_S_OPCODE   0x00000047      /* fmsub.s */
-#define RV64F_FNMSUB_S_OPCODE  0x0000004B      /* fnmsub.s */
-#define RV64F_FNMADD_S_OPCODE  0x0000004F      /* fnmadd.s */
-#define RV64F_FADD_S_OPCODE    0x00000053      /* fadd.s */
-#define RV64F_FSUB_S_OPCODE    0x08000053      /* fsub.s */
-#define RV64F_FMUL_S_OPCODE    0x10000053      /* fmul.s */
-#define RV64F_FDIV_S_OPCODE    0x18000053      /* fdiv.s */
-#define RV64F_FSQRT_S_OPCODE   0x58000053      /* fsqrt.s */
-#define RV64F_FSGNJ_S_OPCODE   0x20000053      /* fsgnj.s */
-#define RV64F_FSGNJN_S_OPCODE  0x20001053      /* fsgnjn.s */
-#define RV64F_FSGNJX_S_OPCODE  0x20002053      /* fsgnjx.s */
-#define RV64F_FMIN_S_OPCODE    0x28000053      /* fmin.s */
-#define RV64F_FMAX_S_OPCODE    0x28001053      /* fmax.s */
-#define RV64F_FMAX_S_OPCODE    0x28001053      /* fmax.s */
-#define RV64F_FCVT_W_S_OPCODE  0xC0000053      /* fcvt.w.s */
-#define RV64F_FCVT_WU_S_OPCODE 0xC0100053      /* fcvt.wu.s */
-#define RV64F_FMV_X_W_OPCODE   0xE0000053      /* fmv.x.w */
-#define RV64F_FEQ_S_OPCODE     0xA0002053      /* feq.s */
-#define RV64F_FLT_S_OPCODE     0xA0001053      /* flt.s */
-#define RV64F_FLE_S_OPCODE     0xA0000053      /* fle.s */
-#define RV64F_FCLASS_S_OPCODE  0xE0001053      /* fclass.s */
-#define RV64F_FCVT_S_W_OPCODE  0xD0000053      /* fcvt.s.w */
-#define RV64F_FCVT_S_WU_OPCODE 0xD0100053      /* fcvt.s.wu */
-#define RV64F_FMV_W_X_OPCODE   0xF0000053      /* fmv.w.x */
-#define RV64D_FLD_OPCODE       0x00003007      /* fld */
-#define RV64D_FSD_OPCODE       0x00003027      /* fsd */
-#define RV64D_FMADD_D_OPCODE   0x00000043      /* fmadd.d */
-#define RV64D_FMSUB_D_OPCODE   0x00000047      /* fmsub.d */
-#define RV64D_FNMSUB_D_OPCODE  0x0000004B      /* fnmsub.d */
-#define RV64D_FNMADD_D_OPCODE  0x0000004F      /* fnmadd.d */
-#define RV64D_FADD_D_OPCODE    0x02000053      /* fadd.d */
-#define RV64D_FSUB_D_OPCODE    0x0A000053      /* fsub.d */
-#define RV64D_FMUL_D_OPCODE    0x12000053      /* fmul.d */
-#define RV64D_FDIV_D_OPCODE    0x1A000053      /* fdiv.d */
-#define RV64D_FSQRT_D_OPCODE   0x5A000053      /* fsqrt.d */
-#define RV64D_FSGNJ_D_OPCODE   0x22000053      /* fsgnj.d */
-#define RV64D_FSGNJN_D_OPCODE  0x22001053      /* fsgnjn.d */
-#define RV64D_FSGNJX_D_OPCODE  0x22002053      /* fsgnjx.d */
-#define RV64D_FMIN_D_OPCODE    0x2A000053      /* fmin.d */
-#define RV64D_FMAX_D_OPCODE    0x2A001053      /* fmax.d */
-#define RV64D_FCVT_S_D_OPCODE  0x40100053      /* fcvt.s.d */
-#define RV64D_FCVT_D_S_OPCODE  0x42000053      /* fcvt.d.s */
-#define RV64D_FEQ_D_OPCODE     0xA2002053      /* feq.d */
-#define RV64D_FLT_D_OPCODE     0xA2001053      /* flt.d */
-#define RV64D_FLE_D_OPCODE     0xA2000053      /* fle.d */
-#define RV64D_FCLASS_D_OPCODE  0xE2001053      /* fclass.d */
-#define RV64D_FCVT_W_D_OPCODE  0xC2000053      /* fcvt.w.d */
-#define RV64D_FCVT_WU_D_OPCODE 0xC2100053      /* fcvt.wu.d */
-#define RV64D_FCVT_D_W_OPCODE  0xD2000053      /* fcvt.d.w */
-#define RV64D_FCVT_D_WU_OPCODE 0xD2100053      /* fcvt.d.wu */
-#define RV64I_LWU_OPCODE       0x00006003      /* lwu */
-#define RV64I_LD_OPCODE        0x00003003      /* ld */
-#define RV64I_SD_OPCODE        0x00003023      /* sd */
-#define RV64I_SLLI_OPCODE      0x00001013      /* slli */
-#define RV64I_SRLI_OPCODE      0x00005013      /* srli */
-#define RV64I_SRAI_OPCODE      0x40005013      /* srai */
-#define RV64I_ADDIW_OPCODE     0x0000001B      /* addiw */
-#define RV64I_SLLIW_OPCODE     0x0000101B      /* slliw */
-#define RV64I_SRLIW_OPCODE     0x0000501B      /* srliw */
-#define RV64I_SRAIW_OPCODE     0x4000501B      /* sraiw */
-#define RV64I_ADDW_OPCODE      0x0000003B      /* addw */
-#define RV64I_SUBW_OPCODE      0x4000003B      /* subw */
-#define RV64I_SLLW_OPCODE      0x0000103B      /* sllw */
-#define RV64I_SRLW_OPCODE      0x0000503B      /* srlw */
-#define RV64I_SRAW_OPCODE      0x4000503B      /* sraw */
-#define RV64M_MULW_OPCODE      0x0200003B      /* mulw */
-#define RV64M_DIVW_OPCODE      0x0200403B      /* divw */
-#define RV64M_DIVUW_OPCODE     0x0200503B      /* divuw */
-#define RV64M_REMW_OPCODE      0x0200603B      /* remw */
-#define RV64M_REMUW_OPCODE     0x0200703B      /* remuw */
-#define RV64A_LR_D_OPCODE      0x1000302F      /* lr.d */
-#define RV64A_SC_D_OPCODE      0x1800302F      /* sc.d */
-#define RV64A_AMOSWAP_D_OPCODE 0x0800302F      /* amoswap.d */
-#define RV64A_AMOADD_D_OPCODE  0x0000302F      /* amoadd.d */
-#define RV64A_AMOXOR_D_OPCODE  0x2000302F      /* amoxor.d */
-#define RV64A_AMOAND_D_OPCODE  0x6000302F      /* amoand.d */
-#define RV64A_AMOOR_D_OPCODE   0x4000302F      /* amoor.d */
-#define RV64A_AMOMIN_D_OPCODE  0x8000302F      /* amomin.d */
-#define RV64A_AMOMAX_D_OPCODE  0xA000302F      /* amomax.d */
-#define RV64A_AMOMAX_D_OPCODE  0xA000302F      /* amomax.d */
-#define RV64A_AMOMINU_D_OPCODE 0xC000302F      /* amominu.d */
-#define RV64A_AMOMAXU_D_OPCODE 0xE000302F      /* amomaxu.d */
-#define RV64F_FCVT_L_S_OPCODE  0xC0200053      /* fcvt.l.s */
-#define RV64F_FCVT_LU_S_OPCODE 0xC0300053      /* fcvt.lu.s */
-#define RV64F_FCVT_S_L_OPCODE  0xD0200053      /* fcvt.s.l */
-#define RV64F_FCVT_S_LU_OPCODE 0xD0300053      /* fcvt.s.lu */
-#define RV64D_FCVT_L_D_OPCODE  0xC2200053      /* fcvt.l.d */
-#define RV64D_FCVT_LU_D_OPCODE 0xC2300053      /* fcvt.lu.d */
-#define RV64D_FMV_X_D_OPCODE   0xE2000053      /* fmv.x.d */
-#define RV64D_FCVT_D_L_OPCODE  0xD2200053      /* fcvt.d.l */
-#define RV64D_FCVT_D_LU_OPCODE 0xD2300053      /* fcvt.d.lu */
-#define RV64D_FMV_D_X_OPCODE   0xF2000053      /* fmv.d.x */
-#define RV64Q_URET_OPCODE      0x00200073      /* uret */
-#define RV64Q_DRET_OPCODE      0x7B200073      /* dret */
-#define RV64Q_FADD_Q_OPCODE    0x06000053      /* fadd.q */
-#define RV64Q_FSUB_Q_OPCODE    0x0E000053      /* fsub.q */
-#define RV64Q_FMUL_Q_OPCODE    0x16000053      /* fmul.q */
-#define RV64Q_FDIV_Q_OPCODE    0x1E000053      /* fdiv.q */
-#define RV64Q_FSGNJ_Q_OPCODE   0x26000053      /* fsgnj.q */
-#define RV64Q_FSGNJN_Q_OPCODE  0x26001053      /* fsgnjn.q */
-#define RV64Q_FSGNJX_Q_OPCODE  0x26002053      /* fsgnjx.q */
-#define RV64Q_FMIN_Q_OPCODE    0x2E000053      /* fmin.q */
-#define RV64Q_FMAX_Q_OPCODE    0x2E001053      /* fmax.q */
-#define RV64Q_FCVT_S_Q_OPCODE  0x40300053      /* fcvt.s.q */
-#define RV64Q_FCVT_Q_S_OPCODE  0x46000053      /* fcvt.q.s */
-#define RV64Q_FCVT_D_Q_OPCODE  0x42300053      /* fcvt.d.q */
-#define RV64Q_FCVT_Q_D_OPCODE  0x46100053      /* fcvt.q.d */
-#define RV64Q_FSQRT_Q_OPCODE   0x5E000053      /* fsqrt.q */
-#define RV64Q_FLE_Q_OPCODE     0xA6000053      /* fle.q */
-#define RV64Q_FLT_Q_OPCODE     0xA6001053      /* flt.q */
-#define RV64Q_FEQ_Q_OPCODE     0xA6002053      /* feq.q */
-#define RV64Q_FCVT_W_Q_OPCODE  0xC6000053      /* fcvt.w.q */
-#define RV64Q_FCVT_WU_Q_OPCODE 0xC6100053      /* fcvt.wu.q */
-#define RV64Q_FCVT_L_Q_OPCODE  0xC6200053      /* fcvt.l.q */
-#define RV64Q_FCVT_LU_Q_OPCODE 0xC6300053      /* fcvt.lu.q */
-#define RV64Q_FMV_X_Q_OPCODE   0xE6000053      /* fmv.x.q */
-#define RV64Q_FCLASS_Q_OPCODE  0xE6001053      /* fclass.q */
-#define RV64Q_FCVT_Q_W_OPCODE  0xD6000053      /* fcvt.q.w */
-#define RV64Q_FCVT_Q_WU_OPCODE 0xD6100053      /* fcvt.q.wu */
-#define RV64Q_FCVT_Q_L_OPCODE  0xD6200053      /* fcvt.q.l */
-#define RV64Q_FCVT_Q_LU_OPCODE 0xD6300053      /* fcvt.q.lu */
-#define RV64Q_FMV_Q_X_OPCODE   0xF6000053      /* fmv.q.x */
-#define RV64Q_FLQ_OPCODE       0x00004007      /* flq */
-#define RV64Q_FSQ_OPCODE       0x00004027      /* fsq */
-#define RV64Q_FMADD_Q_OPCODE   0x06000043      /* fmadd.q */
-#define RV64Q_FMSUB_Q_OPCODE   0x06000047      /* fmsub.q */
-#define RV64Q_FNMSUB_Q_OPCODE  0x0600004B      /* fnmsub.q */
-#define RV64Q_FNMADD_Q_OPCODE  0x0600004F      /* fnmadd.q */
+#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
 
-struct rv64_op {
-       char *opcode;
-       uint32_t num_op;
-       uint32_t num_mask;
-} rv64_opcodes[] = {
-       { "lui", RV64I_LUI_OPCODE, RV64_MASK13 },
-       { "auipc", RV64I_AUIPC_OPCODE, RV64_MASK13 },
-       { "jal", RV64I_JAL_OPCODE, RV64_MASK13 },
-       { "jalr", RV64I_JALR_OPCODE, RV64_MASK12 },
-       { "beq", RV64I_BEQ_OPCODE, RV64_MASK12 },
-       { "bne", RV64I_BNE_OPCODE, RV64_MASK12 },
-       { "blt", RV64I_BLT_OPCODE, RV64_MASK12 },
-       { "bge", RV64I_BGE_OPCODE, RV64_MASK12 },
-       { "bltu", RV64I_BLTU_OPCODE, RV64_MASK12 },
-       { "bgeu", RV64I_BGEU_OPCODE, RV64_MASK12 },
-       { "lb", RV64I_LB_OPCODE, RV64_MASK12 },
-       { "lh", RV64I_LH_OPCODE, RV64_MASK12 },
-       { "lhu", RV64I_LHU_OPCODE, RV64_MASK12 },
-       { "lw", RV64I_LW_OPCODE, RV64_MASK12 },
-       { "lbu", RV64I_LBU_OPCODE, RV64_MASK12 },
-       { "sb", RV64I_SB_OPCODE, RV64_MASK12 },
-       { "sh", RV64I_SH_OPCODE, RV64_MASK12 },
-       { "sw", RV64I_SW_OPCODE, RV64_MASK12 },
-       { "addi", RV64I_ADDI_OPCODE, RV64_MASK12 },
-       { "slti", RV64I_SLTI_OPCODE, RV64_MASK12 },
-       { "sltiu", RV64I_SLTIU_OPCODE, RV64_MASK12 },
-       { "xori", RV64I_XORI_OPCODE, RV64_MASK12 },
-       { "ori", RV64I_ORI_OPCODE, RV64_MASK12 },
-       { "andi", RV64I_ANDI_OPCODE, RV64_MASK12 },
-       { "add", RV64I_ADD_OPCODE, RV64_MASK11 },
-       { "sub", RV64I_SUB_OPCODE, RV64_MASK11 },
-       { "sll", RV64I_SLL_OPCODE, RV64_MASK11 },
-       { "slt", RV64I_SLT_OPCODE, RV64_MASK11 },
-       { "sltu", RV64I_SLTU_OPCODE, RV64_MASK11 },
-       { "xor", RV64I_XOR_OPCODE, RV64_MASK11 },
-       { "srl", RV64I_SRL_OPCODE, RV64_MASK11 },
-       { "sra", RV64I_SRA_OPCODE, RV64_MASK11 },
-       { "or", RV64I_OR_OPCODE, RV64_MASK11 },
-       { "and", RV64I_AND_OPCODE, RV64_MASK11 },
-       { "fence", RV64I_FENCE_OPCODE, RV64_MASK10 },
-       { "fence.i", RV64I_FENCE_I_OPCODE, RV64_MASK9 },
-       { "wfi", RV64I_WFI_OPCODE, RV64_MASK9 },
-       { "sfence.vma", RV64I_SFENCE_VMA_OPCODE, RV64_MASK8 },
-       { "ecall", RV64I_ECALL_OPCODE, RV64_MASK9 },
-       { "ebreak", RV64I_EBREAK_OPCODE, RV64_MASK9 },
-       { "csrrw", RV64I_CSRRW_OPCODE, RV64_MASK12 },
-       { "csrrs", RV64I_CSRRS_OPCODE, RV64_MASK12 },
-       { "csrrc", RV64I_CSRRC_OPCODE, RV64_MASK12 },
-       { "csrrwi", RV64I_CSRRWI_OPCODE, RV64_MASK12 },
-       { "csrrsi", RV64I_CSRRSI_OPCODE, RV64_MASK12 },
-       { "csrrci", RV64I_CSRRCI_OPCODE, RV64_MASK12 },
-       { "sret", RV64I_SRET_OPCODE, RV64_MASK9 },
-       { "mret", RV64I_MRET_OPCODE, RV64_MASK9 },
-       { "mul", RV64M_MUL_OPCODE, RV64_MASK11 },
-       { "mulh", RV64M_MULH_OPCODE, RV64_MASK11 },
-       { "mulhsu", RV64M_MULHSU_OPCODE, RV64_MASK11 },
-       { "mulhu", RV64M_MULHU_OPCODE, RV64_MASK11 },
-       { "div", RV64M_DIV_OPCODE, RV64_MASK11 },
-       { "divu", RV64M_DIVU_OPCODE, RV64_MASK11 },
-       { "rem", RV64M_REM_OPCODE, RV64_MASK11 },
-       { "remu", RV64M_REMU_OPCODE, RV64_MASK11 },
-       { "lr.w", RV64A_LR_W_OPCODE, RV64_MASK7 },
-       { "sc.w", RV64A_SC_W_OPCODE, RV64_MASK6 },
-       { "amoswap.w", RV64A_AMOSWAP_W_OPCODE, RV64_MASK6 },
-       { "amoadd.w", RV64A_AMOADD_W_OPCODE, RV64_MASK6 },
-       { "amoxor.w", RV64A_AMOXOR_W_OPCODE, RV64_MASK6 },
-       { "amoand.w", RV64A_AMOAND_W_OPCODE, RV64_MASK6 },
-       { "amoor.w", RV64A_AMOOR_W_OPCODE, RV64_MASK6 },
-       { "amomin.w", RV64A_AMOMIN_W_OPCODE, RV64_MASK6 },
-       { "amomax.w", RV64A_AMOMAX_W_OPCODE, RV64_MASK6 },
-       { "amominu.w", RV64A_AMOMINU_W_OPCODE, RV64_MASK6 },
-       { "amomaxu.w", RV64A_AMOMAXU_W_OPCODE, RV64_MASK6 },
-       { "flw", RV64F_FLW_OPCODE, RV64_MASK12 },
-       { "fsw", RV64F_FSW_OPCODE, RV64_MASK12 },
-       { "fmadd.s", RV64F_FMADD_S_OPCODE, RV64_MASK5 },
-       { "fmsub.s", RV64F_FMSUB_S_OPCODE, RV64_MASK5 },
-       { "fnmsub.s", RV64F_FNMSUB_S_OPCODE, RV64_MASK5 },
-       { "fnmadd.s", RV64F_FNMADD_S_OPCODE, RV64_MASK5 },
-       { "fadd.s", RV64F_FADD_S_OPCODE, RV64_MASK4 },
-       { "fsub.s", RV64F_FSUB_S_OPCODE, RV64_MASK4 },
-       { "fmul.s", RV64F_FMUL_S_OPCODE, RV64_MASK4 },
-       { "fdiv.s", RV64F_FDIV_S_OPCODE, RV64_MASK4 },
-       { "fsqrt.s", RV64F_FSQRT_S_OPCODE, RV64_MASK3 },
-       { "fsgnj.s", RV64F_FSGNJ_S_OPCODE, RV64_MASK11 },
-       { "fsgnjn.s", RV64F_FSGNJN_S_OPCODE, RV64_MASK11 },
-       { "fsgnjx.s", RV64F_FSGNJX_S_OPCODE, RV64_MASK11 },
-       { "fmin.s", RV64F_FMIN_S_OPCODE, RV64_MASK11 },
-       { "fmax.s", RV64F_FMAX_S_OPCODE, RV64_MASK11 },
-       { "fmax.s", RV64F_FMAX_S_OPCODE, RV64_MASK11 },
-       { "fcvt.w.s", RV64F_FCVT_W_S_OPCODE, RV64_MASK3 },
-       { "fcvt.wu.s", RV64F_FCVT_WU_S_OPCODE, RV64_MASK3 },
-       { "fmv.x.w", RV64F_FMV_X_W_OPCODE, RV64_MASK2 },
-       { "feq.s", RV64F_FEQ_S_OPCODE, RV64_MASK11 },
-       { "flt.s", RV64F_FLT_S_OPCODE, RV64_MASK11 },
-       { "fle.s", RV64F_FLE_S_OPCODE, RV64_MASK11 },
-       { "fclass.s", RV64F_FCLASS_S_OPCODE, RV64_MASK2 },
-       { "fcvt.s.w", RV64F_FCVT_S_W_OPCODE, RV64_MASK3 },
-       { "fcvt.s.wu", RV64F_FCVT_S_WU_OPCODE, RV64_MASK3 },
-       { "fmv.w.x", RV64F_FMV_W_X_OPCODE, RV64_MASK2 },
-       { "fld", RV64D_FLD_OPCODE, RV64_MASK12 },
-       { "fsd", RV64D_FSD_OPCODE, RV64_MASK12 },
-       { "fmadd.d", RV64D_FMADD_D_OPCODE, RV64_MASK1 },
-       { "fmsub.d", RV64D_FMSUB_D_OPCODE, RV64_MASK1 },
-       { "fnmsub.d", RV64D_FNMSUB_D_OPCODE, RV64_MASK1 },
-       { "fnmadd.d", RV64D_FNMADD_D_OPCODE, RV64_MASK1 },
-       { "fadd.d", RV64D_FADD_D_OPCODE, RV64_MASK4 },
-       { "fsub.d", RV64D_FSUB_D_OPCODE, RV64_MASK4 },
-       { "fmul.d", RV64D_FMUL_D_OPCODE, RV64_MASK4 },
-       { "fdiv.d", RV64D_FDIV_D_OPCODE, RV64_MASK4 },
-       { "fsqrt.d", RV64D_FSQRT_D_OPCODE, RV64_MASK3 },
-       { "fsgnj.d", RV64D_FSGNJ_D_OPCODE, RV64_MASK11 },
-       { "fsgnjn.d", RV64D_FSGNJN_D_OPCODE, RV64_MASK11 },
-       { "fsgnjx.d", RV64D_FSGNJX_D_OPCODE, RV64_MASK11 },
-       { "fmin.d", RV64D_FMIN_D_OPCODE, RV64_MASK11 },
-       { "fmax.d", RV64D_FMAX_D_OPCODE, RV64_MASK11 },
-       { "fcvt.s.d", RV64D_FCVT_S_D_OPCODE, RV64_MASK3 },
-       { "fcvt.d.s", RV64D_FCVT_D_S_OPCODE, RV64_MASK3 },
-       { "feq.d", RV64D_FEQ_D_OPCODE, RV64_MASK11 },
-       { "flt.d", RV64D_FLT_D_OPCODE, RV64_MASK11 },
-       { "fle.d", RV64D_FLE_D_OPCODE, RV64_MASK11 },
-       { "fclass.d", RV64D_FCLASS_D_OPCODE, RV64_MASK2 },
-       { "fcvt.w.d", RV64D_FCVT_W_D_OPCODE, RV64_MASK3 },
-       { "fcvt.wu.d", RV64D_FCVT_WU_D_OPCODE, RV64_MASK3 },
-       { "fcvt.d.w", RV64D_FCVT_D_W_OPCODE, RV64_MASK3 },
-       { "fcvt.d.wu", RV64D_FCVT_D_WU_OPCODE, RV64_MASK3 },
-       { "lwu", RV64I_LWU_OPCODE, RV64_MASK12 },
-       { "ld", RV64I_LD_OPCODE, RV64_MASK12 },
-       { "sd", RV64I_SD_OPCODE, RV64_MASK12 },
-       { "slli", RV64I_SLLI_OPCODE, RV64_MASK0 },
-       { "srli", RV64I_SRLI_OPCODE, RV64_MASK0 },
-       { "srai", RV64I_SRAI_OPCODE, RV64_MASK0 },
-       { "addiw", RV64I_ADDIW_OPCODE, RV64_MASK12 },
-       { "slliw", RV64I_SLLIW_OPCODE, RV64_MASK11 },
-       { "srliw", RV64I_SRLIW_OPCODE, RV64_MASK11 },
-       { "sraiw", RV64I_SRAIW_OPCODE, RV64_MASK11 },
-       { "addw", RV64I_ADDW_OPCODE, RV64_MASK11 },
-       { "subw", RV64I_SUBW_OPCODE, RV64_MASK11 },
-       { "sllw", RV64I_SLLW_OPCODE, RV64_MASK11 },
-       { "srlw", RV64I_SRLW_OPCODE, RV64_MASK11 },
-       { "sraw", RV64I_SRAW_OPCODE, RV64_MASK11 },
-       { "mulw", RV64M_MULW_OPCODE, RV64_MASK11 },
-       { "divw", RV64M_DIVW_OPCODE, RV64_MASK11 },
-       { "divuw", RV64M_DIVUW_OPCODE, RV64_MASK11 },
-       { "remw", RV64M_REMW_OPCODE, RV64_MASK11 },
-       { "remuw", RV64M_REMUW_OPCODE, RV64_MASK11 },
-       { "lr.d", RV64A_LR_D_OPCODE, RV64_MASK7 },
-       { "sc.d", RV64A_SC_D_OPCODE, RV64_MASK6 },
-       { "amoswap.d", RV64A_AMOSWAP_D_OPCODE, RV64_MASK6 },
-       { "amoadd.d", RV64A_AMOADD_D_OPCODE, RV64_MASK6 },
-       { "amoxor.d", RV64A_AMOXOR_D_OPCODE, RV64_MASK6 },
-       { "amoand.d", RV64A_AMOAND_D_OPCODE, RV64_MASK6 },
-       { "amoor.d", RV64A_AMOOR_D_OPCODE, RV64_MASK6 },
-       { "amomin.d", RV64A_AMOMIN_D_OPCODE, RV64_MASK6 },
-       { "amomax.d", RV64A_AMOMAX_D_OPCODE, RV64_MASK6 },
-       { "amomax.d", RV64A_AMOMAX_D_OPCODE, RV64_MASK6 },
-       { "amominu.d", RV64A_AMOMINU_D_OPCODE, RV64_MASK6 },
-       { "amomaxu.d", RV64A_AMOMAXU_D_OPCODE, RV64_MASK6 },
-       { "fcvt.l.s", RV64F_FCVT_L_S_OPCODE, RV64_MASK3 },
-       { "fcvt.lu.s", RV64F_FCVT_LU_S_OPCODE, RV64_MASK3 },
-       { "fcvt.s.l", RV64F_FCVT_S_L_OPCODE, RV64_MASK3 },
-       { "fcvt.s.lu", RV64F_FCVT_S_LU_OPCODE, RV64_MASK3 },
-       { "fcvt.l.d", RV64D_FCVT_L_D_OPCODE, RV64_MASK3 },
-       { "fcvt.lu.d", RV64D_FCVT_LU_D_OPCODE, RV64_MASK3 },
-       { "fmv.x.d", RV64D_FMV_X_D_OPCODE, RV64_MASK2 },
-       { "fcvt.d.l", RV64D_FCVT_D_L_OPCODE, RV64_MASK3 },
-       { "fcvt.d.lu", RV64D_FCVT_D_LU_OPCODE, RV64_MASK3 },
-       { "fmv.d.x", RV64D_FMV_D_X_OPCODE, RV64_MASK2 },
-       { "uret", RV64Q_URET_OPCODE, RV64_MASK9 },
-       { "dret", RV64Q_DRET_OPCODE, RV64_MASK9 },
-       { "fadd.q", RV64Q_FADD_Q_OPCODE, RV64_MASK4 },
-       { "fsub.q", RV64Q_FSUB_Q_OPCODE, RV64_MASK4 },
-       { "fmul.q", RV64Q_FMUL_Q_OPCODE, RV64_MASK4 },
-       { "fdiv.q", RV64Q_FDIV_Q_OPCODE, RV64_MASK4 },
-       { "fsgnj.q", RV64Q_FSGNJ_Q_OPCODE, RV64_MASK11 },
-       { "fsgnjn.q", RV64Q_FSGNJN_Q_OPCODE, RV64_MASK11 },
-       { "fsgnjx.q", RV64Q_FSGNJX_Q_OPCODE, RV64_MASK11 },
-       { "fmin.q", RV64Q_FMIN_Q_OPCODE, RV64_MASK11 },
-       { "fmax.q", RV64Q_FMAX_Q_OPCODE, RV64_MASK11 },
-       { "fcvt.s.q", RV64Q_FCVT_S_Q_OPCODE, RV64_MASK3 },
-       { "fcvt.q.s", RV64Q_FCVT_Q_S_OPCODE, RV64_MASK3 },
-       { "fcvt.d.q", RV64Q_FCVT_D_Q_OPCODE, RV64_MASK3 },
-       { "fcvt.q.d", RV64Q_FCVT_Q_D_OPCODE, RV64_MASK3 },
-       { "fsqrt.q", RV64Q_FSQRT_Q_OPCODE, RV64_MASK3 },
-       { "fle.q", RV64Q_FLE_Q_OPCODE, RV64_MASK11 },
-       { "flt.q", RV64Q_FLT_Q_OPCODE, RV64_MASK11 },
-       { "feq.q", RV64Q_FEQ_Q_OPCODE, RV64_MASK11 },
-       { "fcvt.w.q", RV64Q_FCVT_W_Q_OPCODE, RV64_MASK3 },
-       { "fcvt.wu.q", RV64Q_FCVT_WU_Q_OPCODE, RV64_MASK3 },
-       { "fcvt.l.q", RV64Q_FCVT_L_Q_OPCODE, RV64_MASK3 },
-       { "fcvt.lu.q", RV64Q_FCVT_LU_Q_OPCODE, RV64_MASK3 },
-       { "fmv.x.q", RV64Q_FMV_X_Q_OPCODE, RV64_MASK2 },
-       { "fclass.q", RV64Q_FCLASS_Q_OPCODE, RV64_MASK2 },
-       { "fcvt.q.w", RV64Q_FCVT_Q_W_OPCODE, RV64_MASK3 },
-       { "fcvt.q.wu", RV64Q_FCVT_Q_WU_OPCODE, RV64_MASK3 },
-       { "fcvt.q.l", RV64Q_FCVT_Q_L_OPCODE, RV64_MASK3 },
-       { "fcvt.q.lu", RV64Q_FCVT_Q_LU_OPCODE, RV64_MASK3 },
-       { "fmv.q.x", RV64Q_FMV_Q_X_OPCODE, RV64_MASK2 },
-       { "flq", RV64Q_FLQ_OPCODE, RV64_MASK12 },
-       { "fsq", RV64Q_FSQ_OPCODE, RV64_MASK12 },
-       { "fmadd.q", RV64Q_FMADD_Q_OPCODE, RV64_MASK1 },
-       { "fmsub.q", RV64Q_FMSUB_Q_OPCODE, RV64_MASK1 },
-       { "fnmsub.q", RV64Q_FNMSUB_Q_OPCODE, RV64_MASK1 },
-       { "fnmadd.q", RV64Q_FNMADD_Q_OPCODE, RV64_MASK1 },
-       { NULL, 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)
+
+static char *reg_name[32] = {
+       "zero", "ra",   "sp",   "gp",   "tp",   "t0",   "t1",   "t2",
+       "s0",   "s1",   "a0",   "a1",   "a2",   "a3",   "a4",   "a5",
+       "a6",   "a7",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
+       "s8",   "s9",   "s10",  "s11",  "t3",   "t4",   "t5",   "t6"
 };
 
-vaddr_t
-db_disasm(vaddr_t loc, int altfmt)
+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"
+};
+
+struct riscv_op {
+       char *name;
+       char *fmt;
+       int match;
+       int mask;
+       int (*match_func)(struct riscv_op *op, uint32_t insn);
+};
+
+static int
+m_op(struct riscv_op *op, uint32_t insn)
 {
-       struct rv64_op *rvo;
-       uint32_t instruction;
 
-       db_read_bytes(loc, sizeof(instruction), (char *)&instruction);
+       if (((insn ^ op->match) & op->mask) == 0)
+               return (1);
+
+       return (0);
+}
+
+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 },
 
-       for (rvo = &rv64_opcodes[0]; rvo->opcode != NULL; rvo++) {
-               if ((instruction & rvo->num_mask) == rvo->num_op) {
-                       db_printf("%s\n", rvo->opcode);
-                       return loc + 4;
+       { "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 },
+#ifdef RV128Q
+       { "fmv.x.q",    "d,S",          MATCH_FMV_X_Q, MASK_FMV_X_Q,    m_op },
+#endif
+       { "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 },
+#ifdef RV128Q
+       { "fmv.q.x",    "D,s",          MATCH_FMV_Q_X, MASK_FMV_Q_X,    m_op },
+#endif
+       { "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 },
+};
+
+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, vaddr_t loc, int insn)
+{
+       uint32_t rd, rs1, rs2, rs3;
+       uint32_t val;
+       const char *csr_name;
+       int imm;
+       char *p;
+
+       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) {
+               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%x", 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]);
+                       break;
+               case 'D':
+                       db_printf("%s", fp_reg_name[rd]);
+                       break;
+               case 's':
+                       db_printf("%s", reg_name[rs1]);
+                       break;
+               case 'S':
+                       db_printf("%s", fp_reg_name[rs1]);
+                       break;
+               case 't':
+                       db_printf("%s", reg_name[rs2]);
+                       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);
+                       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));
+                       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%x", 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 "riscv64/riscv64/db_instruction.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;
                }
+
+               p++;
        }
 
-       /*
-        * we went through the last instruction and didn't find it in our
-        * list, pretend it's a compressed instruction then (for now)
-        */
+       return (0);
+}
+
+vaddr_t
+db_disasm(vaddr_t loc, int altfmt)
+{
+       struct riscv_op *op;
+       uint32_t insn;
+       int j;
+
+       insn = db_get_value(loc, 4, 0);
+       for (j = 0; riscv_opcodes[j].name != NULL; j++) {
+               op = &riscv_opcodes[j];
+               if (op->match_func(op, insn)) {
+                       oprint(op, loc, insn);
+                       return (loc + 4);
+               }
+       };
+
+       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;
+               }
+       };
 
-       db_printf("[not displaying compressed instruction]\n");
-       return loc + 2;
+       return (loc + 2);
 }