2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (c) 2018, Joyent, Inc.
17 * RISC-V Instruction set decoder
20 #include <libdisasm.h>
21 #include <sys/byteorder.h>
22 #include <sys/debug.h>
24 #include "libdisasm_impl.h"
28 extern int strcmp(const char *, const char *);
31 * Register names based on their ABI name.
33 static const char *dis_riscv_regs
[32] = {
34 "x0", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
35 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
36 "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
37 "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
40 static const char *dis_riscv_fpregs
[32] = {
41 "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
42 "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
43 "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
44 "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
47 static const char *dis_riscv_c_regs
[8] = {
48 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5"
51 static const char *dis_riscv_c_fpregs
[8] = {
52 "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5"
56 * RM names have the leading comma in them because the last value represents
57 * that the hardware register decides the rounding mode and therefore nothing
58 * should be appended to the instruction.
60 static const char *dis_riscv_rm
[8] = {
61 ",rne", ",rtz", ",rdn", ",rup", ",rmm", ",???", ",???", ""
64 typedef struct dis_riscv_csr
{
70 * The current set of CSR names as per Table 2.2-2.5 from RISC-V Privileged
71 * Architectures V1.10. These include all of the ones in the User-Level ISA.
72 * These are ordered per the doc.
74 static dis_riscv_csr_t dis_riscv_csr_map
[] = {
76 { 0x000, "ustatus" }, { 0x004, "uie" }, { 0x005, "utvec" },
77 /* User Trap Handling */
78 { 0x040, "uscratch" }, { 0x041, "uepc" }, { 0x042, "ucause" },
79 { 0x043, "utval" }, { 0x044, "uip" },
80 /* User Floating-Point CSRs */
81 { 0x001, "fflags" }, { 0x002, "frm" }, { 0x003, "fcsr" },
82 /* User Counters/Timers */
83 { 0xc00, "cycle" }, { 0xc01, "time" }, { 0xc02, "instret" },
84 { 0xc03, "hpmcounter3" }, { 0xc04, "hpmcounter4" },
85 { 0xc05, "hpmcounter5" }, { 0xc06, "hpmcounter6" },
86 { 0xc07, "hpmcounter7" }, { 0xc08, "hpmcounter8" },
87 { 0xc09, "hpmcounter9" }, { 0xc0a, "hpmcounter10" },
88 { 0xc0b, "hpmcounter11" }, { 0xc0c, "hpmcounter12" },
89 { 0xc0d, "hpmcounter13" }, { 0xc0e, "hpmcounter14" },
90 { 0xc0f, "hpmcounter15" }, { 0xc10, "hpmcounter16" },
91 { 0xc11, "hpmcounter17" }, { 0xc12, "hpmcounter18" },
92 { 0xc13, "hpmcounter19" }, { 0xc14, "hpmcounter20" },
93 { 0xc15, "hpmcounter21" }, { 0xc16, "hpmcounter22" },
94 { 0xc17, "hpmcounter23" }, { 0xc18, "hpmcounter24" },
95 { 0xc19, "hpmcounter25" }, { 0xc1a, "hpmcounter26" },
96 { 0xc1b, "hpmcounter27" }, { 0xc1c, "hpmcounter28" },
97 { 0xc1d, "hpmcounter29" }, { 0xc1e, "hpmcounter30" },
98 { 0xc1f, "hpmcounter31" },
99 { 0xc80, "cycleh" }, { 0xc81, "timeh" }, { 0xc82, "instreth" },
100 { 0xc83, "hpmcounter3h" }, { 0xc84, "hpmcounter4h" },
101 { 0xc85, "hpmcounter5h" }, { 0xc86, "hpmcounter6h" },
102 { 0xc87, "hpmcounter7h" }, { 0xc88, "hpmcounter8h" },
103 { 0xc89, "hpmcounter9h" }, { 0xc8a, "hpmcounter10h" },
104 { 0xc8b, "hpmcounter11h" }, { 0xc8c, "hpmcounter12h" },
105 { 0xc8d, "hpmcounter13h" }, { 0xc8e, "hpmcounter14h" },
106 { 0xc8f, "hpmcounter15h" }, { 0xc90, "hpmcounter16h" },
107 { 0xc91, "hpmcounter17h" }, { 0xc92, "hpmcounter18h" },
108 { 0xc93, "hpmcounter19h" }, { 0xc94, "hpmcounter20h" },
109 { 0xc95, "hpmcounter21h" }, { 0xc96, "hpmcounter22h" },
110 { 0xc97, "hpmcounter23h" }, { 0xc98, "hpmcounter24h" },
111 { 0xc99, "hpmcounter25h" }, { 0xc9a, "hpmcounter26h" },
112 { 0xc9b, "hpmcounter27h" }, { 0xc9c, "hpmcounter28h" },
113 { 0xc9d, "hpmcounter29h" }, { 0xc9e, "hpmcounter30h" },
114 { 0xc9f, "hpmcounter31h" },
115 /* Supervisor Trap Status */
116 { 0x100, "sstatus" }, { 0x102, "sedeleg" }, { 0x103, "sideleg" },
117 { 0x104, "sie" }, { 0x105, "stvec" }, { 0x106, "scounteren" },
118 /* Supervisor Trap Handling */
119 { 0x140, "sscratch" }, { 0x141, "sepc" }, { 0x142, "scause" },
120 { 0x143, "stval" }, { 0x144, "sip" },
121 /* Supervisor Protection and Translation */
123 /* Machine Information Registers */
124 { 0xf11, "mvendorid" }, { 0xf12, "marchid" },
125 { 0xf13, "mimpid" }, { 0xf14, "mhartid" },
126 /* Machine Trap Setup */
127 { 0x300, "mstatus" }, { 0x301, "misa" }, { 0x302, "medeleg" },
128 { 0x303, "mideleg" }, { 0x304, "mie" }, { 0x305, "mtvec" },
129 { 0x306, "mcounteren" },
130 /* Machine Trap Handling */
131 { 0x340, "mscratch" }, { 0x341, "mepc" }, { 0x342, "mcause" },
132 { 0x343, "mtval" }, { 0x344, "mip" },
133 /* Machine Protection and Translation */
134 { 0x3a0, "pmpcfg0" }, { 0x3a1, "pmpcfg1" },
135 { 0x3a2, "pmpcfg2" }, { 0x3a3, "pmpcfg3" },
136 { 0x3b0, "pmpaddr0" }, { 0x3b1, "pmpaddr1" },
137 { 0x3b2, "pmpaddr2" }, { 0x3b3, "pmpaddr3" },
138 { 0x3b4, "pmpaddr4" }, { 0x3b5, "pmpaddr5" },
139 { 0x3b6, "pmpaddr6" }, { 0x3b7, "pmpaddr7" },
140 { 0x3b8, "pmpaddr8" }, { 0x3b9, "pmpaddr9" },
141 { 0x3ba, "pmpaddr10" }, { 0x3bb, "pmpaddr11" },
142 { 0x3bc, "pmpaddr12" }, { 0x3bd, "pmpaddr13" },
143 { 0x3be, "pmpaddr14" }, { 0x3bf, "pmpaddr15" }
146 typedef enum dis_riscv_csr_alias_type
{
148 DIS_RISCV_CSR_READ_GEN
,
150 DIS_RISCV_CSR_SWAP_IMM
,
152 DIS_RISCV_CSR_WRITE_GEN
,
153 DIS_RISCV_CSR_WRITE_IMM
,
154 DIS_RISCV_CSR_WRITE_IMM_GEN
155 } dis_riscv_csr_alias_type_t
;
157 typedef struct dis_riscv_csr_alias
{
158 const char *drca_alias
;
159 dis_riscv_csr_alias_type_t drca_type
;
160 const char *drca_base
;
161 const char *drca_csr
;
164 } dis_riscv_csr_alias_t
;
167 * Table of aliases. A NULL or -1 indicates a don't care.
169 static dis_riscv_csr_alias_t dis_riscv_csr_alias
[] = {
170 { "rdinstret", DIS_RISCV_CSR_READ
, "csrrs", "instret", -1, 0 },
171 { "rdinstreth", DIS_RISCV_CSR_READ
, "csrrs", "instreth", -1, 0 },
172 { "rdcycle", DIS_RISCV_CSR_READ
, "csrrs", "cycle", -1, 0 },
173 { "rdcycleh", DIS_RISCV_CSR_READ
, "csrrs", "cycleh", -1, 0 },
174 { "rdtime", DIS_RISCV_CSR_READ
, "csrrs", "time", -1, 0 },
175 { "rdtimeh", DIS_RISCV_CSR_READ
, "csrrs", "timeh", -1, 0 },
176 { "frcsr", DIS_RISCV_CSR_READ
, "csrrs", "fcsr", -1, 0 },
177 { "fscsr", DIS_RISCV_CSR_WRITE
, "csrrw", "fcsr", 0, -1 },
178 { "fscsr", DIS_RISCV_CSR_SWAP
, "csrrw", "fcsr", -1, -1 },
179 { "frrm", DIS_RISCV_CSR_READ
, "csrrs", "frm", -1, 0 },
180 { "fsrm", DIS_RISCV_CSR_WRITE
, "csrrw", "frm", 0, -1 },
181 { "fsrm", DIS_RISCV_CSR_SWAP
, "csrrw", "frm", -1, -1 },
182 { "fsrmi", DIS_RISCV_CSR_WRITE_IMM
, "csrrwi", "frm", 0, -1 },
183 { "fsrmi", DIS_RISCV_CSR_SWAP_IMM
, "csrrwi", "frm", -1, -1 },
184 { "frflags", DIS_RISCV_CSR_READ
, "csrrs", "fflags", -1, 0 },
185 { "fsflags", DIS_RISCV_CSR_WRITE
, "csrrw", "fflags", 0, -1 },
186 { "fsflags", DIS_RISCV_CSR_SWAP
, "csrrw", "fflags", -1, -1 },
187 { "fsflagsi", DIS_RISCV_CSR_WRITE_IMM
, "csrrwi", "fflags", 0, -1 },
188 { "fsflagsi", DIS_RISCV_CSR_SWAP_IMM
, "csrrwi", "fflags", -1, -1 },
190 * These are the generic aliases that aren't based on the CSR. Keep
193 { "csrr", DIS_RISCV_CSR_READ_GEN
, "csrrs", NULL
, -1, 0 },
194 { "csrw", DIS_RISCV_CSR_WRITE_GEN
, "csrrw", NULL
, 0, -1 },
195 { "csrs", DIS_RISCV_CSR_WRITE_GEN
, "csrrs", NULL
, 0, -1 },
196 { "csrc", DIS_RISCV_CSR_WRITE_GEN
, "csrrc", NULL
, 0, -1 },
197 { "csrwi", DIS_RISCV_CSR_WRITE_IMM_GEN
, "csrrwi", NULL
, 0, -1 },
198 { "csrsi", DIS_RISCV_CSR_WRITE_IMM_GEN
, "csrrsi", NULL
, 0, -1 },
199 { "csrci", DIS_RISCV_CSR_WRITE_IMM_GEN
, "csrrci", NULL
, 0, -1 },
203 * Take an n-bit value whose sign bit is indicated by the big sign and convert
207 dis_riscv_sign_extend(uint_t val
, uint_t sbit
, const char **sign
)
209 VERIFY3U(sbit
, <=, 31);
211 if (val
>= 1 << sbit
) {
213 return ((1 << (sbit
+ 1)) - val
);
221 * Four byte decode tables. This is derived from the RV32/64G Instruction Set
222 * Listings. We describe a table entry based on the opcode and optional opcodes
223 * based on the type of instruction that it is and its encoding format. Most
224 * sets of instructions have one of several uniform encoding types.
226 * 31 25 24 20 19 15 14 12 11 7 6 0
227 * | funct7 | r2 | rs1 | funct3 | rd | opcode | R-type
228 * | imm[11:0] | rs1 | funct3 | rd | opcode | I-type
229 * | imm[11:5] | r2 | rs1 | funct3 | imm[4:0] | opcode | S-type
230 * | imm[12|10:5] | r2 | rs1 | funct3 | imm[4:1|11] | opcode | B-type
231 * | imm[31:12] | rd | opcode | U-type
232 * | imm[10|10:1|11|19:12] | rd | opcode | J-type
234 typedef enum dis_riscv_itype
{
243 * This is a variant of the standard R type where the first bit of
244 * funct7 is actually used for this shift.
246 DIS_RISCV_I_SHIFT64_TYPE
,
248 * This type isn't explicitly defined in the ISA doc; however, it is a
249 * standard format that is for all of the Atomic class instructions.
250 * This is treated like an R-type, except the funct7 is really a funct5.
251 * The load variant is similar; however, rs2 must be zero.
253 DIS_RISCV_I_RV32A_TYPE
,
254 DIS_RISCV_I_RV32A_LOAD_TYPE
,
256 * This is a custom type we've defined where the first value is the
257 * instruction mask and the second value is the value of the bits in it.
258 * This is used for a few irregular instructions ala FENCE and ECALL.
260 DIS_RISCV_I_MASK_TYPE
,
262 * This type is used for FP arguments that use rs2 as an opcode.
264 DIS_RISCV_I_FP_RS2OP_TYPE
,
266 * This type uses the opcode and funct7 and uses funct3 as a rounding
269 DIS_RISCV_I_FP_RM_TYPE
,
271 * This fp type uses the opcode, funct7, funct3, and rs2 as an op type.
273 DIS_RISCV_I_FP_R_RS2_TYPE
,
276 #define DIS_RISCV_OPCODE(x) ((x) & 0x7f)
277 #define DIS_RISCV_FUNCT3(x) (((x) >> 12) & 0x7)
278 #define DIS_RISCV_FUNCT7(x) (((x) >> 25) & 0x7f)
279 #define DIS_RISCV_RD(x) (((x) >> 7) & 0x1f)
280 #define DIS_RISCV_RS1(x) (((x) >> 15) & 0x1f)
281 #define DIS_RISCV_RS2(x) (((x) >> 20) & 0x1f)
282 #define DIS_RISCV_FP_RS3(x) (((x) >> 27) & 0x1f)
283 #define DIS_RISCV_FUNCT2(x) (((x) >> 25) & 0x03)
286 * SHIFT funct7 variant.
288 #define DIS_RISCV_SFUNCT7(x) (((x) >> 26) & 0x3f)
290 #define DIS_RISCV_UIMM(x) (((x) >> 12) & 0xfffff)
292 #define DIS_RISCV_IIMM(x) (((x) >> 20) & 0xfff)
294 #define DIS_RISCV_BIMM_12(x) (((x) >> 19) & 0x1000)
295 #define DIS_RISCV_BIMM_11(x) (((x) & 0x80) << 4)
296 #define DIS_RISCV_BIMM_10_5(x) (((x) >> 20) & 0x7e0)
297 #define DIS_RISCV_BIMM_4_1(x) (((x) >> 7) & 0x1e)
299 #define DIS_RISCV_SIMM_UP(x) ((((x) >> 25) & 0x7f) << 5)
300 #define DIS_RISCV_SIMM_LOW(x) (((x) >> 7) & 0x1f)
302 #define DIS_RISCV_JIMM_20(x) (((x) & 0x80000000) >> 11)
303 #define DIS_RISCV_JIMM_19_12(x) ((x) & 0xff000)
304 #define DIS_RISCV_JIMM_11(x) (((x) & 100000) >> 9)
305 #define DIS_RISCV_JIMM_10_1(x) (((x) & 0x7fe00000) >> 20)
307 #define DIS_RISCV_RVA_FUNCT5(x) (((x) >> 27) & 0x1f)
308 #define DIS_RISCV_RVA_AQ(x) (((x) >> 26) & 0x1)
309 #define DIS_RISCV_RVA_RL(x) (((x) >> 25) & 0x1)
311 struct dis_riscv_instr
;
312 typedef void (*dis_riscv_func_t
)(dis_handle_t
*, uint32_t,
313 struct dis_riscv_instr
*, char *, size_t);
315 typedef struct dis_riscv_instr
{
316 const char *drv_name
;
317 dis_riscv_itype_t drv_type
;
318 dis_riscv_func_t drv_print
;
327 dis_riscv_rtype_32(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
328 char *buf
, size_t buflen
)
330 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s", table
->drv_name
,
331 dis_riscv_regs
[DIS_RISCV_RD(instr
)],
332 dis_riscv_regs
[DIS_RISCV_RS1(instr
)],
333 dis_riscv_regs
[DIS_RISCV_RS2(instr
)]);
337 dis_riscv_itype_32(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
338 char *buf
, size_t buflen
)
341 uint_t imm
= dis_riscv_sign_extend(DIS_RISCV_IIMM(instr
), 11, &s
);
343 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
344 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s0%o",
345 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
346 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], s
, imm
);
348 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s0x%x",
349 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
350 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], s
, imm
);
355 dis_riscv_btype_32(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
356 char *buf
, size_t buflen
)
359 uint_t bimm
= DIS_RISCV_BIMM_12(instr
) | DIS_RISCV_BIMM_11(instr
) |
360 DIS_RISCV_BIMM_10_5(instr
) | DIS_RISCV_BIMM_4_1(instr
);
361 uint_t imm
= dis_riscv_sign_extend(bimm
, 12, &s
);
363 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
364 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s0%o",
365 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
366 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], s
, imm
);
368 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s0x%x",
369 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
370 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], s
, imm
);
375 dis_riscv_load(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
376 char *buf
, size_t buflen
)
379 uint_t imm
= dis_riscv_sign_extend(DIS_RISCV_IIMM(instr
), 11, &s
);
381 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
382 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0%o(%s)",
383 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
384 s
, imm
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
386 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0x%x(%s)",
387 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
388 s
, imm
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
393 dis_riscv_stype_32(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
394 char *buf
, size_t buflen
)
397 uint_t simm
= DIS_RISCV_SIMM_UP(instr
) | DIS_RISCV_SIMM_LOW(instr
);
398 uint_t val
= dis_riscv_sign_extend(simm
, 11, &s
);
400 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
401 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0%o(%s)",
402 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RS2(instr
)],
403 s
, val
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
405 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0x%x(%s)",
406 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RS2(instr
)],
407 s
, val
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
413 dis_riscv_utype_32(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
414 char *buf
, size_t buflen
)
416 (void) dis_snprintf(buf
, buflen
, "%s %s,0x%x", table
->drv_name
,
417 dis_riscv_regs
[DIS_RISCV_RD(instr
)], DIS_RISCV_UIMM(instr
));
421 dis_riscv_jtype_32(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
422 char *buf
, size_t buflen
)
425 uint_t jimm
= DIS_RISCV_JIMM_20(instr
) | DIS_RISCV_JIMM_19_12(instr
) |
426 DIS_RISCV_JIMM_11(instr
) | DIS_RISCV_JIMM_10_1(instr
);
427 uint_t imm
= dis_riscv_sign_extend(jimm
, 20, &s
);
429 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
430 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0%o",
431 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
434 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0x%x",
435 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
441 * The shift instructions are a variant on the R-type instructions where RS2 is
442 * an immediate to perform the shift by as opposed to a register.
445 dis_riscv_shift_32(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
446 char *buf
, size_t buflen
)
448 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
449 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,0%o",
450 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
451 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], DIS_RISCV_RS2(instr
));
453 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,0x%x",
454 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
455 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], DIS_RISCV_RS2(instr
));
460 * The 64-bit version of shift instructions steals an extra bit from funct7 to
461 * construct the shift amount.
464 dis_riscv_shift_64(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
465 char *buf
, size_t buflen
)
467 uint_t shift
= DIS_RISCV_RS2(instr
) | ((instr
& (1UL << 25)) >> 20);
468 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
469 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,0%o",
470 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
471 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], shift
);
473 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,0x%x",
474 table
->drv_name
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
475 dis_riscv_regs
[DIS_RISCV_RS1(instr
)], shift
);
481 dis_riscv_csr(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
482 char *buf
, size_t buflen
)
484 uint_t rd
, csr
, rs
, i
;
485 const char *csrstr
= NULL
;
487 dis_riscv_csr_alias_t
*alias
= NULL
;
489 rd
= DIS_RISCV_RD(instr
);
490 rs
= DIS_RISCV_RS1(instr
);
491 csr
= DIS_RISCV_IIMM(instr
);
493 for (i
= 0; i
< ARRAY_SIZE(dis_riscv_csr_map
); i
++) {
494 if (csr
== dis_riscv_csr_map
[i
].drc_val
) {
495 csrstr
= dis_riscv_csr_map
[i
].drc_name
;
500 if (csrstr
== NULL
) {
501 (void) dis_snprintf(csrval
, sizeof (csrval
), "0x%x", csr
);
505 for (i
= 0; i
< ARRAY_SIZE(dis_riscv_csr_alias
); i
++) {
506 dis_riscv_csr_alias_t
*a
= &dis_riscv_csr_alias
[i
];
507 if (strcmp(a
->drca_base
, table
->drv_name
) != 0)
509 if (a
->drca_csr
!= NULL
&& strcmp(a
->drca_csr
, csrstr
) != 0)
511 if (a
->drca_rd
!= -1 && a
->drca_rd
!= rd
)
513 if (a
->drca_rs
!= -1 && a
->drca_rs
!= rs
)
520 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s", table
->drv_name
,
521 dis_riscv_regs
[rd
], csrstr
, dis_riscv_regs
[rs
]);
525 switch (alias
->drca_type
) {
526 case DIS_RISCV_CSR_READ
:
527 (void) dis_snprintf(buf
, buflen
, "%s %s", alias
->drca_alias
,
530 case DIS_RISCV_CSR_READ_GEN
:
531 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", alias
->drca_alias
,
532 dis_riscv_regs
[rd
], csrstr
);
534 case DIS_RISCV_CSR_SWAP
:
535 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", alias
->drca_alias
,
536 dis_riscv_regs
[rd
], dis_riscv_regs
[rs
]);
538 case DIS_RISCV_CSR_WRITE
:
539 (void) dis_snprintf(buf
, buflen
, "%s %s", alias
->drca_alias
,
542 case DIS_RISCV_CSR_WRITE_GEN
:
543 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", alias
->drca_alias
,
544 csrstr
, dis_riscv_regs
[rs
]);
547 (void) dis_snprintf(buf
, buflen
, "<unknown>");
553 dis_riscv_csri(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
554 char *buf
, size_t buflen
)
556 uint_t rd
, csr
, imm
, i
;
557 const char *csrstr
= NULL
;
559 dis_riscv_csr_alias_t
*alias
= NULL
;
561 rd
= DIS_RISCV_RD(instr
);
562 imm
= DIS_RISCV_RS1(instr
);
563 csr
= DIS_RISCV_IIMM(instr
);
565 for (i
= 0; i
< ARRAY_SIZE(dis_riscv_csr_map
); i
++) {
566 if (csr
== dis_riscv_csr_map
[i
].drc_val
) {
567 csrstr
= dis_riscv_csr_map
[i
].drc_name
;
572 if (csrstr
== NULL
) {
573 (void) dis_snprintf(csrval
, sizeof (csrval
), "0x%x", csr
);
577 for (i
= 0; i
< ARRAY_SIZE(dis_riscv_csr_alias
); i
++) {
578 dis_riscv_csr_alias_t
*a
= &dis_riscv_csr_alias
[i
];
579 if (strcmp(a
->drca_base
, table
->drv_name
) != 0)
581 if (a
->drca_csr
!= NULL
&& strcmp(a
->drca_csr
, csrstr
) != 0)
583 if (a
->drca_rd
!= -1 && a
->drca_rd
!= rd
)
585 if (a
->drca_rs
!= -1)
592 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
593 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,0%o",
594 table
->drv_name
, dis_riscv_regs
[rd
], csrstr
, imm
);
596 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,0x%x",
597 table
->drv_name
, dis_riscv_regs
[rd
], csrstr
, imm
);
602 switch (alias
->drca_type
) {
603 case DIS_RISCV_CSR_SWAP_IMM
:
604 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
605 (void) dis_snprintf(buf
, buflen
, "%s %s,0%o",
606 alias
->drca_alias
, dis_riscv_regs
[rd
], imm
);
608 (void) dis_snprintf(buf
, buflen
, "%s %s,0x%x",
609 alias
->drca_alias
, dis_riscv_regs
[rd
], imm
);
612 case DIS_RISCV_CSR_WRITE_IMM
:
613 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
614 (void) dis_snprintf(buf
, buflen
, "%s 0%o",
615 alias
->drca_alias
, imm
);
617 (void) dis_snprintf(buf
, buflen
, "%s 0x%x",
618 alias
->drca_alias
, imm
);
621 case DIS_RISCV_CSR_WRITE_IMM_GEN
:
622 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
623 (void) dis_snprintf(buf
, buflen
, "%s %s,0%o",
624 alias
->drca_alias
, csrstr
, imm
);
626 (void) dis_snprintf(buf
, buflen
, "%s %s,0x%x",
627 alias
->drca_alias
, csrstr
, imm
);
631 (void) dis_snprintf(buf
, buflen
, "<unknown>");
636 #define DIS_RISCV_FENCE_PRED(x) (((x) >> 24) & 0xf)
637 #define DIS_RISCV_FENCE_SUCC(x) (((x) >> 20) & 0xf)
638 #define DIS_RISCV_FENCE_I 0x8
639 #define DIS_RISCV_FENCE_O 0x4
640 #define DIS_RISCV_FENCE_R 0x2
641 #define DIS_RISCV_FENCE_W 0x1
642 #define DIS_RISCV_FENCE_IORW 0xf
646 dis_riscv_fence(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
647 char *buf
, size_t buflen
)
651 pred
= DIS_RISCV_FENCE_PRED(instr
);
652 succ
= DIS_RISCV_FENCE_SUCC(instr
);
655 * If both halves are iorw that is aliased to just an empty fence
656 * instruction per Chapter 20 - RISC-V Assembly Programmer's Handbook in
657 * the RISC-V user spec.
659 if (pred
== DIS_RISCV_FENCE_IORW
&& succ
== DIS_RISCV_FENCE_IORW
) {
660 (void) dis_snprintf(buf
, buflen
, "%s", table
->drv_name
);
664 (void) dis_snprintf(buf
, buflen
, "%s %s%s%s%s, %s%s%s%s",
666 pred
& DIS_RISCV_FENCE_I
? "i" : "",
667 pred
& DIS_RISCV_FENCE_O
? "o" : "",
668 pred
& DIS_RISCV_FENCE_R
? "r" : "",
669 pred
& DIS_RISCV_FENCE_W
? "w" : "",
670 succ
& DIS_RISCV_FENCE_I
? "i" : "",
671 succ
& DIS_RISCV_FENCE_O
? "o" : "",
672 succ
& DIS_RISCV_FENCE_R
? "r" : "",
673 succ
& DIS_RISCV_FENCE_W
? "w" : "");
678 dis_riscv_name(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
679 char *buf
, size_t buflen
)
681 (void) dis_snprintf(buf
, buflen
, "%s", table
->drv_name
);
686 dis_riscv_rs1_rs2(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
687 char *buf
, size_t buflen
)
689 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", table
->drv_name
,
690 dis_riscv_regs
[DIS_RISCV_RS1(instr
)],
691 dis_riscv_regs
[DIS_RISCV_RS2(instr
)]);
696 dis_riscv_rv32a_load(dis_handle_t
*dhp
, uint32_t instr
,
697 dis_riscv_instr_t
*table
, char *buf
, size_t buflen
)
699 const char *suffix
= "";
701 if (DIS_RISCV_RVA_AQ(instr
) && DIS_RISCV_RVA_RL(instr
)) {
703 } else if (DIS_RISCV_RVA_AQ(instr
)) {
705 } else if (DIS_RISCV_RVA_RL(instr
)) {
709 (void) dis_snprintf(buf
, buflen
, "%s%s %s,(%s)", table
->drv_name
,
710 suffix
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
711 dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
716 dis_riscv_rv32a(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
717 char *buf
, size_t buflen
)
719 const char *suffix
= "";
721 if (DIS_RISCV_RVA_AQ(instr
) && DIS_RISCV_RVA_RL(instr
)) {
723 } else if (DIS_RISCV_RVA_AQ(instr
)) {
725 } else if (DIS_RISCV_RVA_RL(instr
)) {
729 (void) dis_snprintf(buf
, buflen
, "%s%s %s,%s,(%s)", table
->drv_name
,
730 suffix
, dis_riscv_regs
[DIS_RISCV_RD(instr
)],
731 dis_riscv_regs
[DIS_RISCV_RS2(instr
)],
732 dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
736 dis_riscv_fp_load(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
737 char *buf
, size_t buflen
)
740 uint_t imm
= dis_riscv_sign_extend(DIS_RISCV_IIMM(instr
), 11, &s
);
742 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
743 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0%o(%s)",
744 table
->drv_name
, dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
745 s
, imm
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
747 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0x%x(%s)",
748 table
->drv_name
, dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
749 s
, imm
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
754 dis_riscv_fp_store(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
755 char *buf
, size_t buflen
)
758 uint_t simm
= DIS_RISCV_SIMM_UP(instr
) | DIS_RISCV_SIMM_LOW(instr
);
759 uint_t val
= dis_riscv_sign_extend(simm
, 11, &s
);
761 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
762 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0%o(%s)",
763 table
->drv_name
, dis_riscv_fpregs
[DIS_RISCV_RS2(instr
)],
764 s
, val
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
766 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0x%x(%s)",
767 table
->drv_name
, dis_riscv_fpregs
[DIS_RISCV_RS2(instr
)],
768 s
, val
, dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
774 dis_riscv_fp_r(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
775 char *buf
, size_t buflen
)
777 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s", table
->drv_name
,
778 dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
779 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)],
780 dis_riscv_fpregs
[DIS_RISCV_RS2(instr
)]);
784 * Variant of fp_r type that goes to integer destination registers.
788 dis_riscv_fp_r_fpi(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
789 char *buf
, size_t buflen
)
791 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s", table
->drv_name
,
792 dis_riscv_regs
[DIS_RISCV_RD(instr
)],
793 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)],
794 dis_riscv_fpregs
[DIS_RISCV_RS2(instr
)]);
799 dis_riscv_fp_r4(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
800 char *buf
, size_t buflen
)
802 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s,%s%s", table
->drv_name
,
803 dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
804 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)],
805 dis_riscv_fpregs
[DIS_RISCV_RS2(instr
)],
806 dis_riscv_fpregs
[DIS_RISCV_FP_RS3(instr
)],
807 dis_riscv_rm
[DIS_RISCV_FUNCT3(instr
)]);
812 dis_riscv_fp_rs2_fp(dis_handle_t
*dhp
, uint32_t instr
, dis_riscv_instr_t
*table
,
813 char *buf
, size_t buflen
)
815 (void) dis_snprintf(buf
, buflen
, "%s %s,%s%s", table
->drv_name
,
816 dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
817 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)],
818 dis_riscv_rm
[DIS_RISCV_FUNCT3(instr
)]);
823 dis_riscv_fp_rs2_fp_nr(dis_handle_t
*dhp
, uint32_t instr
,
824 dis_riscv_instr_t
*table
, char *buf
, size_t buflen
)
826 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", table
->drv_name
,
827 dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
828 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)]);
833 dis_riscv_fp_rs2_fpi(dis_handle_t
*dhp
, uint32_t instr
,
834 dis_riscv_instr_t
*table
, char *buf
, size_t buflen
)
836 (void) dis_snprintf(buf
, buflen
, "%s %s,%s%s", table
->drv_name
,
837 dis_riscv_regs
[DIS_RISCV_RD(instr
)],
838 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)],
839 dis_riscv_rm
[DIS_RISCV_FUNCT3(instr
)]);
844 dis_riscv_fp_rs2_ifp(dis_handle_t
*dhp
, uint32_t instr
,
845 dis_riscv_instr_t
*table
, char *buf
, size_t buflen
)
847 (void) dis_snprintf(buf
, buflen
, "%s %s,%s%s", table
->drv_name
,
848 dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
849 dis_riscv_regs
[DIS_RISCV_RS1(instr
)],
850 dis_riscv_rm
[DIS_RISCV_FUNCT3(instr
)]);
855 dis_riscv_fp_rs2_fpi_nr(dis_handle_t
*dhp
, uint32_t instr
,
856 dis_riscv_instr_t
*table
, char *buf
, size_t buflen
)
858 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", table
->drv_name
,
859 dis_riscv_regs
[DIS_RISCV_RD(instr
)],
860 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)]);
865 dis_riscv_fp_rs2_ifp_nr(dis_handle_t
*dhp
, uint32_t instr
,
866 dis_riscv_instr_t
*table
, char *buf
, size_t buflen
)
868 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", table
->drv_name
,
869 dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
870 dis_riscv_regs
[DIS_RISCV_RS1(instr
)]);
876 dis_riscv_fp_rm(dis_handle_t
*dhp
, uint32_t instr
,
877 dis_riscv_instr_t
*table
, char *buf
, size_t buflen
)
879 (void) dis_snprintf(buf
, buflen
, "%s %s,%s,%s%s", table
->drv_name
,
880 dis_riscv_fpregs
[DIS_RISCV_RD(instr
)],
881 dis_riscv_fpregs
[DIS_RISCV_RS1(instr
)],
882 dis_riscv_fpregs
[DIS_RISCV_RS2(instr
)],
883 dis_riscv_rm
[DIS_RISCV_FUNCT3(instr
)]);
886 #define DIS_RISCV_R32(str, op, f3, f7) \
887 { str, DIS_RISCV_I_R_TYPE, dis_riscv_rtype_32, op, f3, f7 }
888 #define DIS_RISCV_I32(str, op, f3) \
889 { str, DIS_RISCV_I_I_TYPE, dis_riscv_itype_32, op, f3 }
890 #define DIS_RISCV_S32(str, op, f3) \
891 { str, DIS_RISCV_I_S_TYPE, dis_riscv_stype_32, op, f3 }
892 #define DIS_RISCV_B32(str, op, f3) \
893 { str, DIS_RISCV_I_B_TYPE, dis_riscv_btype_32, op, f3 }
894 #define DIS_RISCV_U32(str, op) \
895 { str, DIS_RISCV_I_U_TYPE, dis_riscv_utype_32, op }
896 #define DIS_RISCV_J32(str, op) \
897 { str, DIS_RISCV_I_J_TYPE, dis_riscv_jtype_32, op }
900 * These are non-standard types that we've defined because they require
901 * different handling.
903 #define DIS_RISCV_SHIFT32(str, op, f3, f7) \
904 { str, DIS_RISCV_I_R_TYPE, dis_riscv_shift_32, op, f3, f7 }
905 #define DIS_RISCV_SHIFT64(str, op, f3, f7) \
906 { str, DIS_RISCV_I_SHIFT64_TYPE, dis_riscv_shift_64, op, f3, f7 }
907 #define DIS_RISCV_CSR(str, op, f3) \
908 { str, DIS_RISCV_I_I_TYPE, dis_riscv_csr, op, f3 }
909 #define DIS_RISCV_CSRI(str, op, f3) \
910 { str, DIS_RISCV_I_I_TYPE, dis_riscv_csri, op, f3 }
911 #define DIS_RISCV_LOAD(str, op, f3) \
912 { str, DIS_RISCV_I_I_TYPE, dis_riscv_load, op, f3 }
914 #define DIS_RISCV_MASK(str, mask, val, func) \
915 { str, DIS_RISCV_I_MASK_TYPE, func, mask, val }
919 * Atomic-extension specific entries
921 #define DIS_RISCV_A32(str, op, f3, f5) \
922 { str, DIS_RISCV_I_RV32A_TYPE, dis_riscv_rv32a, op, f3, f5 }
923 #define DIS_RISCV_A32LOAD(str, op, f3, f5, f2) \
924 { str, DIS_RISCV_I_RV32A_LOAD_TYPE, dis_riscv_rv32a_load, op, f3, \
928 * Floating-point specific entries
930 #define DIS_RISCV_FP_LOAD(str, op, f3) \
931 { str, DIS_RISCV_I_I_TYPE, dis_riscv_fp_load, op, f3 }
932 #define DIS_RISCV_FP_STORE(str, op, f3) \
933 { str, DIS_RISCV_I_S_TYPE, dis_riscv_fp_store, op, f3 }
934 #define DIS_RISCV_FP_R(str, op, f3, f7) \
935 { str, DIS_RISCV_I_R_TYPE, dis_riscv_fp_r, op, f3, f7 }
936 #define DIS_RISCV_FP_R4(str, op, f2) \
937 { str, DIS_RISCV_I_R4_TYPE, dis_riscv_fp_r4, op, 0, 0, f2 }
938 #define DIS_RISCV_FP_RS2_FP(str, op, rs2, f7) \
939 { str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fp, op, rs2, f7 }
940 #define DIS_RISCV_FP_RS2_FP_NR(str, op, rs2, f7) \
941 { str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fp_nr, op, rs2, f7 }
942 #define DIS_RISCV_FP_RS2_FPI(str, op, rs2, f7) \
943 { str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_fpi, op, rs2, f7 }
944 #define DIS_RISCV_FP_RS2_IFP(str, op, rs2, f7) \
945 { str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_ifp, op, rs2, f7 }
946 #define DIS_RISCV_FP_RS2_IFP_NR(str, op, rs2, f7) \
947 { str, DIS_RISCV_I_FP_RS2OP_TYPE, dis_riscv_fp_rs2_ifp_nr, op, rs2, f7 }
948 #define DIS_RISCV_FP_RM(str, op, f7) \
949 { str, DIS_RISCV_I_FP_RM_TYPE, dis_riscv_fp_rm, op, 0, f7 }
950 #define DIS_RISCV_FP_R_RS2_FPI(str, op, f3, rs2, f7) \
951 { str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_fpi, op, f3, f7, \
953 #define DIS_RISCV_FP_R_RS2_IFP(str, op, f3, rs2, f7) \
954 { str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_ifp, op, f3, f7, \
956 #define DIS_RISCV_FP_R_RS2_FPI_NR(str, op, f3, rs2, f7) \
957 { str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_fpi_nr, op, f3, \
959 #define DIS_RISCV_FP_R_RS2_IFP_NR(str, op, f3, rs2, f7) \
960 { str, DIS_RISCV_I_FP_R_RS2_TYPE, dis_riscv_fp_rs2_ifp_nr, op, f3, \
962 #define DIS_RISCV_FP_RI(str, op, f3, f7) \
963 { str, DIS_RISCV_I_R_TYPE, dis_riscv_fp_r_fpi, op, f3, f7 }
966 * This table is ordered such that it follows the ordering in the RISC-V ISA
969 static dis_riscv_instr_t dis_riscv_4byte
[] = {
973 DIS_RISCV_U32("lui", 0x37),
974 DIS_RISCV_U32("auipc", 0x17),
975 DIS_RISCV_J32("jal", 0x6f),
976 /* ret is a special case of jalr */
977 DIS_RISCV_MASK("ret", 0xffffffff, 0x00008067, dis_riscv_name
),
978 DIS_RISCV_I32("jalr", 0x67, 0x0),
979 DIS_RISCV_B32("beq", 0x63, 0x0),
980 DIS_RISCV_B32("bne", 0x63, 0x1),
981 DIS_RISCV_B32("blt", 0x63, 0x4),
982 DIS_RISCV_B32("bge", 0x63, 0x5),
983 DIS_RISCV_B32("bltu", 0x63, 0x6),
984 DIS_RISCV_B32("bgeu", 0x63, 0x7),
985 DIS_RISCV_LOAD("lb", 0x03, 0x0),
986 DIS_RISCV_LOAD("lh", 0x03, 0x1),
987 DIS_RISCV_LOAD("lw", 0x03, 0x2),
988 DIS_RISCV_LOAD("lbu", 0x03, 0x4),
989 DIS_RISCV_LOAD("lhu", 0x03, 0x5),
990 DIS_RISCV_S32("sb", 0x23, 0x0),
991 DIS_RISCV_S32("sh", 0x23, 0x1),
992 DIS_RISCV_S32("sw", 0x23, 0x2),
993 /* nop is addi x0, x0, 0 */
994 DIS_RISCV_MASK("nop", 0xffffffff, 0x00000013, dis_riscv_name
),
995 DIS_RISCV_I32("addi", 0x13, 0x0),
996 DIS_RISCV_I32("slti", 0x13, 0x2),
997 DIS_RISCV_I32("sltiu", 0x13, 0x3),
998 DIS_RISCV_I32("xori", 0x13, 0x4),
999 DIS_RISCV_I32("ori", 0x13, 0x6),
1000 DIS_RISCV_I32("andi", 0x13, 0x7),
1001 DIS_RISCV_SHIFT32("slli", 0x13, 0x1, 0x00),
1002 DIS_RISCV_SHIFT32("srli", 0x13, 0x5, 0x00),
1003 DIS_RISCV_SHIFT32("srai", 0x13, 0x5, 0x20),
1004 DIS_RISCV_R32("add", 0x33, 0x0, 0x00),
1005 DIS_RISCV_R32("sub", 0x33, 0x0, 0x20),
1006 DIS_RISCV_R32("sll", 0x33, 0x1, 0x00),
1007 DIS_RISCV_R32("slt", 0x33, 0x2, 0x00),
1008 DIS_RISCV_R32("sltu", 0x33, 0x3, 0x00),
1009 DIS_RISCV_R32("xor", 0x33, 0x4, 0x00),
1010 DIS_RISCV_R32("srl", 0x33, 0x5, 0x00),
1011 DIS_RISCV_R32("sra", 0x33, 0x5, 0x20),
1012 DIS_RISCV_R32("or", 0x33, 0x6, 0x00),
1013 DIS_RISCV_R32("and", 0x33, 0x7, 0x00),
1014 DIS_RISCV_MASK("fence", 0xf00fffff, 0xf, dis_riscv_fence
),
1015 DIS_RISCV_MASK("fence.i", 0xfffff00f, 0x100f, dis_riscv_name
),
1016 DIS_RISCV_MASK("ecall", 0xffffffff, 0x73, dis_riscv_name
),
1017 DIS_RISCV_MASK("ebreak", 0xffffffff, 0x100073, dis_riscv_name
),
1018 DIS_RISCV_CSR("csrrw", 0x73, 0x1),
1019 DIS_RISCV_CSR("csrrs", 0x73, 0x2),
1020 DIS_RISCV_CSR("csrrc", 0x73, 0x3),
1021 DIS_RISCV_CSRI("csrrwi", 0x73, 0x5),
1022 DIS_RISCV_CSRI("csrrsi", 0x73, 0x6),
1023 DIS_RISCV_CSRI("csrrci", 0x73, 0x7),
1027 DIS_RISCV_LOAD("lwu", 0x03, 0x6),
1028 DIS_RISCV_LOAD("ld", 0x03, 0x3),
1029 DIS_RISCV_S32("sd", 0x23, 0x3),
1030 DIS_RISCV_SHIFT64("slli", 0x13, 0x1, 0x0),
1031 DIS_RISCV_SHIFT64("srli", 0x13, 0x5, 0x0),
1032 DIS_RISCV_SHIFT64("srai", 0x13, 0x5, 0x10),
1033 DIS_RISCV_I32("addiw", 0x1b, 0x0),
1034 DIS_RISCV_SHIFT32("slliw", 0x1b, 0x1, 0x0),
1035 DIS_RISCV_SHIFT32("srliw", 0x1b, 0x5, 0x0),
1036 DIS_RISCV_SHIFT32("sraiw", 0x1b, 0x5, 0x20),
1037 DIS_RISCV_R32("addw", 0x3b, 0x0, 0x00),
1038 DIS_RISCV_R32("subw", 0x3b, 0x0, 0x20),
1039 DIS_RISCV_R32("sllw", 0x3b, 0x1, 0x00),
1040 DIS_RISCV_R32("srlw", 0x3b, 0x5, 0x00),
1041 DIS_RISCV_R32("sraw", 0x3b, 0x5, 0x20),
1045 DIS_RISCV_R32("mul", 0x33, 0x0, 0x01),
1046 DIS_RISCV_R32("mulh", 0x33, 0x1, 0x01),
1047 DIS_RISCV_R32("mulhsu", 0x33, 0x2, 0x01),
1048 DIS_RISCV_R32("mulhu", 0x33, 0x3, 0x01),
1049 DIS_RISCV_R32("div", 0x33, 0x4, 0x01),
1050 DIS_RISCV_R32("divu", 0x33, 0x5, 0x01),
1051 DIS_RISCV_R32("rem", 0x33, 0x6, 0x01),
1052 DIS_RISCV_R32("remu", 0x33, 0x7, 0x01),
1056 DIS_RISCV_R32("mulw", 0x3b, 0x0, 0x01),
1057 DIS_RISCV_R32("divw", 0x3b, 0x4, 0x01),
1058 DIS_RISCV_R32("divuw", 0x3b, 0x5, 0x01),
1059 DIS_RISCV_R32("remw", 0x3b, 0x6, 0x01),
1060 DIS_RISCV_R32("remuw", 0x3b, 0x7, 0x01),
1064 DIS_RISCV_A32LOAD("lr.w", 0x2f, 0x2, 0x02, 0x0),
1065 DIS_RISCV_A32("sc.w", 0x2f, 0x2, 0x03),
1066 DIS_RISCV_A32("amoswap.w", 0x2f, 0x2, 0x01),
1067 DIS_RISCV_A32("amoadd.w", 0x2f, 0x2, 0x00),
1068 DIS_RISCV_A32("amoxor.w", 0x2f, 0x2, 0x04),
1069 DIS_RISCV_A32("amoand.w", 0x2f, 0x2, 0x0c),
1070 DIS_RISCV_A32("amoor.w", 0x2f, 0x2, 0x08),
1071 DIS_RISCV_A32("amomin.w", 0x2f, 0x2, 0x10),
1072 DIS_RISCV_A32("amomax.w", 0x2f, 0x2, 0x14),
1073 DIS_RISCV_A32("amominu.w", 0x2f, 0x2, 0x18),
1074 DIS_RISCV_A32("amomaxu.w", 0x2f, 0x2, 0x1c),
1078 DIS_RISCV_A32LOAD("lr.d", 0x2f, 0x3, 0x02, 0x0),
1079 DIS_RISCV_A32("sc.d", 0x2f, 0x3, 0x03),
1080 DIS_RISCV_A32("amoswap.d", 0x2f, 0x3, 0x01),
1081 DIS_RISCV_A32("amoadd.d", 0x2f, 0x3, 0x00),
1082 DIS_RISCV_A32("amoxor.d", 0x2f, 0x3, 0x04),
1083 DIS_RISCV_A32("amoand.d", 0x2f, 0x3, 0x0c),
1084 DIS_RISCV_A32("amoor.d", 0x2f, 0x3, 0x08),
1085 DIS_RISCV_A32("amomin.d", 0x2f, 0x3, 0x10),
1086 DIS_RISCV_A32("amomax.d", 0x2f, 0x3, 0x14),
1087 DIS_RISCV_A32("amominu.d", 0x2f, 0x3, 0x18),
1088 DIS_RISCV_A32("amomaxu.d", 0x2f, 0x3, 0x1c),
1092 DIS_RISCV_FP_LOAD("flw", 0x07, 0x2),
1093 DIS_RISCV_FP_STORE("fsw", 0x27, 0x2),
1094 DIS_RISCV_FP_R4("fmadd.s", 0x43, 0x0),
1095 DIS_RISCV_FP_R4("fmsub.s", 0x47, 0x0),
1096 DIS_RISCV_FP_R4("fnmsub.s", 0x4b, 0x0),
1097 DIS_RISCV_FP_R4("fnmadd.s", 0x4f, 0x0),
1098 DIS_RISCV_FP_RM("fadd.s", 0x53, 0x00),
1099 DIS_RISCV_FP_RM("fsub.s", 0x53, 0x04),
1100 DIS_RISCV_FP_RM("fmul.s", 0x53, 0x08),
1101 DIS_RISCV_FP_RM("fdiv.s", 0x53, 0xc),
1102 DIS_RISCV_FP_RS2_FP("fsqrt.s", 0x53, 0x00, 0x2c),
1103 DIS_RISCV_FP_R("fsgnj.s", 0x53, 0x0, 0x10),
1104 DIS_RISCV_FP_R("fsgnjn.s", 0x53, 0x1, 0x10),
1105 DIS_RISCV_FP_R("fsgnjx.s", 0x53, 0x2, 0x10),
1106 DIS_RISCV_FP_R("fmin.s", 0x53, 0x0, 0x14),
1107 DIS_RISCV_FP_R("fmax.s", 0x53, 0x1, 0x14),
1108 DIS_RISCV_FP_RS2_FPI("fcvt.w.s", 0x53, 0x00, 0x60),
1109 DIS_RISCV_FP_RS2_FPI("fcvt.wu.s", 0x53, 0x01, 0x60),
1110 DIS_RISCV_FP_R_RS2_FPI_NR("fmv.x.w", 0x53, 0x00, 0x00, 0x70),
1111 DIS_RISCV_FP_RI("feq.s", 0x53, 0x2, 0x50),
1112 DIS_RISCV_FP_RI("flt.s", 0x53, 0x1, 0x50),
1113 DIS_RISCV_FP_RI("fle.s", 0x53, 0x0, 0x50),
1114 DIS_RISCV_FP_R_RS2_FPI_NR("fclass.s", 0x53, 0x1, 0x00, 0x70),
1115 DIS_RISCV_FP_RS2_IFP("fcvt.s.w", 0x53, 0x00, 0x68),
1116 DIS_RISCV_FP_RS2_IFP("fcvt.s.wu", 0x53, 0x01, 0x68),
1117 DIS_RISCV_FP_R_RS2_IFP_NR("fmv.w.x", 0x53, 0x0, 0x00, 0x78),
1121 DIS_RISCV_FP_RS2_FPI("fcvt.l.s", 0x53, 0x02, 0x60),
1122 DIS_RISCV_FP_RS2_FPI("fcvt.lu.s", 0x53, 0x03, 0x60),
1123 DIS_RISCV_FP_RS2_IFP("fcvt.s.l", 0x53, 0x02, 0x68),
1124 DIS_RISCV_FP_RS2_IFP("fcvt.s.lu", 0x53, 0x03, 0x68),
1128 DIS_RISCV_FP_LOAD("fld", 0x07, 0x3),
1129 DIS_RISCV_FP_STORE("fsd", 0x27, 0x3),
1130 DIS_RISCV_FP_R4("fmadd.d", 0x43, 0x1),
1131 DIS_RISCV_FP_R4("fmsub.d", 0x47, 0x1),
1132 DIS_RISCV_FP_R4("fnmsub.d", 0x4b, 0x1),
1133 DIS_RISCV_FP_R4("fnmadd.d", 0x4f, 0x1),
1134 DIS_RISCV_FP_RM("fadd.d", 0x53, 0x01),
1135 DIS_RISCV_FP_RM("fsub.d", 0x53, 0x05),
1136 DIS_RISCV_FP_RM("fmul.d", 0x53, 0x09),
1137 DIS_RISCV_FP_RM("fdiv.d", 0x53, 0xd),
1138 DIS_RISCV_FP_RS2_FP("fsqrt.d", 0x53, 0x00, 0x2d),
1139 DIS_RISCV_FP_R("fsgnj.d", 0x53, 0x0, 0x11),
1140 DIS_RISCV_FP_R("fsgnjn.d", 0x53, 0x1, 0x11),
1141 DIS_RISCV_FP_R("fsgnjx.d", 0x53, 0x2, 0x11),
1142 DIS_RISCV_FP_R("fmin.d", 0x53, 0x0, 0x15),
1143 DIS_RISCV_FP_R("fmax.d", 0x53, 0x1, 0x15),
1144 DIS_RISCV_FP_RS2_FP("fcvt.s.d", 0x53, 0x01, 0x20),
1145 DIS_RISCV_FP_RS2_FP_NR("fcvt.d.s", 0x53, 0x00, 0x21),
1146 DIS_RISCV_FP_RI("feq.d", 0x53, 0x2, 0x51),
1147 DIS_RISCV_FP_RI("flt.d", 0x53, 0x1, 0x51),
1148 DIS_RISCV_FP_RI("fle.d", 0x53, 0x0, 0x51),
1149 DIS_RISCV_FP_R_RS2_FPI_NR("fclass.d", 0x53, 0x1, 0x00, 0x71),
1150 DIS_RISCV_FP_RS2_FPI("fcvt.w.d", 0x53, 0x00, 0x61),
1151 DIS_RISCV_FP_RS2_FPI("fcvt.wu.d", 0x53, 0x01, 0x61),
1152 DIS_RISCV_FP_RS2_IFP_NR("fcvt.d.w", 0x53, 0x00, 0x69),
1153 DIS_RISCV_FP_RS2_IFP_NR("fcvt.d.wu", 0x53, 0x01, 0x69),
1157 DIS_RISCV_FP_RS2_FPI("fcvt.l.d", 0x53, 0x02, 0x61),
1158 DIS_RISCV_FP_RS2_FPI("fcvt.lu.d", 0x53, 0x03, 0x61),
1159 DIS_RISCV_FP_R_RS2_FPI_NR("fmv.x.d", 0x53, 0x0, 0x00, 0x71),
1160 DIS_RISCV_FP_RS2_IFP("fcvt.d.l", 0x53, 0x02, 0x69),
1161 DIS_RISCV_FP_RS2_IFP("fcvt.d.lu", 0x53, 0x03, 0x69),
1162 DIS_RISCV_FP_R_RS2_IFP_NR("fmv.d.x", 0x53, 0x0, 0x00, 0x79),
1164 * Privileged Instructions from RISC-V Privileged Architectures V1.10.
1166 DIS_RISCV_MASK("uret", 0xffffffff, 0x00200073, dis_riscv_name
),
1167 DIS_RISCV_MASK("sret", 0xffffffff, 0x10200073, dis_riscv_name
),
1168 DIS_RISCV_MASK("mret", 0xffffffff, 0x30200073, dis_riscv_name
),
1169 DIS_RISCV_MASK("wfi", 0xffffffff, 0x10500073, dis_riscv_name
),
1170 DIS_RISCV_MASK("sfence.vma", 0xfe007fff, 0x12000073, dis_riscv_rs1_rs2
)
1174 dis_riscv_decode_4byte(dis_handle_t
*dhp
, uint32_t instr
, char *buf
,
1179 for (i
= 0; i
< ARRAY_SIZE(dis_riscv_4byte
); i
++) {
1180 dis_riscv_instr_t
*t
= &dis_riscv_4byte
[i
];
1181 switch (t
->drv_type
) {
1182 case DIS_RISCV_I_R_TYPE
:
1183 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1184 DIS_RISCV_FUNCT3(instr
) == t
->drv_funct3
&&
1185 DIS_RISCV_FUNCT7(instr
) == t
->drv_funct7
) {
1189 case DIS_RISCV_I_I_TYPE
:
1190 case DIS_RISCV_I_S_TYPE
:
1191 case DIS_RISCV_I_B_TYPE
:
1192 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1193 DIS_RISCV_FUNCT3(instr
) == t
->drv_funct3
) {
1197 case DIS_RISCV_I_U_TYPE
:
1198 case DIS_RISCV_I_J_TYPE
:
1199 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
) {
1203 case DIS_RISCV_I_R4_TYPE
:
1204 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1205 DIS_RISCV_FUNCT2(instr
) == t
->drv_funct2
) {
1209 case DIS_RISCV_I_MASK_TYPE
:
1210 if ((instr
& t
->drv_opcode
) == t
->drv_funct3
) {
1214 case DIS_RISCV_I_SHIFT64_TYPE
:
1215 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1216 DIS_RISCV_FUNCT3(instr
) == t
->drv_funct3
&&
1217 DIS_RISCV_SFUNCT7(instr
) == t
->drv_funct7
) {
1222 case DIS_RISCV_I_RV32A_LOAD_TYPE
:
1223 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1224 DIS_RISCV_FUNCT3(instr
) == t
->drv_funct3
&&
1225 DIS_RISCV_RVA_FUNCT5(instr
) == t
->drv_funct7
&&
1226 DIS_RISCV_RS2(instr
) == t
->drv_funct2
) {
1230 case DIS_RISCV_I_RV32A_TYPE
:
1231 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1232 DIS_RISCV_FUNCT3(instr
) == t
->drv_funct3
&&
1233 DIS_RISCV_RVA_FUNCT5(instr
) == t
->drv_funct7
) {
1237 case DIS_RISCV_I_FP_RS2OP_TYPE
:
1238 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1239 DIS_RISCV_RS2(instr
) == t
->drv_funct3
&&
1240 DIS_RISCV_FUNCT7(instr
) == t
->drv_funct7
) {
1244 case DIS_RISCV_I_FP_RM_TYPE
:
1245 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1246 DIS_RISCV_FUNCT7(instr
) == t
->drv_funct7
) {
1250 case DIS_RISCV_I_FP_R_RS2_TYPE
:
1251 if (DIS_RISCV_OPCODE(instr
) == t
->drv_opcode
&&
1252 DIS_RISCV_FUNCT3(instr
) == t
->drv_funct3
&&
1253 DIS_RISCV_RS2(instr
) == t
->drv_funct2
&&
1254 DIS_RISCV_FUNCT7(instr
) == t
->drv_funct7
) {
1262 t
->drv_print(dhp
, instr
, t
, buf
, buflen
);
1266 (void) dis_snprintf(buf
, buflen
, "<unknown>");
1270 * Two byte decode table types.
1272 typedef enum dis_riscv_ctype
{
1274 * Indicates that we should match based on the opcode and funct3.
1278 * Indicates that we should match the instruction based on a mask.
1281 } dis_riscv_ctype_t
;
1284 * The compact forms are depending on the elf class. This is used to keep track
1285 * of the class and match it.
1287 typedef enum dis_riscv_c_class
{
1293 } dis_riscv_c_class_t
;
1295 struct dis_riscv_c_instr
;
1296 typedef void (*dis_riscv_c_func_t
)(dis_handle_t
*, uint32_t,
1297 struct dis_riscv_c_instr
*, char *, size_t);
1299 typedef struct dis_riscv_c_instr
{
1300 const char *drv_c_name
;
1301 dis_riscv_ctype_t drv_c_type
;
1302 dis_riscv_c_func_t drv_c_print
;
1303 dis_riscv_c_class_t drv_c_class
;
1304 uint_t drv_c_opcode
;
1308 } dis_riscv_c_instr_t
;
1310 #define DIS_RISCV_C_OPCODE(x) ((x) & 0x03)
1311 #define DIS_RISCV_C_FUNCT3(x) (((x) & 0xe000) >> 13)
1313 #define DIS_RISCV_C_RS1(x) (((x) & 0x0f80) >> 7)
1314 #define DIS_RISCV_C_RS2(x) (((x) & 0x007c) >> 2)
1315 #define DIS_RISCV_C_RD(x) DIS_RISCV_C_RS1(x)
1317 #define DIS_RISCV_C_RS1P(x) (((x) & 0x0380) >> 7)
1318 #define DIS_RISCV_C_RS2P(x) DIS_RISCV_C_RDP(x)
1319 #define DIS_RISCV_C_RDP(x) (((x) & 0x001c) >> 2)
1322 * CJ format immediate extractor
1324 #define DIS_RISCV_C_J_11(x) (((x) & 0x1000) >> 1)
1325 #define DIS_RISCV_C_J_4(x) (((x) & 0x0800) >> 7)
1326 #define DIS_RISCV_C_J_9_8(x) (((x) & 0x0600) >> 1)
1327 #define DIS_RISCV_C_J_10(x) (((x) & 0x0100) << 2)
1328 #define DIS_RISCV_C_J_6(x) (((x) & 0x0080) >> 1)
1329 #define DIS_RISCV_C_J_7(x) (((x) & 0x0040) << 1)
1330 #define DIS_RISCV_C_J_3_1(x) (((x) & 0x0038) >> 3)
1331 #define DIS_RISCV_C_J_5(x) (((x) & 0x0004) << 3)
1334 * Compact Branch extractor
1336 #define DIS_RISCV_C_B_8(x) (((x) & 0x1000) >> 4)
1337 #define DIS_RISCV_C_B_4_3(x) (((x) & 0x0c00) >> 7)
1338 #define DIS_RISCV_C_B_7_6(x) (((x) & 0x0060) << 1)
1339 #define DIS_RISCV_C_B_2_1(x) (((x) & 0x0018) >> 2)
1340 #define DIS_RISCV_C_B_5(x) (((x) & 0x0004) << 3)
1343 * c.addi16spn extractor
1345 #define DIS_RISCV_C_A16_9(x) (((x) & 0x1000) >> 3)
1346 #define DIS_RISCV_C_A16_4(x) (((x) & 0x0040) >> 2)
1347 #define DIS_RISCV_C_A16_6(x) (((x) & 0x0020) << 1)
1348 #define DIS_RISCV_C_A16_8_7(x) (((x) & 0x0018) << 4)
1349 #define DIS_RISCV_C_A16_5(x) (((x) & 0x0004) << 3)
1352 * c.addi4spn extractor
1354 #define DIS_RISCV_C_A4_5_4(x) (((x) & 0x1800) >> 7)
1355 #define DIS_RISCV_C_A4_9_6(x) (((x) & 0x0700) >> 2)
1356 #define DIS_RISCV_C_A4_2(x) (((x) & 0x0040) >> 4)
1357 #define DIS_RISCV_C_A4_3(x) (((x) & 0x0020) >> 2)
1361 dis_riscv_c_name(dis_handle_t
*dhp
, uint32_t instr
,
1362 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1364 (void) dis_snprintf(buf
, buflen
, "%s", table
->drv_c_name
);
1368 dis_riscv_c_loadstore(dis_handle_t
*dhp
, const char *name
, const char *dreg
,
1369 const char *sreg
, uint32_t off
, char *buf
, size_t buflen
)
1372 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
1373 (void) dis_snprintf(buf
, buflen
, "%s %s,0%o(%s)", name
, dreg
,
1376 (void) dis_snprintf(buf
, buflen
, "%s %s,0x%x(%s)", name
, dreg
,
1382 dis_riscv_c_lwsp(dis_handle_t
*dhp
, uint32_t instr
,
1383 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1385 uint32_t imm
= ((instr
& 0x000c) << 4) |
1386 ((instr
& 0x1000) >> 7) | ((instr
& 0x0070) >> 2);
1388 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1389 dis_riscv_regs
[DIS_RISCV_C_RD(instr
)], dis_riscv_regs
[2], imm
, buf
,
1394 dis_riscv_c_ldsp(dis_handle_t
*dhp
, uint32_t instr
,
1395 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1397 uint32_t imm
= ((instr
& 0x001c) << 4) |
1398 ((instr
& 0x1000) >> 7) | ((instr
& 0x0060) >> 2);
1400 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1401 dis_riscv_regs
[DIS_RISCV_C_RD(instr
)], dis_riscv_regs
[2],
1406 dis_riscv_c_flwsp(dis_handle_t
*dhp
, uint32_t instr
,
1407 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1409 uint32_t imm
= ((instr
& 0x000c) << 4) |
1410 ((instr
& 0x1000) >> 7) | ((instr
& 0x0070) >> 2);
1412 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1413 dis_riscv_fpregs
[DIS_RISCV_C_RD(instr
)], dis_riscv_regs
[2],
1418 dis_riscv_c_fldsp(dis_handle_t
*dhp
, uint32_t instr
,
1419 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1421 uint32_t imm
= ((instr
& 0x001c) << 4) |
1422 ((instr
& 0x1000) >> 7) | ((instr
& 0x0060) >> 2);
1424 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1425 dis_riscv_fpregs
[DIS_RISCV_C_RD(instr
)], dis_riscv_regs
[2],
1430 dis_riscv_c_swsp(dis_handle_t
*dhp
, uint32_t instr
,
1431 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1433 uint32_t imm
= ((instr
& 0x0180) >> 1) | ((instr
& 0x1e00) >> 7);
1435 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1436 dis_riscv_regs
[DIS_RISCV_C_RS2(instr
)], dis_riscv_regs
[2], imm
,
1441 dis_riscv_c_sdsp(dis_handle_t
*dhp
, uint32_t instr
,
1442 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1444 uint32_t imm
= ((instr
& 0x0380) >> 1) | ((instr
& 0x1c00) >> 7);
1446 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1447 dis_riscv_regs
[DIS_RISCV_C_RS2(instr
)], dis_riscv_regs
[2], imm
,
1452 dis_riscv_c_fswsp(dis_handle_t
*dhp
, uint32_t instr
,
1453 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1455 uint32_t imm
= ((instr
& 0x0180) >> 1) | ((instr
& 0x1e00) >> 7);
1457 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1458 dis_riscv_fpregs
[DIS_RISCV_C_RS2(instr
)], dis_riscv_regs
[2], imm
,
1463 dis_riscv_c_fsdsp(dis_handle_t
*dhp
, uint32_t instr
,
1464 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1466 uint32_t imm
= ((instr
& 0x0380) >> 1) | ((instr
& 0x1c00) >> 7);
1468 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1469 dis_riscv_fpregs
[DIS_RISCV_C_RS2(instr
)], dis_riscv_regs
[2], imm
,
1474 dis_riscv_c_lw(dis_handle_t
*dhp
, uint32_t instr
,
1475 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1477 uint32_t imm
= ((instr
& 0x0020) << 1) | ((instr
& 0x1c) >> 7) |
1478 ((instr
& 0x0040) >> 3);
1480 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1481 dis_riscv_c_regs
[DIS_RISCV_C_RDP(instr
)],
1482 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)],
1487 dis_riscv_c_ld(dis_handle_t
*dhp
, uint32_t instr
,
1488 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1490 uint32_t imm
= ((instr
& 0x0060) << 1) | ((instr
& 0x1c) >> 7);
1492 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1493 dis_riscv_c_regs
[DIS_RISCV_C_RDP(instr
)],
1494 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)],
1499 dis_riscv_c_flw(dis_handle_t
*dhp
, uint32_t instr
,
1500 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1502 uint32_t imm
= ((instr
& 0x0020) << 1) | ((instr
& 0x1c) >> 7) |
1503 ((instr
& 0x0040) >> 3);
1505 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1506 dis_riscv_c_fpregs
[DIS_RISCV_C_RDP(instr
)],
1507 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)],
1512 dis_riscv_c_fld(dis_handle_t
*dhp
, uint32_t instr
,
1513 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1515 uint32_t imm
= ((instr
& 0x0060) << 1) | ((instr
& 0x1c) >> 7);
1517 dis_riscv_c_loadstore(dhp
, table
->drv_c_name
,
1518 dis_riscv_c_fpregs
[DIS_RISCV_C_RDP(instr
)],
1519 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)],
1524 * The J type has the 11 bit immediate arranged as:
1526 * offset[11|4|9:8|10|6|7|3:1|5] going from bits 2 to 12.
1529 dis_riscv_c_j(dis_handle_t
*dhp
, uint32_t instr
,
1530 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1533 uint_t jimm
= DIS_RISCV_C_J_11(instr
) | DIS_RISCV_C_J_10(instr
) |
1534 DIS_RISCV_C_J_9_8(instr
) | DIS_RISCV_C_J_7(instr
) |
1535 DIS_RISCV_C_J_6(instr
) | DIS_RISCV_C_J_5(instr
) |
1536 DIS_RISCV_C_J_4(instr
) | DIS_RISCV_C_J_3_1(instr
);
1537 uint_t imm
= dis_riscv_sign_extend(jimm
, 11, &s
);
1539 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
1540 (void) dis_snprintf(buf
, buflen
, "%s %s0%o", table
->drv_c_name
,
1543 (void) dis_snprintf(buf
, buflen
, "%s %s0x%x", table
->drv_c_name
,
1550 dis_riscv_c_jr(dis_handle_t
*dhp
, uint32_t instr
,
1551 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1553 (void) dis_snprintf(buf
, buflen
, "%s %s", table
->drv_c_name
,
1554 dis_riscv_regs
[DIS_RISCV_C_RS1(instr
)]);
1558 dis_riscv_c_regimm(dis_handle_t
*dhp
, const char *instr
, const char *dreg
,
1559 const char *sign
, uint_t imm
, char *buf
, size_t buflen
)
1561 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
1562 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0%o", instr
, dreg
,
1565 (void) dis_snprintf(buf
, buflen
, "%s %s,%s0x%x", instr
, dreg
,
1571 dis_riscv_c_branch(dis_handle_t
*dhp
, uint32_t instr
,
1572 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1575 uint_t bimm
= DIS_RISCV_C_B_8(instr
) | DIS_RISCV_C_B_7_6(instr
) |
1576 DIS_RISCV_C_B_5(instr
) | DIS_RISCV_C_B_4_3(instr
) |
1577 DIS_RISCV_C_B_2_1(instr
);
1578 uint_t imm
= dis_riscv_sign_extend(bimm
, 8, &s
);
1580 dis_riscv_c_regimm(dhp
, table
->drv_c_name
,
1581 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)], s
, imm
, buf
, buflen
);
1585 dis_riscv_c_bigimmint(dis_handle_t
*dhp
, uint32_t instr
,
1586 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1589 uint_t limm
= ((instr
& 0x1000) >> 7) | ((instr
& 0x007c) >> 2);
1590 uint_t imm
= dis_riscv_sign_extend(limm
, 5, &s
);
1592 dis_riscv_c_regimm(dhp
, table
->drv_c_name
,
1593 dis_riscv_regs
[DIS_RISCV_C_RD(instr
)], s
, imm
, buf
, buflen
);
1597 dis_riscv_c_zext_bigimmint(dis_handle_t
*dhp
, uint32_t instr
,
1598 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1600 uint_t imm
= ((instr
& 0x1000) >> 7) | ((instr
& 0x007c) >> 2);
1602 dis_riscv_c_regimm(dhp
, table
->drv_c_name
,
1603 dis_riscv_regs
[DIS_RISCV_C_RD(instr
)], "", imm
, buf
, buflen
);
1607 dis_riscv_c_addi16sp(dis_handle_t
*dhp
, uint32_t instr
,
1608 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1611 uint_t aimm
= DIS_RISCV_C_A16_9(instr
) | DIS_RISCV_C_A16_8_7(instr
) |
1612 DIS_RISCV_C_A16_6(instr
) | DIS_RISCV_C_A16_5(instr
) |
1613 DIS_RISCV_C_A16_4(instr
);
1614 int imm
= dis_riscv_sign_extend(aimm
, 9, &s
);
1616 dis_riscv_c_regimm(dhp
, table
->drv_c_name
,
1617 dis_riscv_regs
[DIS_RISCV_C_RD(instr
)], s
, imm
, buf
, buflen
);
1621 dis_riscv_c_addi4spn(dis_handle_t
*dhp
, uint32_t instr
,
1622 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1624 uint_t imm
= DIS_RISCV_C_A4_9_6(instr
) | DIS_RISCV_C_A4_5_4(instr
) |
1625 DIS_RISCV_C_A4_3(instr
) | DIS_RISCV_C_A4_2(instr
);
1627 if ((dhp
->dh_flags
& DIS_OCTAL
) != 0) {
1628 (void) dis_snprintf(buf
, buflen
, "%s %s,sp,0%o",
1629 table
->drv_c_name
, dis_riscv_c_regs
[DIS_RISCV_C_RDP(instr
)],
1632 (void) dis_snprintf(buf
, buflen
, "%s %s,sp,0x%x",
1633 table
->drv_c_name
, dis_riscv_c_regs
[DIS_RISCV_C_RDP(instr
)],
1639 dis_riscv_c_immint(dis_handle_t
*dhp
, uint32_t instr
,
1640 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1643 uint_t limm
= ((instr
& 0x1000) >> 7) | ((instr
& 0x007c) >> 2);
1644 uint_t imm
= dis_riscv_sign_extend(limm
, 5, &s
);
1646 dis_riscv_c_regimm(dhp
, table
->drv_c_name
,
1647 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)], s
, imm
, buf
, buflen
);
1651 dis_riscv_c_zext_immint(dis_handle_t
*dhp
, uint32_t instr
,
1652 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1654 uint_t imm
= ((instr
& 0x1000) >> 7) | ((instr
& 0x007c) >> 2);
1656 dis_riscv_c_regimm(dhp
, table
->drv_c_name
,
1657 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)], "", imm
, buf
, buflen
);
1662 dis_riscv_c_bigint(dis_handle_t
*dhp
, uint32_t instr
,
1663 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1665 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", table
->drv_c_name
,
1666 dis_riscv_regs
[DIS_RISCV_C_RD(instr
)],
1667 dis_riscv_regs
[DIS_RISCV_C_RS2(instr
)]);
1673 dis_riscv_c_int(dis_handle_t
*dhp
, uint32_t instr
,
1674 dis_riscv_c_instr_t
*table
, char *buf
, size_t buflen
)
1676 (void) dis_snprintf(buf
, buflen
, "%s %s,%s", table
->drv_c_name
,
1677 dis_riscv_c_regs
[DIS_RISCV_C_RS1P(instr
)],
1678 dis_riscv_c_regs
[DIS_RISCV_C_RS2P(instr
)]);
1681 #define DIS_RISCV_CFUNCT3(name, class, op, funct, print) \
1682 { name, DIS_RISCV_C_FUNCT3, print, class, op, funct, 0, 0 }
1683 #define DIS_RISCV_CMATCH(name, class, op, funct, mask, match, print) \
1684 { name, DIS_RISCV_C_MATCH, print, class, op, funct, mask, match }
1686 static dis_riscv_c_instr_t dis_riscv_2byte
[] = {
1688 DIS_RISCV_CFUNCT3("c.addi4spn", DIS_RISCV_CL_32_64
, 0x0, 0x0,
1689 dis_riscv_c_addi4spn
),
1690 DIS_RISCV_CFUNCT3("c.fld", DIS_RISCV_CL_32_64
, 0x0, 0x01,
1692 DIS_RISCV_CFUNCT3("c.lw", DIS_RISCV_CL_ALL
, 0x0, 0x2,
1694 DIS_RISCV_CFUNCT3("c.flw", DIS_RISCV_CL_32
, 0x0, 0x3,
1696 DIS_RISCV_CFUNCT3("f.ld", DIS_RISCV_CL_64_128
, 0x0, 0x3,
1698 DIS_RISCV_CFUNCT3("c.fsd", DIS_RISCV_CL_32_64
, 0x0, 0x5,
1700 DIS_RISCV_CFUNCT3("c.sw", DIS_RISCV_CL_ALL
, 0x0, 0x6,
1702 DIS_RISCV_CFUNCT3("c.fsw", DIS_RISCV_CL_32
, 0x0, 0x7,
1704 DIS_RISCV_CFUNCT3("c.sd", DIS_RISCV_CL_64_128
, 0x0, 0x7,
1707 DIS_RISCV_CMATCH("c.nop", DIS_RISCV_CL_ALL
, 0x01, 0x00, 0x1ffc, 0x0,
1709 DIS_RISCV_CFUNCT3("c.addi", DIS_RISCV_CL_ALL
, 0x01, 0x00,
1710 dis_riscv_c_bigimmint
),
1711 DIS_RISCV_CFUNCT3("c.jal", DIS_RISCV_CL_32
, 0x01, 0x01,
1713 DIS_RISCV_CFUNCT3("c.addiw", DIS_RISCV_CL_64_128
, 0x01, 0x01,
1714 dis_riscv_c_bigimmint
),
1715 DIS_RISCV_CFUNCT3("c.li", DIS_RISCV_CL_ALL
, 0x01, 0x02,
1716 dis_riscv_c_bigimmint
),
1717 DIS_RISCV_CMATCH("c.addi16sp", DIS_RISCV_CL_ALL
, 0x01, 0x03, 0x0f80,
1718 0x0100, dis_riscv_c_addi16sp
),
1719 DIS_RISCV_CFUNCT3("c.lui", DIS_RISCV_CL_ALL
, 0x01, 0x03,
1720 dis_riscv_c_zext_bigimmint
),
1721 DIS_RISCV_CMATCH("c.srli", DIS_RISCV_CL_ALL
, 0x1, 0x4, 0x0c00, 0x0000,
1722 dis_riscv_c_zext_immint
),
1723 DIS_RISCV_CMATCH("c.srai", DIS_RISCV_CL_ALL
, 0x1, 0x4, 0x0c00, 0x0400,
1724 dis_riscv_c_zext_immint
),
1725 DIS_RISCV_CMATCH("c.andi", DIS_RISCV_CL_ALL
, 0x1, 0x4, 0x0c00, 0x0800,
1726 dis_riscv_c_immint
),
1727 DIS_RISCV_CMATCH("c.sub", DIS_RISCV_CL_ALL
, 0x1, 0x4, 0x1c60, 0x0c00,
1729 DIS_RISCV_CMATCH("c.xor", DIS_RISCV_CL_ALL
, 0x1, 0x4, 0x1c60, 0x0c20,
1731 DIS_RISCV_CMATCH("c.or", DIS_RISCV_CL_ALL
, 0x1, 0x4, 0x1c60, 0x0c40,
1733 DIS_RISCV_CMATCH("c.and", DIS_RISCV_CL_ALL
, 0x1, 0x4, 0x1c60, 0x0c60,
1735 DIS_RISCV_CMATCH("c.subw", DIS_RISCV_CL_64_128
, 0x1, 0x4, 0x1c60,
1736 0x1c00, dis_riscv_c_int
),
1737 DIS_RISCV_CMATCH("c.addw", DIS_RISCV_CL_64_128
, 0x1, 0x4, 0x1c60,
1738 0x1c20, dis_riscv_c_int
),
1739 DIS_RISCV_CFUNCT3("c.j", DIS_RISCV_CL_ALL
, 0x1, 0x5,
1741 DIS_RISCV_CFUNCT3("c.beqz", DIS_RISCV_CL_ALL
, 0x1, 0x6,
1742 dis_riscv_c_branch
),
1743 DIS_RISCV_CFUNCT3("c.bnez", DIS_RISCV_CL_ALL
, 0x1, 0x7,
1744 dis_riscv_c_branch
),
1746 DIS_RISCV_CFUNCT3("c.slli", DIS_RISCV_CL_ALL
, 0x2, 0x0,
1747 dis_riscv_c_zext_bigimmint
),
1748 DIS_RISCV_CFUNCT3("c.fldsp", DIS_RISCV_CL_32_64
, 0x2, 0x1,
1750 DIS_RISCV_CFUNCT3("c.lwsp", DIS_RISCV_CL_ALL
, 0x2, 0x2,
1752 DIS_RISCV_CFUNCT3("c.flwsp", DIS_RISCV_CL_32
, 0x2, 0x3,
1754 DIS_RISCV_CFUNCT3("c.ldsp", DIS_RISCV_CL_64_128
, 0x2, 0x3,
1756 DIS_RISCV_CMATCH("c.jr", DIS_RISCV_CL_ALL
, 0x2, 0x4, 0x107c, 0x0,
1758 DIS_RISCV_CMATCH("c.mv", DIS_RISCV_CL_ALL
, 0x2, 0x4, 0x1000, 0x0,
1759 dis_riscv_c_bigint
),
1760 DIS_RISCV_CMATCH("c.ebreak", DIS_RISCV_CL_ALL
, 0x2, 0x4, 0x1ffc, 0x1000,
1762 DIS_RISCV_CMATCH("c.jalr", DIS_RISCV_CL_ALL
, 0x2, 0x4, 0x107c, 0x1000,
1764 DIS_RISCV_CMATCH("c.add", DIS_RISCV_CL_ALL
, 0x2, 0x4, 0x1000, 0x1000,
1765 dis_riscv_c_bigint
),
1766 DIS_RISCV_CFUNCT3("c.fsdsp", DIS_RISCV_CL_32_64
, 0x2, 0x5,
1768 DIS_RISCV_CFUNCT3("c.swsp", DIS_RISCV_CL_ALL
, 0x2, 0x6,
1770 DIS_RISCV_CFUNCT3("c.fswsp", DIS_RISCV_CL_32
, 0x2, 0x7,
1772 DIS_RISCV_CFUNCT3("c.sdsp", DIS_RISCV_CL_64_128
, 0x2, 0x7,
1777 dis_riscv_decode_2byte(dis_handle_t
*dhp
, uint32_t instr
, char *buf
,
1782 for (i
= 0; i
< ARRAY_SIZE(dis_riscv_2byte
); i
++) {
1783 dis_riscv_c_instr_t
*t
= &dis_riscv_2byte
[i
];
1784 switch (t
->drv_c_class
) {
1785 case DIS_RISCV_CL_ALL
:
1787 case DIS_RISCV_CL_32
:
1788 if ((dhp
->dh_flags
& DIS_SIZE_32
) == 0)
1791 case DIS_RISCV_CL_64
:
1792 if ((dhp
->dh_flags
& DIS_SIZE_64
) == 0)
1795 case DIS_RISCV_CL_32_64
:
1796 if ((dhp
->dh_flags
&
1797 (DIS_SIZE_32
| DIS_SIZE_64
)) == 0) {
1801 case DIS_RISCV_CL_64_128
:
1802 if ((dhp
->dh_flags
& DIS_SIZE_64
) == 0)
1807 switch (t
->drv_c_type
) {
1808 case DIS_RISCV_C_FUNCT3
:
1809 if (DIS_RISCV_C_OPCODE(instr
) == t
->drv_c_opcode
&&
1810 DIS_RISCV_C_FUNCT3(instr
) == t
->drv_c_funct
) {
1814 case DIS_RISCV_C_MATCH
:
1815 if (DIS_RISCV_C_OPCODE(instr
) == t
->drv_c_opcode
&&
1816 DIS_RISCV_C_FUNCT3(instr
) == t
->drv_c_funct
&&
1817 ((instr
& t
->drv_c_mask
) == t
->drv_c_match
)) {
1825 t
->drv_c_print(dhp
, instr
, t
, buf
, buflen
);
1829 (void) dis_snprintf(buf
, buflen
, "<unknown>");
1834 * RISC-V instructions always come in parcels of two bytes. Read the next two
1835 * byte parcel and advance the address in the handle. Also, take care of endian
1836 * issues if required.
1839 dis_riscv_read_parcel(dis_handle_t
*dhp
, uint16_t *valp
)
1841 if ((dhp
->dh_addr
% 2) != 0)
1844 if (dhp
->dh_read(dhp
->dh_data
, dhp
->dh_addr
, valp
, sizeof (*valp
)) !=
1848 *valp
= LE_16(*valp
);
1856 * The first 'parcel' (uint16_t) of any instruction can be used to determine the
1857 * instruction length. This is derived from Section 1.2 Instruction Length
1858 * Encoding of Volume I: RISC-V User-Level ISA V2.2.
1860 * | xxxxxxxxxxxxxxaa | 16-bit iff aa != 11
1861 * | xxxxxxxxxxxbbb11 | 32-bit iff bbb != 111
1862 * | xxxxxxxxxx011111 | 48-bit iff bbb != 111
1863 * | xxxxxxxxx0111111 | 64-bit iff bbb != 111
1864 * | xnnnxxxxx1111111 | (80 + 16*nnn)-bit iff nnn != 111
1866 #define RISCV_LEN_16_MASK 0x0003
1867 #define RISCV_LEN_32_MASK 0x001c
1868 #define RISCV_LEN_48_MASK 0x0020
1869 #define RISCV_LEN_64_MASK 0x0040
1870 #define RISCV_LEN_80_MASK 0x7000
1871 #define RISCV_LEN_80_SHIFT 12
1874 dis_riscv_decode_len(uint16_t instr
)
1876 if ((instr
& RISCV_LEN_16_MASK
) != RISCV_LEN_16_MASK
)
1879 if ((instr
& RISCV_LEN_32_MASK
) != RISCV_LEN_32_MASK
)
1882 if ((instr
& RISCV_LEN_48_MASK
) != RISCV_LEN_48_MASK
)
1885 if ((instr
& RISCV_LEN_64_MASK
) != RISCV_LEN_64_MASK
)
1888 if ((instr
& RISCV_LEN_80_MASK
) != RISCV_LEN_80_MASK
) {
1889 uint_t factor
= (instr
& RISCV_LEN_80_MASK
) >>
1891 return ((10 + 2 * factor
));
1898 dis_riscv_supports_flags(int flags
)
1900 if ((flags
& DIS_ARCH_MASK
) == DIS_RISCV
&&
1901 DIS_SIZE_CHECK(flags
, DIS_SIZE_32
| DIS_SIZE_64
))
1908 dis_riscv_disassemble(dis_handle_t
*dhp
, uint64_t addr
, char *buf
,
1916 dhp
->dh_addr
= addr
;
1919 * All instructions have to be 2-byte aligned. Most have to be four byte
1920 * aligned, but we determine that after we decode the instruction size.
1921 * The 2-byte alignment check is done when we read the parcel.
1923 if (dis_riscv_read_parcel(dhp
, &parcel
) != 0)
1926 len
= dis_riscv_decode_len(parcel
);
1927 if (len
< 2 || (len
% 2) != 0)
1932 dis_riscv_decode_2byte(dhp
, instr
, buf
, buflen
);
1936 if (dis_riscv_read_parcel(dhp
, &parcel
) != 0)
1938 instr
|= parcel
<< 16;
1939 dis_riscv_decode_4byte(dhp
, instr
, buf
, buflen
);
1943 * This case represents a valid instruction length, but
1944 * something we don't understand. Treat this as an unknown
1945 * instruction. However, read the rest of the length of the
1946 * instruction to make sure that we read things correctly.
1948 (void) dis_snprintf(buf
, buflen
, "<unknown>");
1949 for (; len
> 0; len
-= 2) {
1950 if (dis_riscv_read_parcel(dhp
, &parcel
) != 0) {
1962 dis_riscv_min_instrlen(dis_handle_t
*dhp
)
1969 dis_riscv_max_instrlen(dis_handle_t
*dhp
)
1975 dis_riscv_instrlen(dis_handle_t
*dhp
, uint64_t addr
)
1980 dhp
->dh_addr
= addr
;
1982 if (dis_riscv_read_parcel(dhp
, &parcel
) != 0)
1986 * Get length based on this parcel. Check for required alignment. 2-byte
1987 * alignment was already taken care of when we read the parcel.
1989 ret
= dis_riscv_decode_len(parcel
);
1990 if (ret
>= 4 && (addr
% 4) != 0)
1996 dis_arch_t dis_arch_riscv
= {
1997 .da_supports_flags
= dis_riscv_supports_flags
,
1998 .da_disassemble
= dis_riscv_disassemble
,
1999 .da_min_instrlen
= dis_riscv_min_instrlen
,
2000 .da_max_instrlen
= dis_riscv_max_instrlen
,
2001 .da_instrlen
= dis_riscv_instrlen