11f154020SRobert Mustacchi /*
21f154020SRobert Mustacchi  * This file and its contents are supplied under the terms of the
31f154020SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
41f154020SRobert Mustacchi  * You may only use this file in accordance with the terms of version
51f154020SRobert Mustacchi  * 1.0 of the CDDL.
61f154020SRobert Mustacchi  *
71f154020SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
81f154020SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
91f154020SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
101f154020SRobert Mustacchi  */
111f154020SRobert Mustacchi 
121f154020SRobert Mustacchi /*
131f154020SRobert Mustacchi  * Copyright (c) 2018, Joyent, Inc.
141f154020SRobert Mustacchi  */
151f154020SRobert Mustacchi 
161f154020SRobert Mustacchi /*
171f154020SRobert Mustacchi  * RISC-V Instruction set decoder
181f154020SRobert Mustacchi  */
191f154020SRobert Mustacchi 
201f154020SRobert Mustacchi #include <libdisasm.h>
211f154020SRobert Mustacchi #include <sys/byteorder.h>
221f154020SRobert Mustacchi #include <sys/debug.h>
231f154020SRobert Mustacchi 
241f154020SRobert Mustacchi #include "libdisasm_impl.h"
251f154020SRobert Mustacchi 
261f154020SRobert Mustacchi #include <stdio.h>
271f154020SRobert Mustacchi 
281f154020SRobert Mustacchi extern int strcmp(const char *, const char *);
291f154020SRobert Mustacchi 
301f154020SRobert Mustacchi /*
311f154020SRobert Mustacchi  * Register names based on their ABI name.
321f154020SRobert Mustacchi  */
331f154020SRobert Mustacchi static const char *dis_riscv_regs[32] = {
341f154020SRobert Mustacchi 	"x0", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
351f154020SRobert Mustacchi 	"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
361f154020SRobert Mustacchi 	"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
371f154020SRobert Mustacchi 	"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
381f154020SRobert Mustacchi };
391f154020SRobert Mustacchi 
401f154020SRobert Mustacchi static const char *dis_riscv_fpregs[32] = {
411f154020SRobert Mustacchi 	"ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
421f154020SRobert Mustacchi 	"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
431f154020SRobert Mustacchi 	"fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
441f154020SRobert Mustacchi 	"fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
451f154020SRobert Mustacchi };
461f154020SRobert Mustacchi 
471f154020SRobert Mustacchi static const char *dis_riscv_c_regs[8] = {
481f154020SRobert Mustacchi 	"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5"
491f154020SRobert Mustacchi };
501f154020SRobert Mustacchi 
511f154020SRobert Mustacchi static const char *dis_riscv_c_fpregs[8] = {
521f154020SRobert Mustacchi 	"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5"
531f154020SRobert Mustacchi };
541f154020SRobert Mustacchi 
551f154020SRobert Mustacchi /*
561f154020SRobert Mustacchi  * RM names have the leading comma in them because the last value represents
571f154020SRobert Mustacchi  * that the hardware register decides the rounding mode and therefore nothing
581f154020SRobert Mustacchi  * should be appended to the instruction.
591f154020SRobert Mustacchi  */
601f154020SRobert Mustacchi static const char *dis_riscv_rm[8] = {
611f154020SRobert Mustacchi 	",rne", ",rtz", ",rdn", ",rup", ",rmm", ",???", ",???", ""
621f154020SRobert Mustacchi };
631f154020SRobert Mustacchi 
641f154020SRobert Mustacchi typedef struct dis_riscv_csr {
651f154020SRobert Mustacchi 	uint_t		drc_val;
661f154020SRobert Mustacchi 	const char	*drc_name;
671f154020SRobert Mustacchi } dis_riscv_csr_t;
681f154020SRobert Mustacchi 
691f154020SRobert Mustacchi /*
701f154020SRobert Mustacchi  * The current set of CSR names as per Table 2.2-2.5 from RISC-V Privileged
711f154020SRobert Mustacchi  * Architectures V1.10. These include all of the ones in the User-Level ISA.
721f154020SRobert Mustacchi  * These are ordered per the doc.
731f154020SRobert Mustacchi  */
741f154020SRobert Mustacchi static dis_riscv_csr_t dis_riscv_csr_map[] = {
751f154020SRobert Mustacchi 	/* User Trap */
761f154020SRobert Mustacchi 	{ 0x000, "ustatus" },	{ 0x004, "uie" },	{ 0x005, "utvec" },
771f154020SRobert Mustacchi 	/* User Trap Handling */
781f154020SRobert Mustacchi 	{ 0x040, "uscratch" },	{ 0x041, "uepc" },	{ 0x042, "ucause" },
791f154020SRobert Mustacchi 	{ 0x043, "utval" },	{ 0x044, "uip" },
801f154020SRobert Mustacchi 	/* User Floating-Point CSRs */
811f154020SRobert Mustacchi 	{ 0x001, "fflags" },	{ 0x002, "frm" },	{ 0x003, "fcsr" },
821f154020SRobert Mustacchi 	/* User Counters/Timers */
831f154020SRobert Mustacchi 	{ 0xc00, "cycle" },	{ 0xc01, "time" },	{ 0xc02, "instret" },
841f154020SRobert Mustacchi 	{ 0xc03, "hpmcounter3" },	{ 0xc04, "hpmcounter4" },
851f154020SRobert Mustacchi 	{ 0xc05, "hpmcounter5" },	{ 0xc06, "hpmcounter6" },
861f154020SRobert Mustacchi 	{ 0xc07, "hpmcounter7" },	{ 0xc08, "hpmcounter8" },
871f154020SRobert Mustacchi 	{ 0xc09, "hpmcounter9" },	{ 0xc0a, "hpmcounter10" },
881f154020SRobert Mustacchi 	{ 0xc0b, "hpmcounter11" },	{ 0xc0c, "hpmcounter12" },
891f154020SRobert Mustacchi 	{ 0xc0d, "hpmcounter13" },	{ 0xc0e, "hpmcounter14" },
901f154020SRobert Mustacchi 	{ 0xc0f, "hpmcounter15" },	{ 0xc10, "hpmcounter16" },
911f154020SRobert Mustacchi 	{ 0xc11, "hpmcounter17" },	{ 0xc12, "hpmcounter18" },
921f154020SRobert Mustacchi 	{ 0xc13, "hpmcounter19" },	{ 0xc14, "hpmcounter20" },
931f154020SRobert Mustacchi 	{ 0xc15, "hpmcounter21" },	{ 0xc16, "hpmcounter22" },
941f154020SRobert Mustacchi 	{ 0xc17, "hpmcounter23" },	{ 0xc18, "hpmcounter24" },
951f154020SRobert Mustacchi 	{ 0xc19, "hpmcounter25" },	{ 0xc1a, "hpmcounter26" },
961f154020SRobert Mustacchi 	{ 0xc1b, "hpmcounter27" },	{ 0xc1c, "hpmcounter28" },
971f154020SRobert Mustacchi 	{ 0xc1d, "hpmcounter29" },	{ 0xc1e, "hpmcounter30" },
981f154020SRobert Mustacchi 	{ 0xc1f, "hpmcounter31" },
991f154020SRobert Mustacchi 	{ 0xc80, "cycleh" },	{ 0xc81, "timeh" },	{ 0xc82, "instreth" },
1001f154020SRobert Mustacchi 	{ 0xc83, "hpmcounter3h" },	{ 0xc84, "hpmcounter4h" },
1011f154020SRobert Mustacchi 	{ 0xc85, "hpmcounter5h" },	{ 0xc86, "hpmcounter6h" },
1021f154020SRobert Mustacchi 	{ 0xc87, "hpmcounter7h" },	{ 0xc88, "hpmcounter8h" },
1031f154020SRobert Mustacchi 	{ 0xc89, "hpmcounter9h" },	{ 0xc8a, "hpmcounter10h" },
1041f154020SRobert Mustacchi 	{ 0xc8b, "hpmcounter11h" },	{ 0xc8c, "hpmcounter12h" },
1051f154020SRobert Mustacchi 	{ 0xc8d, "hpmcounter13h" },	{ 0xc8e, "hpmcounter14h" },
1061f154020SRobert Mustacchi 	{ 0xc8f, "hpmcounter15h" },	{ 0xc90, "hpmcounter16h" },
1071f154020SRobert Mustacchi 	{ 0xc91, "hpmcounter17h" },	{ 0xc92, "hpmcounter18h" },
1081f154020SRobert Mustacchi 	{ 0xc93, "hpmcounter19h" },	{ 0xc94, "hpmcounter20h" },
1091f154020SRobert Mustacchi 	{ 0xc95, "hpmcounter21h" },	{ 0xc96, "hpmcounter22h" },
1101f154020SRobert Mustacchi 	{ 0xc97, "hpmcounter23h" },	{ 0xc98, "hpmcounter24h" },
1111f154020SRobert Mustacchi 	{ 0xc99, "hpmcounter25h" },	{ 0xc9a, "hpmcounter26h" },
1121f154020SRobert Mustacchi 	{ 0xc9b, "hpmcounter27h" },	{ 0xc9c, "hpmcounter28h" },
1131f154020SRobert Mustacchi 	{ 0xc9d, "hpmcounter29h" },	{ 0xc9e, "hpmcounter30h" },
1141f154020SRobert Mustacchi 	{ 0xc9f, "hpmcounter31h" },
1151f154020SRobert Mustacchi 	/* Supervisor Trap Status */
1161f154020SRobert Mustacchi 	{ 0x100, "sstatus" },	{ 0x102, "sedeleg" },	{ 0x103, "sideleg" },
1171f154020SRobert Mustacchi 	{ 0x104, "sie" },	{ 0x105, "stvec" },	{ 0x106, "scounteren" },
1181f154020SRobert Mustacchi 	/* Supervisor Trap Handling */
1191f154020SRobert Mustacchi 	{ 0x140, "sscratch" },	{ 0x141, "sepc" },	{ 0x142, "scause" },
1201f154020SRobert Mustacchi 	{ 0x143, "stval" },	{ 0x144, "sip" },
1211f154020SRobert Mustacchi 	/* Supervisor Protection and Translation */
1221f154020SRobert Mustacchi 	{ 0x180, "satp" },
1231f154020SRobert Mustacchi 	/* Machine Information Registers */
1241f154020SRobert Mustacchi 	{ 0xf11, "mvendorid" },	{ 0xf12, "marchid" },
1251f154020SRobert Mustacchi 	{ 0xf13, "mimpid" },	{ 0xf14, "mhartid" },
1261f154020SRobert Mustacchi 	/* Machine Trap Setup */
1271f154020SRobert Mustacchi 	{ 0x300, "mstatus" },	{ 0x301, "misa" },	{ 0x302, "medeleg" },
1281f154020SRobert Mustacchi 	{ 0x303, "mideleg" },	{ 0x304, "mie" },	{ 0x305, "mtvec" },
1291f154020SRobert Mustacchi 	{ 0x306, "mcounteren" },
1301f154020SRobert Mustacchi 	/* Machine Trap Handling */
1311f154020SRobert Mustacchi 	{ 0x340, "mscratch" },	{ 0x341, "mepc" },	{ 0x342, "mcause" },
1321f154020SRobert Mustacchi 	{ 0x343, "mtval" },	{ 0x344, "mip" },
1331f154020SRobert Mustacchi 	/* Machine Protection and Translation */
1341f154020SRobert Mustacchi 	{ 0x3a0, "pmpcfg0" },	{ 0x3a1, "pmpcfg1" },
1351f154020SRobert Mustacchi 	{ 0x3a2, "pmpcfg2" },	{ 0x3a3, "pmpcfg3" },
1361f154020SRobert Mustacchi 	{ 0x3b0, "pmpaddr0" },	{ 0x3b1, "pmpaddr1" },
1371f154020SRobert Mustacchi 	{ 0x3b2, "pmpaddr2" },	{ 0x3b3, "pmpaddr3" },
1381f154020SRobert Mustacchi 	{ 0x3b4, "pmpaddr4" },	{ 0x3b5, "pmpaddr5" },
1391f154020SRobert Mustacchi 	{ 0x3b6, "pmpaddr6" },	{ 0x3b7, "pmpaddr7" },
1401f154020SRobert Mustacchi 	{ 0x3b8, "pmpaddr8" },	{ 0x3b9, "pmpaddr9" },
1411f154020SRobert Mustacchi 	{ 0x3ba, "pmpaddr10" },	{ 0x3bb, "pmpaddr11" },
1421f154020SRobert Mustacchi 	{ 0x3bc, "pmpaddr12" },	{ 0x3bd, "pmpaddr13" },
1431f154020SRobert Mustacchi 	{ 0x3be, "pmpaddr14" },	{ 0x3bf, "pmpaddr15" }
1441f154020SRobert Mustacchi };
1451f154020SRobert Mustacchi 
1461f154020SRobert Mustacchi typedef enum dis_riscv_csr_alias_type {
1471f154020SRobert Mustacchi 	DIS_RISCV_CSR_READ,
1481f154020SRobert Mustacchi 	DIS_RISCV_CSR_READ_GEN,
1491f154020SRobert Mustacchi 	DIS_RISCV_CSR_SWAP,
1501f154020SRobert Mustacchi 	DIS_RISCV_CSR_SWAP_IMM,
1511f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE,
1521f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE_GEN,
1531f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE_IMM,
1541f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE_IMM_GEN
1551f154020SRobert Mustacchi } dis_riscv_csr_alias_type_t;
1561f154020SRobert Mustacchi 
1571f154020SRobert Mustacchi typedef struct dis_riscv_csr_alias {
1581f154020SRobert Mustacchi 	const char *drca_alias;
1591f154020SRobert Mustacchi 	dis_riscv_csr_alias_type_t drca_type;
1601f154020SRobert Mustacchi 	const char *drca_base;
1611f154020SRobert Mustacchi 	const char *drca_csr;
1621f154020SRobert Mustacchi 	int drca_rd;
1631f154020SRobert Mustacchi 	int drca_rs;
1641f154020SRobert Mustacchi } dis_riscv_csr_alias_t;
1651f154020SRobert Mustacchi 
1661f154020SRobert Mustacchi /*
1671f154020SRobert Mustacchi  * Table of aliases. A NULL or -1 indicates a don't care.
1681f154020SRobert Mustacchi  */
1691f154020SRobert Mustacchi static dis_riscv_csr_alias_t dis_riscv_csr_alias[] = {
1701f154020SRobert Mustacchi 	{ "rdinstret", DIS_RISCV_CSR_READ, "csrrs", "instret", -1, 0 },
1711f154020SRobert Mustacchi 	{ "rdinstreth", DIS_RISCV_CSR_READ, "csrrs", "instreth", -1, 0 },
1721f154020SRobert Mustacchi 	{ "rdcycle", DIS_RISCV_CSR_READ, "csrrs", "cycle", -1, 0 },
1731f154020SRobert Mustacchi 	{ "rdcycleh", DIS_RISCV_CSR_READ, "csrrs", "cycleh", -1, 0 },
1741f154020SRobert Mustacchi 	{ "rdtime", DIS_RISCV_CSR_READ, "csrrs", "time", -1, 0 },
1751f154020SRobert Mustacchi 	{ "rdtimeh", DIS_RISCV_CSR_READ, "csrrs", "timeh", -1, 0 },
1761f154020SRobert Mustacchi 	{ "frcsr", DIS_RISCV_CSR_READ, "csrrs", "fcsr", -1, 0 },
1771f154020SRobert Mustacchi 	{ "fscsr", DIS_RISCV_CSR_WRITE, "csrrw", "fcsr", 0, -1 },
1781f154020SRobert Mustacchi 	{ "fscsr", DIS_RISCV_CSR_SWAP, "csrrw", "fcsr", -1, -1 },
1791f154020SRobert Mustacchi 	{ "frrm", DIS_RISCV_CSR_READ, "csrrs", "frm", -1, 0 },
1801f154020SRobert Mustacchi 	{ "fsrm", DIS_RISCV_CSR_WRITE, "csrrw", "frm", 0, -1 },
1811f154020SRobert Mustacchi 	{ "fsrm", DIS_RISCV_CSR_SWAP, "csrrw", "frm", -1, -1 },
1821f154020SRobert Mustacchi 	{ "fsrmi", DIS_RISCV_CSR_WRITE_IMM, "csrrwi", "frm", 0, -1 },
1831f154020SRobert Mustacchi 	{ "fsrmi", DIS_RISCV_CSR_SWAP_IMM, "csrrwi", "frm", -1, -1 },
1841f154020SRobert Mustacchi 	{ "frflags", DIS_RISCV_CSR_READ, "csrrs", "fflags", -1, 0 },
1851f154020SRobert Mustacchi 	{ "fsflags", DIS_RISCV_CSR_WRITE, "csrrw", "fflags", 0, -1 },
1861f154020SRobert Mustacchi 	{ "fsflags", DIS_RISCV_CSR_SWAP, "csrrw", "fflags", -1, -1 },
1871f154020SRobert Mustacchi 	{ "fsflagsi", DIS_RISCV_CSR_WRITE_IMM, "csrrwi", "fflags", 0, -1 },
1881f154020SRobert Mustacchi 	{ "fsflagsi", DIS_RISCV_CSR_SWAP_IMM, "csrrwi", "fflags", -1, -1 },
1891f154020SRobert Mustacchi 	/*
1901f154020SRobert Mustacchi 	 * These are the generic aliases that aren't based on the CSR. Keep
1911f154020SRobert Mustacchi 	 * them last.
1921f154020SRobert Mustacchi 	 */
1931f154020SRobert Mustacchi 	{ "csrr", DIS_RISCV_CSR_READ_GEN, "csrrs", NULL, -1, 0 },
1941f154020SRobert Mustacchi 	{ "csrw", DIS_RISCV_CSR_WRITE_GEN, "csrrw", NULL, 0, -1 },
1951f154020SRobert Mustacchi 	{ "csrs", DIS_RISCV_CSR_WRITE_GEN, "csrrs", NULL, 0, -1 },
1961f154020SRobert Mustacchi 	{ "csrc", DIS_RISCV_CSR_WRITE_GEN, "csrrc", NULL, 0, -1 },
1971f154020SRobert Mustacchi 	{ "csrwi", DIS_RISCV_CSR_WRITE_IMM_GEN, "csrrwi", NULL, 0, -1 },
1981f154020SRobert Mustacchi 	{ "csrsi", DIS_RISCV_CSR_WRITE_IMM_GEN, "csrrsi", NULL, 0, -1 },
1991f154020SRobert Mustacchi 	{ "csrci", DIS_RISCV_CSR_WRITE_IMM_GEN, "csrrci", NULL, 0, -1 },
2001f154020SRobert Mustacchi };
2011f154020SRobert Mustacchi 
2021f154020SRobert Mustacchi /*
2031f154020SRobert Mustacchi  * Take an n-bit value whose sign bit is indicated by the big sign and convert
2041f154020SRobert Mustacchi  * to a signed type.
2051f154020SRobert Mustacchi  */
2061f154020SRobert Mustacchi static uint_t
dis_riscv_sign_extend(uint_t val,uint_t sbit,const char ** sign)2071f154020SRobert Mustacchi dis_riscv_sign_extend(uint_t val, uint_t sbit, const char **sign)
2081f154020SRobert Mustacchi {
2091f154020SRobert Mustacchi 	VERIFY3U(sbit, <=, 31);
2101f154020SRobert Mustacchi 
2111f154020SRobert Mustacchi 	if (val >= 1 << sbit) {
2121f154020SRobert Mustacchi 		*sign = "-";
2131f154020SRobert Mustacchi 		return ((1 << (sbit + 1)) - val);
2141f154020SRobert Mustacchi 	} else {
2151f154020SRobert Mustacchi 		*sign = "";
2161f154020SRobert Mustacchi 		return (val);
2171f154020SRobert Mustacchi 	}
2181f154020SRobert Mustacchi }
2191f154020SRobert Mustacchi 
2201f154020SRobert Mustacchi /*
2211f154020SRobert Mustacchi  * Four byte decode tables. This is derived from the RV32/64G Instruction Set
2221f154020SRobert Mustacchi  * Listings. We describe a table entry based on the opcode and optional opcodes
2231f154020SRobert Mustacchi  * based on the type of instruction that it is and its encoding format. Most
2241f154020SRobert Mustacchi  * sets of instructions have one of several uniform encoding types.
2251f154020SRobert Mustacchi  *
2261f154020SRobert Mustacchi  *  31             25 24     20 19  15 14    12  11        7  6      0
2271f154020SRobert Mustacchi  * |    funct7       |   r2    |  rs1 | funct3 | rd          | opcode | R-type
2281f154020SRobert Mustacchi  * |    imm[11:0]              |  rs1 | funct3 | rd          | opcode | I-type
2291f154020SRobert Mustacchi  * |    imm[11:5]    |   r2    |  rs1 | funct3 | imm[4:0]    | opcode | S-type
2301f154020SRobert Mustacchi  * |    imm[12|10:5] |   r2    |  rs1 | funct3 | imm[4:1|11] | opcode | B-type
2311f154020SRobert Mustacchi  * |    imm[31:12]                             | rd          | opcode | U-type
2321f154020SRobert Mustacchi  * |    imm[10|10:1|11|19:12]                  | rd          | opcode | J-type
2331f154020SRobert Mustacchi  */
2341f154020SRobert Mustacchi typedef enum dis_riscv_itype {
2351f154020SRobert Mustacchi 	DIS_RISCV_I_R_TYPE,
2361f154020SRobert Mustacchi 	DIS_RISCV_I_I_TYPE,
2371f154020SRobert Mustacchi 	DIS_RISCV_I_S_TYPE,
2381f154020SRobert Mustacchi 	DIS_RISCV_I_B_TYPE,
2391f154020SRobert Mustacchi 	DIS_RISCV_I_U_TYPE,
2401f154020SRobert Mustacchi 	DIS_RISCV_I_J_TYPE,
2411f154020SRobert Mustacchi 	DIS_RISCV_I_R4_TYPE,
2421f154020SRobert Mustacchi 	/*
2431f154020SRobert Mustacchi 	 * This is a variant of the standard R type where the first bit of
2441f154020SRobert Mustacchi 	 * funct7 is actually used for this shift.
2451f154020SRobert Mustacchi 	 */
2461f154020SRobert Mustacchi 	DIS_RISCV_I_SHIFT64_TYPE,
2471f154020SRobert Mustacchi 	/*
2481f154020SRobert Mustacchi 	 * This type isn't explicitly defined in the ISA doc; however, it is a
2491f154020SRobert Mustacchi 	 * standard format that is for all of the Atomic class instructions.
2501f154020SRobert Mustacchi 	 * This is treated like an R-type, except the funct7 is really a funct5.
2511f154020SRobert Mustacchi 	 * The load variant is similar; however, rs2 must be zero.
2521f154020SRobert Mustacchi 	 */
2531f154020SRobert Mustacchi 	DIS_RISCV_I_RV32A_TYPE,
2541f154020SRobert Mustacchi 	DIS_RISCV_I_RV32A_LOAD_TYPE,
2551f154020SRobert Mustacchi 	/*
2561f154020SRobert Mustacchi 	 * This is a custom type we've defined where the first value is the
2571f154020SRobert Mustacchi 	 * instruction mask and the second value is the value of the bits in it.
2581f154020SRobert Mustacchi 	 * This is used for a few irregular instructions ala FENCE and ECALL.
2591f154020SRobert Mustacchi 	 */
2601f154020SRobert Mustacchi 	DIS_RISCV_I_MASK_TYPE,
2611f154020SRobert Mustacchi 	/*
2621f154020SRobert Mustacchi 	 * This type is used for FP arguments that use rs2 as an opcode.
2631f154020SRobert Mustacchi 	 */
2641f154020SRobert Mustacchi 	DIS_RISCV_I_FP_RS2OP_TYPE,
2651f154020SRobert Mustacchi 	/*
2661f154020SRobert Mustacchi 	 * This type uses the opcode and funct7 and uses funct3 as a rounding
2671f154020SRobert Mustacchi 	 * mode argument.
2681f154020SRobert Mustacchi 	 */
2691f154020SRobert Mustacchi 	DIS_RISCV_I_FP_RM_TYPE,
2701f154020SRobert Mustacchi 	/*
2711f154020SRobert Mustacchi 	 * This fp type uses the opcode, funct7, funct3, and rs2 as an op type.
2721f154020SRobert Mustacchi 	 */
2731f154020SRobert Mustacchi 	DIS_RISCV_I_FP_R_RS2_TYPE,
2741f154020SRobert Mustacchi } dis_riscv_itype_t;
2751f154020SRobert Mustacchi 
2761f154020SRobert Mustacchi #define	DIS_RISCV_OPCODE(x)	((x) & 0x7f)
2771f154020SRobert Mustacchi #define	DIS_RISCV_FUNCT3(x)	(((x) >> 12) & 0x7)
2781f154020SRobert Mustacchi #define	DIS_RISCV_FUNCT7(x)	(((x) >> 25) & 0x7f)
2791f154020SRobert Mustacchi #define	DIS_RISCV_RD(x)		(((x) >> 7) & 0x1f)
2801f154020SRobert Mustacchi #define	DIS_RISCV_RS1(x)	(((x) >> 15) & 0x1f)
2811f154020SRobert Mustacchi #define	DIS_RISCV_RS2(x)	(((x) >> 20) & 0x1f)
2821f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS3(x)	(((x) >> 27) & 0x1f)
2831f154020SRobert Mustacchi #define	DIS_RISCV_FUNCT2(x)	(((x) >> 25) & 0x03)
2841f154020SRobert Mustacchi 
2851f154020SRobert Mustacchi /*
2861f154020SRobert Mustacchi  * SHIFT funct7 variant.
2871f154020SRobert Mustacchi  */
2881f154020SRobert Mustacchi #define	DIS_RISCV_SFUNCT7(x)	(((x) >> 26) & 0x3f)
2891f154020SRobert Mustacchi 
2901f154020SRobert Mustacchi #define	DIS_RISCV_UIMM(x)	(((x) >> 12) & 0xfffff)
2911f154020SRobert Mustacchi 
2921f154020SRobert Mustacchi #define	DIS_RISCV_IIMM(x)	(((x) >> 20) & 0xfff)
2931f154020SRobert Mustacchi 
2941f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_12(x)	(((x) >> 19) & 0x1000)
2951f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_11(x)	(((x) & 0x80) << 4)
2961f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_10_5(x)	(((x) >> 20) & 0x7e0)
2971f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_4_1(x)	(((x) >> 7) & 0x1e)
2981f154020SRobert Mustacchi 
2991f154020SRobert Mustacchi #define	DIS_RISCV_SIMM_UP(x)	((((x) >> 25) & 0x7f) << 5)
3001f154020SRobert Mustacchi #define	DIS_RISCV_SIMM_LOW(x)	(((x) >> 7) & 0x1f)
3011f154020SRobert Mustacchi 
3021f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_20(x)	(((x) & 0x80000000) >> 11)
3031f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_19_12(x)	((x) & 0xff000)
3041f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_11(x)	(((x) & 100000) >> 9)
3051f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_10_1(x)	(((x) & 0x7fe00000) >> 20)
3061f154020SRobert Mustacchi 
3071f154020SRobert Mustacchi #define	DIS_RISCV_RVA_FUNCT5(x)	(((x) >> 27) & 0x1f)
3081f154020SRobert Mustacchi #define	DIS_RISCV_RVA_AQ(x)	(((x) >> 26) & 0x1)
3091f154020SRobert Mustacchi #define	DIS_RISCV_RVA_RL(x)	(((x) >> 25) & 0x1)
3101f154020SRobert Mustacchi 
3111f154020SRobert Mustacchi struct dis_riscv_instr;
3121f154020SRobert Mustacchi typedef void (*dis_riscv_func_t)(dis_handle_t *, uint32_t,
3131f154020SRobert Mustacchi     struct dis_riscv_instr *, char *, size_t);
3141f154020SRobert Mustacchi 
3151f154020SRobert Mustacchi typedef struct dis_riscv_instr {
316*38848811SRobert Mustacchi 	const char		*drv_name;
3171f154020SRobert Mustacchi 	dis_riscv_itype_t	drv_type;
3181f154020SRobert Mustacchi 	dis_riscv_func_t	drv_print;
3191f154020SRobert Mustacchi 	uint_t			drv_opcode;
3201f154020SRobert Mustacchi 	uint_t			drv_funct3;
3211f154020SRobert Mustacchi 	uint_t			drv_funct7;
3221f154020SRobert Mustacchi 	uint_t			drv_funct2;
3231f154020SRobert Mustacchi } dis_riscv_instr_t;
3241f154020SRobert Mustacchi 
3251f154020SRobert Mustacchi /*ARGSUSED*/
3261f154020SRobert Mustacchi static void
dis_riscv_rtype_32(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)3271f154020SRobert Mustacchi dis_riscv_rtype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
3281f154020SRobert Mustacchi     char *buf, size_t buflen)
3291f154020SRobert Mustacchi {
3301f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
3311f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
3321f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)],
3331f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS2(instr)]);
3341f154020SRobert Mustacchi }
3351f154020SRobert Mustacchi 
3361f154020SRobert Mustacchi static void
dis_riscv_itype_32(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)3371f154020SRobert Mustacchi dis_riscv_itype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
3381f154020SRobert Mustacchi     char *buf, size_t buflen)
3391f154020SRobert Mustacchi {
3401f154020SRobert Mustacchi 	const char *s;
3411f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(DIS_RISCV_IIMM(instr), 11, &s);
3421f154020SRobert Mustacchi 
3431f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
3441f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0%o",
3451f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
3461f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
3471f154020SRobert Mustacchi 	} else {
3481f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0x%x",
3491f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
3501f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
3511f154020SRobert Mustacchi 	}
3521f154020SRobert Mustacchi }
3531f154020SRobert Mustacchi 
3541f154020SRobert Mustacchi static void
dis_riscv_btype_32(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)3551f154020SRobert Mustacchi dis_riscv_btype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
3561f154020SRobert Mustacchi     char *buf, size_t buflen)
3571f154020SRobert Mustacchi {
3581f154020SRobert Mustacchi 	const char *s;
3591f154020SRobert Mustacchi 	uint_t bimm = DIS_RISCV_BIMM_12(instr) | DIS_RISCV_BIMM_11(instr) |
3601f154020SRobert Mustacchi 	    DIS_RISCV_BIMM_10_5(instr) | DIS_RISCV_BIMM_4_1(instr);
3611f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(bimm, 12, &s);
3621f154020SRobert Mustacchi 
3631f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
3641f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0%o",
3651f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
3661f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
3671f154020SRobert Mustacchi 	} else {
3681f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0x%x",
3691f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
3701f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
3711f154020SRobert Mustacchi 	}
3721f154020SRobert Mustacchi }
3731f154020SRobert Mustacchi 
3741f154020SRobert Mustacchi static void
dis_riscv_load(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)3751f154020SRobert Mustacchi dis_riscv_load(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
3761f154020SRobert Mustacchi     char *buf, size_t buflen)
3771f154020SRobert Mustacchi {
3781f154020SRobert Mustacchi 	const char *s;
3791f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(DIS_RISCV_IIMM(instr), 11, &s);
3801f154020SRobert Mustacchi 
3811f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
3821f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
3831f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
3841f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
3851f154020SRobert Mustacchi 	} else {
3861f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
3871f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
3881f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
3891f154020SRobert Mustacchi 	}
3901f154020SRobert Mustacchi }
3911f154020SRobert Mustacchi 
3921f154020SRobert Mustacchi static void
dis_riscv_stype_32(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)3931f154020SRobert Mustacchi dis_riscv_stype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
3941f154020SRobert Mustacchi     char *buf, size_t buflen)
3951f154020SRobert Mustacchi {
3961f154020SRobert Mustacchi 	const char *s;
3971f154020SRobert Mustacchi 	uint_t simm = DIS_RISCV_SIMM_UP(instr) | DIS_RISCV_SIMM_LOW(instr);
3981f154020SRobert Mustacchi 	uint_t val = dis_riscv_sign_extend(simm, 11, &s);
3991f154020SRobert Mustacchi 
4001f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
4011f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
4021f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RS2(instr)],
4031f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
4041f154020SRobert Mustacchi 	} else {
4051f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
4061f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RS2(instr)],
4071f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
4081f154020SRobert Mustacchi 	}
4091f154020SRobert Mustacchi }
4101f154020SRobert Mustacchi 
4111f154020SRobert Mustacchi /*ARGSUSED*/
4121f154020SRobert Mustacchi static void
dis_riscv_utype_32(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)4131f154020SRobert Mustacchi dis_riscv_utype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
4141f154020SRobert Mustacchi     char *buf, size_t buflen)
4151f154020SRobert Mustacchi {
4161f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,0x%x", table->drv_name,
4171f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)], DIS_RISCV_UIMM(instr));
4181f154020SRobert Mustacchi }
4191f154020SRobert Mustacchi 
4201f154020SRobert Mustacchi static void
dis_riscv_jtype_32(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)4211f154020SRobert Mustacchi dis_riscv_jtype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
4221f154020SRobert Mustacchi     char *buf, size_t buflen)
4231f154020SRobert Mustacchi {
4241f154020SRobert Mustacchi 	const char *s;
4251f154020SRobert Mustacchi 	uint_t jimm = DIS_RISCV_JIMM_20(instr) | DIS_RISCV_JIMM_19_12(instr) |
4261f154020SRobert Mustacchi 	    DIS_RISCV_JIMM_11(instr) | DIS_RISCV_JIMM_10_1(instr);
4271f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(jimm, 20, &s);
4281f154020SRobert Mustacchi 
4291f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
4301f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o",
4311f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
4321f154020SRobert Mustacchi 		    s, imm);
4331f154020SRobert Mustacchi 	} else {
4341f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x",
4351f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
4361f154020SRobert Mustacchi 		    s, imm);
4371f154020SRobert Mustacchi 	}
4381f154020SRobert Mustacchi }
4391f154020SRobert Mustacchi 
4401f154020SRobert Mustacchi /*
4411f154020SRobert Mustacchi  * The shift instructions are a variant on the R-type instructions where RS2 is
4421f154020SRobert Mustacchi  * an immediate to perform the shift by as opposed to a register.
4431f154020SRobert Mustacchi  */
4441f154020SRobert Mustacchi static void
dis_riscv_shift_32(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)4451f154020SRobert Mustacchi dis_riscv_shift_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
4461f154020SRobert Mustacchi     char *buf, size_t buflen)
4471f154020SRobert Mustacchi {
4481f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
4491f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0%o",
4501f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
4511f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], DIS_RISCV_RS2(instr));
4521f154020SRobert Mustacchi 	} else {
4531f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0x%x",
4541f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
4551f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], DIS_RISCV_RS2(instr));
4561f154020SRobert Mustacchi 	}
4571f154020SRobert Mustacchi }
4581f154020SRobert Mustacchi 
4591f154020SRobert Mustacchi /*
4601f154020SRobert Mustacchi  * The 64-bit version of shift instructions steals an extra bit from funct7 to
4611f154020SRobert Mustacchi  * construct the shift amount.
4621f154020SRobert Mustacchi  */
4631f154020SRobert Mustacchi static void
dis_riscv_shift_64(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)4641f154020SRobert Mustacchi dis_riscv_shift_64(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
4651f154020SRobert Mustacchi     char *buf, size_t buflen)
4661f154020SRobert Mustacchi {
4671f154020SRobert Mustacchi 	uint_t shift = DIS_RISCV_RS2(instr) | ((instr & (1UL << 25)) >> 20);
4681f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
4691f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0%o",
4701f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
4711f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], shift);
4721f154020SRobert Mustacchi 	} else {
4731f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0x%x",
4741f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
4751f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], shift);
4761f154020SRobert Mustacchi 	}
4771f154020SRobert Mustacchi }
4781f154020SRobert Mustacchi 
4791f154020SRobert Mustacchi /*ARGSUSED*/
4801f154020SRobert Mustacchi static void
dis_riscv_csr(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)4811f154020SRobert Mustacchi dis_riscv_csr(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
4821f154020SRobert Mustacchi     char *buf, size_t buflen)
4831f154020SRobert Mustacchi {
4841f154020SRobert Mustacchi 	uint_t rd, csr, rs, i;
4851f154020SRobert Mustacchi 	const char *csrstr = NULL;
4861f154020SRobert Mustacchi 	char csrval[32];
4871f154020SRobert Mustacchi 	dis_riscv_csr_alias_t *alias = NULL;
4881f154020SRobert Mustacchi 
4891f154020SRobert Mustacchi 	rd = DIS_RISCV_RD(instr);
4901f154020SRobert Mustacchi 	rs = DIS_RISCV_RS1(instr);
4911f154020SRobert Mustacchi 	csr = DIS_RISCV_IIMM(instr);
4921f154020SRobert Mustacchi 
4931f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_map); i++) {
4941f154020SRobert Mustacchi 		if (csr == dis_riscv_csr_map[i].drc_val) {
4951f154020SRobert Mustacchi 			csrstr = dis_riscv_csr_map[i].drc_name;
4961f154020SRobert Mustacchi 			break;
4971f154020SRobert Mustacchi 		}
4981f154020SRobert Mustacchi 	}
4991f154020SRobert Mustacchi 
5001f154020SRobert Mustacchi 	if (csrstr == NULL) {
5011f154020SRobert Mustacchi 		(void) dis_snprintf(csrval, sizeof (csrval), "0x%x", csr);
5021f154020SRobert Mustacchi 		csrstr = csrval;
5031f154020SRobert Mustacchi 	}
5041f154020SRobert Mustacchi 
5051f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_alias); i++) {
5061f154020SRobert Mustacchi 		dis_riscv_csr_alias_t *a = &dis_riscv_csr_alias[i];
5071f154020SRobert Mustacchi 		if (strcmp(a->drca_base, table->drv_name) != 0)
5081f154020SRobert Mustacchi 			continue;
5091f154020SRobert Mustacchi 		if (a->drca_csr != NULL && strcmp(a->drca_csr, csrstr) != 0)
5101f154020SRobert Mustacchi 			continue;
5111f154020SRobert Mustacchi 		if (a->drca_rd != -1 && a->drca_rd != rd)
5121f154020SRobert Mustacchi 			continue;
5131f154020SRobert Mustacchi 		if (a->drca_rs != -1 && a->drca_rs != rs)
5141f154020SRobert Mustacchi 			continue;
5151f154020SRobert Mustacchi 		alias = a;
5161f154020SRobert Mustacchi 		break;
5171f154020SRobert Mustacchi 	}
5181f154020SRobert Mustacchi 
5191f154020SRobert Mustacchi 	if (alias == NULL) {
5201f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
5211f154020SRobert Mustacchi 		    dis_riscv_regs[rd], csrstr, dis_riscv_regs[rs]);
5221f154020SRobert Mustacchi 		return;
5231f154020SRobert Mustacchi 	}
5241f154020SRobert Mustacchi 
5251f154020SRobert Mustacchi 	switch (alias->drca_type) {
5261f154020SRobert Mustacchi 	case DIS_RISCV_CSR_READ:
5271f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s", alias->drca_alias,
5281f154020SRobert Mustacchi 		    dis_riscv_regs[rd]);
5291f154020SRobert Mustacchi 		break;
5301f154020SRobert Mustacchi 	case DIS_RISCV_CSR_READ_GEN:
5311f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s", alias->drca_alias,
5321f154020SRobert Mustacchi 		    dis_riscv_regs[rd], csrstr);
5331f154020SRobert Mustacchi 		break;
5341f154020SRobert Mustacchi 	case DIS_RISCV_CSR_SWAP:
5351f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s", alias->drca_alias,
5361f154020SRobert Mustacchi 		    dis_riscv_regs[rd], dis_riscv_regs[rs]);
5371f154020SRobert Mustacchi 		break;
5381f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE:
5391f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s", alias->drca_alias,
5401f154020SRobert Mustacchi 		    dis_riscv_regs[rs]);
5411f154020SRobert Mustacchi 		break;
5421f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE_GEN:
5431f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s", alias->drca_alias,
5441f154020SRobert Mustacchi 		    csrstr, dis_riscv_regs[rs]);
5451f154020SRobert Mustacchi 		break;
5461f154020SRobert Mustacchi 	default:
5471f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "<unknown>");
5481f154020SRobert Mustacchi 		break;
5491f154020SRobert Mustacchi 	}
5501f154020SRobert Mustacchi }
5511f154020SRobert Mustacchi 
5521f154020SRobert Mustacchi static void
dis_riscv_csri(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)5531f154020SRobert Mustacchi dis_riscv_csri(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
5541f154020SRobert Mustacchi     char *buf, size_t buflen)
5551f154020SRobert Mustacchi {
5561f154020SRobert Mustacchi 	uint_t rd, csr, imm, i;
5571f154020SRobert Mustacchi 	const char *csrstr = NULL;
5581f154020SRobert Mustacchi 	char csrval[32];
5591f154020SRobert Mustacchi 	dis_riscv_csr_alias_t *alias = NULL;
5601f154020SRobert Mustacchi 
5611f154020SRobert Mustacchi 	rd = DIS_RISCV_RD(instr);
5621f154020SRobert Mustacchi 	imm = DIS_RISCV_RS1(instr);
5631f154020SRobert Mustacchi 	csr = DIS_RISCV_IIMM(instr);
5641f154020SRobert Mustacchi 
5651f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_map); i++) {
5661f154020SRobert Mustacchi 		if (csr == dis_riscv_csr_map[i].drc_val) {
5671f154020SRobert Mustacchi 			csrstr = dis_riscv_csr_map[i].drc_name;
5681f154020SRobert Mustacchi 			break;
5691f154020SRobert Mustacchi 		}
5701f154020SRobert Mustacchi 	}
5711f154020SRobert Mustacchi 
5721f154020SRobert Mustacchi 	if (csrstr == NULL) {
5731f154020SRobert Mustacchi 		(void) dis_snprintf(csrval, sizeof (csrval), "0x%x", csr);
5741f154020SRobert Mustacchi 		csrstr = csrval;
5751f154020SRobert Mustacchi 	}
5761f154020SRobert Mustacchi 
5771f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_alias); i++) {
5781f154020SRobert Mustacchi 		dis_riscv_csr_alias_t *a = &dis_riscv_csr_alias[i];
5791f154020SRobert Mustacchi 		if (strcmp(a->drca_base, table->drv_name) != 0)
5801f154020SRobert Mustacchi 			continue;
5811f154020SRobert Mustacchi 		if (a->drca_csr != NULL && strcmp(a->drca_csr, csrstr) != 0)
5821f154020SRobert Mustacchi 			continue;
5831f154020SRobert Mustacchi 		if (a->drca_rd != -1 && a->drca_rd != rd)
5841f154020SRobert Mustacchi 			continue;
5851f154020SRobert Mustacchi 		if (a->drca_rs != -1)
5861f154020SRobert Mustacchi 			continue;
5871f154020SRobert Mustacchi 		alias = a;
5881f154020SRobert Mustacchi 		break;
5891f154020SRobert Mustacchi 	}
5901f154020SRobert Mustacchi 
5911f154020SRobert Mustacchi 	if (alias == NULL) {
5921f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
5931f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,%s,0%o",
5941f154020SRobert Mustacchi 			    table->drv_name, dis_riscv_regs[rd], csrstr, imm);
5951f154020SRobert Mustacchi 		} else {
5961f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,%s,0x%x",
5971f154020SRobert Mustacchi 			    table->drv_name, dis_riscv_regs[rd], csrstr, imm);
5981f154020SRobert Mustacchi 		}
5991f154020SRobert Mustacchi 		return;
6001f154020SRobert Mustacchi 	}
6011f154020SRobert Mustacchi 
6021f154020SRobert Mustacchi 	switch (alias->drca_type) {
6031f154020SRobert Mustacchi 	case DIS_RISCV_CSR_SWAP_IMM:
6041f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
6051f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0%o",
6061f154020SRobert Mustacchi 			    alias->drca_alias, dis_riscv_regs[rd], imm);
6071f154020SRobert Mustacchi 		} else {
6081f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0x%x",
6091f154020SRobert Mustacchi 			    alias->drca_alias, dis_riscv_regs[rd], imm);
6101f154020SRobert Mustacchi 		}
6111f154020SRobert Mustacchi 		break;
6121f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE_IMM:
6131f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
6141f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s 0%o",
6151f154020SRobert Mustacchi 			    alias->drca_alias, imm);
6161f154020SRobert Mustacchi 		} else {
6171f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s 0x%x",
6181f154020SRobert Mustacchi 			    alias->drca_alias, imm);
6191f154020SRobert Mustacchi 		}
6201f154020SRobert Mustacchi 		break;
6211f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE_IMM_GEN:
6221f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
6231f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0%o",
6241f154020SRobert Mustacchi 			    alias->drca_alias, csrstr, imm);
6251f154020SRobert Mustacchi 		} else {
6261f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0x%x",
6271f154020SRobert Mustacchi 			    alias->drca_alias, csrstr, imm);
6281f154020SRobert Mustacchi 		}
6291f154020SRobert Mustacchi 		break;
6301f154020SRobert Mustacchi 	default:
6311f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "<unknown>");
6321f154020SRobert Mustacchi 		break;
6331f154020SRobert Mustacchi 	}
6341f154020SRobert Mustacchi }
6351f154020SRobert Mustacchi 
6361f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_PRED(x)	(((x) >> 24) & 0xf)
6371f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_SUCC(x)	(((x) >> 20) & 0xf)
6381f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_I	0x8
6391f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_O	0x4
6401f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_R	0x2
6411f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_W	0x1
6421f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_IORW	0xf
6431f154020SRobert Mustacchi 
6441f154020SRobert Mustacchi /*ARGSUSED*/
6451f154020SRobert Mustacchi static void
dis_riscv_fence(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)6461f154020SRobert Mustacchi dis_riscv_fence(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
6471f154020SRobert Mustacchi     char *buf, size_t buflen)
6481f154020SRobert Mustacchi {
6491f154020SRobert Mustacchi 	uint_t pred, succ;
6501f154020SRobert Mustacchi 
6511f154020SRobert Mustacchi 	pred = DIS_RISCV_FENCE_PRED(instr);
6521f154020SRobert Mustacchi 	succ = DIS_RISCV_FENCE_SUCC(instr);
6531f154020SRobert Mustacchi 
6541f154020SRobert Mustacchi 	/*
6551f154020SRobert Mustacchi 	 * If both halves are iorw that is aliased to just an empty fence
6561f154020SRobert Mustacchi 	 * instruction per Chapter 20 - RISC-V Assembly Programmer's Handbook in
6571f154020SRobert Mustacchi 	 * the RISC-V user spec.
6581f154020SRobert Mustacchi 	 */
6591f154020SRobert Mustacchi 	if (pred == DIS_RISCV_FENCE_IORW && succ == DIS_RISCV_FENCE_IORW) {
6601f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s", table->drv_name);
6611f154020SRobert Mustacchi 		return;
6621f154020SRobert Mustacchi 	}
6631f154020SRobert Mustacchi 
6641f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s%s%s%s, %s%s%s%s",
6651f154020SRobert Mustacchi 	    table->drv_name,
6661f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_I ? "i" : "",
6671f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_O ? "o" : "",
6681f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_R ? "r" : "",
6691f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_W ? "w" : "",
6701f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_I ? "i" : "",
6711f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_O ? "o" : "",
6721f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_R ? "r" : "",
6731f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_W ? "w" : "");
6741f154020SRobert Mustacchi }
6751f154020SRobert Mustacchi 
6761f154020SRobert Mustacchi /*ARGSUSED*/
6771f154020SRobert Mustacchi static void
dis_riscv_name(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)6781f154020SRobert Mustacchi dis_riscv_name(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
6791f154020SRobert Mustacchi     char *buf, size_t buflen)
6801f154020SRobert Mustacchi {
6811f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s", table->drv_name);
6821f154020SRobert Mustacchi }
6831f154020SRobert Mustacchi 
6841f154020SRobert Mustacchi /*ARGSUSED*/
6851f154020SRobert Mustacchi static void
dis_riscv_rs1_rs2(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)6861f154020SRobert Mustacchi dis_riscv_rs1_rs2(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
6871f154020SRobert Mustacchi     char *buf, size_t buflen)
6881f154020SRobert Mustacchi {
6891f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
6901f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)],
6911f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS2(instr)]);
6921f154020SRobert Mustacchi }
6931f154020SRobert Mustacchi 
6941f154020SRobert Mustacchi /*ARGSUSED*/
6951f154020SRobert Mustacchi static void
dis_riscv_rv32a_load(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)6961f154020SRobert Mustacchi dis_riscv_rv32a_load(dis_handle_t *dhp, uint32_t instr,
6971f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
6981f154020SRobert Mustacchi {
6991f154020SRobert Mustacchi 	const char *suffix = "";
7001f154020SRobert Mustacchi 
7011f154020SRobert Mustacchi 	if (DIS_RISCV_RVA_AQ(instr) && DIS_RISCV_RVA_RL(instr)) {
7021f154020SRobert Mustacchi 		suffix = ".aqrl";
7031f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_AQ(instr)) {
7041f154020SRobert Mustacchi 		suffix = ".aq";
7051f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_RL(instr)) {
7061f154020SRobert Mustacchi 		suffix = ".rl";
7071f154020SRobert Mustacchi 	}
7081f154020SRobert Mustacchi 
7091f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s%s %s,(%s)", table->drv_name,
7101f154020SRobert Mustacchi 	    suffix, dis_riscv_regs[DIS_RISCV_RD(instr)],
7111f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)]);
7121f154020SRobert Mustacchi }
7131f154020SRobert Mustacchi 
7141f154020SRobert Mustacchi /*ARGSUSED*/
7151f154020SRobert Mustacchi static void
dis_riscv_rv32a(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)7161f154020SRobert Mustacchi dis_riscv_rv32a(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
7171f154020SRobert Mustacchi     char *buf, size_t buflen)
7181f154020SRobert Mustacchi {
7191f154020SRobert Mustacchi 	const char *suffix = "";
7201f154020SRobert Mustacchi 
7211f154020SRobert Mustacchi 	if (DIS_RISCV_RVA_AQ(instr) && DIS_RISCV_RVA_RL(instr)) {
7221f154020SRobert Mustacchi 		suffix = ".aqrl";
7231f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_AQ(instr)) {
7241f154020SRobert Mustacchi 		suffix = ".aq";
7251f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_RL(instr)) {
7261f154020SRobert Mustacchi 		suffix = ".rl";
7271f154020SRobert Mustacchi 	}
7281f154020SRobert Mustacchi 
7291f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s%s %s,%s,(%s)", table->drv_name,
7301f154020SRobert Mustacchi 	    suffix, dis_riscv_regs[DIS_RISCV_RD(instr)],
7311f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS2(instr)],
7321f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)]);
7331f154020SRobert Mustacchi }
7341f154020SRobert Mustacchi 
7351f154020SRobert Mustacchi static void
dis_riscv_fp_load(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)7361f154020SRobert Mustacchi dis_riscv_fp_load(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
7371f154020SRobert Mustacchi     char *buf, size_t buflen)
7381f154020SRobert Mustacchi {
7391f154020SRobert Mustacchi 	const char *s;
7401f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(DIS_RISCV_IIMM(instr), 11, &s);
7411f154020SRobert Mustacchi 
7421f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
7431f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
7441f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RD(instr)],
7451f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
7461f154020SRobert Mustacchi 	} else {
7471f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
7481f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RD(instr)],
7491f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
7501f154020SRobert Mustacchi 	}
7511f154020SRobert Mustacchi }
7521f154020SRobert Mustacchi 
7531f154020SRobert Mustacchi static void
dis_riscv_fp_store(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)7541f154020SRobert Mustacchi dis_riscv_fp_store(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
7551f154020SRobert Mustacchi     char *buf, size_t buflen)
7561f154020SRobert Mustacchi {
7571f154020SRobert Mustacchi 	const char *s;
7581f154020SRobert Mustacchi 	uint_t simm = DIS_RISCV_SIMM_UP(instr) | DIS_RISCV_SIMM_LOW(instr);
7591f154020SRobert Mustacchi 	uint_t val = dis_riscv_sign_extend(simm, 11, &s);
7601f154020SRobert Mustacchi 
7611f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
7621f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
7631f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
7641f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
7651f154020SRobert Mustacchi 	} else {
7661f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
7671f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
7681f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
7691f154020SRobert Mustacchi 	}
7701f154020SRobert Mustacchi }
7711f154020SRobert Mustacchi 
7721f154020SRobert Mustacchi /*ARGSUSED*/
7731f154020SRobert Mustacchi static void
dis_riscv_fp_r(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)7741f154020SRobert Mustacchi dis_riscv_fp_r(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
7751f154020SRobert Mustacchi     char *buf, size_t buflen)
7761f154020SRobert Mustacchi {
7771f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
7781f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
7791f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
7801f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)]);
7811f154020SRobert Mustacchi }
7821f154020SRobert Mustacchi 
7831f154020SRobert Mustacchi /*
7841f154020SRobert Mustacchi  * Variant of fp_r type that goes to integer destination registers.
7851f154020SRobert Mustacchi  */
7861f154020SRobert Mustacchi /*ARGSUSED*/
7871f154020SRobert Mustacchi static void
dis_riscv_fp_r_fpi(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)7881f154020SRobert Mustacchi dis_riscv_fp_r_fpi(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
7891f154020SRobert Mustacchi     char *buf, size_t buflen)
7901f154020SRobert Mustacchi {
7911f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
7921f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
7931f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
7941f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)]);
7951f154020SRobert Mustacchi }
7961f154020SRobert Mustacchi 
7971f154020SRobert Mustacchi /*ARGSUSED*/
7981f154020SRobert Mustacchi static void
dis_riscv_fp_r4(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)7991f154020SRobert Mustacchi dis_riscv_fp_r4(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
8001f154020SRobert Mustacchi     char *buf, size_t buflen)
8011f154020SRobert Mustacchi {
8021f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s,%s%s", table->drv_name,
8031f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
8041f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
8051f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
8061f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_FP_RS3(instr)],
8071f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
8081f154020SRobert Mustacchi }
8091f154020SRobert Mustacchi 
8101f154020SRobert Mustacchi /*ARGSUSED*/
8111f154020SRobert Mustacchi static void
dis_riscv_fp_rs2_fp(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)8121f154020SRobert Mustacchi dis_riscv_fp_rs2_fp(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
8131f154020SRobert Mustacchi     char *buf, size_t buflen)
8141f154020SRobert Mustacchi {
8151f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s%s", table->drv_name,
8161f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
8171f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
8181f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
8191f154020SRobert Mustacchi }
8201f154020SRobert Mustacchi 
8211f154020SRobert Mustacchi /*ARGSUSED*/
8221f154020SRobert Mustacchi static void
dis_riscv_fp_rs2_fp_nr(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)8231f154020SRobert Mustacchi dis_riscv_fp_rs2_fp_nr(dis_handle_t *dhp, uint32_t instr,
8241f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
8251f154020SRobert Mustacchi {
8261f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
8271f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
8281f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)]);
8291f154020SRobert Mustacchi }
8301f154020SRobert Mustacchi 
8311f154020SRobert Mustacchi /*ARGSUSED*/
8321f154020SRobert Mustacchi static void
dis_riscv_fp_rs2_fpi(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)8331f154020SRobert Mustacchi dis_riscv_fp_rs2_fpi(dis_handle_t *dhp, uint32_t instr,
8341f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
8351f154020SRobert Mustacchi {
8361f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s%s", table->drv_name,
8371f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
8381f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
8391f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
8401f154020SRobert Mustacchi }
8411f154020SRobert Mustacchi 
8421f154020SRobert Mustacchi /*ARGSUSED*/
8431f154020SRobert Mustacchi static void
dis_riscv_fp_rs2_ifp(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)8441f154020SRobert Mustacchi dis_riscv_fp_rs2_ifp(dis_handle_t *dhp, uint32_t instr,
8451f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
8461f154020SRobert Mustacchi {
8471f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s%s", table->drv_name,
8481f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
8491f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)],
8501f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
8511f154020SRobert Mustacchi }
8521f154020SRobert Mustacchi 
8531f154020SRobert Mustacchi /*ARGSUSED*/
8541f154020SRobert Mustacchi static void
dis_riscv_fp_rs2_fpi_nr(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)8551f154020SRobert Mustacchi dis_riscv_fp_rs2_fpi_nr(dis_handle_t *dhp, uint32_t instr,
8561f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
8571f154020SRobert Mustacchi {
8581f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
8591f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
8601f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)]);
8611f154020SRobert Mustacchi }
8621f154020SRobert Mustacchi 
8631f154020SRobert Mustacchi /*ARGSUSED*/
8641f154020SRobert Mustacchi static void
dis_riscv_fp_rs2_ifp_nr(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)8651f154020SRobert Mustacchi dis_riscv_fp_rs2_ifp_nr(dis_handle_t *dhp, uint32_t instr,
8661f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
8671f154020SRobert Mustacchi {
8681f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
8691f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
8701f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)]);
8711f154020SRobert Mustacchi }
8721f154020SRobert Mustacchi 
8731f154020SRobert Mustacchi 
8741f154020SRobert Mustacchi /*ARGSUSED*/
8751f154020SRobert Mustacchi static void
dis_riscv_fp_rm(dis_handle_t * dhp,uint32_t instr,dis_riscv_instr_t * table,char * buf,size_t buflen)8761f154020SRobert Mustacchi dis_riscv_fp_rm(dis_handle_t *dhp, uint32_t instr,
8771f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
8781f154020SRobert Mustacchi {
8791f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s%s", table->drv_name,
8801f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
8811f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
8821f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
8831f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
8841f154020SRobert Mustacchi }
8851f154020SRobert Mustacchi 
8861f154020SRobert Mustacchi #define	DIS_RISCV_R32(str, op, f3, f7)	\
8871f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_rtype_32, op, f3, f7 }
8881f154020SRobert Mustacchi #define	DIS_RISCV_I32(str, op, f3)	\
8891f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_itype_32, op, f3 }
8901f154020SRobert Mustacchi #define	DIS_RISCV_S32(str, op, f3)	\
8911f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_S_TYPE, dis_riscv_stype_32, op, f3 }
8921f154020SRobert Mustacchi #define	DIS_RISCV_B32(str, op, f3)	\
8931f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_B_TYPE, dis_riscv_btype_32, op, f3 }
8941f154020SRobert Mustacchi #define	DIS_RISCV_U32(str, op)		\
8951f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_U_TYPE, dis_riscv_utype_32, op }
8961f154020SRobert Mustacchi #define	DIS_RISCV_J32(str, op)		\
8971f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_J_TYPE, dis_riscv_jtype_32, op }
8981f154020SRobert Mustacchi 
8991f154020SRobert Mustacchi /*
9001f154020SRobert Mustacchi  * These are non-standard types that we've defined because they require
9011f154020SRobert Mustacchi  * different handling.
9021f154020SRobert Mustacchi  */
9031f154020SRobert Mustacchi #define	DIS_RISCV_SHIFT32(str, op, f3, f7)	\
9041f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_shift_32, op, f3, f7 }
9051f154020SRobert Mustacchi #define	DIS_RISCV_SHIFT64(str, op, f3, f7)	\
9061f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_SHIFT64_TYPE, dis_riscv_shift_64, op, f3, f7 }
9071f154020SRobert Mustacchi #define	DIS_RISCV_CSR(str, op, f3)		\
9081f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_csr, op, f3 }
9091f154020SRobert Mustacchi #define	DIS_RISCV_CSRI(str, op, f3)		\
9101f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_csri, op, f3 }
9111f154020SRobert Mustacchi #define	DIS_RISCV_LOAD(str, op, f3)		\
9121f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_load, op, f3 }
9131f154020SRobert Mustacchi 
9141f154020SRobert Mustacchi #define	DIS_RISCV_MASK(str, mask, val, func)	\
9151f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_MASK_TYPE, func, mask, val }
9161f154020SRobert Mustacchi 
9171f154020SRobert Mustacchi 
9181f154020SRobert Mustacchi /*
9191f154020SRobert Mustacchi  * Atomic-extension specific entries
9201f154020SRobert Mustacchi  */
9211f154020SRobert Mustacchi #define	DIS_RISCV_A32(str, op, f3, f5)		\
9221f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_RV32A_TYPE, dis_riscv_rv32a, op, f3, f5 }
9231f154020SRobert Mustacchi #define	DIS_RISCV_A32LOAD(str, op, f3, f5, f2)	\
9241f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_RV32A_LOAD_TYPE, dis_riscv_rv32a_load, op, f3, \
9251f154020SRobert Mustacchi 	    f5, f2 }
9261f154020SRobert Mustacchi 
9271f154020SRobert Mustacchi /*
9281f154020SRobert Mustacchi  * Floating-point specific entries
9291f154020SRobert Mustacchi  */
9301f154020SRobert Mustacchi #define	DIS_RISCV_FP_LOAD(str, op, f3)				\
9311f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_fp_load, op, f3 }
9321f154020SRobert Mustacchi #define	DIS_RISCV_FP_STORE(str, op, f3)				\
9331f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_S_TYPE, dis_riscv_fp_store, op, f3 }
9341f154020SRobert Mustacchi #define	DIS_RISCV_FP_R(str, op, f3, f7)				\
9351f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_fp_r, op, f3, f7 }
9361f154020SRobert Mustacchi #define	DIS_RISCV_FP_R4(str, op, f2)				\
9371f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R4_TYPE, dis_riscv_fp_r4, op, 0, 0, f2 }
9381f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_FP(str, op, rs2, f7)			\
9391f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fp, op, rs2, f7 }
9401f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_FP_NR(str, op, rs2, f7)		\
9411f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fp_nr, op, rs2, f7 }
9421f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_FPI(str, op, rs2, f7)			\
9431f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fpi, op, rs2, f7 }
9441f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_IFP(str, op, rs2, f7)			\
9451f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_ifp, op, rs2, f7 }
9461f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_IFP_NR(str, op, rs2, f7)		\
9471f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_ifp_nr, op, rs2, f7 }
9481f154020SRobert Mustacchi #define	DIS_RISCV_FP_RM(str, op, f7)				\
9491f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RM_TYPE, dis_riscv_fp_rm, op, 0, f7 }
9501f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_FPI(str, op, f3, rs2, f7)		\
9511f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_fpi, op, f3, f7, \
9521f154020SRobert Mustacchi 	    rs2 }
9531f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_IFP(str, op, f3, rs2, f7)		\
9541f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_ifp, op, f3, f7, \
9551f154020SRobert Mustacchi 	    rs2 }
9561f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_FPI_NR(str, op, f3, rs2, f7)		\
9571f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_fpi_nr, op, f3, \
9581f154020SRobert Mustacchi 	    f7, rs2 }
9591f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_IFP_NR(str, op, f3, rs2, f7)		\
9601f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_ifp_nr, op, f3, \
9611f154020SRobert Mustacchi 	    f7, rs2 }
962*38848811SRobert Mustacchi #define	DIS_RISCV_FP_RI(str, op, f3, f7)			\
9631f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_fp_r_fpi, op, f3, f7 }
9641f154020SRobert Mustacchi 
9651f154020SRobert Mustacchi /*
9661f154020SRobert Mustacchi  * This table is ordered such that it follows the ordering in the RISC-V ISA
9671f154020SRobert Mustacchi  * Manual.
9681f154020SRobert Mustacchi  */
9691f154020SRobert Mustacchi static dis_riscv_instr_t dis_riscv_4byte[] = {
9701f154020SRobert Mustacchi 	/*
9711f154020SRobert Mustacchi 	 * RV32I
9721f154020SRobert Mustacchi 	 */
9731f154020SRobert Mustacchi 	DIS_RISCV_U32("lui", 0x37),
9741f154020SRobert Mustacchi 	DIS_RISCV_U32("auipc", 0x17),
9751f154020SRobert Mustacchi 	DIS_RISCV_J32("jal", 0x6f),
9761f154020SRobert Mustacchi 	/* ret is a special case of jalr */
9771f154020SRobert Mustacchi 	DIS_RISCV_MASK("ret", 0xffffffff, 0x00008067, dis_riscv_name),
9781f154020SRobert Mustacchi 	DIS_RISCV_I32("jalr", 0x67, 0x0),
9791f154020SRobert Mustacchi 	DIS_RISCV_B32("beq", 0x63, 0x0),
9801f154020SRobert Mustacchi 	DIS_RISCV_B32("bne", 0x63, 0x1),
9811f154020SRobert Mustacchi 	DIS_RISCV_B32("blt", 0x63, 0x4),
9821f154020SRobert Mustacchi 	DIS_RISCV_B32("bge", 0x63, 0x5),
9831f154020SRobert Mustacchi 	DIS_RISCV_B32("bltu", 0x63, 0x6),
9841f154020SRobert Mustacchi 	DIS_RISCV_B32("bgeu", 0x63, 0x7),
9851f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lb", 0x03, 0x0),
9861f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lh", 0x03, 0x1),
9871f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lw", 0x03, 0x2),
9881f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lbu", 0x03, 0x4),
9891f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lhu", 0x03, 0x5),
9901f154020SRobert Mustacchi 	DIS_RISCV_S32("sb", 0x23, 0x0),
9911f154020SRobert Mustacchi 	DIS_RISCV_S32("sh", 0x23, 0x1),
9921f154020SRobert Mustacchi 	DIS_RISCV_S32("sw", 0x23, 0x2),
9931f154020SRobert Mustacchi 	/* nop is addi x0, x0, 0 */
9941f154020SRobert Mustacchi 	DIS_RISCV_MASK("nop", 0xffffffff, 0x00000013, dis_riscv_name),
9951f154020SRobert Mustacchi 	DIS_RISCV_I32("addi", 0x13, 0x0),
9961f154020SRobert Mustacchi 	DIS_RISCV_I32("slti", 0x13, 0x2),
9971f154020SRobert Mustacchi 	DIS_RISCV_I32("sltiu", 0x13, 0x3),
9981f154020SRobert Mustacchi 	DIS_RISCV_I32("xori", 0x13, 0x4),
9991f154020SRobert Mustacchi 	DIS_RISCV_I32("ori", 0x13, 0x6),
10001f154020SRobert Mustacchi 	DIS_RISCV_I32("andi", 0x13, 0x7),
10011f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("slli", 0x13, 0x1, 0x00),
10021f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("srli", 0x13, 0x5, 0x00),
10031f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("srai", 0x13, 0x5, 0x20),
10041f154020SRobert Mustacchi 	DIS_RISCV_R32("add", 0x33, 0x0, 0x00),
10051f154020SRobert Mustacchi 	DIS_RISCV_R32("sub", 0x33, 0x0, 0x20),
10061f154020SRobert Mustacchi 	DIS_RISCV_R32("sll", 0x33, 0x1, 0x00),
10071f154020SRobert Mustacchi 	DIS_RISCV_R32("slt", 0x33, 0x2, 0x00),
10081f154020SRobert Mustacchi 	DIS_RISCV_R32("sltu", 0x33, 0x3, 0x00),
10091f154020SRobert Mustacchi 	DIS_RISCV_R32("xor", 0x33, 0x4, 0x00),
10101f154020SRobert Mustacchi 	DIS_RISCV_R32("srl", 0x33, 0x5, 0x00),
10111f154020SRobert Mustacchi 	DIS_RISCV_R32("sra", 0x33, 0x5, 0x20),
10121f154020SRobert Mustacchi 	DIS_RISCV_R32("or", 0x33, 0x6, 0x00),
10131f154020SRobert Mustacchi 	DIS_RISCV_R32("and", 0x33, 0x7, 0x00),
10141f154020SRobert Mustacchi 	DIS_RISCV_MASK("fence", 0xf00fffff, 0xf, dis_riscv_fence),
10151f154020SRobert Mustacchi 	DIS_RISCV_MASK("fence.i", 0xfffff00f, 0x100f, dis_riscv_name),
10161f154020SRobert Mustacchi 	DIS_RISCV_MASK("ecall", 0xffffffff, 0x73, dis_riscv_name),
10171f154020SRobert Mustacchi 	DIS_RISCV_MASK("ebreak", 0xffffffff, 0x100073, dis_riscv_name),
10181f154020SRobert Mustacchi 	DIS_RISCV_CSR("csrrw", 0x73, 0x1),
10191f154020SRobert Mustacchi 	DIS_RISCV_CSR("csrrs", 0x73, 0x2),
10201f154020SRobert Mustacchi 	DIS_RISCV_CSR("csrrc", 0x73, 0x3),
10211f154020SRobert Mustacchi 	DIS_RISCV_CSRI("csrrwi", 0x73, 0x5),
10221f154020SRobert Mustacchi 	DIS_RISCV_CSRI("csrrsi", 0x73, 0x6),
10231f154020SRobert Mustacchi 	DIS_RISCV_CSRI("csrrci", 0x73, 0x7),
10241f154020SRobert Mustacchi 	/*
10251f154020SRobert Mustacchi 	 * RV64I
10261f154020SRobert Mustacchi 	 */
10271f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lwu", 0x03, 0x6),
10281f154020SRobert Mustacchi 	DIS_RISCV_LOAD("ld", 0x03, 0x3),
10291f154020SRobert Mustacchi 	DIS_RISCV_S32("sd", 0x23, 0x3),
10301f154020SRobert Mustacchi 	DIS_RISCV_SHIFT64("slli", 0x13, 0x1, 0x0),
10311f154020SRobert Mustacchi 	DIS_RISCV_SHIFT64("srli", 0x13, 0x5, 0x0),
10321f154020SRobert Mustacchi 	DIS_RISCV_SHIFT64("srai", 0x13, 0x5, 0x10),
10331f154020SRobert Mustacchi 	DIS_RISCV_I32("addiw", 0x1b, 0x0),
10341f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("slliw", 0x1b, 0x1, 0x0),
10351f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("srliw", 0x1b, 0x5, 0x0),
10361f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("sraiw", 0x1b, 0x5, 0x20),
10371f154020SRobert Mustacchi 	DIS_RISCV_R32("addw", 0x3b, 0x0, 0x00),
10381f154020SRobert Mustacchi 	DIS_RISCV_R32("subw", 0x3b, 0x0, 0x20),
10391f154020SRobert Mustacchi 	DIS_RISCV_R32("sllw", 0x3b, 0x1, 0x00),
10401f154020SRobert Mustacchi 	DIS_RISCV_R32("srlw", 0x3b, 0x5, 0x00),
10411f154020SRobert Mustacchi 	DIS_RISCV_R32("sraw", 0x3b, 0x5, 0x20),
10421f154020SRobert Mustacchi 	/*
10431f154020SRobert Mustacchi 	 * RV32M
10441f154020SRobert Mustacchi 	 */
10451f154020SRobert Mustacchi 	DIS_RISCV_R32("mul", 0x33, 0x0, 0x01),
10461f154020SRobert Mustacchi 	DIS_RISCV_R32("mulh", 0x33, 0x1, 0x01),
10471f154020SRobert Mustacchi 	DIS_RISCV_R32("mulhsu", 0x33, 0x2, 0x01),
10481f154020SRobert Mustacchi 	DIS_RISCV_R32("mulhu", 0x33, 0x3, 0x01),
10491f154020SRobert Mustacchi 	DIS_RISCV_R32("div", 0x33, 0x4, 0x01),
10501f154020SRobert Mustacchi 	DIS_RISCV_R32("divu", 0x33, 0x5, 0x01),
10511f154020SRobert Mustacchi 	DIS_RISCV_R32("rem", 0x33, 0x6, 0x01),
10521f154020SRobert Mustacchi 	DIS_RISCV_R32("remu", 0x33, 0x7, 0x01),
10531f154020SRobert Mustacchi 	/*
10541f154020SRobert Mustacchi 	 * RV64M
10551f154020SRobert Mustacchi 	 */
10561f154020SRobert Mustacchi 	DIS_RISCV_R32("mulw", 0x3b, 0x0, 0x01),
10571f154020SRobert Mustacchi 	DIS_RISCV_R32("divw", 0x3b, 0x4, 0x01),
10581f154020SRobert Mustacchi 	DIS_RISCV_R32("divuw", 0x3b, 0x5, 0x01),
10591f154020SRobert Mustacchi 	DIS_RISCV_R32("remw", 0x3b, 0x6, 0x01),
10601f154020SRobert Mustacchi 	DIS_RISCV_R32("remuw", 0x3b, 0x7, 0x01),
10611f154020SRobert Mustacchi 	/*
10621f154020SRobert Mustacchi 	 * RV32A
10631f154020SRobert Mustacchi 	 */
10641f154020SRobert Mustacchi 	DIS_RISCV_A32LOAD("lr.w", 0x2f, 0x2, 0x02, 0x0),
10651f154020SRobert Mustacchi 	DIS_RISCV_A32("sc.w", 0x2f, 0x2, 0x03),
10661f154020SRobert Mustacchi 	DIS_RISCV_A32("amoswap.w", 0x2f, 0x2, 0x01),
10671f154020SRobert Mustacchi 	DIS_RISCV_A32("amoadd.w", 0x2f, 0x2, 0x00),
10681f154020SRobert Mustacchi 	DIS_RISCV_A32("amoxor.w", 0x2f, 0x2, 0x04),
10691f154020SRobert Mustacchi 	DIS_RISCV_A32("amoand.w", 0x2f, 0x2, 0x0c),
10701f154020SRobert Mustacchi 	DIS_RISCV_A32("amoor.w", 0x2f, 0x2, 0x08),
10711f154020SRobert Mustacchi 	DIS_RISCV_A32("amomin.w", 0x2f, 0x2, 0x10),
10721f154020SRobert Mustacchi 	DIS_RISCV_A32("amomax.w", 0x2f, 0x2, 0x14),
10731f154020SRobert Mustacchi 	DIS_RISCV_A32("amominu.w", 0x2f, 0x2, 0x18),
10741f154020SRobert Mustacchi 	DIS_RISCV_A32("amomaxu.w", 0x2f, 0x2, 0x1c),
10751f154020SRobert Mustacchi 	/*
10761f154020SRobert Mustacchi 	 * RV64A
10771f154020SRobert Mustacchi 	 */
10781f154020SRobert Mustacchi 	DIS_RISCV_A32LOAD("lr.d", 0x2f, 0x3, 0x02, 0x0),
10791f154020SRobert Mustacchi 	DIS_RISCV_A32("sc.d", 0x2f, 0x3, 0x03),
10801f154020SRobert Mustacchi 	DIS_RISCV_A32("amoswap.d", 0x2f, 0x3, 0x01),
10811f154020SRobert Mustacchi 	DIS_RISCV_A32("amoadd.d", 0x2f, 0x3, 0x00),
10821f154020SRobert Mustacchi 	DIS_RISCV_A32("amoxor.d", 0x2f, 0x3, 0x04),
10831f154020SRobert Mustacchi 	DIS_RISCV_A32("amoand.d", 0x2f, 0x3, 0x0c),
10841f154020SRobert Mustacchi 	DIS_RISCV_A32("amoor.d", 0x2f, 0x3, 0x08),
10851f154020SRobert Mustacchi 	DIS_RISCV_A32("amomin.d", 0x2f, 0x3, 0x10),
10861f154020SRobert Mustacchi 	DIS_RISCV_A32("amomax.d", 0x2f, 0x3, 0x14),
10871f154020SRobert Mustacchi 	DIS_RISCV_A32("amominu.d", 0x2f, 0x3, 0x18),
10881f154020SRobert Mustacchi 	DIS_RISCV_A32("amomaxu.d", 0x2f, 0x3, 0x1c),
10891f154020SRobert Mustacchi 	/*
10901f154020SRobert Mustacchi 	 * RV32F
10911f154020SRobert Mustacchi 	 */
10921f154020SRobert Mustacchi 	DIS_RISCV_FP_LOAD("flw", 0x07, 0x2),
10931f154020SRobert Mustacchi 	DIS_RISCV_FP_STORE("fsw", 0x27, 0x2),
10941f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmadd.s", 0x43, 0x0),
10951f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmsub.s", 0x47, 0x0),
10961f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmsub.s", 0x4b, 0x0),
10971f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmadd.s", 0x4f, 0x0),
10981f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fadd.s", 0x53, 0x00),
10991f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fsub.s", 0x53, 0x04),
11001f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fmul.s", 0x53, 0x08),
11011f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fdiv.s", 0x53, 0xc),
11021f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP("fsqrt.s", 0x53, 0x00, 0x2c),
11031f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnj.s", 0x53, 0x0, 0x10),
11041f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjn.s", 0x53, 0x1, 0x10),
11051f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjx.s", 0x53, 0x2, 0x10),
11061f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmin.s", 0x53, 0x0, 0x14),
11071f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmax.s", 0x53, 0x1, 0x14),
11081f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.w.s", 0x53, 0x00, 0x60),
11091f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.wu.s", 0x53, 0x01, 0x60),
11101f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fmv.x.w", 0x53, 0x00, 0x00, 0x70),
11111f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("feq.s", 0x53, 0x2, 0x50),
11121f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("flt.s", 0x53, 0x1, 0x50),
11131f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("fle.s", 0x53, 0x0, 0x50),
11141f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fclass.s", 0x53, 0x1, 0x00, 0x70),
11151f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.w", 0x53, 0x00, 0x68),
11161f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.wu", 0x53, 0x01, 0x68),
11171f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_IFP_NR("fmv.w.x", 0x53, 0x0, 0x00, 0x78),
11181f154020SRobert Mustacchi 	/*
11191f154020SRobert Mustacchi 	 * RV64F
11201f154020SRobert Mustacchi 	 */
11211f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.l.s", 0x53, 0x02, 0x60),
11221f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.lu.s", 0x53, 0x03, 0x60),
11231f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.l", 0x53, 0x02, 0x68),
11241f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.lu", 0x53, 0x03, 0x68),
11251f154020SRobert Mustacchi 	/*
11261f154020SRobert Mustacchi 	 * RV32D
11271f154020SRobert Mustacchi 	 */
11281f154020SRobert Mustacchi 	DIS_RISCV_FP_LOAD("fld", 0x07, 0x3),
11291f154020SRobert Mustacchi 	DIS_RISCV_FP_STORE("fsd", 0x27, 0x3),
11301f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmadd.d", 0x43, 0x1),
11311f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmsub.d", 0x47, 0x1),
11321f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmsub.d", 0x4b, 0x1),
11331f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmadd.d", 0x4f, 0x1),
11341f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fadd.d", 0x53, 0x01),
11351f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fsub.d", 0x53, 0x05),
11361f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fmul.d", 0x53, 0x09),
11371f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fdiv.d", 0x53, 0xd),
11381f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP("fsqrt.d", 0x53, 0x00, 0x2d),
11391f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnj.d", 0x53, 0x0, 0x11),
11401f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjn.d", 0x53, 0x1, 0x11),
11411f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjx.d", 0x53, 0x2, 0x11),
11421f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmin.d", 0x53, 0x0, 0x15),
11431f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmax.d", 0x53, 0x1, 0x15),
11441f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP("fcvt.s.d", 0x53, 0x01, 0x20),
11451f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP_NR("fcvt.d.s", 0x53, 0x00, 0x21),
11461f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("feq.d", 0x53, 0x2, 0x51),
11471f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("flt.d", 0x53, 0x1, 0x51),
11481f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("fle.d", 0x53, 0x0, 0x51),
11491f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fclass.d", 0x53, 0x1, 0x00, 0x71),
11501f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.w.d", 0x53, 0x00, 0x61),
11511f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.wu.d", 0x53, 0x01, 0x61),
11521f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP_NR("fcvt.d.w", 0x53, 0x00, 0x69),
11531f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP_NR("fcvt.d.wu", 0x53, 0x01, 0x69),
11541f154020SRobert Mustacchi 	/*
11551f154020SRobert Mustacchi 	 * RV64D
11561f154020SRobert Mustacchi 	 */
11571f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.l.d", 0x53, 0x02, 0x61),
11581f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.lu.d", 0x53, 0x03, 0x61),
11591f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fmv.x.d", 0x53, 0x0, 0x00, 0x71),
11601f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.d.l", 0x53, 0x02, 0x69),
11611f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.d.lu", 0x53, 0x03, 0x69),
11621f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_IFP_NR("fmv.d.x", 0x53, 0x0, 0x00, 0x79),
11631f154020SRobert Mustacchi 	/*
11641f154020SRobert Mustacchi 	 * Privileged Instructions from RISC-V Privileged Architectures V1.10.
11651f154020SRobert Mustacchi 	 */
11661f154020SRobert Mustacchi 	DIS_RISCV_MASK("uret", 0xffffffff, 0x00200073, dis_riscv_name),
11671f154020SRobert Mustacchi 	DIS_RISCV_MASK("sret", 0xffffffff, 0x10200073, dis_riscv_name),
11681f154020SRobert Mustacchi 	DIS_RISCV_MASK("mret", 0xffffffff, 0x30200073, dis_riscv_name),
11691f154020SRobert Mustacchi 	DIS_RISCV_MASK("wfi", 0xffffffff, 0x10500073, dis_riscv_name),
11701f154020SRobert Mustacchi 	DIS_RISCV_MASK("sfence.vma", 0xfe007fff, 0x12000073, dis_riscv_rs1_rs2)
11711f154020SRobert Mustacchi };
11721f154020SRobert Mustacchi 
11731f154020SRobert Mustacchi static void
dis_riscv_decode_4byte(dis_handle_t * dhp,uint32_t instr,char * buf,size_t buflen)11741f154020SRobert Mustacchi dis_riscv_decode_4byte(dis_handle_t *dhp, uint32_t instr, char *buf,
11751f154020SRobert Mustacchi     size_t buflen)
11761f154020SRobert Mustacchi {
11771f154020SRobert Mustacchi 	uint_t i;
11781f154020SRobert Mustacchi 
11791f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_4byte); i++) {
11801f154020SRobert Mustacchi 		dis_riscv_instr_t *t = &dis_riscv_4byte[i];
11811f154020SRobert Mustacchi 		switch (t->drv_type) {
11821f154020SRobert Mustacchi 		case DIS_RISCV_I_R_TYPE:
11831f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
11841f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
11851f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
11861f154020SRobert Mustacchi 				break;
11871f154020SRobert Mustacchi 			}
11881f154020SRobert Mustacchi 			continue;
11891f154020SRobert Mustacchi 		case DIS_RISCV_I_I_TYPE:
11901f154020SRobert Mustacchi 		case DIS_RISCV_I_S_TYPE:
11911f154020SRobert Mustacchi 		case DIS_RISCV_I_B_TYPE:
11921f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
11931f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3) {
11941f154020SRobert Mustacchi 				break;
11951f154020SRobert Mustacchi 			}
11961f154020SRobert Mustacchi 			continue;
11971f154020SRobert Mustacchi 		case DIS_RISCV_I_U_TYPE:
11981f154020SRobert Mustacchi 		case DIS_RISCV_I_J_TYPE:
11991f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode) {
12001f154020SRobert Mustacchi 				break;
12011f154020SRobert Mustacchi 			}
12021f154020SRobert Mustacchi 			continue;
12031f154020SRobert Mustacchi 		case DIS_RISCV_I_R4_TYPE:
12041f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
12051f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT2(instr) == t->drv_funct2) {
12061f154020SRobert Mustacchi 				break;
12071f154020SRobert Mustacchi 			}
12081f154020SRobert Mustacchi 			continue;
12091f154020SRobert Mustacchi 		case DIS_RISCV_I_MASK_TYPE:
12101f154020SRobert Mustacchi 			if ((instr & t->drv_opcode) == t->drv_funct3) {
12111f154020SRobert Mustacchi 				break;
12121f154020SRobert Mustacchi 			}
12131f154020SRobert Mustacchi 			continue;
12141f154020SRobert Mustacchi 		case DIS_RISCV_I_SHIFT64_TYPE:
12151f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
12161f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
12171f154020SRobert Mustacchi 			    DIS_RISCV_SFUNCT7(instr) == t->drv_funct7) {
12181f154020SRobert Mustacchi 				break;
12191f154020SRobert Mustacchi 			}
12201f154020SRobert Mustacchi 			continue;
12211f154020SRobert Mustacchi 
12221f154020SRobert Mustacchi 		case DIS_RISCV_I_RV32A_LOAD_TYPE:
12231f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
12241f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
12251f154020SRobert Mustacchi 			    DIS_RISCV_RVA_FUNCT5(instr) == t->drv_funct7 &&
12261f154020SRobert Mustacchi 			    DIS_RISCV_RS2(instr) == t->drv_funct2) {
12271f154020SRobert Mustacchi 				break;
12281f154020SRobert Mustacchi 			}
12291f154020SRobert Mustacchi 			continue;
12301f154020SRobert Mustacchi 		case DIS_RISCV_I_RV32A_TYPE:
12311f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
12321f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
12331f154020SRobert Mustacchi 			    DIS_RISCV_RVA_FUNCT5(instr) == t->drv_funct7) {
12341f154020SRobert Mustacchi 				break;
12351f154020SRobert Mustacchi 			}
12361f154020SRobert Mustacchi 			continue;
12371f154020SRobert Mustacchi 		case DIS_RISCV_I_FP_RS2OP_TYPE:
12381f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
12391f154020SRobert Mustacchi 			    DIS_RISCV_RS2(instr) == t->drv_funct3 &&
12401f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
12411f154020SRobert Mustacchi 				break;
12421f154020SRobert Mustacchi 			}
12431f154020SRobert Mustacchi 			continue;
12441f154020SRobert Mustacchi 		case DIS_RISCV_I_FP_RM_TYPE:
12451f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
12461f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
12471f154020SRobert Mustacchi 				break;
12481f154020SRobert Mustacchi 			}
12491f154020SRobert Mustacchi 			continue;
12501f154020SRobert Mustacchi 		case DIS_RISCV_I_FP_R_RS2_TYPE:
12511f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
12521f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
12531f154020SRobert Mustacchi 			    DIS_RISCV_RS2(instr) == t->drv_funct2 &&
12541f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
12551f154020SRobert Mustacchi 				break;
12561f154020SRobert Mustacchi 			}
12571f154020SRobert Mustacchi 			continue;
12581f154020SRobert Mustacchi 		default:
12591f154020SRobert Mustacchi 			continue;
12601f154020SRobert Mustacchi 		}
12611f154020SRobert Mustacchi 
12621f154020SRobert Mustacchi 		t->drv_print(dhp, instr, t, buf, buflen);
12631f154020SRobert Mustacchi 		return;
12641f154020SRobert Mustacchi 	}
12651f154020SRobert Mustacchi 
12661f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "<unknown>");
12671f154020SRobert Mustacchi }
12681f154020SRobert Mustacchi 
12691f154020SRobert Mustacchi /*
12701f154020SRobert Mustacchi  * Two byte decode table types.
12711f154020SRobert Mustacchi  */
12721f154020SRobert Mustacchi typedef enum dis_riscv_ctype {
12731f154020SRobert Mustacchi 	/*
12741f154020SRobert Mustacchi 	 * Indicates that we should match based on the opcode and funct3.
12751f154020SRobert Mustacchi 	 */
12761f154020SRobert Mustacchi 	DIS_RISCV_C_FUNCT3,
12771f154020SRobert Mustacchi 	/*
12781f154020SRobert Mustacchi 	 * Indicates that we should match the instruction based on a mask.
12791f154020SRobert Mustacchi 	 */
12801f154020SRobert Mustacchi 	DIS_RISCV_C_MATCH
12811f154020SRobert Mustacchi } dis_riscv_ctype_t;
12821f154020SRobert Mustacchi 
12831f154020SRobert Mustacchi /*
12841f154020SRobert Mustacchi  * The compact forms are depending on the elf class. This is used to keep track
12851f154020SRobert Mustacchi  * of the class and match it.
12861f154020SRobert Mustacchi  */
12871f154020SRobert Mustacchi typedef enum dis_riscv_c_class {
12881f154020SRobert Mustacchi 	DIS_RISCV_CL_ALL,
12891f154020SRobert Mustacchi 	DIS_RISCV_CL_32,
12901f154020SRobert Mustacchi 	DIS_RISCV_CL_64,
12911f154020SRobert Mustacchi 	DIS_RISCV_CL_32_64,
12921f154020SRobert Mustacchi 	DIS_RISCV_CL_64_128
12931f154020SRobert Mustacchi } dis_riscv_c_class_t;
12941f154020SRobert Mustacchi 
12951f154020SRobert Mustacchi struct dis_riscv_c_instr;
12961f154020SRobert Mustacchi typedef void (*dis_riscv_c_func_t)(dis_handle_t *, uint32_t,
12971f154020SRobert Mustacchi     struct dis_riscv_c_instr *, char *, size_t);
12981f154020SRobert Mustacchi 
12991f154020SRobert Mustacchi typedef struct dis_riscv_c_instr {
13001f154020SRobert Mustacchi 	const char		*drv_c_name;
13011f154020SRobert Mustacchi 	dis_riscv_ctype_t	drv_c_type;
13021f154020SRobert Mustacchi 	dis_riscv_c_func_t	drv_c_print;
1303*38848811SRobert Mustacchi 	dis_riscv_c_class_t	drv_c_class;
13041f154020SRobert Mustacchi 	uint_t			drv_c_opcode;
13051f154020SRobert Mustacchi 	uint_t			drv_c_funct;
13061f154020SRobert Mustacchi 	uint_t			drv_c_mask;
13071f154020SRobert Mustacchi 	uint_t			drv_c_match;
13081f154020SRobert Mustacchi } dis_riscv_c_instr_t;
13091f154020SRobert Mustacchi 
13101f154020SRobert Mustacchi #define	DIS_RISCV_C_OPCODE(x)	((x) & 0x03)
13111f154020SRobert Mustacchi #define	DIS_RISCV_C_FUNCT3(x)	(((x) & 0xe000) >> 13)
13121f154020SRobert Mustacchi 
13131f154020SRobert Mustacchi #define	DIS_RISCV_C_RS1(x)	(((x) & 0x0f80) >> 7)
13141f154020SRobert Mustacchi #define	DIS_RISCV_C_RS2(x)	(((x) & 0x007c) >> 2)
13151f154020SRobert Mustacchi #define	DIS_RISCV_C_RD(x)	DIS_RISCV_C_RS1(x)
13161f154020SRobert Mustacchi 
13171f154020SRobert Mustacchi #define	DIS_RISCV_C_RS1P(x)	(((x) & 0x0380) >> 7)
13181f154020SRobert Mustacchi #define	DIS_RISCV_C_RS2P(x)	DIS_RISCV_C_RDP(x)
13191f154020SRobert Mustacchi #define	DIS_RISCV_C_RDP(x)	(((x) & 0x001c) >> 2)
13201f154020SRobert Mustacchi 
13211f154020SRobert Mustacchi /*
13221f154020SRobert Mustacchi  * CJ format immediate extractor
13231f154020SRobert Mustacchi  */
13241f154020SRobert Mustacchi #define	DIS_RISCV_C_J_11(x)	(((x) & 0x1000) >> 1)
13251f154020SRobert Mustacchi #define	DIS_RISCV_C_J_4(x)	(((x) & 0x0800) >> 7)
13261f154020SRobert Mustacchi #define	DIS_RISCV_C_J_9_8(x)	(((x) & 0x0600) >> 1)
13271f154020SRobert Mustacchi #define	DIS_RISCV_C_J_10(x)	(((x) & 0x0100) << 2)
13281f154020SRobert Mustacchi #define	DIS_RISCV_C_J_6(x)	(((x) & 0x0080) >> 1)
13291f154020SRobert Mustacchi #define	DIS_RISCV_C_J_7(x)	(((x) & 0x0040) << 1)
13301f154020SRobert Mustacchi #define	DIS_RISCV_C_J_3_1(x)	(((x) & 0x0038) >> 3)
13311f154020SRobert Mustacchi #define	DIS_RISCV_C_J_5(x)	(((x) & 0x0004) << 3)
13321f154020SRobert Mustacchi 
13331f154020SRobert Mustacchi /*
13341f154020SRobert Mustacchi  * Compact Branch extractor
13351f154020SRobert Mustacchi  */
13361f154020SRobert Mustacchi #define	DIS_RISCV_C_B_8(x)	(((x) & 0x1000) >> 4)
13371f154020SRobert Mustacchi #define	DIS_RISCV_C_B_4_3(x)	(((x) & 0x0c00) >> 7)
13381f154020SRobert Mustacchi #define	DIS_RISCV_C_B_7_6(x)	(((x) & 0x0060) << 1)
13391f154020SRobert Mustacchi #define	DIS_RISCV_C_B_2_1(x)	(((x) & 0x0018) >> 2)
13401f154020SRobert Mustacchi #define	DIS_RISCV_C_B_5(x)	(((x) & 0x0004) << 3)
13411f154020SRobert Mustacchi 
13421f154020SRobert Mustacchi /*
13431f154020SRobert Mustacchi  * c.addi16spn extractor
13441f154020SRobert Mustacchi  */
13451f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_9(x)	(((x) & 0x1000) >> 3)
13461f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_4(x)	(((x) & 0x0040) >> 2)
13471f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_6(x)	(((x) & 0x0020) << 1)
13481f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_8_7(x)	(((x) & 0x0018) << 4)
13491f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_5(x)	(((x) & 0x0004) << 3)
13501f154020SRobert Mustacchi 
13511f154020SRobert Mustacchi /*
13521f154020SRobert Mustacchi  * c.addi4spn extractor
13531f154020SRobert Mustacchi  */
13541f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_5_4(x)	(((x) & 0x1800) >> 7)
13551f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_9_6(x)	(((x) & 0x0700) >> 2)
13561f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_2(x)	(((x) & 0x0040) >> 4)
13571f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_3(x)	(((x) & 0x0020) >> 2)
13581f154020SRobert Mustacchi 
13591f154020SRobert Mustacchi /*ARGSUSED*/
13601f154020SRobert Mustacchi static void
dis_riscv_c_name(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)13611f154020SRobert Mustacchi dis_riscv_c_name(dis_handle_t *dhp, uint32_t instr,
13621f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
13631f154020SRobert Mustacchi {
13641f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s", table->drv_c_name);
13651f154020SRobert Mustacchi }
13661f154020SRobert Mustacchi 
13671f154020SRobert Mustacchi static void
dis_riscv_c_loadstore(dis_handle_t * dhp,const char * name,const char * dreg,const char * sreg,uint32_t off,char * buf,size_t buflen)13681f154020SRobert Mustacchi dis_riscv_c_loadstore(dis_handle_t *dhp, const char *name, const char *dreg,
13691f154020SRobert Mustacchi     const char *sreg, uint32_t off, char *buf, size_t buflen)
13701f154020SRobert Mustacchi {
13711f154020SRobert Mustacchi 
13721f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
13731f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,0%o(%s)", name, dreg,
13741f154020SRobert Mustacchi 		    off, sreg);
13751f154020SRobert Mustacchi 	} else {
13761f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,0x%x(%s)", name, dreg,
13771f154020SRobert Mustacchi 		    off, sreg);
13781f154020SRobert Mustacchi 	}
13791f154020SRobert Mustacchi }
13801f154020SRobert Mustacchi 
13811f154020SRobert Mustacchi static void
dis_riscv_c_lwsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)13821f154020SRobert Mustacchi dis_riscv_c_lwsp(dis_handle_t *dhp, uint32_t instr,
13831f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
13841f154020SRobert Mustacchi {
13851f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x000c) << 4) |
13861f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0070) >> 2);
13871f154020SRobert Mustacchi 
13881f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
13891f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2], imm, buf,
13901f154020SRobert Mustacchi 	    buflen);
13911f154020SRobert Mustacchi }
13921f154020SRobert Mustacchi 
13931f154020SRobert Mustacchi static void
dis_riscv_c_ldsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)13941f154020SRobert Mustacchi dis_riscv_c_ldsp(dis_handle_t *dhp, uint32_t instr,
13951f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
13961f154020SRobert Mustacchi {
13971f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x001c) << 4) |
13981f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0060) >> 2);
13991f154020SRobert Mustacchi 
14001f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14011f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2],
14021f154020SRobert Mustacchi 	    imm, buf, buflen);
14031f154020SRobert Mustacchi }
14041f154020SRobert Mustacchi 
14051f154020SRobert Mustacchi static void
dis_riscv_c_flwsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14061f154020SRobert Mustacchi dis_riscv_c_flwsp(dis_handle_t *dhp, uint32_t instr,
14071f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14081f154020SRobert Mustacchi {
14091f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x000c) << 4) |
14101f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0070) >> 2);
14111f154020SRobert Mustacchi 
14121f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14131f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2],
14141f154020SRobert Mustacchi 	    imm, buf, buflen);
14151f154020SRobert Mustacchi }
14161f154020SRobert Mustacchi 
14171f154020SRobert Mustacchi static void
dis_riscv_c_fldsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14181f154020SRobert Mustacchi dis_riscv_c_fldsp(dis_handle_t *dhp, uint32_t instr,
14191f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14201f154020SRobert Mustacchi {
14211f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x001c) << 4) |
14221f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0060) >> 2);
14231f154020SRobert Mustacchi 
14241f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14251f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2],
14261f154020SRobert Mustacchi 	    imm, buf, buflen);
14271f154020SRobert Mustacchi }
14281f154020SRobert Mustacchi 
14291f154020SRobert Mustacchi static void
dis_riscv_c_swsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14301f154020SRobert Mustacchi dis_riscv_c_swsp(dis_handle_t *dhp, uint32_t instr,
14311f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14321f154020SRobert Mustacchi {
14331f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0180) >> 1) | ((instr & 0x1e00) >> 7);
14341f154020SRobert Mustacchi 
14351f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14361f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
14371f154020SRobert Mustacchi 	    buf, buflen);
14381f154020SRobert Mustacchi }
14391f154020SRobert Mustacchi 
14401f154020SRobert Mustacchi static void
dis_riscv_c_sdsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14411f154020SRobert Mustacchi dis_riscv_c_sdsp(dis_handle_t *dhp, uint32_t instr,
14421f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14431f154020SRobert Mustacchi {
14441f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0380) >> 1) | ((instr & 0x1c00) >> 7);
14451f154020SRobert Mustacchi 
14461f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14471f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
14481f154020SRobert Mustacchi 	    buf, buflen);
14491f154020SRobert Mustacchi }
14501f154020SRobert Mustacchi 
14511f154020SRobert Mustacchi static void
dis_riscv_c_fswsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14521f154020SRobert Mustacchi dis_riscv_c_fswsp(dis_handle_t *dhp, uint32_t instr,
14531f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14541f154020SRobert Mustacchi {
14551f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0180) >> 1) | ((instr & 0x1e00) >> 7);
14561f154020SRobert Mustacchi 
14571f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14581f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
14591f154020SRobert Mustacchi 	    buf, buflen);
14601f154020SRobert Mustacchi }
14611f154020SRobert Mustacchi 
14621f154020SRobert Mustacchi static void
dis_riscv_c_fsdsp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14631f154020SRobert Mustacchi dis_riscv_c_fsdsp(dis_handle_t *dhp, uint32_t instr,
14641f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14651f154020SRobert Mustacchi {
14661f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0380) >> 1) | ((instr & 0x1c00) >> 7);
14671f154020SRobert Mustacchi 
14681f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14691f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
14701f154020SRobert Mustacchi 	    buf, buflen);
14711f154020SRobert Mustacchi }
14721f154020SRobert Mustacchi 
14731f154020SRobert Mustacchi static void
dis_riscv_c_lw(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14741f154020SRobert Mustacchi dis_riscv_c_lw(dis_handle_t *dhp, uint32_t instr,
14751f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14761f154020SRobert Mustacchi {
14771f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0020) << 1) | ((instr & 0x1c) >> 7) |
14781f154020SRobert Mustacchi 	    ((instr & 0x0040) >> 3);
14791f154020SRobert Mustacchi 
14801f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14811f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
14821f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
14831f154020SRobert Mustacchi 	    imm, buf, buflen);
14841f154020SRobert Mustacchi }
14851f154020SRobert Mustacchi 
14861f154020SRobert Mustacchi static void
dis_riscv_c_ld(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14871f154020SRobert Mustacchi dis_riscv_c_ld(dis_handle_t *dhp, uint32_t instr,
14881f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
14891f154020SRobert Mustacchi {
14901f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0060) << 1) | ((instr & 0x1c) >> 7);
14911f154020SRobert Mustacchi 
14921f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
14931f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
14941f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
14951f154020SRobert Mustacchi 	    imm, buf, buflen);
14961f154020SRobert Mustacchi }
14971f154020SRobert Mustacchi 
14981f154020SRobert Mustacchi static void
dis_riscv_c_flw(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)14991f154020SRobert Mustacchi dis_riscv_c_flw(dis_handle_t *dhp, uint32_t instr,
15001f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
15011f154020SRobert Mustacchi {
15021f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0020) << 1) | ((instr & 0x1c) >> 7) |
15031f154020SRobert Mustacchi 	    ((instr & 0x0040) >> 3);
15041f154020SRobert Mustacchi 
15051f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
15061f154020SRobert Mustacchi 	    dis_riscv_c_fpregs[DIS_RISCV_C_RDP(instr)],
15071f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
15081f154020SRobert Mustacchi 	    imm, buf, buflen);
15091f154020SRobert Mustacchi }
15101f154020SRobert Mustacchi 
15111f154020SRobert Mustacchi static void
dis_riscv_c_fld(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)15121f154020SRobert Mustacchi dis_riscv_c_fld(dis_handle_t *dhp, uint32_t instr,
15131f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
15141f154020SRobert Mustacchi {
15151f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0060) << 1) | ((instr & 0x1c) >> 7);
15161f154020SRobert Mustacchi 
15171f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
15181f154020SRobert Mustacchi 	    dis_riscv_c_fpregs[DIS_RISCV_C_RDP(instr)],
15191f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
15201f154020SRobert Mustacchi 	    imm, buf, buflen);
15211f154020SRobert Mustacchi }
15221f154020SRobert Mustacchi 
15231f154020SRobert Mustacchi /*
15241f154020SRobert Mustacchi  * The J type has the 11 bit immediate arranged as:
15251f154020SRobert Mustacchi  *
15261f154020SRobert Mustacchi  *  offset[11|4|9:8|10|6|7|3:1|5] going from bits 2 to 12.
15271f154020SRobert Mustacchi  */
15281f154020SRobert Mustacchi static void
dis_riscv_c_j(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)15291f154020SRobert Mustacchi dis_riscv_c_j(dis_handle_t *dhp, uint32_t instr,
15301f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
15311f154020SRobert Mustacchi {
15321f154020SRobert Mustacchi 	const char *s;
15331f154020SRobert Mustacchi 	uint_t jimm = DIS_RISCV_C_J_11(instr) | DIS_RISCV_C_J_10(instr) |
15341f154020SRobert Mustacchi 	    DIS_RISCV_C_J_9_8(instr) | DIS_RISCV_C_J_7(instr) |
15351f154020SRobert Mustacchi 	    DIS_RISCV_C_J_6(instr) | DIS_RISCV_C_J_5(instr) |
15361f154020SRobert Mustacchi 	    DIS_RISCV_C_J_4(instr) | DIS_RISCV_C_J_3_1(instr);
15371f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(jimm, 11, &s);
15381f154020SRobert Mustacchi 
15391f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
15401f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s0%o", table->drv_c_name,
15411f154020SRobert Mustacchi 		    s, imm);
15421f154020SRobert Mustacchi 	} else {
15431f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s0x%x", table->drv_c_name,
15441f154020SRobert Mustacchi 		    s, imm);
15451f154020SRobert Mustacchi 	}
15461f154020SRobert Mustacchi }
15471f154020SRobert Mustacchi 
15481f154020SRobert Mustacchi /*ARGSUSED*/
15491f154020SRobert Mustacchi static void
dis_riscv_c_jr(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)15501f154020SRobert Mustacchi dis_riscv_c_jr(dis_handle_t *dhp, uint32_t instr,
15511f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
15521f154020SRobert Mustacchi {
15531f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s", table->drv_c_name,
15541f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS1(instr)]);
15551f154020SRobert Mustacchi }
15561f154020SRobert Mustacchi 
15571f154020SRobert Mustacchi static void
dis_riscv_c_regimm(dis_handle_t * dhp,const char * instr,const char * dreg,const char * sign,uint_t imm,char * buf,size_t buflen)15581f154020SRobert Mustacchi dis_riscv_c_regimm(dis_handle_t *dhp, const char *instr, const char *dreg,
15591f154020SRobert Mustacchi     const char *sign, uint_t imm, char *buf, size_t buflen)
15601f154020SRobert Mustacchi {
15611f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
15621f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o", instr, dreg,
15631f154020SRobert Mustacchi 		    sign, imm);
15641f154020SRobert Mustacchi 	} else {
15651f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x", instr, dreg,
15661f154020SRobert Mustacchi 		    sign, imm);
15671f154020SRobert Mustacchi 	}
15681f154020SRobert Mustacchi }
15691f154020SRobert Mustacchi 
15701f154020SRobert Mustacchi static void
dis_riscv_c_branch(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)15711f154020SRobert Mustacchi dis_riscv_c_branch(dis_handle_t *dhp, uint32_t instr,
15721f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
15731f154020SRobert Mustacchi {
15741f154020SRobert Mustacchi 	const char *s;
15751f154020SRobert Mustacchi 	uint_t bimm = DIS_RISCV_C_B_8(instr) | DIS_RISCV_C_B_7_6(instr) |
15761f154020SRobert Mustacchi 	    DIS_RISCV_C_B_5(instr) | DIS_RISCV_C_B_4_3(instr) |
15771f154020SRobert Mustacchi 	    DIS_RISCV_C_B_2_1(instr);
15781f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(bimm, 8, &s);
15791f154020SRobert Mustacchi 
15801f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
15811f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)], s, imm, buf, buflen);
15821f154020SRobert Mustacchi }
15831f154020SRobert Mustacchi 
15841f154020SRobert Mustacchi static void
dis_riscv_c_bigimmint(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)15851f154020SRobert Mustacchi dis_riscv_c_bigimmint(dis_handle_t *dhp, uint32_t instr,
15861f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
15871f154020SRobert Mustacchi {
15881f154020SRobert Mustacchi 	const char *s;
15891f154020SRobert Mustacchi 	uint_t limm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
15901f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(limm, 5, &s);
15911f154020SRobert Mustacchi 
15921f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
15931f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], s, imm, buf, buflen);
15941f154020SRobert Mustacchi }
15951f154020SRobert Mustacchi 
15961f154020SRobert Mustacchi static void
dis_riscv_c_zext_bigimmint(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)15971f154020SRobert Mustacchi dis_riscv_c_zext_bigimmint(dis_handle_t *dhp, uint32_t instr,
15981f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
15991f154020SRobert Mustacchi {
16001f154020SRobert Mustacchi 	uint_t imm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
16011f154020SRobert Mustacchi 
16021f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
16031f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], "", imm, buf, buflen);
16041f154020SRobert Mustacchi }
16051f154020SRobert Mustacchi 
16061f154020SRobert Mustacchi static void
dis_riscv_c_addi16sp(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)16071f154020SRobert Mustacchi dis_riscv_c_addi16sp(dis_handle_t *dhp, uint32_t instr,
16081f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
16091f154020SRobert Mustacchi {
16101f154020SRobert Mustacchi 	const char *s;
16111f154020SRobert Mustacchi 	uint_t aimm = DIS_RISCV_C_A16_9(instr) | DIS_RISCV_C_A16_8_7(instr) |
16121f154020SRobert Mustacchi 	    DIS_RISCV_C_A16_6(instr) | DIS_RISCV_C_A16_5(instr) |
16131f154020SRobert Mustacchi 	    DIS_RISCV_C_A16_4(instr);
16141f154020SRobert Mustacchi 	int imm = dis_riscv_sign_extend(aimm, 9, &s);
16151f154020SRobert Mustacchi 
16161f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
16171f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], s, imm, buf, buflen);
16181f154020SRobert Mustacchi }
16191f154020SRobert Mustacchi 
16201f154020SRobert Mustacchi static void
dis_riscv_c_addi4spn(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)16211f154020SRobert Mustacchi dis_riscv_c_addi4spn(dis_handle_t *dhp, uint32_t instr,
16221f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
16231f154020SRobert Mustacchi {
16241f154020SRobert Mustacchi 	uint_t imm = DIS_RISCV_C_A4_9_6(instr) | DIS_RISCV_C_A4_5_4(instr) |
16251f154020SRobert Mustacchi 	    DIS_RISCV_C_A4_3(instr) | DIS_RISCV_C_A4_2(instr);
16261f154020SRobert Mustacchi 
16271f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
16281f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,sp,0%o",
16291f154020SRobert Mustacchi 		    table->drv_c_name, dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
16301f154020SRobert Mustacchi 		    imm);
16311f154020SRobert Mustacchi 	} else {
16321f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,sp,0x%x",
16331f154020SRobert Mustacchi 		    table->drv_c_name, dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
16341f154020SRobert Mustacchi 		    imm);
16351f154020SRobert Mustacchi 	}
16361f154020SRobert Mustacchi }
16371f154020SRobert Mustacchi 
16381f154020SRobert Mustacchi static void
dis_riscv_c_immint(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)16391f154020SRobert Mustacchi dis_riscv_c_immint(dis_handle_t *dhp, uint32_t instr,
16401f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
16411f154020SRobert Mustacchi {
16421f154020SRobert Mustacchi 	const char *s;
16431f154020SRobert Mustacchi 	uint_t limm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
16441f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(limm, 5, &s);
16451f154020SRobert Mustacchi 
16461f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
16471f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)], s, imm, buf, buflen);
16481f154020SRobert Mustacchi }
16491f154020SRobert Mustacchi 
16501f154020SRobert Mustacchi static void
dis_riscv_c_zext_immint(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)16511f154020SRobert Mustacchi dis_riscv_c_zext_immint(dis_handle_t *dhp, uint32_t instr,
16521f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
16531f154020SRobert Mustacchi {
16541f154020SRobert Mustacchi 	uint_t imm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
16551f154020SRobert Mustacchi 
16561f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
16571f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)], "", imm, buf, buflen);
16581f154020SRobert Mustacchi }
16591f154020SRobert Mustacchi 
16601f154020SRobert Mustacchi /*ARGSUSED*/
16611f154020SRobert Mustacchi static void
dis_riscv_c_bigint(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)16621f154020SRobert Mustacchi dis_riscv_c_bigint(dis_handle_t *dhp, uint32_t instr,
16631f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
16641f154020SRobert Mustacchi {
16651f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_c_name,
16661f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)],
16671f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS2(instr)]);
16681f154020SRobert Mustacchi }
16691f154020SRobert Mustacchi 
16701f154020SRobert Mustacchi 
16711f154020SRobert Mustacchi /*ARGSUSED*/
16721f154020SRobert Mustacchi static void
dis_riscv_c_int(dis_handle_t * dhp,uint32_t instr,dis_riscv_c_instr_t * table,char * buf,size_t buflen)16731f154020SRobert Mustacchi dis_riscv_c_int(dis_handle_t *dhp, uint32_t instr,
16741f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
16751f154020SRobert Mustacchi {
16761f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_c_name,
16771f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
16781f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS2P(instr)]);
16791f154020SRobert Mustacchi }
16801f154020SRobert Mustacchi 
16811f154020SRobert Mustacchi #define	DIS_RISCV_CFUNCT3(name, class, op, funct, print)		\
16821f154020SRobert Mustacchi 	{ name, DIS_RISCV_C_FUNCT3, print, class, op, funct, 0, 0 }
1683*38848811SRobert Mustacchi #define	DIS_RISCV_CMATCH(name, class, op, funct, mask, match, print)	\
16841f154020SRobert Mustacchi 	{ name, DIS_RISCV_C_MATCH, print, class, op, funct, mask, match }
16851f154020SRobert Mustacchi 
16861f154020SRobert Mustacchi static dis_riscv_c_instr_t dis_riscv_2byte[] = {
16871f154020SRobert Mustacchi 	/* Quadrant 0 */
16881f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.addi4spn", DIS_RISCV_CL_32_64, 0x0, 0x0,
16891f154020SRobert Mustacchi 	    dis_riscv_c_addi4spn),
16901f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fld", DIS_RISCV_CL_32_64, 0x0, 0x01,
16911f154020SRobert Mustacchi 	    dis_riscv_c_fld),
16921f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.lw", DIS_RISCV_CL_ALL, 0x0, 0x2,
16931f154020SRobert Mustacchi 	    dis_riscv_c_lw),
16941f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.flw", DIS_RISCV_CL_32, 0x0, 0x3,
16951f154020SRobert Mustacchi 	    dis_riscv_c_flw),
16961f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("f.ld", DIS_RISCV_CL_64_128, 0x0, 0x3,
16971f154020SRobert Mustacchi 	    dis_riscv_c_ld),
16981f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fsd", DIS_RISCV_CL_32_64, 0x0, 0x5,
16991f154020SRobert Mustacchi 	    dis_riscv_c_fld),
17001f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.sw", DIS_RISCV_CL_ALL, 0x0, 0x6,
17011f154020SRobert Mustacchi 	    dis_riscv_c_lw),
17021f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fsw", DIS_RISCV_CL_32, 0x0, 0x7,
17031f154020SRobert Mustacchi 	    dis_riscv_c_flw),
17041f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.sd", DIS_RISCV_CL_64_128, 0x0, 0x7,
17051f154020SRobert Mustacchi 	    dis_riscv_c_ld),
17061f154020SRobert Mustacchi 	/* Quadrant 1 */
17071f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.nop", DIS_RISCV_CL_ALL, 0x01, 0x00, 0x1ffc, 0x0,
17081f154020SRobert Mustacchi 	    dis_riscv_c_name),
17091f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.addi", DIS_RISCV_CL_ALL, 0x01, 0x00,
17101f154020SRobert Mustacchi 	    dis_riscv_c_bigimmint),
17111f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.jal", DIS_RISCV_CL_32, 0x01, 0x01,
17121f154020SRobert Mustacchi 	    dis_riscv_c_j),
17131f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.addiw", DIS_RISCV_CL_64_128, 0x01, 0x01,
17141f154020SRobert Mustacchi 	    dis_riscv_c_bigimmint),
17151f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.li", DIS_RISCV_CL_ALL, 0x01, 0x02,
17161f154020SRobert Mustacchi 	    dis_riscv_c_bigimmint),
17171f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.addi16sp", DIS_RISCV_CL_ALL, 0x01, 0x03, 0x0f80,
17181f154020SRobert Mustacchi 	    0x0100, dis_riscv_c_addi16sp),
17191f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.lui", DIS_RISCV_CL_ALL, 0x01, 0x03,
17201f154020SRobert Mustacchi 	    dis_riscv_c_zext_bigimmint),
17211f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.srli", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x0c00, 0x0000,
17221f154020SRobert Mustacchi 	    dis_riscv_c_zext_immint),
17231f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.srai", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x0c00, 0x0400,
17241f154020SRobert Mustacchi 	    dis_riscv_c_zext_immint),
17251f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.andi", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x0c00, 0x0800,
17261f154020SRobert Mustacchi 	    dis_riscv_c_immint),
17271f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.sub", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c00,
17281f154020SRobert Mustacchi 	    dis_riscv_c_int),
17291f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.xor", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c20,
17301f154020SRobert Mustacchi 	    dis_riscv_c_int),
17311f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.or", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c40,
17321f154020SRobert Mustacchi 	    dis_riscv_c_int),
17331f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.and", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c60,
17341f154020SRobert Mustacchi 	    dis_riscv_c_int),
17351f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.subw", DIS_RISCV_CL_64_128, 0x1, 0x4, 0x1c60,
17361f154020SRobert Mustacchi 	    0x1c00, dis_riscv_c_int),
17371f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.addw", DIS_RISCV_CL_64_128, 0x1, 0x4, 0x1c60,
17381f154020SRobert Mustacchi 	    0x1c20, dis_riscv_c_int),
17391f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.j", DIS_RISCV_CL_ALL, 0x1, 0x5,
17401f154020SRobert Mustacchi 	    dis_riscv_c_j),
17411f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.beqz", DIS_RISCV_CL_ALL, 0x1, 0x6,
17421f154020SRobert Mustacchi 	    dis_riscv_c_branch),
17431f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.bnez", DIS_RISCV_CL_ALL, 0x1, 0x7,
17441f154020SRobert Mustacchi 	    dis_riscv_c_branch),
17451f154020SRobert Mustacchi 	/* Quadrant 2 */
17461f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.slli", DIS_RISCV_CL_ALL, 0x2, 0x0,
17471f154020SRobert Mustacchi 	    dis_riscv_c_zext_bigimmint),
17481f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fldsp", DIS_RISCV_CL_32_64, 0x2, 0x1,
17491f154020SRobert Mustacchi 	    dis_riscv_c_fldsp),
17501f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.lwsp", DIS_RISCV_CL_ALL, 0x2, 0x2,
17511f154020SRobert Mustacchi 	    dis_riscv_c_lwsp),
17521f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.flwsp", DIS_RISCV_CL_32, 0x2, 0x3,
17531f154020SRobert Mustacchi 	    dis_riscv_c_flwsp),
17541f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.ldsp", DIS_RISCV_CL_64_128, 0x2, 0x3,
17551f154020SRobert Mustacchi 	    dis_riscv_c_ldsp),
17561f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.jr", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x107c, 0x0,
17571f154020SRobert Mustacchi 	    dis_riscv_c_jr),
17581f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.mv", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x1000, 0x0,
17591f154020SRobert Mustacchi 	    dis_riscv_c_bigint),
17601f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.ebreak", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x1ffc, 0x1000,
17611f154020SRobert Mustacchi 	    dis_riscv_c_name),
17621f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.jalr", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x107c, 0x1000,
17631f154020SRobert Mustacchi 	    dis_riscv_c_jr),
17641f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.add", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x1000, 0x1000,
17651f154020SRobert Mustacchi 	    dis_riscv_c_bigint),
17661f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fsdsp", DIS_RISCV_CL_32_64, 0x2, 0x5,
17671f154020SRobert Mustacchi 	    dis_riscv_c_fsdsp),
17681f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.swsp", DIS_RISCV_CL_ALL, 0x2, 0x6,
17691f154020SRobert Mustacchi 	    dis_riscv_c_swsp),
17701f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fswsp", DIS_RISCV_CL_32, 0x2, 0x7,
17711f154020SRobert Mustacchi 	    dis_riscv_c_fswsp),
17721f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.sdsp", DIS_RISCV_CL_64_128, 0x2, 0x7,
17731f154020SRobert Mustacchi 	    dis_riscv_c_sdsp),
17741f154020SRobert Mustacchi };
17751f154020SRobert Mustacchi 
17761f154020SRobert Mustacchi static void
dis_riscv_decode_2byte(dis_handle_t * dhp,uint32_t instr,char * buf,size_t buflen)17771f154020SRobert Mustacchi dis_riscv_decode_2byte(dis_handle_t *dhp, uint32_t instr, char *buf,
17781f154020SRobert Mustacchi     size_t buflen)
17791f154020SRobert Mustacchi {
17801f154020SRobert Mustacchi 	uint_t i;
17811f154020SRobert Mustacchi 
17821f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_2byte); i++) {
17831f154020SRobert Mustacchi 		dis_riscv_c_instr_t *t = &dis_riscv_2byte[i];
17841f154020SRobert Mustacchi 		switch (t->drv_c_class) {
17851f154020SRobert Mustacchi 		case DIS_RISCV_CL_ALL:
17861f154020SRobert Mustacchi 			break;
17871f154020SRobert Mustacchi 		case DIS_RISCV_CL_32:
17881f154020SRobert Mustacchi 			if ((dhp->dh_flags & DIS_RISCV_32) == 0)
17891f154020SRobert Mustacchi 				continue;
17901f154020SRobert Mustacchi 			break;
17911f154020SRobert Mustacchi 		case DIS_RISCV_CL_64:
17921f154020SRobert Mustacchi 			if ((dhp->dh_flags & DIS_RISCV_64) == 0)
17931f154020SRobert Mustacchi 				continue;
17941f154020SRobert Mustacchi 			break;
17951f154020SRobert Mustacchi 		case DIS_RISCV_CL_32_64:
17961f154020SRobert Mustacchi 			if ((dhp->dh_flags &
17971f154020SRobert Mustacchi 			    (DIS_RISCV_32 | DIS_RISCV_64)) == 0) {
17981f154020SRobert Mustacchi 				continue;
17991f154020SRobert Mustacchi 			}
18001f154020SRobert Mustacchi 			break;
18011f154020SRobert Mustacchi 		case DIS_RISCV_CL_64_128:
18021f154020SRobert Mustacchi 			if ((dhp->dh_flags & DIS_RISCV_64) == 0)
18031f154020SRobert Mustacchi 				continue;
18041f154020SRobert Mustacchi 			break;
18051f154020SRobert Mustacchi 		}
18061f154020SRobert Mustacchi 
18071f154020SRobert Mustacchi 		switch (t->drv_c_type) {
18081f154020SRobert Mustacchi 		case DIS_RISCV_C_FUNCT3:
18091f154020SRobert Mustacchi 			if (DIS_RISCV_C_OPCODE(instr) == t->drv_c_opcode &&
18101f154020SRobert Mustacchi 			    DIS_RISCV_C_FUNCT3(instr) == t->drv_c_funct) {
18111f154020SRobert Mustacchi 				break;
18121f154020SRobert Mustacchi 			}
18131f154020SRobert Mustacchi 			continue;
18141f154020SRobert Mustacchi 		case DIS_RISCV_C_MATCH:
18151f154020SRobert Mustacchi 			if (DIS_RISCV_C_OPCODE(instr) == t->drv_c_opcode &&
18161f154020SRobert Mustacchi 			    DIS_RISCV_C_FUNCT3(instr) == t->drv_c_funct &&
18171f154020SRobert Mustacchi 			    ((instr & t->drv_c_mask) == t->drv_c_match)) {
18181f154020SRobert Mustacchi 				break;
18191f154020SRobert Mustacchi 			}
18201f154020SRobert Mustacchi 			continue;
18211f154020SRobert Mustacchi 		default:
18221f154020SRobert Mustacchi 			continue;
18231f154020SRobert Mustacchi 		}
18241f154020SRobert Mustacchi 
18251f154020SRobert Mustacchi 		t->drv_c_print(dhp, instr, t, buf, buflen);
18261f154020SRobert Mustacchi 		return;
18271f154020SRobert Mustacchi 	}
18281f154020SRobert Mustacchi 
18291f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "<unknown>");
18301f154020SRobert Mustacchi }
18311f154020SRobert Mustacchi 
18321f154020SRobert Mustacchi 
18331f154020SRobert Mustacchi /*
18341f154020SRobert Mustacchi  * RISC-V instructions always come in parcels of two bytes. Read the next two
18351f154020SRobert Mustacchi  * byte parcel and advance the address in the handle. Also, take care of endian
18361f154020SRobert Mustacchi  * issues if required.
18371f154020SRobert Mustacchi  */
18381f154020SRobert Mustacchi static int
dis_riscv_read_parcel(dis_handle_t * dhp,uint16_t * valp)18391f154020SRobert Mustacchi dis_riscv_read_parcel(dis_handle_t *dhp, uint16_t *valp)
18401f154020SRobert Mustacchi {
18411f154020SRobert Mustacchi 	if ((dhp->dh_addr % 2) != 0)
18421f154020SRobert Mustacchi 		return (-1);
18431f154020SRobert Mustacchi 
18441f154020SRobert Mustacchi 	if (dhp->dh_read(dhp->dh_data, dhp->dh_addr, valp, sizeof (*valp)) !=
18451f154020SRobert Mustacchi 	    sizeof (*valp))
18461f154020SRobert Mustacchi 		return (-1);
18471f154020SRobert Mustacchi 
18481f154020SRobert Mustacchi 	*valp = LE_16(*valp);
18491f154020SRobert Mustacchi 
18501f154020SRobert Mustacchi 	dhp->dh_addr += 2;
18511f154020SRobert Mustacchi 
18521f154020SRobert Mustacchi 	return (0);
18531f154020SRobert Mustacchi }
18541f154020SRobert Mustacchi 
18551f154020SRobert Mustacchi /*
18561f154020SRobert Mustacchi  * The first 'parcel' (uint16_t) of any instruction can be used to determine the
18571f154020SRobert Mustacchi  * instruction length. This is derived from Section 1.2 Instruction Length
18581f154020SRobert Mustacchi  * Encoding of Volume I: RISC-V User-Level ISA V2.2.
18591f154020SRobert Mustacchi  *
18601f154020SRobert Mustacchi  *  | xxxxxxxxxxxxxxaa | 16-bit iff aa != 11
18611f154020SRobert Mustacchi  *  | xxxxxxxxxxxbbb11 | 32-bit iff bbb != 111
18621f154020SRobert Mustacchi  *  | xxxxxxxxxx011111 | 48-bit iff bbb != 111
18631f154020SRobert Mustacchi  *  | xxxxxxxxx0111111 | 64-bit iff bbb != 111
18641f154020SRobert Mustacchi  *  | xnnnxxxxx1111111 | (80 + 16*nnn)-bit iff nnn != 111
18651f154020SRobert Mustacchi  */
18661f154020SRobert Mustacchi #define	RISCV_LEN_16_MASK	0x0003
18671f154020SRobert Mustacchi #define	RISCV_LEN_32_MASK	0x001c
18681f154020SRobert Mustacchi #define	RISCV_LEN_48_MASK	0x0020
18691f154020SRobert Mustacchi #define	RISCV_LEN_64_MASK	0x0040
18701f154020SRobert Mustacchi #define	RISCV_LEN_80_MASK	0x7000
18711f154020SRobert Mustacchi #define	RISCV_LEN_80_SHIFT	12
18721f154020SRobert Mustacchi 
18731f154020SRobert Mustacchi static int
dis_riscv_decode_len(uint16_t instr)18741f154020SRobert Mustacchi dis_riscv_decode_len(uint16_t instr)
18751f154020SRobert Mustacchi {
18761f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_16_MASK) != RISCV_LEN_16_MASK)
18771f154020SRobert Mustacchi 		return (2);
18781f154020SRobert Mustacchi 
18791f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_32_MASK) != RISCV_LEN_32_MASK)
18801f154020SRobert Mustacchi 		return (4);
18811f154020SRobert Mustacchi 
18821f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_48_MASK) != RISCV_LEN_48_MASK)
18831f154020SRobert Mustacchi 		return (6);
18841f154020SRobert Mustacchi 
18851f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_64_MASK) != RISCV_LEN_64_MASK)
18861f154020SRobert Mustacchi 		return (8);
18871f154020SRobert Mustacchi 
18881f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_80_MASK) != RISCV_LEN_80_MASK) {
18891f154020SRobert Mustacchi 		uint_t factor = (instr & RISCV_LEN_80_MASK) >>
18901f154020SRobert Mustacchi 		    RISCV_LEN_80_SHIFT;
18911f154020SRobert Mustacchi 		return ((10 + 2 * factor));
18921f154020SRobert Mustacchi 	}
18931f154020SRobert Mustacchi 
18941f154020SRobert Mustacchi 	return (-1);
18951f154020SRobert Mustacchi }
18961f154020SRobert Mustacchi 
18971f154020SRobert Mustacchi static int
dis_riscv_supports_flags(int flags)18981f154020SRobert Mustacchi dis_riscv_supports_flags(int flags)
18991f154020SRobert Mustacchi {
19001f154020SRobert Mustacchi 	int archflags = flags & DIS_ARCH_MASK;
19011f154020SRobert Mustacchi 
19021f154020SRobert Mustacchi 	return (archflags == DIS_RISCV_32 || archflags == DIS_RISCV_64);
19031f154020SRobert Mustacchi }
19041f154020SRobert Mustacchi 
19051f154020SRobert Mustacchi static int
dis_riscv_disassemble(dis_handle_t * dhp,uint64_t addr,char * buf,size_t buflen)19061f154020SRobert Mustacchi dis_riscv_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
19071f154020SRobert Mustacchi     size_t buflen)
19081f154020SRobert Mustacchi {
19091f154020SRobert Mustacchi 	int len;
19101f154020SRobert Mustacchi 	uint16_t parcel;
19111f154020SRobert Mustacchi 	uint32_t instr;
19121f154020SRobert Mustacchi 
19131f154020SRobert Mustacchi 
19141f154020SRobert Mustacchi 	dhp->dh_addr = addr;
19151f154020SRobert Mustacchi 
19161f154020SRobert Mustacchi 	/*
19171f154020SRobert Mustacchi 	 * All instructions have to be 2-byte aligned. Most have to be four byte
19181f154020SRobert Mustacchi 	 * aligned, but we determine that after we decode the instruction size.
19191f154020SRobert Mustacchi 	 * The 2-byte alignment check is done when we read the parcel.
19201f154020SRobert Mustacchi 	 */
19211f154020SRobert Mustacchi 	if (dis_riscv_read_parcel(dhp, &parcel) != 0)
19221f154020SRobert Mustacchi 		return (-1);
19231f154020SRobert Mustacchi 
19241f154020SRobert Mustacchi 	len = dis_riscv_decode_len(parcel);
19251f154020SRobert Mustacchi 	if (len < 2 || (len % 2) != 0)
19261f154020SRobert Mustacchi 		return (-1);
19271f154020SRobert Mustacchi 	switch (len) {
19281f154020SRobert Mustacchi 	case 2:
19291f154020SRobert Mustacchi 		instr = parcel;
19301f154020SRobert Mustacchi 		dis_riscv_decode_2byte(dhp, instr, buf, buflen);
19311f154020SRobert Mustacchi 		break;
19321f154020SRobert Mustacchi 	case 4:
19331f154020SRobert Mustacchi 		instr = parcel;
19341f154020SRobert Mustacchi 		if (dis_riscv_read_parcel(dhp, &parcel) != 0)
19351f154020SRobert Mustacchi 			return (-1);
19361f154020SRobert Mustacchi 		instr |= parcel << 16;
19371f154020SRobert Mustacchi 		dis_riscv_decode_4byte(dhp, instr, buf, buflen);
19381f154020SRobert Mustacchi 		break;
19391f154020SRobert Mustacchi 	default:
19401f154020SRobert Mustacchi 		/*
19411f154020SRobert Mustacchi 		 * This case represents a valid instruction length, but
19421f154020SRobert Mustacchi 		 * something we don't understand. Treat this as an unknown
19431f154020SRobert Mustacchi 		 * instruction. However, read the rest of the length of the
19441f154020SRobert Mustacchi 		 * instruction to make sure that we read things correctly.
19451f154020SRobert Mustacchi 		 */
19461f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "<unknown>");
19471f154020SRobert Mustacchi 		for (; len > 0; len -= 2) {
19481f154020SRobert Mustacchi 			if (dis_riscv_read_parcel(dhp, &parcel) != 0) {
19491f154020SRobert Mustacchi 				return (-1);
19501f154020SRobert Mustacchi 			}
19511f154020SRobert Mustacchi 		}
19521f154020SRobert Mustacchi 		break;
19531f154020SRobert Mustacchi 	}
19541f154020SRobert Mustacchi 
19551f154020SRobert Mustacchi 	return (0);
19561f154020SRobert Mustacchi }
19571f154020SRobert Mustacchi 
19581f154020SRobert Mustacchi /*ARGSUSED*/
19591f154020SRobert Mustacchi static int
dis_riscv_min_instrlen(dis_handle_t * dhp)19601f154020SRobert Mustacchi dis_riscv_min_instrlen(dis_handle_t *dhp)
19611f154020SRobert Mustacchi {
19621f154020SRobert Mustacchi 	return (2);
19631f154020SRobert Mustacchi }
19641f154020SRobert Mustacchi 
19651f154020SRobert Mustacchi /*ARGSUSED*/
19661f154020SRobert Mustacchi static int
dis_riscv_max_instrlen(dis_handle_t * dhp)19671f154020SRobert Mustacchi dis_riscv_max_instrlen(dis_handle_t *dhp)
19681f154020SRobert Mustacchi {
19691f154020SRobert Mustacchi 	return (22);
19701f154020SRobert Mustacchi }
19711f154020SRobert Mustacchi 
19721f154020SRobert Mustacchi static int
dis_riscv_instrlen(dis_handle_t * dhp,uint64_t addr)19731f154020SRobert Mustacchi dis_riscv_instrlen(dis_handle_t *dhp, uint64_t addr)
19741f154020SRobert Mustacchi {
19751f154020SRobert Mustacchi 	uint16_t parcel;
19761f154020SRobert Mustacchi 
19771f154020SRobert Mustacchi 	dhp->dh_addr = addr;
19781f154020SRobert Mustacchi 
19791f154020SRobert Mustacchi 	if (dis_riscv_read_parcel(dhp, &parcel) != 0)
19801f154020SRobert Mustacchi 		return (-1);
19811f154020SRobert Mustacchi 
1982*38848811SRobert Mustacchi 	return (dis_riscv_decode_len(parcel));
19831f154020SRobert Mustacchi }
19841f154020SRobert Mustacchi 
19851f154020SRobert Mustacchi dis_arch_t dis_arch_riscv = {
19861f154020SRobert Mustacchi 	.da_supports_flags = dis_riscv_supports_flags,
19871f154020SRobert Mustacchi 	.da_disassemble = dis_riscv_disassemble,
19881f154020SRobert Mustacchi 	.da_min_instrlen = dis_riscv_min_instrlen,
19891f154020SRobert Mustacchi 	.da_max_instrlen = dis_riscv_max_instrlen,
19901f154020SRobert Mustacchi 	.da_instrlen = dis_riscv_instrlen
19911f154020SRobert Mustacchi };
1992