1*1f154020SRobert Mustacchi /*
2*1f154020SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*1f154020SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*1f154020SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*1f154020SRobert Mustacchi  * 1.0 of the CDDL.
6*1f154020SRobert Mustacchi  *
7*1f154020SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*1f154020SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*1f154020SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*1f154020SRobert Mustacchi  */
11*1f154020SRobert Mustacchi 
12*1f154020SRobert Mustacchi /*
13*1f154020SRobert Mustacchi  * Copyright (c) 2018, Joyent, Inc.
14*1f154020SRobert Mustacchi  */
15*1f154020SRobert Mustacchi 
16*1f154020SRobert Mustacchi /*
17*1f154020SRobert Mustacchi  * RISC-V Instruction set decoder
18*1f154020SRobert Mustacchi  */
19*1f154020SRobert Mustacchi 
20*1f154020SRobert Mustacchi #include <libdisasm.h>
21*1f154020SRobert Mustacchi #include <sys/byteorder.h>
22*1f154020SRobert Mustacchi #include <sys/debug.h>
23*1f154020SRobert Mustacchi 
24*1f154020SRobert Mustacchi #include "libdisasm_impl.h"
25*1f154020SRobert Mustacchi 
26*1f154020SRobert Mustacchi #include <stdio.h>
27*1f154020SRobert Mustacchi 
28*1f154020SRobert Mustacchi extern int strcmp(const char *, const char *);
29*1f154020SRobert Mustacchi 
30*1f154020SRobert Mustacchi /*
31*1f154020SRobert Mustacchi  * Register names based on their ABI name.
32*1f154020SRobert Mustacchi  */
33*1f154020SRobert Mustacchi static const char *dis_riscv_regs[32] = {
34*1f154020SRobert Mustacchi 	"x0", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
35*1f154020SRobert Mustacchi 	"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
36*1f154020SRobert Mustacchi 	"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
37*1f154020SRobert Mustacchi 	"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
38*1f154020SRobert Mustacchi };
39*1f154020SRobert Mustacchi 
40*1f154020SRobert Mustacchi static const char *dis_riscv_fpregs[32] = {
41*1f154020SRobert Mustacchi 	"ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
42*1f154020SRobert Mustacchi 	"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
43*1f154020SRobert Mustacchi 	"fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
44*1f154020SRobert Mustacchi 	"fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
45*1f154020SRobert Mustacchi };
46*1f154020SRobert Mustacchi 
47*1f154020SRobert Mustacchi static const char *dis_riscv_c_regs[8] = {
48*1f154020SRobert Mustacchi 	"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5"
49*1f154020SRobert Mustacchi };
50*1f154020SRobert Mustacchi 
51*1f154020SRobert Mustacchi static const char *dis_riscv_c_fpregs[8] = {
52*1f154020SRobert Mustacchi 	"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5"
53*1f154020SRobert Mustacchi };
54*1f154020SRobert Mustacchi 
55*1f154020SRobert Mustacchi /*
56*1f154020SRobert Mustacchi  * RM names have the leading comma in them because the last value represents
57*1f154020SRobert Mustacchi  * that the hardware register decides the rounding mode and therefore nothing
58*1f154020SRobert Mustacchi  * should be appended to the instruction.
59*1f154020SRobert Mustacchi  */
60*1f154020SRobert Mustacchi static const char *dis_riscv_rm[8] = {
61*1f154020SRobert Mustacchi 	",rne", ",rtz", ",rdn", ",rup", ",rmm", ",???", ",???", ""
62*1f154020SRobert Mustacchi };
63*1f154020SRobert Mustacchi 
64*1f154020SRobert Mustacchi typedef struct dis_riscv_csr {
65*1f154020SRobert Mustacchi 	uint_t		drc_val;
66*1f154020SRobert Mustacchi 	const char	*drc_name;
67*1f154020SRobert Mustacchi } dis_riscv_csr_t;
68*1f154020SRobert Mustacchi 
69*1f154020SRobert Mustacchi /*
70*1f154020SRobert Mustacchi  * The current set of CSR names as per Table 2.2-2.5 from RISC-V Privileged
71*1f154020SRobert Mustacchi  * Architectures V1.10. These include all of the ones in the User-Level ISA.
72*1f154020SRobert Mustacchi  * These are ordered per the doc.
73*1f154020SRobert Mustacchi  */
74*1f154020SRobert Mustacchi static dis_riscv_csr_t dis_riscv_csr_map[] = {
75*1f154020SRobert Mustacchi 	/* User Trap */
76*1f154020SRobert Mustacchi 	{ 0x000, "ustatus" },	{ 0x004, "uie" },	{ 0x005, "utvec" },
77*1f154020SRobert Mustacchi 	/* User Trap Handling */
78*1f154020SRobert Mustacchi 	{ 0x040, "uscratch" },	{ 0x041, "uepc" },	{ 0x042, "ucause" },
79*1f154020SRobert Mustacchi 	{ 0x043, "utval" },	{ 0x044, "uip" },
80*1f154020SRobert Mustacchi 	/* User Floating-Point CSRs */
81*1f154020SRobert Mustacchi 	{ 0x001, "fflags" },	{ 0x002, "frm" },	{ 0x003, "fcsr" },
82*1f154020SRobert Mustacchi 	/* User Counters/Timers */
83*1f154020SRobert Mustacchi 	{ 0xc00, "cycle" },	{ 0xc01, "time" },	{ 0xc02, "instret" },
84*1f154020SRobert Mustacchi 	{ 0xc03, "hpmcounter3" },	{ 0xc04, "hpmcounter4" },
85*1f154020SRobert Mustacchi 	{ 0xc05, "hpmcounter5" },	{ 0xc06, "hpmcounter6" },
86*1f154020SRobert Mustacchi 	{ 0xc07, "hpmcounter7" },	{ 0xc08, "hpmcounter8" },
87*1f154020SRobert Mustacchi 	{ 0xc09, "hpmcounter9" },	{ 0xc0a, "hpmcounter10" },
88*1f154020SRobert Mustacchi 	{ 0xc0b, "hpmcounter11" },	{ 0xc0c, "hpmcounter12" },
89*1f154020SRobert Mustacchi 	{ 0xc0d, "hpmcounter13" },	{ 0xc0e, "hpmcounter14" },
90*1f154020SRobert Mustacchi 	{ 0xc0f, "hpmcounter15" },	{ 0xc10, "hpmcounter16" },
91*1f154020SRobert Mustacchi 	{ 0xc11, "hpmcounter17" },	{ 0xc12, "hpmcounter18" },
92*1f154020SRobert Mustacchi 	{ 0xc13, "hpmcounter19" },	{ 0xc14, "hpmcounter20" },
93*1f154020SRobert Mustacchi 	{ 0xc15, "hpmcounter21" },	{ 0xc16, "hpmcounter22" },
94*1f154020SRobert Mustacchi 	{ 0xc17, "hpmcounter23" },	{ 0xc18, "hpmcounter24" },
95*1f154020SRobert Mustacchi 	{ 0xc19, "hpmcounter25" },	{ 0xc1a, "hpmcounter26" },
96*1f154020SRobert Mustacchi 	{ 0xc1b, "hpmcounter27" },	{ 0xc1c, "hpmcounter28" },
97*1f154020SRobert Mustacchi 	{ 0xc1d, "hpmcounter29" },	{ 0xc1e, "hpmcounter30" },
98*1f154020SRobert Mustacchi 	{ 0xc1f, "hpmcounter31" },
99*1f154020SRobert Mustacchi 	{ 0xc80, "cycleh" },	{ 0xc81, "timeh" },	{ 0xc82, "instreth" },
100*1f154020SRobert Mustacchi 	{ 0xc83, "hpmcounter3h" },	{ 0xc84, "hpmcounter4h" },
101*1f154020SRobert Mustacchi 	{ 0xc85, "hpmcounter5h" },	{ 0xc86, "hpmcounter6h" },
102*1f154020SRobert Mustacchi 	{ 0xc87, "hpmcounter7h" },	{ 0xc88, "hpmcounter8h" },
103*1f154020SRobert Mustacchi 	{ 0xc89, "hpmcounter9h" },	{ 0xc8a, "hpmcounter10h" },
104*1f154020SRobert Mustacchi 	{ 0xc8b, "hpmcounter11h" },	{ 0xc8c, "hpmcounter12h" },
105*1f154020SRobert Mustacchi 	{ 0xc8d, "hpmcounter13h" },	{ 0xc8e, "hpmcounter14h" },
106*1f154020SRobert Mustacchi 	{ 0xc8f, "hpmcounter15h" },	{ 0xc90, "hpmcounter16h" },
107*1f154020SRobert Mustacchi 	{ 0xc91, "hpmcounter17h" },	{ 0xc92, "hpmcounter18h" },
108*1f154020SRobert Mustacchi 	{ 0xc93, "hpmcounter19h" },	{ 0xc94, "hpmcounter20h" },
109*1f154020SRobert Mustacchi 	{ 0xc95, "hpmcounter21h" },	{ 0xc96, "hpmcounter22h" },
110*1f154020SRobert Mustacchi 	{ 0xc97, "hpmcounter23h" },	{ 0xc98, "hpmcounter24h" },
111*1f154020SRobert Mustacchi 	{ 0xc99, "hpmcounter25h" },	{ 0xc9a, "hpmcounter26h" },
112*1f154020SRobert Mustacchi 	{ 0xc9b, "hpmcounter27h" },	{ 0xc9c, "hpmcounter28h" },
113*1f154020SRobert Mustacchi 	{ 0xc9d, "hpmcounter29h" },	{ 0xc9e, "hpmcounter30h" },
114*1f154020SRobert Mustacchi 	{ 0xc9f, "hpmcounter31h" },
115*1f154020SRobert Mustacchi 	/* Supervisor Trap Status */
116*1f154020SRobert Mustacchi 	{ 0x100, "sstatus" },	{ 0x102, "sedeleg" },	{ 0x103, "sideleg" },
117*1f154020SRobert Mustacchi 	{ 0x104, "sie" },	{ 0x105, "stvec" },	{ 0x106, "scounteren" },
118*1f154020SRobert Mustacchi 	/* Supervisor Trap Handling */
119*1f154020SRobert Mustacchi 	{ 0x140, "sscratch" },	{ 0x141, "sepc" },	{ 0x142, "scause" },
120*1f154020SRobert Mustacchi 	{ 0x143, "stval" },	{ 0x144, "sip" },
121*1f154020SRobert Mustacchi 	/* Supervisor Protection and Translation */
122*1f154020SRobert Mustacchi 	{ 0x180, "satp" },
123*1f154020SRobert Mustacchi 	/* Machine Information Registers */
124*1f154020SRobert Mustacchi 	{ 0xf11, "mvendorid" },	{ 0xf12, "marchid" },
125*1f154020SRobert Mustacchi 	{ 0xf13, "mimpid" },	{ 0xf14, "mhartid" },
126*1f154020SRobert Mustacchi 	/* Machine Trap Setup */
127*1f154020SRobert Mustacchi 	{ 0x300, "mstatus" },	{ 0x301, "misa" },	{ 0x302, "medeleg" },
128*1f154020SRobert Mustacchi 	{ 0x303, "mideleg" },	{ 0x304, "mie" },	{ 0x305, "mtvec" },
129*1f154020SRobert Mustacchi 	{ 0x306, "mcounteren" },
130*1f154020SRobert Mustacchi 	/* Machine Trap Handling */
131*1f154020SRobert Mustacchi 	{ 0x340, "mscratch" },	{ 0x341, "mepc" },	{ 0x342, "mcause" },
132*1f154020SRobert Mustacchi 	{ 0x343, "mtval" },	{ 0x344, "mip" },
133*1f154020SRobert Mustacchi 	/* Machine Protection and Translation */
134*1f154020SRobert Mustacchi 	{ 0x3a0, "pmpcfg0" },	{ 0x3a1, "pmpcfg1" },
135*1f154020SRobert Mustacchi 	{ 0x3a2, "pmpcfg2" },	{ 0x3a3, "pmpcfg3" },
136*1f154020SRobert Mustacchi 	{ 0x3b0, "pmpaddr0" },	{ 0x3b1, "pmpaddr1" },
137*1f154020SRobert Mustacchi 	{ 0x3b2, "pmpaddr2" },	{ 0x3b3, "pmpaddr3" },
138*1f154020SRobert Mustacchi 	{ 0x3b4, "pmpaddr4" },	{ 0x3b5, "pmpaddr5" },
139*1f154020SRobert Mustacchi 	{ 0x3b6, "pmpaddr6" },	{ 0x3b7, "pmpaddr7" },
140*1f154020SRobert Mustacchi 	{ 0x3b8, "pmpaddr8" },	{ 0x3b9, "pmpaddr9" },
141*1f154020SRobert Mustacchi 	{ 0x3ba, "pmpaddr10" },	{ 0x3bb, "pmpaddr11" },
142*1f154020SRobert Mustacchi 	{ 0x3bc, "pmpaddr12" },	{ 0x3bd, "pmpaddr13" },
143*1f154020SRobert Mustacchi 	{ 0x3be, "pmpaddr14" },	{ 0x3bf, "pmpaddr15" }
144*1f154020SRobert Mustacchi };
145*1f154020SRobert Mustacchi 
146*1f154020SRobert Mustacchi typedef enum dis_riscv_csr_alias_type {
147*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_READ,
148*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_READ_GEN,
149*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_SWAP,
150*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_SWAP_IMM,
151*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE,
152*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE_GEN,
153*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE_IMM,
154*1f154020SRobert Mustacchi 	DIS_RISCV_CSR_WRITE_IMM_GEN
155*1f154020SRobert Mustacchi } dis_riscv_csr_alias_type_t;
156*1f154020SRobert Mustacchi 
157*1f154020SRobert Mustacchi typedef struct dis_riscv_csr_alias {
158*1f154020SRobert Mustacchi 	const char *drca_alias;
159*1f154020SRobert Mustacchi 	dis_riscv_csr_alias_type_t drca_type;
160*1f154020SRobert Mustacchi 	const char *drca_base;
161*1f154020SRobert Mustacchi 	const char *drca_csr;
162*1f154020SRobert Mustacchi 	int drca_rd;
163*1f154020SRobert Mustacchi 	int drca_rs;
164*1f154020SRobert Mustacchi } dis_riscv_csr_alias_t;
165*1f154020SRobert Mustacchi 
166*1f154020SRobert Mustacchi /*
167*1f154020SRobert Mustacchi  * Table of aliases. A NULL or -1 indicates a don't care.
168*1f154020SRobert Mustacchi  */
169*1f154020SRobert Mustacchi static dis_riscv_csr_alias_t dis_riscv_csr_alias[] = {
170*1f154020SRobert Mustacchi 	{ "rdinstret", DIS_RISCV_CSR_READ, "csrrs", "instret", -1, 0 },
171*1f154020SRobert Mustacchi 	{ "rdinstreth", DIS_RISCV_CSR_READ, "csrrs", "instreth", -1, 0 },
172*1f154020SRobert Mustacchi 	{ "rdcycle", DIS_RISCV_CSR_READ, "csrrs", "cycle", -1, 0 },
173*1f154020SRobert Mustacchi 	{ "rdcycleh", DIS_RISCV_CSR_READ, "csrrs", "cycleh", -1, 0 },
174*1f154020SRobert Mustacchi 	{ "rdtime", DIS_RISCV_CSR_READ, "csrrs", "time", -1, 0 },
175*1f154020SRobert Mustacchi 	{ "rdtimeh", DIS_RISCV_CSR_READ, "csrrs", "timeh", -1, 0 },
176*1f154020SRobert Mustacchi 	{ "frcsr", DIS_RISCV_CSR_READ, "csrrs", "fcsr", -1, 0 },
177*1f154020SRobert Mustacchi 	{ "fscsr", DIS_RISCV_CSR_WRITE, "csrrw", "fcsr", 0, -1 },
178*1f154020SRobert Mustacchi 	{ "fscsr", DIS_RISCV_CSR_SWAP, "csrrw", "fcsr", -1, -1 },
179*1f154020SRobert Mustacchi 	{ "frrm", DIS_RISCV_CSR_READ, "csrrs", "frm", -1, 0 },
180*1f154020SRobert Mustacchi 	{ "fsrm", DIS_RISCV_CSR_WRITE, "csrrw", "frm", 0, -1 },
181*1f154020SRobert Mustacchi 	{ "fsrm", DIS_RISCV_CSR_SWAP, "csrrw", "frm", -1, -1 },
182*1f154020SRobert Mustacchi 	{ "fsrmi", DIS_RISCV_CSR_WRITE_IMM, "csrrwi", "frm", 0, -1 },
183*1f154020SRobert Mustacchi 	{ "fsrmi", DIS_RISCV_CSR_SWAP_IMM, "csrrwi", "frm", -1, -1 },
184*1f154020SRobert Mustacchi 	{ "frflags", DIS_RISCV_CSR_READ, "csrrs", "fflags", -1, 0 },
185*1f154020SRobert Mustacchi 	{ "fsflags", DIS_RISCV_CSR_WRITE, "csrrw", "fflags", 0, -1 },
186*1f154020SRobert Mustacchi 	{ "fsflags", DIS_RISCV_CSR_SWAP, "csrrw", "fflags", -1, -1 },
187*1f154020SRobert Mustacchi 	{ "fsflagsi", DIS_RISCV_CSR_WRITE_IMM, "csrrwi", "fflags", 0, -1 },
188*1f154020SRobert Mustacchi 	{ "fsflagsi", DIS_RISCV_CSR_SWAP_IMM, "csrrwi", "fflags", -1, -1 },
189*1f154020SRobert Mustacchi 	/*
190*1f154020SRobert Mustacchi 	 * These are the generic aliases that aren't based on the CSR. Keep
191*1f154020SRobert Mustacchi 	 * them last.
192*1f154020SRobert Mustacchi 	 */
193*1f154020SRobert Mustacchi 	{ "csrr", DIS_RISCV_CSR_READ_GEN, "csrrs", NULL, -1, 0 },
194*1f154020SRobert Mustacchi 	{ "csrw", DIS_RISCV_CSR_WRITE_GEN, "csrrw", NULL, 0, -1 },
195*1f154020SRobert Mustacchi 	{ "csrs", DIS_RISCV_CSR_WRITE_GEN, "csrrs", NULL, 0, -1 },
196*1f154020SRobert Mustacchi 	{ "csrc", DIS_RISCV_CSR_WRITE_GEN, "csrrc", NULL, 0, -1 },
197*1f154020SRobert Mustacchi 	{ "csrwi", DIS_RISCV_CSR_WRITE_IMM_GEN, "csrrwi", NULL, 0, -1 },
198*1f154020SRobert Mustacchi 	{ "csrsi", DIS_RISCV_CSR_WRITE_IMM_GEN, "csrrsi", NULL, 0, -1 },
199*1f154020SRobert Mustacchi 	{ "csrci", DIS_RISCV_CSR_WRITE_IMM_GEN, "csrrci", NULL, 0, -1 },
200*1f154020SRobert Mustacchi };
201*1f154020SRobert Mustacchi 
202*1f154020SRobert Mustacchi /*
203*1f154020SRobert Mustacchi  * Take an n-bit value whose sign bit is indicated by the big sign and convert
204*1f154020SRobert Mustacchi  * to a signed type.
205*1f154020SRobert Mustacchi  */
206*1f154020SRobert Mustacchi static uint_t
207*1f154020SRobert Mustacchi dis_riscv_sign_extend(uint_t val, uint_t sbit, const char **sign)
208*1f154020SRobert Mustacchi {
209*1f154020SRobert Mustacchi 	VERIFY3U(sbit, <=, 31);
210*1f154020SRobert Mustacchi 
211*1f154020SRobert Mustacchi 	if (val >= 1 << sbit) {
212*1f154020SRobert Mustacchi 		*sign = "-";
213*1f154020SRobert Mustacchi 		return ((1 << (sbit + 1)) - val);
214*1f154020SRobert Mustacchi 	} else {
215*1f154020SRobert Mustacchi 		*sign = "";
216*1f154020SRobert Mustacchi 		return (val);
217*1f154020SRobert Mustacchi 	}
218*1f154020SRobert Mustacchi }
219*1f154020SRobert Mustacchi 
220*1f154020SRobert Mustacchi /*
221*1f154020SRobert Mustacchi  * Four byte decode tables. This is derived from the RV32/64G Instruction Set
222*1f154020SRobert Mustacchi  * Listings. We describe a table entry based on the opcode and optional opcodes
223*1f154020SRobert Mustacchi  * based on the type of instruction that it is and its encoding format. Most
224*1f154020SRobert Mustacchi  * sets of instructions have one of several uniform encoding types.
225*1f154020SRobert Mustacchi  *
226*1f154020SRobert Mustacchi  *  31             25 24     20 19  15 14    12  11        7  6      0
227*1f154020SRobert Mustacchi  * |    funct7       |   r2    |  rs1 | funct3 | rd          | opcode | R-type
228*1f154020SRobert Mustacchi  * |    imm[11:0]              |  rs1 | funct3 | rd          | opcode | I-type
229*1f154020SRobert Mustacchi  * |    imm[11:5]    |   r2    |  rs1 | funct3 | imm[4:0]    | opcode | S-type
230*1f154020SRobert Mustacchi  * |    imm[12|10:5] |   r2    |  rs1 | funct3 | imm[4:1|11] | opcode | B-type
231*1f154020SRobert Mustacchi  * |    imm[31:12]                             | rd          | opcode | U-type
232*1f154020SRobert Mustacchi  * |    imm[10|10:1|11|19:12]                  | rd          | opcode | J-type
233*1f154020SRobert Mustacchi  */
234*1f154020SRobert Mustacchi typedef enum dis_riscv_itype {
235*1f154020SRobert Mustacchi 	DIS_RISCV_I_R_TYPE,
236*1f154020SRobert Mustacchi 	DIS_RISCV_I_I_TYPE,
237*1f154020SRobert Mustacchi 	DIS_RISCV_I_S_TYPE,
238*1f154020SRobert Mustacchi 	DIS_RISCV_I_B_TYPE,
239*1f154020SRobert Mustacchi 	DIS_RISCV_I_U_TYPE,
240*1f154020SRobert Mustacchi 	DIS_RISCV_I_J_TYPE,
241*1f154020SRobert Mustacchi 	DIS_RISCV_I_R4_TYPE,
242*1f154020SRobert Mustacchi 	/*
243*1f154020SRobert Mustacchi 	 * This is a variant of the standard R type where the first bit of
244*1f154020SRobert Mustacchi 	 * funct7 is actually used for this shift.
245*1f154020SRobert Mustacchi 	 */
246*1f154020SRobert Mustacchi 	DIS_RISCV_I_SHIFT64_TYPE,
247*1f154020SRobert Mustacchi 	/*
248*1f154020SRobert Mustacchi 	 * This type isn't explicitly defined in the ISA doc; however, it is a
249*1f154020SRobert Mustacchi 	 * standard format that is for all of the Atomic class instructions.
250*1f154020SRobert Mustacchi 	 * This is treated like an R-type, except the funct7 is really a funct5.
251*1f154020SRobert Mustacchi 	 * The load variant is similar; however, rs2 must be zero.
252*1f154020SRobert Mustacchi 	 */
253*1f154020SRobert Mustacchi 	DIS_RISCV_I_RV32A_TYPE,
254*1f154020SRobert Mustacchi 	DIS_RISCV_I_RV32A_LOAD_TYPE,
255*1f154020SRobert Mustacchi 	/*
256*1f154020SRobert Mustacchi 	 * This is a custom type we've defined where the first value is the
257*1f154020SRobert Mustacchi 	 * instruction mask and the second value is the value of the bits in it.
258*1f154020SRobert Mustacchi 	 * This is used for a few irregular instructions ala FENCE and ECALL.
259*1f154020SRobert Mustacchi 	 */
260*1f154020SRobert Mustacchi 	DIS_RISCV_I_MASK_TYPE,
261*1f154020SRobert Mustacchi 	/*
262*1f154020SRobert Mustacchi 	 * This type is used for FP arguments that use rs2 as an opcode.
263*1f154020SRobert Mustacchi 	 */
264*1f154020SRobert Mustacchi 	DIS_RISCV_I_FP_RS2OP_TYPE,
265*1f154020SRobert Mustacchi 	/*
266*1f154020SRobert Mustacchi 	 * This type uses the opcode and funct7 and uses funct3 as a rounding
267*1f154020SRobert Mustacchi 	 * mode argument.
268*1f154020SRobert Mustacchi 	 */
269*1f154020SRobert Mustacchi 	DIS_RISCV_I_FP_RM_TYPE,
270*1f154020SRobert Mustacchi 	/*
271*1f154020SRobert Mustacchi 	 * This fp type uses the opcode, funct7, funct3, and rs2 as an op type.
272*1f154020SRobert Mustacchi 	 */
273*1f154020SRobert Mustacchi 	DIS_RISCV_I_FP_R_RS2_TYPE,
274*1f154020SRobert Mustacchi } dis_riscv_itype_t;
275*1f154020SRobert Mustacchi 
276*1f154020SRobert Mustacchi #define	DIS_RISCV_OPCODE(x)	((x) & 0x7f)
277*1f154020SRobert Mustacchi #define	DIS_RISCV_FUNCT3(x)	(((x) >> 12) & 0x7)
278*1f154020SRobert Mustacchi #define	DIS_RISCV_FUNCT7(x)	(((x) >> 25) & 0x7f)
279*1f154020SRobert Mustacchi #define	DIS_RISCV_RD(x)		(((x) >> 7) & 0x1f)
280*1f154020SRobert Mustacchi #define	DIS_RISCV_RS1(x)	(((x) >> 15) & 0x1f)
281*1f154020SRobert Mustacchi #define	DIS_RISCV_RS2(x)	(((x) >> 20) & 0x1f)
282*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS3(x)	(((x) >> 27) & 0x1f)
283*1f154020SRobert Mustacchi #define	DIS_RISCV_FUNCT2(x)	(((x) >> 25) & 0x03)
284*1f154020SRobert Mustacchi 
285*1f154020SRobert Mustacchi /*
286*1f154020SRobert Mustacchi  * SHIFT funct7 variant.
287*1f154020SRobert Mustacchi  */
288*1f154020SRobert Mustacchi #define	DIS_RISCV_SFUNCT7(x)	(((x) >> 26) & 0x3f)
289*1f154020SRobert Mustacchi 
290*1f154020SRobert Mustacchi #define	DIS_RISCV_UIMM(x)	(((x) >> 12) & 0xfffff)
291*1f154020SRobert Mustacchi 
292*1f154020SRobert Mustacchi #define	DIS_RISCV_IIMM(x)	(((x) >> 20) & 0xfff)
293*1f154020SRobert Mustacchi 
294*1f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_12(x)	(((x) >> 19) & 0x1000)
295*1f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_11(x)	(((x) & 0x80) << 4)
296*1f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_10_5(x)	(((x) >> 20) & 0x7e0)
297*1f154020SRobert Mustacchi #define	DIS_RISCV_BIMM_4_1(x)	(((x) >> 7) & 0x1e)
298*1f154020SRobert Mustacchi 
299*1f154020SRobert Mustacchi #define	DIS_RISCV_SIMM_UP(x)	((((x) >> 25) & 0x7f) << 5)
300*1f154020SRobert Mustacchi #define	DIS_RISCV_SIMM_LOW(x)	(((x) >> 7) & 0x1f)
301*1f154020SRobert Mustacchi 
302*1f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_20(x)	(((x) & 0x80000000) >> 11)
303*1f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_19_12(x)	((x) & 0xff000)
304*1f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_11(x)	(((x) & 100000) >> 9)
305*1f154020SRobert Mustacchi #define	DIS_RISCV_JIMM_10_1(x)	(((x) & 0x7fe00000) >> 20)
306*1f154020SRobert Mustacchi 
307*1f154020SRobert Mustacchi #define	DIS_RISCV_RVA_FUNCT5(x)	(((x) >> 27) & 0x1f)
308*1f154020SRobert Mustacchi #define	DIS_RISCV_RVA_AQ(x)	(((x) >> 26) & 0x1)
309*1f154020SRobert Mustacchi #define	DIS_RISCV_RVA_RL(x)	(((x) >> 25) & 0x1)
310*1f154020SRobert Mustacchi 
311*1f154020SRobert Mustacchi struct dis_riscv_instr;
312*1f154020SRobert Mustacchi typedef void (*dis_riscv_func_t)(dis_handle_t *, uint32_t,
313*1f154020SRobert Mustacchi     struct dis_riscv_instr *, char *, size_t);
314*1f154020SRobert Mustacchi 
315*1f154020SRobert Mustacchi typedef struct dis_riscv_instr {
316*1f154020SRobert Mustacchi 	const char 		*drv_name;
317*1f154020SRobert Mustacchi 	dis_riscv_itype_t	drv_type;
318*1f154020SRobert Mustacchi 	dis_riscv_func_t	drv_print;
319*1f154020SRobert Mustacchi 	uint_t			drv_opcode;
320*1f154020SRobert Mustacchi 	uint_t			drv_funct3;
321*1f154020SRobert Mustacchi 	uint_t			drv_funct7;
322*1f154020SRobert Mustacchi 	uint_t			drv_funct2;
323*1f154020SRobert Mustacchi } dis_riscv_instr_t;
324*1f154020SRobert Mustacchi 
325*1f154020SRobert Mustacchi /*ARGSUSED*/
326*1f154020SRobert Mustacchi static void
327*1f154020SRobert Mustacchi dis_riscv_rtype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
328*1f154020SRobert Mustacchi     char *buf, size_t buflen)
329*1f154020SRobert Mustacchi {
330*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
331*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
332*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)],
333*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS2(instr)]);
334*1f154020SRobert Mustacchi }
335*1f154020SRobert Mustacchi 
336*1f154020SRobert Mustacchi static void
337*1f154020SRobert Mustacchi dis_riscv_itype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
338*1f154020SRobert Mustacchi     char *buf, size_t buflen)
339*1f154020SRobert Mustacchi {
340*1f154020SRobert Mustacchi 	const char *s;
341*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(DIS_RISCV_IIMM(instr), 11, &s);
342*1f154020SRobert Mustacchi 
343*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
344*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0%o",
345*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
346*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
347*1f154020SRobert Mustacchi 	} else {
348*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0x%x",
349*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
350*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
351*1f154020SRobert Mustacchi 	}
352*1f154020SRobert Mustacchi }
353*1f154020SRobert Mustacchi 
354*1f154020SRobert Mustacchi static void
355*1f154020SRobert Mustacchi dis_riscv_btype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
356*1f154020SRobert Mustacchi     char *buf, size_t buflen)
357*1f154020SRobert Mustacchi {
358*1f154020SRobert Mustacchi 	const char *s;
359*1f154020SRobert Mustacchi 	uint_t bimm = DIS_RISCV_BIMM_12(instr) | DIS_RISCV_BIMM_11(instr) |
360*1f154020SRobert Mustacchi 	    DIS_RISCV_BIMM_10_5(instr) | DIS_RISCV_BIMM_4_1(instr);
361*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(bimm, 12, &s);
362*1f154020SRobert Mustacchi 
363*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
364*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0%o",
365*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
366*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
367*1f154020SRobert Mustacchi 	} else {
368*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s0x%x",
369*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
370*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], s, imm);
371*1f154020SRobert Mustacchi 	}
372*1f154020SRobert Mustacchi }
373*1f154020SRobert Mustacchi 
374*1f154020SRobert Mustacchi static void
375*1f154020SRobert Mustacchi dis_riscv_load(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
376*1f154020SRobert Mustacchi     char *buf, size_t buflen)
377*1f154020SRobert Mustacchi {
378*1f154020SRobert Mustacchi 	const char *s;
379*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(DIS_RISCV_IIMM(instr), 11, &s);
380*1f154020SRobert Mustacchi 
381*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
382*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
383*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
384*1f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
385*1f154020SRobert Mustacchi 	} else {
386*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
387*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
388*1f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
389*1f154020SRobert Mustacchi 	}
390*1f154020SRobert Mustacchi }
391*1f154020SRobert Mustacchi 
392*1f154020SRobert Mustacchi static void
393*1f154020SRobert Mustacchi dis_riscv_stype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
394*1f154020SRobert Mustacchi     char *buf, size_t buflen)
395*1f154020SRobert Mustacchi {
396*1f154020SRobert Mustacchi 	const char *s;
397*1f154020SRobert Mustacchi 	uint_t simm = DIS_RISCV_SIMM_UP(instr) | DIS_RISCV_SIMM_LOW(instr);
398*1f154020SRobert Mustacchi 	uint_t val = dis_riscv_sign_extend(simm, 11, &s);
399*1f154020SRobert Mustacchi 
400*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
401*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
402*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RS2(instr)],
403*1f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
404*1f154020SRobert Mustacchi 	} else {
405*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
406*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RS2(instr)],
407*1f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
408*1f154020SRobert Mustacchi 	}
409*1f154020SRobert Mustacchi }
410*1f154020SRobert Mustacchi 
411*1f154020SRobert Mustacchi /*ARGSUSED*/
412*1f154020SRobert Mustacchi static void
413*1f154020SRobert Mustacchi dis_riscv_utype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
414*1f154020SRobert Mustacchi     char *buf, size_t buflen)
415*1f154020SRobert Mustacchi {
416*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,0x%x", table->drv_name,
417*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)], DIS_RISCV_UIMM(instr));
418*1f154020SRobert Mustacchi }
419*1f154020SRobert Mustacchi 
420*1f154020SRobert Mustacchi static void
421*1f154020SRobert Mustacchi dis_riscv_jtype_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
422*1f154020SRobert Mustacchi     char *buf, size_t buflen)
423*1f154020SRobert Mustacchi {
424*1f154020SRobert Mustacchi 	const char *s;
425*1f154020SRobert Mustacchi 	uint_t jimm = DIS_RISCV_JIMM_20(instr) | DIS_RISCV_JIMM_19_12(instr) |
426*1f154020SRobert Mustacchi 	    DIS_RISCV_JIMM_11(instr) | DIS_RISCV_JIMM_10_1(instr);
427*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(jimm, 20, &s);
428*1f154020SRobert Mustacchi 
429*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
430*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o",
431*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
432*1f154020SRobert Mustacchi 		    s, imm);
433*1f154020SRobert Mustacchi 	} else {
434*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x",
435*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
436*1f154020SRobert Mustacchi 		    s, imm);
437*1f154020SRobert Mustacchi 	}
438*1f154020SRobert Mustacchi }
439*1f154020SRobert Mustacchi 
440*1f154020SRobert Mustacchi /*
441*1f154020SRobert Mustacchi  * The shift instructions are a variant on the R-type instructions where RS2 is
442*1f154020SRobert Mustacchi  * an immediate to perform the shift by as opposed to a register.
443*1f154020SRobert Mustacchi  */
444*1f154020SRobert Mustacchi static void
445*1f154020SRobert Mustacchi dis_riscv_shift_32(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
446*1f154020SRobert Mustacchi     char *buf, size_t buflen)
447*1f154020SRobert Mustacchi {
448*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
449*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0%o",
450*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
451*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], DIS_RISCV_RS2(instr));
452*1f154020SRobert Mustacchi 	} else {
453*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0x%x",
454*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
455*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], DIS_RISCV_RS2(instr));
456*1f154020SRobert Mustacchi 	}
457*1f154020SRobert Mustacchi }
458*1f154020SRobert Mustacchi 
459*1f154020SRobert Mustacchi /*
460*1f154020SRobert Mustacchi  * The 64-bit version of shift instructions steals an extra bit from funct7 to
461*1f154020SRobert Mustacchi  * construct the shift amount.
462*1f154020SRobert Mustacchi  */
463*1f154020SRobert Mustacchi static void
464*1f154020SRobert Mustacchi dis_riscv_shift_64(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
465*1f154020SRobert Mustacchi     char *buf, size_t buflen)
466*1f154020SRobert Mustacchi {
467*1f154020SRobert Mustacchi 	uint_t shift = DIS_RISCV_RS2(instr) | ((instr & (1UL << 25)) >> 20);
468*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
469*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0%o",
470*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
471*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], shift);
472*1f154020SRobert Mustacchi 	} else {
473*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,0x%x",
474*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_regs[DIS_RISCV_RD(instr)],
475*1f154020SRobert Mustacchi 		    dis_riscv_regs[DIS_RISCV_RS1(instr)], shift);
476*1f154020SRobert Mustacchi 	}
477*1f154020SRobert Mustacchi }
478*1f154020SRobert Mustacchi 
479*1f154020SRobert Mustacchi /*ARGSUSED*/
480*1f154020SRobert Mustacchi static void
481*1f154020SRobert Mustacchi dis_riscv_csr(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
482*1f154020SRobert Mustacchi     char *buf, size_t buflen)
483*1f154020SRobert Mustacchi {
484*1f154020SRobert Mustacchi 	uint_t rd, csr, rs, i;
485*1f154020SRobert Mustacchi 	const char *csrstr = NULL;
486*1f154020SRobert Mustacchi 	char csrval[32];
487*1f154020SRobert Mustacchi 	dis_riscv_csr_alias_t *alias = NULL;
488*1f154020SRobert Mustacchi 
489*1f154020SRobert Mustacchi 	rd = DIS_RISCV_RD(instr);
490*1f154020SRobert Mustacchi 	rs = DIS_RISCV_RS1(instr);
491*1f154020SRobert Mustacchi 	csr = DIS_RISCV_IIMM(instr);
492*1f154020SRobert Mustacchi 
493*1f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_map); i++) {
494*1f154020SRobert Mustacchi 		if (csr == dis_riscv_csr_map[i].drc_val) {
495*1f154020SRobert Mustacchi 			csrstr = dis_riscv_csr_map[i].drc_name;
496*1f154020SRobert Mustacchi 			break;
497*1f154020SRobert Mustacchi 		}
498*1f154020SRobert Mustacchi 	}
499*1f154020SRobert Mustacchi 
500*1f154020SRobert Mustacchi 	if (csrstr == NULL) {
501*1f154020SRobert Mustacchi 		(void) dis_snprintf(csrval, sizeof (csrval), "0x%x", csr);
502*1f154020SRobert Mustacchi 		csrstr = csrval;
503*1f154020SRobert Mustacchi 	}
504*1f154020SRobert Mustacchi 
505*1f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_alias); i++) {
506*1f154020SRobert Mustacchi 		dis_riscv_csr_alias_t *a = &dis_riscv_csr_alias[i];
507*1f154020SRobert Mustacchi 		if (strcmp(a->drca_base, table->drv_name) != 0)
508*1f154020SRobert Mustacchi 			continue;
509*1f154020SRobert Mustacchi 		if (a->drca_csr != NULL && strcmp(a->drca_csr, csrstr) != 0)
510*1f154020SRobert Mustacchi 			continue;
511*1f154020SRobert Mustacchi 		if (a->drca_rd != -1 && a->drca_rd != rd)
512*1f154020SRobert Mustacchi 			continue;
513*1f154020SRobert Mustacchi 		if (a->drca_rs != -1 && a->drca_rs != rs)
514*1f154020SRobert Mustacchi 			continue;
515*1f154020SRobert Mustacchi 		alias = a;
516*1f154020SRobert Mustacchi 		break;
517*1f154020SRobert Mustacchi 	}
518*1f154020SRobert Mustacchi 
519*1f154020SRobert Mustacchi 	if (alias == NULL) {
520*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
521*1f154020SRobert Mustacchi 		    dis_riscv_regs[rd], csrstr, dis_riscv_regs[rs]);
522*1f154020SRobert Mustacchi 		return;
523*1f154020SRobert Mustacchi 	}
524*1f154020SRobert Mustacchi 
525*1f154020SRobert Mustacchi 	switch (alias->drca_type) {
526*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_READ:
527*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s", alias->drca_alias,
528*1f154020SRobert Mustacchi 		    dis_riscv_regs[rd]);
529*1f154020SRobert Mustacchi 		break;
530*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_READ_GEN:
531*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s", alias->drca_alias,
532*1f154020SRobert Mustacchi 		    dis_riscv_regs[rd], csrstr);
533*1f154020SRobert Mustacchi 		break;
534*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_SWAP:
535*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s", alias->drca_alias,
536*1f154020SRobert Mustacchi 		    dis_riscv_regs[rd], dis_riscv_regs[rs]);
537*1f154020SRobert Mustacchi 		break;
538*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE:
539*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s", alias->drca_alias,
540*1f154020SRobert Mustacchi 		    dis_riscv_regs[rs]);
541*1f154020SRobert Mustacchi 		break;
542*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE_GEN:
543*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s", alias->drca_alias,
544*1f154020SRobert Mustacchi 		    csrstr, dis_riscv_regs[rs]);
545*1f154020SRobert Mustacchi 		break;
546*1f154020SRobert Mustacchi 	default:
547*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "<unknown>");
548*1f154020SRobert Mustacchi 		break;
549*1f154020SRobert Mustacchi 	}
550*1f154020SRobert Mustacchi }
551*1f154020SRobert Mustacchi 
552*1f154020SRobert Mustacchi static void
553*1f154020SRobert Mustacchi dis_riscv_csri(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
554*1f154020SRobert Mustacchi     char *buf, size_t buflen)
555*1f154020SRobert Mustacchi {
556*1f154020SRobert Mustacchi 	uint_t rd, csr, imm, i;
557*1f154020SRobert Mustacchi 	const char *csrstr = NULL;
558*1f154020SRobert Mustacchi 	char csrval[32];
559*1f154020SRobert Mustacchi 	dis_riscv_csr_alias_t *alias = NULL;
560*1f154020SRobert Mustacchi 
561*1f154020SRobert Mustacchi 	rd = DIS_RISCV_RD(instr);
562*1f154020SRobert Mustacchi 	imm = DIS_RISCV_RS1(instr);
563*1f154020SRobert Mustacchi 	csr = DIS_RISCV_IIMM(instr);
564*1f154020SRobert Mustacchi 
565*1f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_map); i++) {
566*1f154020SRobert Mustacchi 		if (csr == dis_riscv_csr_map[i].drc_val) {
567*1f154020SRobert Mustacchi 			csrstr = dis_riscv_csr_map[i].drc_name;
568*1f154020SRobert Mustacchi 			break;
569*1f154020SRobert Mustacchi 		}
570*1f154020SRobert Mustacchi 	}
571*1f154020SRobert Mustacchi 
572*1f154020SRobert Mustacchi 	if (csrstr == NULL) {
573*1f154020SRobert Mustacchi 		(void) dis_snprintf(csrval, sizeof (csrval), "0x%x", csr);
574*1f154020SRobert Mustacchi 		csrstr = csrval;
575*1f154020SRobert Mustacchi 	}
576*1f154020SRobert Mustacchi 
577*1f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_csr_alias); i++) {
578*1f154020SRobert Mustacchi 		dis_riscv_csr_alias_t *a = &dis_riscv_csr_alias[i];
579*1f154020SRobert Mustacchi 		if (strcmp(a->drca_base, table->drv_name) != 0)
580*1f154020SRobert Mustacchi 			continue;
581*1f154020SRobert Mustacchi 		if (a->drca_csr != NULL && strcmp(a->drca_csr, csrstr) != 0)
582*1f154020SRobert Mustacchi 			continue;
583*1f154020SRobert Mustacchi 		if (a->drca_rd != -1 && a->drca_rd != rd)
584*1f154020SRobert Mustacchi 			continue;
585*1f154020SRobert Mustacchi 		if (a->drca_rs != -1)
586*1f154020SRobert Mustacchi 			continue;
587*1f154020SRobert Mustacchi 		alias = a;
588*1f154020SRobert Mustacchi 		break;
589*1f154020SRobert Mustacchi 	}
590*1f154020SRobert Mustacchi 
591*1f154020SRobert Mustacchi 	if (alias == NULL) {
592*1f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
593*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,%s,0%o",
594*1f154020SRobert Mustacchi 			    table->drv_name, dis_riscv_regs[rd], csrstr, imm);
595*1f154020SRobert Mustacchi 		} else {
596*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,%s,0x%x",
597*1f154020SRobert Mustacchi 			    table->drv_name, dis_riscv_regs[rd], csrstr, imm);
598*1f154020SRobert Mustacchi 		}
599*1f154020SRobert Mustacchi 		return;
600*1f154020SRobert Mustacchi 	}
601*1f154020SRobert Mustacchi 
602*1f154020SRobert Mustacchi 	switch (alias->drca_type) {
603*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_SWAP_IMM:
604*1f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
605*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0%o",
606*1f154020SRobert Mustacchi 			    alias->drca_alias, dis_riscv_regs[rd], imm);
607*1f154020SRobert Mustacchi 		} else {
608*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0x%x",
609*1f154020SRobert Mustacchi 			    alias->drca_alias, dis_riscv_regs[rd], imm);
610*1f154020SRobert Mustacchi 		}
611*1f154020SRobert Mustacchi 		break;
612*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE_IMM:
613*1f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
614*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s 0%o",
615*1f154020SRobert Mustacchi 			    alias->drca_alias, imm);
616*1f154020SRobert Mustacchi 		} else {
617*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s 0x%x",
618*1f154020SRobert Mustacchi 			    alias->drca_alias, imm);
619*1f154020SRobert Mustacchi 		}
620*1f154020SRobert Mustacchi 		break;
621*1f154020SRobert Mustacchi 	case DIS_RISCV_CSR_WRITE_IMM_GEN:
622*1f154020SRobert Mustacchi 		if ((dhp->dh_flags & DIS_OCTAL) != 0) {
623*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0%o",
624*1f154020SRobert Mustacchi 			    alias->drca_alias, csrstr, imm);
625*1f154020SRobert Mustacchi 		} else {
626*1f154020SRobert Mustacchi 			(void) dis_snprintf(buf, buflen, "%s %s,0x%x",
627*1f154020SRobert Mustacchi 			    alias->drca_alias, csrstr, imm);
628*1f154020SRobert Mustacchi 		}
629*1f154020SRobert Mustacchi 		break;
630*1f154020SRobert Mustacchi 	default:
631*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "<unknown>");
632*1f154020SRobert Mustacchi 		break;
633*1f154020SRobert Mustacchi 	}
634*1f154020SRobert Mustacchi }
635*1f154020SRobert Mustacchi 
636*1f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_PRED(x)	(((x) >> 24) & 0xf)
637*1f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_SUCC(x)	(((x) >> 20) & 0xf)
638*1f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_I	0x8
639*1f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_O	0x4
640*1f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_R	0x2
641*1f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_W	0x1
642*1f154020SRobert Mustacchi #define	DIS_RISCV_FENCE_IORW	0xf
643*1f154020SRobert Mustacchi 
644*1f154020SRobert Mustacchi /*ARGSUSED*/
645*1f154020SRobert Mustacchi static void
646*1f154020SRobert Mustacchi dis_riscv_fence(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
647*1f154020SRobert Mustacchi     char *buf, size_t buflen)
648*1f154020SRobert Mustacchi {
649*1f154020SRobert Mustacchi 	uint_t pred, succ;
650*1f154020SRobert Mustacchi 
651*1f154020SRobert Mustacchi 	pred = DIS_RISCV_FENCE_PRED(instr);
652*1f154020SRobert Mustacchi 	succ = DIS_RISCV_FENCE_SUCC(instr);
653*1f154020SRobert Mustacchi 
654*1f154020SRobert Mustacchi 	/*
655*1f154020SRobert Mustacchi 	 * If both halves are iorw that is aliased to just an empty fence
656*1f154020SRobert Mustacchi 	 * instruction per Chapter 20 - RISC-V Assembly Programmer's Handbook in
657*1f154020SRobert Mustacchi 	 * the RISC-V user spec.
658*1f154020SRobert Mustacchi 	 */
659*1f154020SRobert Mustacchi 	if (pred == DIS_RISCV_FENCE_IORW && succ == DIS_RISCV_FENCE_IORW) {
660*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s", table->drv_name);
661*1f154020SRobert Mustacchi 		return;
662*1f154020SRobert Mustacchi 	}
663*1f154020SRobert Mustacchi 
664*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s%s%s%s, %s%s%s%s",
665*1f154020SRobert Mustacchi 	    table->drv_name,
666*1f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_I ? "i" : "",
667*1f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_O ? "o" : "",
668*1f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_R ? "r" : "",
669*1f154020SRobert Mustacchi 	    pred & DIS_RISCV_FENCE_W ? "w" : "",
670*1f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_I ? "i" : "",
671*1f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_O ? "o" : "",
672*1f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_R ? "r" : "",
673*1f154020SRobert Mustacchi 	    succ & DIS_RISCV_FENCE_W ? "w" : "");
674*1f154020SRobert Mustacchi }
675*1f154020SRobert Mustacchi 
676*1f154020SRobert Mustacchi /*ARGSUSED*/
677*1f154020SRobert Mustacchi static void
678*1f154020SRobert Mustacchi dis_riscv_name(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
679*1f154020SRobert Mustacchi     char *buf, size_t buflen)
680*1f154020SRobert Mustacchi {
681*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s", table->drv_name);
682*1f154020SRobert Mustacchi }
683*1f154020SRobert Mustacchi 
684*1f154020SRobert Mustacchi /*ARGSUSED*/
685*1f154020SRobert Mustacchi static void
686*1f154020SRobert Mustacchi dis_riscv_rs1_rs2(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
687*1f154020SRobert Mustacchi     char *buf, size_t buflen)
688*1f154020SRobert Mustacchi {
689*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
690*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)],
691*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS2(instr)]);
692*1f154020SRobert Mustacchi }
693*1f154020SRobert Mustacchi 
694*1f154020SRobert Mustacchi /*ARGSUSED*/
695*1f154020SRobert Mustacchi static void
696*1f154020SRobert Mustacchi dis_riscv_rv32a_load(dis_handle_t *dhp, uint32_t instr,
697*1f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
698*1f154020SRobert Mustacchi {
699*1f154020SRobert Mustacchi 	const char *suffix = "";
700*1f154020SRobert Mustacchi 
701*1f154020SRobert Mustacchi 	if (DIS_RISCV_RVA_AQ(instr) && DIS_RISCV_RVA_RL(instr)) {
702*1f154020SRobert Mustacchi 		suffix = ".aqrl";
703*1f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_AQ(instr)) {
704*1f154020SRobert Mustacchi 		suffix = ".aq";
705*1f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_RL(instr)) {
706*1f154020SRobert Mustacchi 		suffix = ".rl";
707*1f154020SRobert Mustacchi 	}
708*1f154020SRobert Mustacchi 
709*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s%s %s,(%s)", table->drv_name,
710*1f154020SRobert Mustacchi 	    suffix, dis_riscv_regs[DIS_RISCV_RD(instr)],
711*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)]);
712*1f154020SRobert Mustacchi }
713*1f154020SRobert Mustacchi 
714*1f154020SRobert Mustacchi /*ARGSUSED*/
715*1f154020SRobert Mustacchi static void
716*1f154020SRobert Mustacchi dis_riscv_rv32a(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
717*1f154020SRobert Mustacchi     char *buf, size_t buflen)
718*1f154020SRobert Mustacchi {
719*1f154020SRobert Mustacchi 	const char *suffix = "";
720*1f154020SRobert Mustacchi 
721*1f154020SRobert Mustacchi 	if (DIS_RISCV_RVA_AQ(instr) && DIS_RISCV_RVA_RL(instr)) {
722*1f154020SRobert Mustacchi 		suffix = ".aqrl";
723*1f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_AQ(instr)) {
724*1f154020SRobert Mustacchi 		suffix = ".aq";
725*1f154020SRobert Mustacchi 	} else if (DIS_RISCV_RVA_RL(instr)) {
726*1f154020SRobert Mustacchi 		suffix = ".rl";
727*1f154020SRobert Mustacchi 	}
728*1f154020SRobert Mustacchi 
729*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s%s %s,%s,(%s)", table->drv_name,
730*1f154020SRobert Mustacchi 	    suffix, dis_riscv_regs[DIS_RISCV_RD(instr)],
731*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS2(instr)],
732*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)]);
733*1f154020SRobert Mustacchi }
734*1f154020SRobert Mustacchi 
735*1f154020SRobert Mustacchi static void
736*1f154020SRobert Mustacchi dis_riscv_fp_load(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
737*1f154020SRobert Mustacchi     char *buf, size_t buflen)
738*1f154020SRobert Mustacchi {
739*1f154020SRobert Mustacchi 	const char *s;
740*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(DIS_RISCV_IIMM(instr), 11, &s);
741*1f154020SRobert Mustacchi 
742*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
743*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
744*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RD(instr)],
745*1f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
746*1f154020SRobert Mustacchi 	} else {
747*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
748*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RD(instr)],
749*1f154020SRobert Mustacchi 		    s, imm, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
750*1f154020SRobert Mustacchi 	}
751*1f154020SRobert Mustacchi }
752*1f154020SRobert Mustacchi 
753*1f154020SRobert Mustacchi static void
754*1f154020SRobert Mustacchi dis_riscv_fp_store(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
755*1f154020SRobert Mustacchi     char *buf, size_t buflen)
756*1f154020SRobert Mustacchi {
757*1f154020SRobert Mustacchi 	const char *s;
758*1f154020SRobert Mustacchi 	uint_t simm = DIS_RISCV_SIMM_UP(instr) | DIS_RISCV_SIMM_LOW(instr);
759*1f154020SRobert Mustacchi 	uint_t val = dis_riscv_sign_extend(simm, 11, &s);
760*1f154020SRobert Mustacchi 
761*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
762*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o(%s)",
763*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
764*1f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
765*1f154020SRobert Mustacchi 	} else {
766*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x(%s)",
767*1f154020SRobert Mustacchi 		    table->drv_name, dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
768*1f154020SRobert Mustacchi 		    s, val, dis_riscv_regs[DIS_RISCV_RS1(instr)]);
769*1f154020SRobert Mustacchi 	}
770*1f154020SRobert Mustacchi }
771*1f154020SRobert Mustacchi 
772*1f154020SRobert Mustacchi /*ARGSUSED*/
773*1f154020SRobert Mustacchi static void
774*1f154020SRobert Mustacchi dis_riscv_fp_r(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
775*1f154020SRobert Mustacchi     char *buf, size_t buflen)
776*1f154020SRobert Mustacchi {
777*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
778*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
779*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
780*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)]);
781*1f154020SRobert Mustacchi }
782*1f154020SRobert Mustacchi 
783*1f154020SRobert Mustacchi /*
784*1f154020SRobert Mustacchi  * Variant of fp_r type that goes to integer destination registers.
785*1f154020SRobert Mustacchi  */
786*1f154020SRobert Mustacchi /*ARGSUSED*/
787*1f154020SRobert Mustacchi static void
788*1f154020SRobert Mustacchi dis_riscv_fp_r_fpi(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
789*1f154020SRobert Mustacchi     char *buf, size_t buflen)
790*1f154020SRobert Mustacchi {
791*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s", table->drv_name,
792*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
793*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
794*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)]);
795*1f154020SRobert Mustacchi }
796*1f154020SRobert Mustacchi 
797*1f154020SRobert Mustacchi /*ARGSUSED*/
798*1f154020SRobert Mustacchi static void
799*1f154020SRobert Mustacchi dis_riscv_fp_r4(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
800*1f154020SRobert Mustacchi     char *buf, size_t buflen)
801*1f154020SRobert Mustacchi {
802*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s,%s%s", table->drv_name,
803*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
804*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
805*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
806*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_FP_RS3(instr)],
807*1f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
808*1f154020SRobert Mustacchi }
809*1f154020SRobert Mustacchi 
810*1f154020SRobert Mustacchi /*ARGSUSED*/
811*1f154020SRobert Mustacchi static void
812*1f154020SRobert Mustacchi dis_riscv_fp_rs2_fp(dis_handle_t *dhp, uint32_t instr, dis_riscv_instr_t *table,
813*1f154020SRobert Mustacchi     char *buf, size_t buflen)
814*1f154020SRobert Mustacchi {
815*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s%s", table->drv_name,
816*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
817*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
818*1f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
819*1f154020SRobert Mustacchi }
820*1f154020SRobert Mustacchi 
821*1f154020SRobert Mustacchi /*ARGSUSED*/
822*1f154020SRobert Mustacchi static void
823*1f154020SRobert Mustacchi dis_riscv_fp_rs2_fp_nr(dis_handle_t *dhp, uint32_t instr,
824*1f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
825*1f154020SRobert Mustacchi {
826*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
827*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
828*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)]);
829*1f154020SRobert Mustacchi }
830*1f154020SRobert Mustacchi 
831*1f154020SRobert Mustacchi /*ARGSUSED*/
832*1f154020SRobert Mustacchi static void
833*1f154020SRobert Mustacchi dis_riscv_fp_rs2_fpi(dis_handle_t *dhp, uint32_t instr,
834*1f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
835*1f154020SRobert Mustacchi {
836*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s%s", table->drv_name,
837*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
838*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
839*1f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
840*1f154020SRobert Mustacchi }
841*1f154020SRobert Mustacchi 
842*1f154020SRobert Mustacchi /*ARGSUSED*/
843*1f154020SRobert Mustacchi static void
844*1f154020SRobert Mustacchi dis_riscv_fp_rs2_ifp(dis_handle_t *dhp, uint32_t instr,
845*1f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
846*1f154020SRobert Mustacchi {
847*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s%s", table->drv_name,
848*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
849*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)],
850*1f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
851*1f154020SRobert Mustacchi }
852*1f154020SRobert Mustacchi 
853*1f154020SRobert Mustacchi /*ARGSUSED*/
854*1f154020SRobert Mustacchi static void
855*1f154020SRobert Mustacchi dis_riscv_fp_rs2_fpi_nr(dis_handle_t *dhp, uint32_t instr,
856*1f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
857*1f154020SRobert Mustacchi {
858*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
859*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RD(instr)],
860*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)]);
861*1f154020SRobert Mustacchi }
862*1f154020SRobert Mustacchi 
863*1f154020SRobert Mustacchi /*ARGSUSED*/
864*1f154020SRobert Mustacchi static void
865*1f154020SRobert Mustacchi dis_riscv_fp_rs2_ifp_nr(dis_handle_t *dhp, uint32_t instr,
866*1f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
867*1f154020SRobert Mustacchi {
868*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_name,
869*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
870*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_RS1(instr)]);
871*1f154020SRobert Mustacchi }
872*1f154020SRobert Mustacchi 
873*1f154020SRobert Mustacchi 
874*1f154020SRobert Mustacchi /*ARGSUSED*/
875*1f154020SRobert Mustacchi static void
876*1f154020SRobert Mustacchi dis_riscv_fp_rm(dis_handle_t *dhp, uint32_t instr,
877*1f154020SRobert Mustacchi     dis_riscv_instr_t *table, char *buf, size_t buflen)
878*1f154020SRobert Mustacchi {
879*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s,%s%s", table->drv_name,
880*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RD(instr)],
881*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS1(instr)],
882*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_RS2(instr)],
883*1f154020SRobert Mustacchi 	    dis_riscv_rm[DIS_RISCV_FUNCT3(instr)]);
884*1f154020SRobert Mustacchi }
885*1f154020SRobert Mustacchi 
886*1f154020SRobert Mustacchi #define	DIS_RISCV_R32(str, op, f3, f7)	\
887*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_rtype_32, op, f3, f7 }
888*1f154020SRobert Mustacchi #define	DIS_RISCV_I32(str, op, f3)	\
889*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_itype_32, op, f3 }
890*1f154020SRobert Mustacchi #define	DIS_RISCV_S32(str, op, f3)	\
891*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_S_TYPE, dis_riscv_stype_32, op, f3 }
892*1f154020SRobert Mustacchi #define	DIS_RISCV_B32(str, op, f3)	\
893*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_B_TYPE, dis_riscv_btype_32, op, f3 }
894*1f154020SRobert Mustacchi #define	DIS_RISCV_U32(str, op)		\
895*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_U_TYPE, dis_riscv_utype_32, op }
896*1f154020SRobert Mustacchi #define	DIS_RISCV_J32(str, op)		\
897*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_J_TYPE, dis_riscv_jtype_32, op }
898*1f154020SRobert Mustacchi 
899*1f154020SRobert Mustacchi /*
900*1f154020SRobert Mustacchi  * These are non-standard types that we've defined because they require
901*1f154020SRobert Mustacchi  * different handling.
902*1f154020SRobert Mustacchi  */
903*1f154020SRobert Mustacchi #define	DIS_RISCV_SHIFT32(str, op, f3, f7)	\
904*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_shift_32, op, f3, f7 }
905*1f154020SRobert Mustacchi #define	DIS_RISCV_SHIFT64(str, op, f3, f7)	\
906*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_SHIFT64_TYPE, dis_riscv_shift_64, op, f3, f7 }
907*1f154020SRobert Mustacchi #define	DIS_RISCV_CSR(str, op, f3)		\
908*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_csr, op, f3 }
909*1f154020SRobert Mustacchi #define	DIS_RISCV_CSRI(str, op, f3)		\
910*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_csri, op, f3 }
911*1f154020SRobert Mustacchi #define	DIS_RISCV_LOAD(str, op, f3)		\
912*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_load, op, f3 }
913*1f154020SRobert Mustacchi 
914*1f154020SRobert Mustacchi #define	DIS_RISCV_MASK(str, mask, val, func)	\
915*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_MASK_TYPE, func, mask, val }
916*1f154020SRobert Mustacchi 
917*1f154020SRobert Mustacchi 
918*1f154020SRobert Mustacchi /*
919*1f154020SRobert Mustacchi  * Atomic-extension specific entries
920*1f154020SRobert Mustacchi  */
921*1f154020SRobert Mustacchi #define	DIS_RISCV_A32(str, op, f3, f5)		\
922*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_RV32A_TYPE, dis_riscv_rv32a, op, f3, f5 }
923*1f154020SRobert Mustacchi #define	DIS_RISCV_A32LOAD(str, op, f3, f5, f2)	\
924*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_RV32A_LOAD_TYPE, dis_riscv_rv32a_load, op, f3, \
925*1f154020SRobert Mustacchi 	    f5, f2 }
926*1f154020SRobert Mustacchi 
927*1f154020SRobert Mustacchi /*
928*1f154020SRobert Mustacchi  * Floating-point specific entries
929*1f154020SRobert Mustacchi  */
930*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_LOAD(str, op, f3)				\
931*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_I_TYPE, dis_riscv_fp_load, op, f3 }
932*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_STORE(str, op, f3)				\
933*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_S_TYPE, dis_riscv_fp_store, op, f3 }
934*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_R(str, op, f3, f7)				\
935*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_fp_r, op, f3, f7 }
936*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_R4(str, op, f2)				\
937*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R4_TYPE, dis_riscv_fp_r4, op, 0, 0, f2 }
938*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_FP(str, op, rs2, f7)			\
939*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fp, op, rs2, f7 }
940*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_FP_NR(str, op, rs2, f7)		\
941*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fp_nr, op, rs2, f7 }
942*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_FPI(str, op, rs2, f7)			\
943*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fpi, op, rs2, f7 }
944*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_IFP(str, op, rs2, f7)			\
945*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_ifp, op, rs2, f7 }
946*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RS2_IFP_NR(str, op, rs2, f7)		\
947*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_ifp_nr, op, rs2, f7 }
948*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RM(str, op, f7)				\
949*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_RM_TYPE, dis_riscv_fp_rm, op, 0, f7 }
950*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_FPI(str, op, f3, rs2, f7)		\
951*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_fpi, op, f3, f7, \
952*1f154020SRobert Mustacchi 	    rs2 }
953*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_IFP(str, op, f3, rs2, f7)		\
954*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_ifp, op, f3, f7, \
955*1f154020SRobert Mustacchi 	    rs2 }
956*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_FPI_NR(str, op, f3, rs2, f7)		\
957*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_fpi_nr, op, f3, \
958*1f154020SRobert Mustacchi 	    f7, rs2 }
959*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_R_RS2_IFP_NR(str, op, f3, rs2, f7)		\
960*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_ifp_nr, op, f3, \
961*1f154020SRobert Mustacchi 	    f7, rs2 }
962*1f154020SRobert Mustacchi #define	DIS_RISCV_FP_RI(str, op, f3, f7) 			\
963*1f154020SRobert Mustacchi 	{ str, DIS_RISCV_I_R_TYPE, dis_riscv_fp_r_fpi, op, f3, f7 }
964*1f154020SRobert Mustacchi 
965*1f154020SRobert Mustacchi /*
966*1f154020SRobert Mustacchi  * This table is ordered such that it follows the ordering in the RISC-V ISA
967*1f154020SRobert Mustacchi  * Manual.
968*1f154020SRobert Mustacchi  */
969*1f154020SRobert Mustacchi static dis_riscv_instr_t dis_riscv_4byte[] = {
970*1f154020SRobert Mustacchi 	/*
971*1f154020SRobert Mustacchi 	 * RV32I
972*1f154020SRobert Mustacchi 	 */
973*1f154020SRobert Mustacchi 	DIS_RISCV_U32("lui", 0x37),
974*1f154020SRobert Mustacchi 	DIS_RISCV_U32("auipc", 0x17),
975*1f154020SRobert Mustacchi 	DIS_RISCV_J32("jal", 0x6f),
976*1f154020SRobert Mustacchi 	/* ret is a special case of jalr */
977*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("ret", 0xffffffff, 0x00008067, dis_riscv_name),
978*1f154020SRobert Mustacchi 	DIS_RISCV_I32("jalr", 0x67, 0x0),
979*1f154020SRobert Mustacchi 	DIS_RISCV_B32("beq", 0x63, 0x0),
980*1f154020SRobert Mustacchi 	DIS_RISCV_B32("bne", 0x63, 0x1),
981*1f154020SRobert Mustacchi 	DIS_RISCV_B32("blt", 0x63, 0x4),
982*1f154020SRobert Mustacchi 	DIS_RISCV_B32("bge", 0x63, 0x5),
983*1f154020SRobert Mustacchi 	DIS_RISCV_B32("bltu", 0x63, 0x6),
984*1f154020SRobert Mustacchi 	DIS_RISCV_B32("bgeu", 0x63, 0x7),
985*1f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lb", 0x03, 0x0),
986*1f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lh", 0x03, 0x1),
987*1f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lw", 0x03, 0x2),
988*1f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lbu", 0x03, 0x4),
989*1f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lhu", 0x03, 0x5),
990*1f154020SRobert Mustacchi 	DIS_RISCV_S32("sb", 0x23, 0x0),
991*1f154020SRobert Mustacchi 	DIS_RISCV_S32("sh", 0x23, 0x1),
992*1f154020SRobert Mustacchi 	DIS_RISCV_S32("sw", 0x23, 0x2),
993*1f154020SRobert Mustacchi 	/* nop is addi x0, x0, 0 */
994*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("nop", 0xffffffff, 0x00000013, dis_riscv_name),
995*1f154020SRobert Mustacchi 	DIS_RISCV_I32("addi", 0x13, 0x0),
996*1f154020SRobert Mustacchi 	DIS_RISCV_I32("slti", 0x13, 0x2),
997*1f154020SRobert Mustacchi 	DIS_RISCV_I32("sltiu", 0x13, 0x3),
998*1f154020SRobert Mustacchi 	DIS_RISCV_I32("xori", 0x13, 0x4),
999*1f154020SRobert Mustacchi 	DIS_RISCV_I32("ori", 0x13, 0x6),
1000*1f154020SRobert Mustacchi 	DIS_RISCV_I32("andi", 0x13, 0x7),
1001*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("slli", 0x13, 0x1, 0x00),
1002*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("srli", 0x13, 0x5, 0x00),
1003*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("srai", 0x13, 0x5, 0x20),
1004*1f154020SRobert Mustacchi 	DIS_RISCV_R32("add", 0x33, 0x0, 0x00),
1005*1f154020SRobert Mustacchi 	DIS_RISCV_R32("sub", 0x33, 0x0, 0x20),
1006*1f154020SRobert Mustacchi 	DIS_RISCV_R32("sll", 0x33, 0x1, 0x00),
1007*1f154020SRobert Mustacchi 	DIS_RISCV_R32("slt", 0x33, 0x2, 0x00),
1008*1f154020SRobert Mustacchi 	DIS_RISCV_R32("sltu", 0x33, 0x3, 0x00),
1009*1f154020SRobert Mustacchi 	DIS_RISCV_R32("xor", 0x33, 0x4, 0x00),
1010*1f154020SRobert Mustacchi 	DIS_RISCV_R32("srl", 0x33, 0x5, 0x00),
1011*1f154020SRobert Mustacchi 	DIS_RISCV_R32("sra", 0x33, 0x5, 0x20),
1012*1f154020SRobert Mustacchi 	DIS_RISCV_R32("or", 0x33, 0x6, 0x00),
1013*1f154020SRobert Mustacchi 	DIS_RISCV_R32("and", 0x33, 0x7, 0x00),
1014*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("fence", 0xf00fffff, 0xf, dis_riscv_fence),
1015*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("fence.i", 0xfffff00f, 0x100f, dis_riscv_name),
1016*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("ecall", 0xffffffff, 0x73, dis_riscv_name),
1017*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("ebreak", 0xffffffff, 0x100073, dis_riscv_name),
1018*1f154020SRobert Mustacchi 	DIS_RISCV_CSR("csrrw", 0x73, 0x1),
1019*1f154020SRobert Mustacchi 	DIS_RISCV_CSR("csrrs", 0x73, 0x2),
1020*1f154020SRobert Mustacchi 	DIS_RISCV_CSR("csrrc", 0x73, 0x3),
1021*1f154020SRobert Mustacchi 	DIS_RISCV_CSRI("csrrwi", 0x73, 0x5),
1022*1f154020SRobert Mustacchi 	DIS_RISCV_CSRI("csrrsi", 0x73, 0x6),
1023*1f154020SRobert Mustacchi 	DIS_RISCV_CSRI("csrrci", 0x73, 0x7),
1024*1f154020SRobert Mustacchi 	/*
1025*1f154020SRobert Mustacchi 	 * RV64I
1026*1f154020SRobert Mustacchi 	 */
1027*1f154020SRobert Mustacchi 	DIS_RISCV_LOAD("lwu", 0x03, 0x6),
1028*1f154020SRobert Mustacchi 	DIS_RISCV_LOAD("ld", 0x03, 0x3),
1029*1f154020SRobert Mustacchi 	DIS_RISCV_S32("sd", 0x23, 0x3),
1030*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT64("slli", 0x13, 0x1, 0x0),
1031*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT64("srli", 0x13, 0x5, 0x0),
1032*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT64("srai", 0x13, 0x5, 0x10),
1033*1f154020SRobert Mustacchi 	DIS_RISCV_I32("addiw", 0x1b, 0x0),
1034*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("slliw", 0x1b, 0x1, 0x0),
1035*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("srliw", 0x1b, 0x5, 0x0),
1036*1f154020SRobert Mustacchi 	DIS_RISCV_SHIFT32("sraiw", 0x1b, 0x5, 0x20),
1037*1f154020SRobert Mustacchi 	DIS_RISCV_R32("addw", 0x3b, 0x0, 0x00),
1038*1f154020SRobert Mustacchi 	DIS_RISCV_R32("subw", 0x3b, 0x0, 0x20),
1039*1f154020SRobert Mustacchi 	DIS_RISCV_R32("sllw", 0x3b, 0x1, 0x00),
1040*1f154020SRobert Mustacchi 	DIS_RISCV_R32("srlw", 0x3b, 0x5, 0x00),
1041*1f154020SRobert Mustacchi 	DIS_RISCV_R32("sraw", 0x3b, 0x5, 0x20),
1042*1f154020SRobert Mustacchi 	/*
1043*1f154020SRobert Mustacchi 	 * RV32M
1044*1f154020SRobert Mustacchi 	 */
1045*1f154020SRobert Mustacchi 	DIS_RISCV_R32("mul", 0x33, 0x0, 0x01),
1046*1f154020SRobert Mustacchi 	DIS_RISCV_R32("mulh", 0x33, 0x1, 0x01),
1047*1f154020SRobert Mustacchi 	DIS_RISCV_R32("mulhsu", 0x33, 0x2, 0x01),
1048*1f154020SRobert Mustacchi 	DIS_RISCV_R32("mulhu", 0x33, 0x3, 0x01),
1049*1f154020SRobert Mustacchi 	DIS_RISCV_R32("div", 0x33, 0x4, 0x01),
1050*1f154020SRobert Mustacchi 	DIS_RISCV_R32("divu", 0x33, 0x5, 0x01),
1051*1f154020SRobert Mustacchi 	DIS_RISCV_R32("rem", 0x33, 0x6, 0x01),
1052*1f154020SRobert Mustacchi 	DIS_RISCV_R32("remu", 0x33, 0x7, 0x01),
1053*1f154020SRobert Mustacchi 	/*
1054*1f154020SRobert Mustacchi 	 * RV64M
1055*1f154020SRobert Mustacchi 	 */
1056*1f154020SRobert Mustacchi 	DIS_RISCV_R32("mulw", 0x3b, 0x0, 0x01),
1057*1f154020SRobert Mustacchi 	DIS_RISCV_R32("divw", 0x3b, 0x4, 0x01),
1058*1f154020SRobert Mustacchi 	DIS_RISCV_R32("divuw", 0x3b, 0x5, 0x01),
1059*1f154020SRobert Mustacchi 	DIS_RISCV_R32("remw", 0x3b, 0x6, 0x01),
1060*1f154020SRobert Mustacchi 	DIS_RISCV_R32("remuw", 0x3b, 0x7, 0x01),
1061*1f154020SRobert Mustacchi 	/*
1062*1f154020SRobert Mustacchi 	 * RV32A
1063*1f154020SRobert Mustacchi 	 */
1064*1f154020SRobert Mustacchi 	DIS_RISCV_A32LOAD("lr.w", 0x2f, 0x2, 0x02, 0x0),
1065*1f154020SRobert Mustacchi 	DIS_RISCV_A32("sc.w", 0x2f, 0x2, 0x03),
1066*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoswap.w", 0x2f, 0x2, 0x01),
1067*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoadd.w", 0x2f, 0x2, 0x00),
1068*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoxor.w", 0x2f, 0x2, 0x04),
1069*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoand.w", 0x2f, 0x2, 0x0c),
1070*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoor.w", 0x2f, 0x2, 0x08),
1071*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amomin.w", 0x2f, 0x2, 0x10),
1072*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amomax.w", 0x2f, 0x2, 0x14),
1073*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amominu.w", 0x2f, 0x2, 0x18),
1074*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amomaxu.w", 0x2f, 0x2, 0x1c),
1075*1f154020SRobert Mustacchi 	/*
1076*1f154020SRobert Mustacchi 	 * RV64A
1077*1f154020SRobert Mustacchi 	 */
1078*1f154020SRobert Mustacchi 	DIS_RISCV_A32LOAD("lr.d", 0x2f, 0x3, 0x02, 0x0),
1079*1f154020SRobert Mustacchi 	DIS_RISCV_A32("sc.d", 0x2f, 0x3, 0x03),
1080*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoswap.d", 0x2f, 0x3, 0x01),
1081*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoadd.d", 0x2f, 0x3, 0x00),
1082*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoxor.d", 0x2f, 0x3, 0x04),
1083*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoand.d", 0x2f, 0x3, 0x0c),
1084*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amoor.d", 0x2f, 0x3, 0x08),
1085*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amomin.d", 0x2f, 0x3, 0x10),
1086*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amomax.d", 0x2f, 0x3, 0x14),
1087*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amominu.d", 0x2f, 0x3, 0x18),
1088*1f154020SRobert Mustacchi 	DIS_RISCV_A32("amomaxu.d", 0x2f, 0x3, 0x1c),
1089*1f154020SRobert Mustacchi 	/*
1090*1f154020SRobert Mustacchi 	 * RV32F
1091*1f154020SRobert Mustacchi 	 */
1092*1f154020SRobert Mustacchi 	DIS_RISCV_FP_LOAD("flw", 0x07, 0x2),
1093*1f154020SRobert Mustacchi 	DIS_RISCV_FP_STORE("fsw", 0x27, 0x2),
1094*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmadd.s", 0x43, 0x0),
1095*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmsub.s", 0x47, 0x0),
1096*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmsub.s", 0x4b, 0x0),
1097*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmadd.s", 0x4f, 0x0),
1098*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fadd.s", 0x53, 0x00),
1099*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fsub.s", 0x53, 0x04),
1100*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fmul.s", 0x53, 0x08),
1101*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fdiv.s", 0x53, 0xc),
1102*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP("fsqrt.s", 0x53, 0x00, 0x2c),
1103*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnj.s", 0x53, 0x0, 0x10),
1104*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjn.s", 0x53, 0x1, 0x10),
1105*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjx.s", 0x53, 0x2, 0x10),
1106*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmin.s", 0x53, 0x0, 0x14),
1107*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmax.s", 0x53, 0x1, 0x14),
1108*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.w.s", 0x53, 0x00, 0x60),
1109*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.wu.s", 0x53, 0x01, 0x60),
1110*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fmv.x.w", 0x53, 0x00, 0x00, 0x70),
1111*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("feq.s", 0x53, 0x2, 0x50),
1112*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("flt.s", 0x53, 0x1, 0x50),
1113*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("fle.s", 0x53, 0x0, 0x50),
1114*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fclass.s", 0x53, 0x1, 0x00, 0x70),
1115*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.w", 0x53, 0x00, 0x68),
1116*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.wu", 0x53, 0x01, 0x68),
1117*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_IFP_NR("fmv.w.x", 0x53, 0x0, 0x00, 0x78),
1118*1f154020SRobert Mustacchi 	/*
1119*1f154020SRobert Mustacchi 	 * RV64F
1120*1f154020SRobert Mustacchi 	 */
1121*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.l.s", 0x53, 0x02, 0x60),
1122*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.lu.s", 0x53, 0x03, 0x60),
1123*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.l", 0x53, 0x02, 0x68),
1124*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.s.lu", 0x53, 0x03, 0x68),
1125*1f154020SRobert Mustacchi 	/*
1126*1f154020SRobert Mustacchi 	 * RV32D
1127*1f154020SRobert Mustacchi 	 */
1128*1f154020SRobert Mustacchi 	DIS_RISCV_FP_LOAD("fld", 0x07, 0x3),
1129*1f154020SRobert Mustacchi 	DIS_RISCV_FP_STORE("fsd", 0x27, 0x3),
1130*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmadd.d", 0x43, 0x1),
1131*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fmsub.d", 0x47, 0x1),
1132*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmsub.d", 0x4b, 0x1),
1133*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R4("fnmadd.d", 0x4f, 0x1),
1134*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fadd.d", 0x53, 0x01),
1135*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fsub.d", 0x53, 0x05),
1136*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fmul.d", 0x53, 0x09),
1137*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RM("fdiv.d", 0x53, 0xd),
1138*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP("fsqrt.d", 0x53, 0x00, 0x2d),
1139*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnj.d", 0x53, 0x0, 0x11),
1140*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjn.d", 0x53, 0x1, 0x11),
1141*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fsgnjx.d", 0x53, 0x2, 0x11),
1142*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmin.d", 0x53, 0x0, 0x15),
1143*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R("fmax.d", 0x53, 0x1, 0x15),
1144*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP("fcvt.s.d", 0x53, 0x01, 0x20),
1145*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FP_NR("fcvt.d.s", 0x53, 0x00, 0x21),
1146*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("feq.d", 0x53, 0x2, 0x51),
1147*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("flt.d", 0x53, 0x1, 0x51),
1148*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RI("fle.d", 0x53, 0x0, 0x51),
1149*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fclass.d", 0x53, 0x1, 0x00, 0x71),
1150*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.w.d", 0x53, 0x00, 0x61),
1151*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.wu.d", 0x53, 0x01, 0x61),
1152*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP_NR("fcvt.d.w", 0x53, 0x00, 0x69),
1153*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP_NR("fcvt.d.wu", 0x53, 0x01, 0x69),
1154*1f154020SRobert Mustacchi 	/*
1155*1f154020SRobert Mustacchi 	 * RV64D
1156*1f154020SRobert Mustacchi 	 */
1157*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.l.d", 0x53, 0x02, 0x61),
1158*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_FPI("fcvt.lu.d", 0x53, 0x03, 0x61),
1159*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_FPI_NR("fmv.x.d", 0x53, 0x0, 0x00, 0x71),
1160*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.d.l", 0x53, 0x02, 0x69),
1161*1f154020SRobert Mustacchi 	DIS_RISCV_FP_RS2_IFP("fcvt.d.lu", 0x53, 0x03, 0x69),
1162*1f154020SRobert Mustacchi 	DIS_RISCV_FP_R_RS2_IFP_NR("fmv.d.x", 0x53, 0x0, 0x00, 0x79),
1163*1f154020SRobert Mustacchi 	/*
1164*1f154020SRobert Mustacchi 	 * Privileged Instructions from RISC-V Privileged Architectures V1.10.
1165*1f154020SRobert Mustacchi 	 */
1166*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("uret", 0xffffffff, 0x00200073, dis_riscv_name),
1167*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("sret", 0xffffffff, 0x10200073, dis_riscv_name),
1168*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("mret", 0xffffffff, 0x30200073, dis_riscv_name),
1169*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("wfi", 0xffffffff, 0x10500073, dis_riscv_name),
1170*1f154020SRobert Mustacchi 	DIS_RISCV_MASK("sfence.vma", 0xfe007fff, 0x12000073, dis_riscv_rs1_rs2)
1171*1f154020SRobert Mustacchi };
1172*1f154020SRobert Mustacchi 
1173*1f154020SRobert Mustacchi static void
1174*1f154020SRobert Mustacchi dis_riscv_decode_4byte(dis_handle_t *dhp, uint32_t instr, char *buf,
1175*1f154020SRobert Mustacchi     size_t buflen)
1176*1f154020SRobert Mustacchi {
1177*1f154020SRobert Mustacchi 	uint_t i;
1178*1f154020SRobert Mustacchi 
1179*1f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_4byte); i++) {
1180*1f154020SRobert Mustacchi 		dis_riscv_instr_t *t = &dis_riscv_4byte[i];
1181*1f154020SRobert Mustacchi 		switch (t->drv_type) {
1182*1f154020SRobert Mustacchi 		case DIS_RISCV_I_R_TYPE:
1183*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1184*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
1185*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
1186*1f154020SRobert Mustacchi 				break;
1187*1f154020SRobert Mustacchi 			}
1188*1f154020SRobert Mustacchi 			continue;
1189*1f154020SRobert Mustacchi 		case DIS_RISCV_I_I_TYPE:
1190*1f154020SRobert Mustacchi 		case DIS_RISCV_I_S_TYPE:
1191*1f154020SRobert Mustacchi 		case DIS_RISCV_I_B_TYPE:
1192*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1193*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3) {
1194*1f154020SRobert Mustacchi 				break;
1195*1f154020SRobert Mustacchi 			}
1196*1f154020SRobert Mustacchi 			continue;
1197*1f154020SRobert Mustacchi 		case DIS_RISCV_I_U_TYPE:
1198*1f154020SRobert Mustacchi 		case DIS_RISCV_I_J_TYPE:
1199*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode) {
1200*1f154020SRobert Mustacchi 				break;
1201*1f154020SRobert Mustacchi 			}
1202*1f154020SRobert Mustacchi 			continue;
1203*1f154020SRobert Mustacchi 		case DIS_RISCV_I_R4_TYPE:
1204*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1205*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT2(instr) == t->drv_funct2) {
1206*1f154020SRobert Mustacchi 				break;
1207*1f154020SRobert Mustacchi 			}
1208*1f154020SRobert Mustacchi 			continue;
1209*1f154020SRobert Mustacchi 		case DIS_RISCV_I_MASK_TYPE:
1210*1f154020SRobert Mustacchi 			if ((instr & t->drv_opcode) == t->drv_funct3) {
1211*1f154020SRobert Mustacchi 				break;
1212*1f154020SRobert Mustacchi 			}
1213*1f154020SRobert Mustacchi 			continue;
1214*1f154020SRobert Mustacchi 		case DIS_RISCV_I_SHIFT64_TYPE:
1215*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1216*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
1217*1f154020SRobert Mustacchi 			    DIS_RISCV_SFUNCT7(instr) == t->drv_funct7) {
1218*1f154020SRobert Mustacchi 				break;
1219*1f154020SRobert Mustacchi 			}
1220*1f154020SRobert Mustacchi 			continue;
1221*1f154020SRobert Mustacchi 
1222*1f154020SRobert Mustacchi 		case DIS_RISCV_I_RV32A_LOAD_TYPE:
1223*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1224*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
1225*1f154020SRobert Mustacchi 			    DIS_RISCV_RVA_FUNCT5(instr) == t->drv_funct7 &&
1226*1f154020SRobert Mustacchi 			    DIS_RISCV_RS2(instr) == t->drv_funct2) {
1227*1f154020SRobert Mustacchi 				break;
1228*1f154020SRobert Mustacchi 			}
1229*1f154020SRobert Mustacchi 			continue;
1230*1f154020SRobert Mustacchi 		case DIS_RISCV_I_RV32A_TYPE:
1231*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1232*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
1233*1f154020SRobert Mustacchi 			    DIS_RISCV_RVA_FUNCT5(instr) == t->drv_funct7) {
1234*1f154020SRobert Mustacchi 				break;
1235*1f154020SRobert Mustacchi 			}
1236*1f154020SRobert Mustacchi 			continue;
1237*1f154020SRobert Mustacchi 		case DIS_RISCV_I_FP_RS2OP_TYPE:
1238*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1239*1f154020SRobert Mustacchi 			    DIS_RISCV_RS2(instr) == t->drv_funct3 &&
1240*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
1241*1f154020SRobert Mustacchi 				break;
1242*1f154020SRobert Mustacchi 			}
1243*1f154020SRobert Mustacchi 			continue;
1244*1f154020SRobert Mustacchi 		case DIS_RISCV_I_FP_RM_TYPE:
1245*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1246*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
1247*1f154020SRobert Mustacchi 				break;
1248*1f154020SRobert Mustacchi 			}
1249*1f154020SRobert Mustacchi 			continue;
1250*1f154020SRobert Mustacchi 		case DIS_RISCV_I_FP_R_RS2_TYPE:
1251*1f154020SRobert Mustacchi 			if (DIS_RISCV_OPCODE(instr) == t->drv_opcode &&
1252*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT3(instr) == t->drv_funct3 &&
1253*1f154020SRobert Mustacchi 			    DIS_RISCV_RS2(instr) == t->drv_funct2 &&
1254*1f154020SRobert Mustacchi 			    DIS_RISCV_FUNCT7(instr) == t->drv_funct7) {
1255*1f154020SRobert Mustacchi 				break;
1256*1f154020SRobert Mustacchi 			}
1257*1f154020SRobert Mustacchi 			continue;
1258*1f154020SRobert Mustacchi 		default:
1259*1f154020SRobert Mustacchi 			continue;
1260*1f154020SRobert Mustacchi 		}
1261*1f154020SRobert Mustacchi 
1262*1f154020SRobert Mustacchi 		t->drv_print(dhp, instr, t, buf, buflen);
1263*1f154020SRobert Mustacchi 		return;
1264*1f154020SRobert Mustacchi 	}
1265*1f154020SRobert Mustacchi 
1266*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "<unknown>");
1267*1f154020SRobert Mustacchi }
1268*1f154020SRobert Mustacchi 
1269*1f154020SRobert Mustacchi /*
1270*1f154020SRobert Mustacchi  * Two byte decode table types.
1271*1f154020SRobert Mustacchi  */
1272*1f154020SRobert Mustacchi typedef enum dis_riscv_ctype {
1273*1f154020SRobert Mustacchi 	/*
1274*1f154020SRobert Mustacchi 	 * Indicates that we should match based on the opcode and funct3.
1275*1f154020SRobert Mustacchi 	 */
1276*1f154020SRobert Mustacchi 	DIS_RISCV_C_FUNCT3,
1277*1f154020SRobert Mustacchi 	/*
1278*1f154020SRobert Mustacchi 	 * Indicates that we should match the instruction based on a mask.
1279*1f154020SRobert Mustacchi 	 */
1280*1f154020SRobert Mustacchi 	DIS_RISCV_C_MATCH
1281*1f154020SRobert Mustacchi } dis_riscv_ctype_t;
1282*1f154020SRobert Mustacchi 
1283*1f154020SRobert Mustacchi /*
1284*1f154020SRobert Mustacchi  * The compact forms are depending on the elf class. This is used to keep track
1285*1f154020SRobert Mustacchi  * of the class and match it.
1286*1f154020SRobert Mustacchi  */
1287*1f154020SRobert Mustacchi typedef enum dis_riscv_c_class {
1288*1f154020SRobert Mustacchi 	DIS_RISCV_CL_ALL,
1289*1f154020SRobert Mustacchi 	DIS_RISCV_CL_32,
1290*1f154020SRobert Mustacchi 	DIS_RISCV_CL_64,
1291*1f154020SRobert Mustacchi 	DIS_RISCV_CL_32_64,
1292*1f154020SRobert Mustacchi 	DIS_RISCV_CL_64_128
1293*1f154020SRobert Mustacchi } dis_riscv_c_class_t;
1294*1f154020SRobert Mustacchi 
1295*1f154020SRobert Mustacchi struct dis_riscv_c_instr;
1296*1f154020SRobert Mustacchi typedef void (*dis_riscv_c_func_t)(dis_handle_t *, uint32_t,
1297*1f154020SRobert Mustacchi     struct dis_riscv_c_instr *, char *, size_t);
1298*1f154020SRobert Mustacchi 
1299*1f154020SRobert Mustacchi typedef struct dis_riscv_c_instr {
1300*1f154020SRobert Mustacchi 	const char		*drv_c_name;
1301*1f154020SRobert Mustacchi 	dis_riscv_ctype_t	drv_c_type;
1302*1f154020SRobert Mustacchi 	dis_riscv_c_func_t	drv_c_print;
1303*1f154020SRobert Mustacchi 	dis_riscv_c_class_t 	drv_c_class;
1304*1f154020SRobert Mustacchi 	uint_t			drv_c_opcode;
1305*1f154020SRobert Mustacchi 	uint_t			drv_c_funct;
1306*1f154020SRobert Mustacchi 	uint_t			drv_c_mask;
1307*1f154020SRobert Mustacchi 	uint_t			drv_c_match;
1308*1f154020SRobert Mustacchi } dis_riscv_c_instr_t;
1309*1f154020SRobert Mustacchi 
1310*1f154020SRobert Mustacchi #define	DIS_RISCV_C_OPCODE(x)	((x) & 0x03)
1311*1f154020SRobert Mustacchi #define	DIS_RISCV_C_FUNCT3(x)	(((x) & 0xe000) >> 13)
1312*1f154020SRobert Mustacchi 
1313*1f154020SRobert Mustacchi #define	DIS_RISCV_C_RS1(x)	(((x) & 0x0f80) >> 7)
1314*1f154020SRobert Mustacchi #define	DIS_RISCV_C_RS2(x)	(((x) & 0x007c) >> 2)
1315*1f154020SRobert Mustacchi #define	DIS_RISCV_C_RD(x)	DIS_RISCV_C_RS1(x)
1316*1f154020SRobert Mustacchi 
1317*1f154020SRobert Mustacchi #define	DIS_RISCV_C_RS1P(x)	(((x) & 0x0380) >> 7)
1318*1f154020SRobert Mustacchi #define	DIS_RISCV_C_RS2P(x)	DIS_RISCV_C_RDP(x)
1319*1f154020SRobert Mustacchi #define	DIS_RISCV_C_RDP(x)	(((x) & 0x001c) >> 2)
1320*1f154020SRobert Mustacchi 
1321*1f154020SRobert Mustacchi /*
1322*1f154020SRobert Mustacchi  * CJ format immediate extractor
1323*1f154020SRobert Mustacchi  */
1324*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_11(x)	(((x) & 0x1000) >> 1)
1325*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_4(x)	(((x) & 0x0800) >> 7)
1326*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_9_8(x)	(((x) & 0x0600) >> 1)
1327*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_10(x)	(((x) & 0x0100) << 2)
1328*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_6(x)	(((x) & 0x0080) >> 1)
1329*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_7(x)	(((x) & 0x0040) << 1)
1330*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_3_1(x)	(((x) & 0x0038) >> 3)
1331*1f154020SRobert Mustacchi #define	DIS_RISCV_C_J_5(x)	(((x) & 0x0004) << 3)
1332*1f154020SRobert Mustacchi 
1333*1f154020SRobert Mustacchi /*
1334*1f154020SRobert Mustacchi  * Compact Branch extractor
1335*1f154020SRobert Mustacchi  */
1336*1f154020SRobert Mustacchi #define	DIS_RISCV_C_B_8(x)	(((x) & 0x1000) >> 4)
1337*1f154020SRobert Mustacchi #define	DIS_RISCV_C_B_4_3(x)	(((x) & 0x0c00) >> 7)
1338*1f154020SRobert Mustacchi #define	DIS_RISCV_C_B_7_6(x)	(((x) & 0x0060) << 1)
1339*1f154020SRobert Mustacchi #define	DIS_RISCV_C_B_2_1(x)	(((x) & 0x0018) >> 2)
1340*1f154020SRobert Mustacchi #define	DIS_RISCV_C_B_5(x)	(((x) & 0x0004) << 3)
1341*1f154020SRobert Mustacchi 
1342*1f154020SRobert Mustacchi /*
1343*1f154020SRobert Mustacchi  * c.addi16spn extractor
1344*1f154020SRobert Mustacchi  */
1345*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_9(x)	(((x) & 0x1000) >> 3)
1346*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_4(x)	(((x) & 0x0040) >> 2)
1347*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_6(x)	(((x) & 0x0020) << 1)
1348*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_8_7(x)	(((x) & 0x0018) << 4)
1349*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A16_5(x)	(((x) & 0x0004) << 3)
1350*1f154020SRobert Mustacchi 
1351*1f154020SRobert Mustacchi /*
1352*1f154020SRobert Mustacchi  * c.addi4spn extractor
1353*1f154020SRobert Mustacchi  */
1354*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_5_4(x)	(((x) & 0x1800) >> 7)
1355*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_9_6(x)	(((x) & 0x0700) >> 2)
1356*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_2(x)	(((x) & 0x0040) >> 4)
1357*1f154020SRobert Mustacchi #define	DIS_RISCV_C_A4_3(x)	(((x) & 0x0020) >> 2)
1358*1f154020SRobert Mustacchi 
1359*1f154020SRobert Mustacchi /*ARGSUSED*/
1360*1f154020SRobert Mustacchi static void
1361*1f154020SRobert Mustacchi dis_riscv_c_name(dis_handle_t *dhp, uint32_t instr,
1362*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1363*1f154020SRobert Mustacchi {
1364*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s", table->drv_c_name);
1365*1f154020SRobert Mustacchi }
1366*1f154020SRobert Mustacchi 
1367*1f154020SRobert Mustacchi static void
1368*1f154020SRobert Mustacchi dis_riscv_c_loadstore(dis_handle_t *dhp, const char *name, const char *dreg,
1369*1f154020SRobert Mustacchi     const char *sreg, uint32_t off, char *buf, size_t buflen)
1370*1f154020SRobert Mustacchi {
1371*1f154020SRobert Mustacchi 
1372*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
1373*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,0%o(%s)", name, dreg,
1374*1f154020SRobert Mustacchi 		    off, sreg);
1375*1f154020SRobert Mustacchi 	} else {
1376*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,0x%x(%s)", name, dreg,
1377*1f154020SRobert Mustacchi 		    off, sreg);
1378*1f154020SRobert Mustacchi 	}
1379*1f154020SRobert Mustacchi }
1380*1f154020SRobert Mustacchi 
1381*1f154020SRobert Mustacchi static void
1382*1f154020SRobert Mustacchi dis_riscv_c_lwsp(dis_handle_t *dhp, uint32_t instr,
1383*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1384*1f154020SRobert Mustacchi {
1385*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x000c) << 4) |
1386*1f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0070) >> 2);
1387*1f154020SRobert Mustacchi 
1388*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1389*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2], imm, buf,
1390*1f154020SRobert Mustacchi 	    buflen);
1391*1f154020SRobert Mustacchi }
1392*1f154020SRobert Mustacchi 
1393*1f154020SRobert Mustacchi static void
1394*1f154020SRobert Mustacchi dis_riscv_c_ldsp(dis_handle_t *dhp, uint32_t instr,
1395*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1396*1f154020SRobert Mustacchi {
1397*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x001c) << 4) |
1398*1f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0060) >> 2);
1399*1f154020SRobert Mustacchi 
1400*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1401*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2],
1402*1f154020SRobert Mustacchi 	    imm, buf, buflen);
1403*1f154020SRobert Mustacchi }
1404*1f154020SRobert Mustacchi 
1405*1f154020SRobert Mustacchi static void
1406*1f154020SRobert Mustacchi dis_riscv_c_flwsp(dis_handle_t *dhp, uint32_t instr,
1407*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1408*1f154020SRobert Mustacchi {
1409*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x000c) << 4) |
1410*1f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0070) >> 2);
1411*1f154020SRobert Mustacchi 
1412*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1413*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2],
1414*1f154020SRobert Mustacchi 	    imm, buf, buflen);
1415*1f154020SRobert Mustacchi }
1416*1f154020SRobert Mustacchi 
1417*1f154020SRobert Mustacchi static void
1418*1f154020SRobert Mustacchi dis_riscv_c_fldsp(dis_handle_t *dhp, uint32_t instr,
1419*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1420*1f154020SRobert Mustacchi {
1421*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x001c) << 4) |
1422*1f154020SRobert Mustacchi 	    ((instr & 0x1000) >> 7) | ((instr & 0x0060) >> 2);
1423*1f154020SRobert Mustacchi 
1424*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1425*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RD(instr)], dis_riscv_regs[2],
1426*1f154020SRobert Mustacchi 	    imm, buf, buflen);
1427*1f154020SRobert Mustacchi }
1428*1f154020SRobert Mustacchi 
1429*1f154020SRobert Mustacchi static void
1430*1f154020SRobert Mustacchi dis_riscv_c_swsp(dis_handle_t *dhp, uint32_t instr,
1431*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1432*1f154020SRobert Mustacchi {
1433*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0180) >> 1) | ((instr & 0x1e00) >> 7);
1434*1f154020SRobert Mustacchi 
1435*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1436*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
1437*1f154020SRobert Mustacchi 	    buf, buflen);
1438*1f154020SRobert Mustacchi }
1439*1f154020SRobert Mustacchi 
1440*1f154020SRobert Mustacchi static void
1441*1f154020SRobert Mustacchi dis_riscv_c_sdsp(dis_handle_t *dhp, uint32_t instr,
1442*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1443*1f154020SRobert Mustacchi {
1444*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0380) >> 1) | ((instr & 0x1c00) >> 7);
1445*1f154020SRobert Mustacchi 
1446*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1447*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
1448*1f154020SRobert Mustacchi 	    buf, buflen);
1449*1f154020SRobert Mustacchi }
1450*1f154020SRobert Mustacchi 
1451*1f154020SRobert Mustacchi static void
1452*1f154020SRobert Mustacchi dis_riscv_c_fswsp(dis_handle_t *dhp, uint32_t instr,
1453*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1454*1f154020SRobert Mustacchi {
1455*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0180) >> 1) | ((instr & 0x1e00) >> 7);
1456*1f154020SRobert Mustacchi 
1457*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1458*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
1459*1f154020SRobert Mustacchi 	    buf, buflen);
1460*1f154020SRobert Mustacchi }
1461*1f154020SRobert Mustacchi 
1462*1f154020SRobert Mustacchi static void
1463*1f154020SRobert Mustacchi dis_riscv_c_fsdsp(dis_handle_t *dhp, uint32_t instr,
1464*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1465*1f154020SRobert Mustacchi {
1466*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0380) >> 1) | ((instr & 0x1c00) >> 7);
1467*1f154020SRobert Mustacchi 
1468*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1469*1f154020SRobert Mustacchi 	    dis_riscv_fpregs[DIS_RISCV_C_RS2(instr)], dis_riscv_regs[2], imm,
1470*1f154020SRobert Mustacchi 	    buf, buflen);
1471*1f154020SRobert Mustacchi }
1472*1f154020SRobert Mustacchi 
1473*1f154020SRobert Mustacchi static void
1474*1f154020SRobert Mustacchi dis_riscv_c_lw(dis_handle_t *dhp, uint32_t instr,
1475*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1476*1f154020SRobert Mustacchi {
1477*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0020) << 1) | ((instr & 0x1c) >> 7) |
1478*1f154020SRobert Mustacchi 	    ((instr & 0x0040) >> 3);
1479*1f154020SRobert Mustacchi 
1480*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1481*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
1482*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
1483*1f154020SRobert Mustacchi 	    imm, buf, buflen);
1484*1f154020SRobert Mustacchi }
1485*1f154020SRobert Mustacchi 
1486*1f154020SRobert Mustacchi static void
1487*1f154020SRobert Mustacchi dis_riscv_c_ld(dis_handle_t *dhp, uint32_t instr,
1488*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1489*1f154020SRobert Mustacchi {
1490*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0060) << 1) | ((instr & 0x1c) >> 7);
1491*1f154020SRobert Mustacchi 
1492*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1493*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
1494*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
1495*1f154020SRobert Mustacchi 	    imm, buf, buflen);
1496*1f154020SRobert Mustacchi }
1497*1f154020SRobert Mustacchi 
1498*1f154020SRobert Mustacchi static void
1499*1f154020SRobert Mustacchi dis_riscv_c_flw(dis_handle_t *dhp, uint32_t instr,
1500*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1501*1f154020SRobert Mustacchi {
1502*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0020) << 1) | ((instr & 0x1c) >> 7) |
1503*1f154020SRobert Mustacchi 	    ((instr & 0x0040) >> 3);
1504*1f154020SRobert Mustacchi 
1505*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1506*1f154020SRobert Mustacchi 	    dis_riscv_c_fpregs[DIS_RISCV_C_RDP(instr)],
1507*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
1508*1f154020SRobert Mustacchi 	    imm, buf, buflen);
1509*1f154020SRobert Mustacchi }
1510*1f154020SRobert Mustacchi 
1511*1f154020SRobert Mustacchi static void
1512*1f154020SRobert Mustacchi dis_riscv_c_fld(dis_handle_t *dhp, uint32_t instr,
1513*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1514*1f154020SRobert Mustacchi {
1515*1f154020SRobert Mustacchi 	uint32_t imm = ((instr & 0x0060) << 1) | ((instr & 0x1c) >> 7);
1516*1f154020SRobert Mustacchi 
1517*1f154020SRobert Mustacchi 	dis_riscv_c_loadstore(dhp, table->drv_c_name,
1518*1f154020SRobert Mustacchi 	    dis_riscv_c_fpregs[DIS_RISCV_C_RDP(instr)],
1519*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
1520*1f154020SRobert Mustacchi 	    imm, buf, buflen);
1521*1f154020SRobert Mustacchi }
1522*1f154020SRobert Mustacchi 
1523*1f154020SRobert Mustacchi /*
1524*1f154020SRobert Mustacchi  * The J type has the 11 bit immediate arranged as:
1525*1f154020SRobert Mustacchi  *
1526*1f154020SRobert Mustacchi  *  offset[11|4|9:8|10|6|7|3:1|5] going from bits 2 to 12.
1527*1f154020SRobert Mustacchi  */
1528*1f154020SRobert Mustacchi static void
1529*1f154020SRobert Mustacchi dis_riscv_c_j(dis_handle_t *dhp, uint32_t instr,
1530*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1531*1f154020SRobert Mustacchi {
1532*1f154020SRobert Mustacchi 	const char *s;
1533*1f154020SRobert Mustacchi 	uint_t jimm = DIS_RISCV_C_J_11(instr) | DIS_RISCV_C_J_10(instr) |
1534*1f154020SRobert Mustacchi 	    DIS_RISCV_C_J_9_8(instr) | DIS_RISCV_C_J_7(instr) |
1535*1f154020SRobert Mustacchi 	    DIS_RISCV_C_J_6(instr) | DIS_RISCV_C_J_5(instr) |
1536*1f154020SRobert Mustacchi 	    DIS_RISCV_C_J_4(instr) | DIS_RISCV_C_J_3_1(instr);
1537*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(jimm, 11, &s);
1538*1f154020SRobert Mustacchi 
1539*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
1540*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s0%o", table->drv_c_name,
1541*1f154020SRobert Mustacchi 		    s, imm);
1542*1f154020SRobert Mustacchi 	} else {
1543*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s0x%x", table->drv_c_name,
1544*1f154020SRobert Mustacchi 		    s, imm);
1545*1f154020SRobert Mustacchi 	}
1546*1f154020SRobert Mustacchi }
1547*1f154020SRobert Mustacchi 
1548*1f154020SRobert Mustacchi /*ARGSUSED*/
1549*1f154020SRobert Mustacchi static void
1550*1f154020SRobert Mustacchi dis_riscv_c_jr(dis_handle_t *dhp, uint32_t instr,
1551*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1552*1f154020SRobert Mustacchi {
1553*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s", table->drv_c_name,
1554*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS1(instr)]);
1555*1f154020SRobert Mustacchi }
1556*1f154020SRobert Mustacchi 
1557*1f154020SRobert Mustacchi static void
1558*1f154020SRobert Mustacchi dis_riscv_c_regimm(dis_handle_t *dhp, const char *instr, const char *dreg,
1559*1f154020SRobert Mustacchi     const char *sign, uint_t imm, char *buf, size_t buflen)
1560*1f154020SRobert Mustacchi {
1561*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
1562*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0%o", instr, dreg,
1563*1f154020SRobert Mustacchi 		    sign, imm);
1564*1f154020SRobert Mustacchi 	} else {
1565*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,%s0x%x", instr, dreg,
1566*1f154020SRobert Mustacchi 		    sign, imm);
1567*1f154020SRobert Mustacchi 	}
1568*1f154020SRobert Mustacchi }
1569*1f154020SRobert Mustacchi 
1570*1f154020SRobert Mustacchi static void
1571*1f154020SRobert Mustacchi dis_riscv_c_branch(dis_handle_t *dhp, uint32_t instr,
1572*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1573*1f154020SRobert Mustacchi {
1574*1f154020SRobert Mustacchi 	const char *s;
1575*1f154020SRobert Mustacchi 	uint_t bimm = DIS_RISCV_C_B_8(instr) | DIS_RISCV_C_B_7_6(instr) |
1576*1f154020SRobert Mustacchi 	    DIS_RISCV_C_B_5(instr) | DIS_RISCV_C_B_4_3(instr) |
1577*1f154020SRobert Mustacchi 	    DIS_RISCV_C_B_2_1(instr);
1578*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(bimm, 8, &s);
1579*1f154020SRobert Mustacchi 
1580*1f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
1581*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)], s, imm, buf, buflen);
1582*1f154020SRobert Mustacchi }
1583*1f154020SRobert Mustacchi 
1584*1f154020SRobert Mustacchi static void
1585*1f154020SRobert Mustacchi dis_riscv_c_bigimmint(dis_handle_t *dhp, uint32_t instr,
1586*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1587*1f154020SRobert Mustacchi {
1588*1f154020SRobert Mustacchi 	const char *s;
1589*1f154020SRobert Mustacchi 	uint_t limm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
1590*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(limm, 5, &s);
1591*1f154020SRobert Mustacchi 
1592*1f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
1593*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], s, imm, buf, buflen);
1594*1f154020SRobert Mustacchi }
1595*1f154020SRobert Mustacchi 
1596*1f154020SRobert Mustacchi static void
1597*1f154020SRobert Mustacchi dis_riscv_c_zext_bigimmint(dis_handle_t *dhp, uint32_t instr,
1598*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1599*1f154020SRobert Mustacchi {
1600*1f154020SRobert Mustacchi 	uint_t imm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
1601*1f154020SRobert Mustacchi 
1602*1f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
1603*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], "", imm, buf, buflen);
1604*1f154020SRobert Mustacchi }
1605*1f154020SRobert Mustacchi 
1606*1f154020SRobert Mustacchi static void
1607*1f154020SRobert Mustacchi dis_riscv_c_addi16sp(dis_handle_t *dhp, uint32_t instr,
1608*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1609*1f154020SRobert Mustacchi {
1610*1f154020SRobert Mustacchi 	const char *s;
1611*1f154020SRobert Mustacchi 	uint_t aimm = DIS_RISCV_C_A16_9(instr) | DIS_RISCV_C_A16_8_7(instr) |
1612*1f154020SRobert Mustacchi 	    DIS_RISCV_C_A16_6(instr) | DIS_RISCV_C_A16_5(instr) |
1613*1f154020SRobert Mustacchi 	    DIS_RISCV_C_A16_4(instr);
1614*1f154020SRobert Mustacchi 	int imm = dis_riscv_sign_extend(aimm, 9, &s);
1615*1f154020SRobert Mustacchi 
1616*1f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
1617*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)], s, imm, buf, buflen);
1618*1f154020SRobert Mustacchi }
1619*1f154020SRobert Mustacchi 
1620*1f154020SRobert Mustacchi static void
1621*1f154020SRobert Mustacchi dis_riscv_c_addi4spn(dis_handle_t *dhp, uint32_t instr,
1622*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1623*1f154020SRobert Mustacchi {
1624*1f154020SRobert Mustacchi 	uint_t imm = DIS_RISCV_C_A4_9_6(instr) | DIS_RISCV_C_A4_5_4(instr) |
1625*1f154020SRobert Mustacchi 	    DIS_RISCV_C_A4_3(instr) | DIS_RISCV_C_A4_2(instr);
1626*1f154020SRobert Mustacchi 
1627*1f154020SRobert Mustacchi 	if ((dhp->dh_flags & DIS_OCTAL) != 0) {
1628*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,sp,0%o",
1629*1f154020SRobert Mustacchi 		    table->drv_c_name, dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
1630*1f154020SRobert Mustacchi 		    imm);
1631*1f154020SRobert Mustacchi 	} else {
1632*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "%s %s,sp,0x%x",
1633*1f154020SRobert Mustacchi 		    table->drv_c_name, dis_riscv_c_regs[DIS_RISCV_C_RDP(instr)],
1634*1f154020SRobert Mustacchi 		    imm);
1635*1f154020SRobert Mustacchi 	}
1636*1f154020SRobert Mustacchi }
1637*1f154020SRobert Mustacchi 
1638*1f154020SRobert Mustacchi static void
1639*1f154020SRobert Mustacchi dis_riscv_c_immint(dis_handle_t *dhp, uint32_t instr,
1640*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1641*1f154020SRobert Mustacchi {
1642*1f154020SRobert Mustacchi 	const char *s;
1643*1f154020SRobert Mustacchi 	uint_t limm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
1644*1f154020SRobert Mustacchi 	uint_t imm = dis_riscv_sign_extend(limm, 5, &s);
1645*1f154020SRobert Mustacchi 
1646*1f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
1647*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)], s, imm, buf, buflen);
1648*1f154020SRobert Mustacchi }
1649*1f154020SRobert Mustacchi 
1650*1f154020SRobert Mustacchi static void
1651*1f154020SRobert Mustacchi dis_riscv_c_zext_immint(dis_handle_t *dhp, uint32_t instr,
1652*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1653*1f154020SRobert Mustacchi {
1654*1f154020SRobert Mustacchi 	uint_t imm = ((instr & 0x1000) >> 7) | ((instr & 0x007c) >> 2);
1655*1f154020SRobert Mustacchi 
1656*1f154020SRobert Mustacchi 	dis_riscv_c_regimm(dhp, table->drv_c_name,
1657*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)], "", imm, buf, buflen);
1658*1f154020SRobert Mustacchi }
1659*1f154020SRobert Mustacchi 
1660*1f154020SRobert Mustacchi /*ARGSUSED*/
1661*1f154020SRobert Mustacchi static void
1662*1f154020SRobert Mustacchi dis_riscv_c_bigint(dis_handle_t *dhp, uint32_t instr,
1663*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1664*1f154020SRobert Mustacchi {
1665*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_c_name,
1666*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RD(instr)],
1667*1f154020SRobert Mustacchi 	    dis_riscv_regs[DIS_RISCV_C_RS2(instr)]);
1668*1f154020SRobert Mustacchi }
1669*1f154020SRobert Mustacchi 
1670*1f154020SRobert Mustacchi 
1671*1f154020SRobert Mustacchi /*ARGSUSED*/
1672*1f154020SRobert Mustacchi static void
1673*1f154020SRobert Mustacchi dis_riscv_c_int(dis_handle_t *dhp, uint32_t instr,
1674*1f154020SRobert Mustacchi     dis_riscv_c_instr_t *table, char *buf, size_t buflen)
1675*1f154020SRobert Mustacchi {
1676*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "%s %s,%s", table->drv_c_name,
1677*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS1P(instr)],
1678*1f154020SRobert Mustacchi 	    dis_riscv_c_regs[DIS_RISCV_C_RS2P(instr)]);
1679*1f154020SRobert Mustacchi }
1680*1f154020SRobert Mustacchi 
1681*1f154020SRobert Mustacchi #define	DIS_RISCV_CFUNCT3(name, class, op, funct, print)		\
1682*1f154020SRobert Mustacchi 	{ name, DIS_RISCV_C_FUNCT3, print, class, op, funct, 0, 0 }
1683*1f154020SRobert Mustacchi #define	DIS_RISCV_CMATCH(name, class, op, funct, mask, match, print) 	\
1684*1f154020SRobert Mustacchi 	{ name, DIS_RISCV_C_MATCH, print, class, op, funct, mask, match }
1685*1f154020SRobert Mustacchi 
1686*1f154020SRobert Mustacchi static dis_riscv_c_instr_t dis_riscv_2byte[] = {
1687*1f154020SRobert Mustacchi 	/* Quadrant 0 */
1688*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.addi4spn", DIS_RISCV_CL_32_64, 0x0, 0x0,
1689*1f154020SRobert Mustacchi 	    dis_riscv_c_addi4spn),
1690*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fld", DIS_RISCV_CL_32_64, 0x0, 0x01,
1691*1f154020SRobert Mustacchi 	    dis_riscv_c_fld),
1692*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.lw", DIS_RISCV_CL_ALL, 0x0, 0x2,
1693*1f154020SRobert Mustacchi 	    dis_riscv_c_lw),
1694*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.flw", DIS_RISCV_CL_32, 0x0, 0x3,
1695*1f154020SRobert Mustacchi 	    dis_riscv_c_flw),
1696*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("f.ld", DIS_RISCV_CL_64_128, 0x0, 0x3,
1697*1f154020SRobert Mustacchi 	    dis_riscv_c_ld),
1698*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fsd", DIS_RISCV_CL_32_64, 0x0, 0x5,
1699*1f154020SRobert Mustacchi 	    dis_riscv_c_fld),
1700*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.sw", DIS_RISCV_CL_ALL, 0x0, 0x6,
1701*1f154020SRobert Mustacchi 	    dis_riscv_c_lw),
1702*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fsw", DIS_RISCV_CL_32, 0x0, 0x7,
1703*1f154020SRobert Mustacchi 	    dis_riscv_c_flw),
1704*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.sd", DIS_RISCV_CL_64_128, 0x0, 0x7,
1705*1f154020SRobert Mustacchi 	    dis_riscv_c_ld),
1706*1f154020SRobert Mustacchi 	/* Quadrant 1 */
1707*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.nop", DIS_RISCV_CL_ALL, 0x01, 0x00, 0x1ffc, 0x0,
1708*1f154020SRobert Mustacchi 	    dis_riscv_c_name),
1709*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.addi", DIS_RISCV_CL_ALL, 0x01, 0x00,
1710*1f154020SRobert Mustacchi 	    dis_riscv_c_bigimmint),
1711*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.jal", DIS_RISCV_CL_32, 0x01, 0x01,
1712*1f154020SRobert Mustacchi 	    dis_riscv_c_j),
1713*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.addiw", DIS_RISCV_CL_64_128, 0x01, 0x01,
1714*1f154020SRobert Mustacchi 	    dis_riscv_c_bigimmint),
1715*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.li", DIS_RISCV_CL_ALL, 0x01, 0x02,
1716*1f154020SRobert Mustacchi 	    dis_riscv_c_bigimmint),
1717*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.addi16sp", DIS_RISCV_CL_ALL, 0x01, 0x03, 0x0f80,
1718*1f154020SRobert Mustacchi 	    0x0100, dis_riscv_c_addi16sp),
1719*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.lui", DIS_RISCV_CL_ALL, 0x01, 0x03,
1720*1f154020SRobert Mustacchi 	    dis_riscv_c_zext_bigimmint),
1721*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.srli", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x0c00, 0x0000,
1722*1f154020SRobert Mustacchi 	    dis_riscv_c_zext_immint),
1723*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.srai", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x0c00, 0x0400,
1724*1f154020SRobert Mustacchi 	    dis_riscv_c_zext_immint),
1725*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.andi", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x0c00, 0x0800,
1726*1f154020SRobert Mustacchi 	    dis_riscv_c_immint),
1727*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.sub", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c00,
1728*1f154020SRobert Mustacchi 	    dis_riscv_c_int),
1729*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.xor", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c20,
1730*1f154020SRobert Mustacchi 	    dis_riscv_c_int),
1731*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.or", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c40,
1732*1f154020SRobert Mustacchi 	    dis_riscv_c_int),
1733*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.and", DIS_RISCV_CL_ALL, 0x1, 0x4, 0x1c60, 0x0c60,
1734*1f154020SRobert Mustacchi 	    dis_riscv_c_int),
1735*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.subw", DIS_RISCV_CL_64_128, 0x1, 0x4, 0x1c60,
1736*1f154020SRobert Mustacchi 	    0x1c00, dis_riscv_c_int),
1737*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.addw", DIS_RISCV_CL_64_128, 0x1, 0x4, 0x1c60,
1738*1f154020SRobert Mustacchi 	    0x1c20, dis_riscv_c_int),
1739*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.j", DIS_RISCV_CL_ALL, 0x1, 0x5,
1740*1f154020SRobert Mustacchi 	    dis_riscv_c_j),
1741*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.beqz", DIS_RISCV_CL_ALL, 0x1, 0x6,
1742*1f154020SRobert Mustacchi 	    dis_riscv_c_branch),
1743*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.bnez", DIS_RISCV_CL_ALL, 0x1, 0x7,
1744*1f154020SRobert Mustacchi 	    dis_riscv_c_branch),
1745*1f154020SRobert Mustacchi 	/* Quadrant 2 */
1746*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.slli", DIS_RISCV_CL_ALL, 0x2, 0x0,
1747*1f154020SRobert Mustacchi 	    dis_riscv_c_zext_bigimmint),
1748*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fldsp", DIS_RISCV_CL_32_64, 0x2, 0x1,
1749*1f154020SRobert Mustacchi 	    dis_riscv_c_fldsp),
1750*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.lwsp", DIS_RISCV_CL_ALL, 0x2, 0x2,
1751*1f154020SRobert Mustacchi 	    dis_riscv_c_lwsp),
1752*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.flwsp", DIS_RISCV_CL_32, 0x2, 0x3,
1753*1f154020SRobert Mustacchi 	    dis_riscv_c_flwsp),
1754*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.ldsp", DIS_RISCV_CL_64_128, 0x2, 0x3,
1755*1f154020SRobert Mustacchi 	    dis_riscv_c_ldsp),
1756*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.jr", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x107c, 0x0,
1757*1f154020SRobert Mustacchi 	    dis_riscv_c_jr),
1758*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.mv", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x1000, 0x0,
1759*1f154020SRobert Mustacchi 	    dis_riscv_c_bigint),
1760*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.ebreak", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x1ffc, 0x1000,
1761*1f154020SRobert Mustacchi 	    dis_riscv_c_name),
1762*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.jalr", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x107c, 0x1000,
1763*1f154020SRobert Mustacchi 	    dis_riscv_c_jr),
1764*1f154020SRobert Mustacchi 	DIS_RISCV_CMATCH("c.add", DIS_RISCV_CL_ALL, 0x2, 0x4, 0x1000, 0x1000,
1765*1f154020SRobert Mustacchi 	    dis_riscv_c_bigint),
1766*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fsdsp", DIS_RISCV_CL_32_64, 0x2, 0x5,
1767*1f154020SRobert Mustacchi 	    dis_riscv_c_fsdsp),
1768*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.swsp", DIS_RISCV_CL_ALL, 0x2, 0x6,
1769*1f154020SRobert Mustacchi 	    dis_riscv_c_swsp),
1770*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.fswsp", DIS_RISCV_CL_32, 0x2, 0x7,
1771*1f154020SRobert Mustacchi 	    dis_riscv_c_fswsp),
1772*1f154020SRobert Mustacchi 	DIS_RISCV_CFUNCT3("c.sdsp", DIS_RISCV_CL_64_128, 0x2, 0x7,
1773*1f154020SRobert Mustacchi 	    dis_riscv_c_sdsp),
1774*1f154020SRobert Mustacchi };
1775*1f154020SRobert Mustacchi 
1776*1f154020SRobert Mustacchi static void
1777*1f154020SRobert Mustacchi dis_riscv_decode_2byte(dis_handle_t *dhp, uint32_t instr, char *buf,
1778*1f154020SRobert Mustacchi     size_t buflen)
1779*1f154020SRobert Mustacchi {
1780*1f154020SRobert Mustacchi 	uint_t i;
1781*1f154020SRobert Mustacchi 
1782*1f154020SRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(dis_riscv_2byte); i++) {
1783*1f154020SRobert Mustacchi 		dis_riscv_c_instr_t *t = &dis_riscv_2byte[i];
1784*1f154020SRobert Mustacchi 		switch (t->drv_c_class) {
1785*1f154020SRobert Mustacchi 		case DIS_RISCV_CL_ALL:
1786*1f154020SRobert Mustacchi 			break;
1787*1f154020SRobert Mustacchi 		case DIS_RISCV_CL_32:
1788*1f154020SRobert Mustacchi 			if ((dhp->dh_flags & DIS_RISCV_32) == 0)
1789*1f154020SRobert Mustacchi 				continue;
1790*1f154020SRobert Mustacchi 			break;
1791*1f154020SRobert Mustacchi 		case DIS_RISCV_CL_64:
1792*1f154020SRobert Mustacchi 			if ((dhp->dh_flags & DIS_RISCV_64) == 0)
1793*1f154020SRobert Mustacchi 				continue;
1794*1f154020SRobert Mustacchi 			break;
1795*1f154020SRobert Mustacchi 		case DIS_RISCV_CL_32_64:
1796*1f154020SRobert Mustacchi 			if ((dhp->dh_flags &
1797*1f154020SRobert Mustacchi 			    (DIS_RISCV_32 | DIS_RISCV_64)) == 0) {
1798*1f154020SRobert Mustacchi 				continue;
1799*1f154020SRobert Mustacchi 			}
1800*1f154020SRobert Mustacchi 			break;
1801*1f154020SRobert Mustacchi 		case DIS_RISCV_CL_64_128:
1802*1f154020SRobert Mustacchi 			if ((dhp->dh_flags & DIS_RISCV_64) == 0)
1803*1f154020SRobert Mustacchi 				continue;
1804*1f154020SRobert Mustacchi 			break;
1805*1f154020SRobert Mustacchi 		}
1806*1f154020SRobert Mustacchi 
1807*1f154020SRobert Mustacchi 		switch (t->drv_c_type) {
1808*1f154020SRobert Mustacchi 		case DIS_RISCV_C_FUNCT3:
1809*1f154020SRobert Mustacchi 			if (DIS_RISCV_C_OPCODE(instr) == t->drv_c_opcode &&
1810*1f154020SRobert Mustacchi 			    DIS_RISCV_C_FUNCT3(instr) == t->drv_c_funct) {
1811*1f154020SRobert Mustacchi 				break;
1812*1f154020SRobert Mustacchi 			}
1813*1f154020SRobert Mustacchi 			continue;
1814*1f154020SRobert Mustacchi 		case DIS_RISCV_C_MATCH:
1815*1f154020SRobert Mustacchi 			if (DIS_RISCV_C_OPCODE(instr) == t->drv_c_opcode &&
1816*1f154020SRobert Mustacchi 			    DIS_RISCV_C_FUNCT3(instr) == t->drv_c_funct &&
1817*1f154020SRobert Mustacchi 			    ((instr & t->drv_c_mask) == t->drv_c_match)) {
1818*1f154020SRobert Mustacchi 				break;
1819*1f154020SRobert Mustacchi 			}
1820*1f154020SRobert Mustacchi 			continue;
1821*1f154020SRobert Mustacchi 		default:
1822*1f154020SRobert Mustacchi 			continue;
1823*1f154020SRobert Mustacchi 		}
1824*1f154020SRobert Mustacchi 
1825*1f154020SRobert Mustacchi 		t->drv_c_print(dhp, instr, t, buf, buflen);
1826*1f154020SRobert Mustacchi 		return;
1827*1f154020SRobert Mustacchi 	}
1828*1f154020SRobert Mustacchi 
1829*1f154020SRobert Mustacchi 	(void) dis_snprintf(buf, buflen, "<unknown>");
1830*1f154020SRobert Mustacchi }
1831*1f154020SRobert Mustacchi 
1832*1f154020SRobert Mustacchi 
1833*1f154020SRobert Mustacchi /*
1834*1f154020SRobert Mustacchi  * RISC-V instructions always come in parcels of two bytes. Read the next two
1835*1f154020SRobert Mustacchi  * byte parcel and advance the address in the handle. Also, take care of endian
1836*1f154020SRobert Mustacchi  * issues if required.
1837*1f154020SRobert Mustacchi  */
1838*1f154020SRobert Mustacchi static int
1839*1f154020SRobert Mustacchi dis_riscv_read_parcel(dis_handle_t *dhp, uint16_t *valp)
1840*1f154020SRobert Mustacchi {
1841*1f154020SRobert Mustacchi 	if ((dhp->dh_addr % 2) != 0)
1842*1f154020SRobert Mustacchi 		return (-1);
1843*1f154020SRobert Mustacchi 
1844*1f154020SRobert Mustacchi 	if (dhp->dh_read(dhp->dh_data, dhp->dh_addr, valp, sizeof (*valp)) !=
1845*1f154020SRobert Mustacchi 	    sizeof (*valp))
1846*1f154020SRobert Mustacchi 		return (-1);
1847*1f154020SRobert Mustacchi 
1848*1f154020SRobert Mustacchi 	*valp = LE_16(*valp);
1849*1f154020SRobert Mustacchi 
1850*1f154020SRobert Mustacchi 	dhp->dh_addr += 2;
1851*1f154020SRobert Mustacchi 
1852*1f154020SRobert Mustacchi 	return (0);
1853*1f154020SRobert Mustacchi }
1854*1f154020SRobert Mustacchi 
1855*1f154020SRobert Mustacchi /*
1856*1f154020SRobert Mustacchi  * The first 'parcel' (uint16_t) of any instruction can be used to determine the
1857*1f154020SRobert Mustacchi  * instruction length. This is derived from Section 1.2 Instruction Length
1858*1f154020SRobert Mustacchi  * Encoding of Volume I: RISC-V User-Level ISA V2.2.
1859*1f154020SRobert Mustacchi  *
1860*1f154020SRobert Mustacchi  *  | xxxxxxxxxxxxxxaa | 16-bit iff aa != 11
1861*1f154020SRobert Mustacchi  *  | xxxxxxxxxxxbbb11 | 32-bit iff bbb != 111
1862*1f154020SRobert Mustacchi  *  | xxxxxxxxxx011111 | 48-bit iff bbb != 111
1863*1f154020SRobert Mustacchi  *  | xxxxxxxxx0111111 | 64-bit iff bbb != 111
1864*1f154020SRobert Mustacchi  *  | xnnnxxxxx1111111 | (80 + 16*nnn)-bit iff nnn != 111
1865*1f154020SRobert Mustacchi  */
1866*1f154020SRobert Mustacchi #define	RISCV_LEN_16_MASK	0x0003
1867*1f154020SRobert Mustacchi #define	RISCV_LEN_32_MASK	0x001c
1868*1f154020SRobert Mustacchi #define	RISCV_LEN_48_MASK	0x0020
1869*1f154020SRobert Mustacchi #define	RISCV_LEN_64_MASK	0x0040
1870*1f154020SRobert Mustacchi #define	RISCV_LEN_80_MASK	0x7000
1871*1f154020SRobert Mustacchi #define	RISCV_LEN_80_SHIFT	12
1872*1f154020SRobert Mustacchi 
1873*1f154020SRobert Mustacchi static int
1874*1f154020SRobert Mustacchi dis_riscv_decode_len(uint16_t instr)
1875*1f154020SRobert Mustacchi {
1876*1f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_16_MASK) != RISCV_LEN_16_MASK)
1877*1f154020SRobert Mustacchi 		return (2);
1878*1f154020SRobert Mustacchi 
1879*1f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_32_MASK) != RISCV_LEN_32_MASK)
1880*1f154020SRobert Mustacchi 		return (4);
1881*1f154020SRobert Mustacchi 
1882*1f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_48_MASK) != RISCV_LEN_48_MASK)
1883*1f154020SRobert Mustacchi 		return (6);
1884*1f154020SRobert Mustacchi 
1885*1f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_64_MASK) != RISCV_LEN_64_MASK)
1886*1f154020SRobert Mustacchi 		return (8);
1887*1f154020SRobert Mustacchi 
1888*1f154020SRobert Mustacchi 	if ((instr & RISCV_LEN_80_MASK) != RISCV_LEN_80_MASK) {
1889*1f154020SRobert Mustacchi 		uint_t factor = (instr & RISCV_LEN_80_MASK) >>
1890*1f154020SRobert Mustacchi 		    RISCV_LEN_80_SHIFT;
1891*1f154020SRobert Mustacchi 		return ((10 + 2 * factor));
1892*1f154020SRobert Mustacchi 	}
1893*1f154020SRobert Mustacchi 
1894*1f154020SRobert Mustacchi 	return (-1);
1895*1f154020SRobert Mustacchi }
1896*1f154020SRobert Mustacchi 
1897*1f154020SRobert Mustacchi static int
1898*1f154020SRobert Mustacchi dis_riscv_supports_flags(int flags)
1899*1f154020SRobert Mustacchi {
1900*1f154020SRobert Mustacchi 	int archflags = flags & DIS_ARCH_MASK;
1901*1f154020SRobert Mustacchi 
1902*1f154020SRobert Mustacchi 	return (archflags == DIS_RISCV_32 || archflags == DIS_RISCV_64);
1903*1f154020SRobert Mustacchi }
1904*1f154020SRobert Mustacchi 
1905*1f154020SRobert Mustacchi static int
1906*1f154020SRobert Mustacchi dis_riscv_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
1907*1f154020SRobert Mustacchi     size_t buflen)
1908*1f154020SRobert Mustacchi {
1909*1f154020SRobert Mustacchi 	int len;
1910*1f154020SRobert Mustacchi 	uint16_t parcel;
1911*1f154020SRobert Mustacchi 	uint32_t instr;
1912*1f154020SRobert Mustacchi 
1913*1f154020SRobert Mustacchi 
1914*1f154020SRobert Mustacchi 	dhp->dh_addr = addr;
1915*1f154020SRobert Mustacchi 
1916*1f154020SRobert Mustacchi 	/*
1917*1f154020SRobert Mustacchi 	 * All instructions have to be 2-byte aligned. Most have to be four byte
1918*1f154020SRobert Mustacchi 	 * aligned, but we determine that after we decode the instruction size.
1919*1f154020SRobert Mustacchi 	 * The 2-byte alignment check is done when we read the parcel.
1920*1f154020SRobert Mustacchi 	 */
1921*1f154020SRobert Mustacchi 	if (dis_riscv_read_parcel(dhp, &parcel) != 0)
1922*1f154020SRobert Mustacchi 		return (-1);
1923*1f154020SRobert Mustacchi 
1924*1f154020SRobert Mustacchi 	len = dis_riscv_decode_len(parcel);
1925*1f154020SRobert Mustacchi 	if (len < 2 || (len % 2) != 0)
1926*1f154020SRobert Mustacchi 		return (-1);
1927*1f154020SRobert Mustacchi 	switch (len) {
1928*1f154020SRobert Mustacchi 	case 2:
1929*1f154020SRobert Mustacchi 		instr = parcel;
1930*1f154020SRobert Mustacchi 		dis_riscv_decode_2byte(dhp, instr, buf, buflen);
1931*1f154020SRobert Mustacchi 		break;
1932*1f154020SRobert Mustacchi 	case 4:
1933*1f154020SRobert Mustacchi 		instr = parcel;
1934*1f154020SRobert Mustacchi 		if (dis_riscv_read_parcel(dhp, &parcel) != 0)
1935*1f154020SRobert Mustacchi 			return (-1);
1936*1f154020SRobert Mustacchi 		instr |= parcel << 16;
1937*1f154020SRobert Mustacchi 		dis_riscv_decode_4byte(dhp, instr, buf, buflen);
1938*1f154020SRobert Mustacchi 		break;
1939*1f154020SRobert Mustacchi 	default:
1940*1f154020SRobert Mustacchi 		/*
1941*1f154020SRobert Mustacchi 		 * This case represents a valid instruction length, but
1942*1f154020SRobert Mustacchi 		 * something we don't understand. Treat this as an unknown
1943*1f154020SRobert Mustacchi 		 * instruction. However, read the rest of the length of the
1944*1f154020SRobert Mustacchi 		 * instruction to make sure that we read things correctly.
1945*1f154020SRobert Mustacchi 		 */
1946*1f154020SRobert Mustacchi 		(void) dis_snprintf(buf, buflen, "<unknown>");
1947*1f154020SRobert Mustacchi 		for (; len > 0; len -= 2) {
1948*1f154020SRobert Mustacchi 			if (dis_riscv_read_parcel(dhp, &parcel) != 0) {
1949*1f154020SRobert Mustacchi 				return (-1);
1950*1f154020SRobert Mustacchi 			}
1951*1f154020SRobert Mustacchi 		}
1952*1f154020SRobert Mustacchi 		break;
1953*1f154020SRobert Mustacchi 	}
1954*1f154020SRobert Mustacchi 
1955*1f154020SRobert Mustacchi 	return (0);
1956*1f154020SRobert Mustacchi }
1957*1f154020SRobert Mustacchi 
1958*1f154020SRobert Mustacchi /*ARGSUSED*/
1959*1f154020SRobert Mustacchi static int
1960*1f154020SRobert Mustacchi dis_riscv_min_instrlen(dis_handle_t *dhp)
1961*1f154020SRobert Mustacchi {
1962*1f154020SRobert Mustacchi 	return (2);
1963*1f154020SRobert Mustacchi }
1964*1f154020SRobert Mustacchi 
1965*1f154020SRobert Mustacchi /*ARGSUSED*/
1966*1f154020SRobert Mustacchi static int
1967*1f154020SRobert Mustacchi dis_riscv_max_instrlen(dis_handle_t *dhp)
1968*1f154020SRobert Mustacchi {
1969*1f154020SRobert Mustacchi 	return (22);
1970*1f154020SRobert Mustacchi }
1971*1f154020SRobert Mustacchi 
1972*1f154020SRobert Mustacchi static int
1973*1f154020SRobert Mustacchi dis_riscv_instrlen(dis_handle_t *dhp, uint64_t addr)
1974*1f154020SRobert Mustacchi {
1975*1f154020SRobert Mustacchi 	int ret;
1976*1f154020SRobert Mustacchi 	uint16_t parcel;
1977*1f154020SRobert Mustacchi 
1978*1f154020SRobert Mustacchi 	dhp->dh_addr = addr;
1979*1f154020SRobert Mustacchi 
1980*1f154020SRobert Mustacchi 	if (dis_riscv_read_parcel(dhp, &parcel) != 0)
1981*1f154020SRobert Mustacchi 		return (-1);
1982*1f154020SRobert Mustacchi 
1983*1f154020SRobert Mustacchi 	/*
1984*1f154020SRobert Mustacchi 	 * Get length based on this parcel. Check for required alignment. 2-byte
1985*1f154020SRobert Mustacchi 	 * alignment was already taken care of when we read the parcel.
1986*1f154020SRobert Mustacchi 	 */
1987*1f154020SRobert Mustacchi 	ret = dis_riscv_decode_len(parcel);
1988*1f154020SRobert Mustacchi 	if (ret >= 4 && (addr % 4) != 0)
1989*1f154020SRobert Mustacchi 		return (-1);
1990*1f154020SRobert Mustacchi 
1991*1f154020SRobert Mustacchi 	return (ret);
1992*1f154020SRobert Mustacchi }
1993*1f154020SRobert Mustacchi 
1994*1f154020SRobert Mustacchi dis_arch_t dis_arch_riscv = {
1995*1f154020SRobert Mustacchi 	.da_supports_flags = dis_riscv_supports_flags,
1996*1f154020SRobert Mustacchi 	.da_disassemble = dis_riscv_disassemble,
1997*1f154020SRobert Mustacchi 	.da_min_instrlen = dis_riscv_min_instrlen,
1998*1f154020SRobert Mustacchi 	.da_max_instrlen = dis_riscv_max_instrlen,
1999*1f154020SRobert Mustacchi 	.da_instrlen = dis_riscv_instrlen
2000*1f154020SRobert Mustacchi };
2001