Files
Yaya48 cf256aa081 Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
2026-08-31 02:15:30 +02:00

3544 lines
115 KiB
C

/*
* QEMU RISC-V Disassembler
*
* Copyright (c) 2016-2017 Michael Clark <[email protected]>
* Copyright (c) 2017-2018 SiFive, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "disas/dis-asm.h"
#include "target/riscv/cpu_cfg.h"
#include "disas/riscv.h"
/* Vendor extensions */
#include "disas/riscv-xthead.h"
#include "disas/riscv-xventana.h"
#include "disas/riscv-xlrbr.h"
/* register names */
static const char rv_ireg_name_sym[32][5] = {
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
};
static const char rv_freg_name_sym[32][5] = {
"ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
"fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
"fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
};
static const char rv_vreg_name_sym[32][4] = {
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
};
/* The FLI.[HSDQ] numeric constants (0.0 for symbolic constants).
* The constants use the hex floating-point literal representation
* that is printed when using the printf %a format specifier,
* which matches the output that is generated by the disassembler.
*/
static const char rv_fli_name_const[32][9] =
{
"0x1p+0", "min", "0x1p-16", "0x1p-15",
"0x1p-8", "0x1p-7", "0x1p-4", "0x1p-3",
"0x1p-2", "0x1.4p-2", "0x1.8p-2", "0x1.cp-2",
"0x1p-1", "0x1.4p-1", "0x1.8p-1", "0x1.cp-1",
"0x1p+0", "0x1.4p+0", "0x1.8p+0", "0x1.cp+0",
"0x1p+1", "0x1.4p+1", "0x1.8p+1", "0x1p+2",
"0x1p+3", "0x1p+4", "0x1p+7", "0x1p+8",
"0x1p+15", "0x1p+16", "inf", "nan"
};
/* pseudo-instruction constraints */
static const rvc_constraint rvcc_jal_ra[] = { rvc_rd_eq_ra, rvc_end };
static const rvc_constraint rvcc_jalr_ra[] = { rvc_rd_eq_ra, rvc_imm_eq_zero,
rvc_end };
static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0,
rvc_end };
static const rvc_constraint rvcc_mv[] = { rvc_imm_eq_zero, rvc_end };
static const rvc_constraint rvcc_not[] = { rvc_imm_eq_n1, rvc_end };
static const rvc_constraint rvcc_neg[] = { rvc_rs1_eq_x0, rvc_end };
static const rvc_constraint rvcc_negw[] = { rvc_rs1_eq_x0, rvc_end };
static const rvc_constraint rvcc_sext_w[] = { rvc_imm_eq_zero, rvc_end };
static const rvc_constraint rvcc_seqz[] = { rvc_imm_eq_p1, rvc_end };
static const rvc_constraint rvcc_snez[] = { rvc_rs1_eq_x0, rvc_end };
static const rvc_constraint rvcc_sltz[] = { rvc_rs2_eq_x0, rvc_end };
static const rvc_constraint rvcc_sgtz[] = { rvc_rs1_eq_x0, rvc_end };
static const rvc_constraint rvcc_fmv_s[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fabs_s[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fneg_s[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fmv_d[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fabs_d[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fneg_d[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fmv_q[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fabs_q[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_fneg_q[] = { rvc_rs2_eq_rs1, rvc_end };
static const rvc_constraint rvcc_beqz[] = { rvc_rs2_eq_x0, rvc_end };
static const rvc_constraint rvcc_bnez[] = { rvc_rs2_eq_x0, rvc_end };
static const rvc_constraint rvcc_blez[] = { rvc_rs1_eq_x0, rvc_end };
static const rvc_constraint rvcc_bgez[] = { rvc_rs2_eq_x0, rvc_end };
static const rvc_constraint rvcc_bltz[] = { rvc_rs2_eq_x0, rvc_end };
static const rvc_constraint rvcc_bgtz[] = { rvc_rs1_eq_x0, rvc_end };
static const rvc_constraint rvcc_j[] = { rvc_rd_eq_x0, rvc_end };
static const rvc_constraint rvcc_ret[] = { rvc_rs1_eq_ra, rvc_end };
static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero,
rvc_end };
static const rvc_constraint rvcc_true[] = { rvc_end };
/* pseudo-instruction metadata */
/* Forward declare the all the opcodes so that we may link them. */
#define OP(N, ...) static const rv_opcode_data op_##N;
#include "riscv-op.c.inc"
#undef OP
static const rv_comp_data rvcp_jal[] = {
{ &op_j, rvcc_j },
{ &op_jal_ra, rvcc_jal_ra },
{ },
};
static const rv_comp_data rvcp_jalr[] = {
{ &op_jr, rvcc_jr },
{ &op_jalr_ra, rvcc_jalr_ra },
{ },
};
static const rv_comp_data rvcp_jr[] = {
{ &op_ret, rvcc_ret },
{ },
};
static const rv_comp_data rvcp_beq[] = {
{ &op_beqz, rvcc_beqz },
{ },
};
static const rv_comp_data rvcp_bne[] = {
{ &op_bnez, rvcc_bnez },
{ },
};
static const rv_comp_data rvcp_blt[] = {
{ &op_bltz, rvcc_bltz },
{ &op_bgtz, rvcc_bgtz },
{ },
};
static const rv_comp_data rvcp_bge[] = {
{ &op_blez, rvcc_blez },
{ &op_bgez, rvcc_bgez },
{ },
};
static const rv_comp_data rvcp_addi[] = {
{ &op_mv, rvcc_mv },
{ },
};
static const rv_comp_data rvcp_mv[] = {
{ &op_nop, rvcc_nop },
{ },
};
static const rv_comp_data rvcp_sltiu[] = {
{ &op_seqz, rvcc_seqz },
{ },
};
static const rv_comp_data rvcp_xori[] = {
{ &op_not, rvcc_not },
{ },
};
static const rv_comp_data rvcp_sub[] = {
{ &op_neg, rvcc_neg },
{ },
};
static const rv_comp_data rvcp_slt[] = {
{ &op_sltz, rvcc_sltz },
{ &op_sgtz, rvcc_sgtz },
{ },
};
static const rv_comp_data rvcp_sltu[] = {
{ &op_snez, rvcc_snez },
{ },
};
static const rv_comp_data rvcp_addiw[] = {
{ &op_sext_w, rvcc_sext_w },
{ },
};
static const rv_comp_data rvcp_subw[] = {
{ &op_negw, rvcc_negw },
{ },
};
static const rv_comp_data rvcp_fsgnj_s[] = {
{ &op_fmv_s, rvcc_fmv_s },
{ },
};
static const rv_comp_data rvcp_fsgnjn_s[] = {
{ &op_fneg_s, rvcc_fneg_s },
{ },
};
static const rv_comp_data rvcp_fsgnjx_s[] = {
{ &op_fabs_s, rvcc_fabs_s },
{ },
};
static const rv_comp_data rvcp_fsgnj_d[] = {
{ &op_fmv_d, rvcc_fmv_d },
{ },
};
static const rv_comp_data rvcp_fsgnjn_d[] = {
{ &op_fneg_d, rvcc_fneg_d },
{ },
};
static const rv_comp_data rvcp_fsgnjx_d[] = {
{ &op_fabs_d, rvcc_fabs_d },
{ },
};
static const rv_comp_data rvcp_fsgnj_q[] = {
{ &op_fmv_q, rvcc_fmv_q },
{ },
};
static const rv_comp_data rvcp_fsgnjn_q[] = {
{ &op_fneg_q, rvcc_fneg_q },
{ },
};
static const rv_comp_data rvcp_fsgnjx_q[] = {
{ &op_fabs_q, rvcc_fabs_q },
{ },
};
/* Convert compressed insns into normal insns via pseudo expansion. */
#define DECOMP(X) &(const rv_comp_data){ &X, rvcc_true }
/* operand extractors */
static uint32_t operand_rd(rv_inst inst)
{
return extract32(inst, 7, 5);
}
static uint32_t operand_rs1(rv_inst inst)
{
return extract32(inst, 15, 5);
}
static uint32_t operand_rs2(rv_inst inst)
{
return extract32(inst, 20, 5);
}
static uint32_t operand_rs3(rv_inst inst)
{
return extract32(inst, 27, 5);
}
static uint32_t operand_aq(rv_inst inst)
{
return extract32(inst, 26, 1);
}
static uint32_t operand_rl(rv_inst inst)
{
return extract32(inst, 25, 1);
}
static uint32_t operand_pred(rv_inst inst)
{
return extract32(inst, 24, 4);
}
static uint32_t operand_succ(rv_inst inst)
{
return extract32(inst, 20, 4);
}
static uint32_t operand_rm(rv_inst inst)
{
return extract32(inst, 12, 3);
}
static uint32_t operand_shamt5(rv_inst inst)
{
return extract32(inst, 20, 5);
}
static uint32_t operand_shamt6(rv_inst inst)
{
return extract32(inst, 20, 6);
}
static uint32_t operand_shamt7(rv_inst inst)
{
return extract32(inst, 20, 7);
}
static uint32_t operand_crdq(rv_inst inst)
{
return extract32(inst, 2, 3);
}
static uint32_t operand_crs1q(rv_inst inst)
{
return extract32(inst, 7, 3);
}
static uint32_t operand_crs1rdq(rv_inst inst)
{
return extract32(inst, 7, 3);
}
static uint32_t operand_crs2q(rv_inst inst)
{
return extract32(inst, 2, 3);
}
static uint32_t calculate_xreg(uint32_t sreg)
{
return sreg < 2 ? sreg + 8 : sreg + 16;
}
static uint32_t operand_sreg1(rv_inst inst)
{
return calculate_xreg(extract32(inst, 7, 3));
}
static uint32_t operand_sreg2(rv_inst inst)
{
return calculate_xreg(extract32(inst, 2, 3));
}
static uint32_t operand_crd(rv_inst inst)
{
return extract32(inst, 7, 5);
}
static uint32_t operand_crs1(rv_inst inst)
{
return extract32(inst, 7, 5);
}
static uint32_t operand_crs1rd(rv_inst inst)
{
return extract32(inst, 7, 5);
}
static uint32_t operand_crs2(rv_inst inst)
{
return extract32(inst, 2, 5);
}
static uint32_t operand_cimmsh5(rv_inst inst)
{
return extract32(inst, 2, 5);
}
static uint32_t operand_csr12(rv_inst inst)
{
return extract32(inst, 20, 12);
}
static int32_t operand_imm12(rv_inst inst)
{
return sextract32(inst, 20, 12);
}
static int32_t operand_imm20(rv_inst inst)
{
return sextract32(inst, 12, 20) << 12;
}
static int32_t operand_jimm20(rv_inst inst)
{
return sextract32(inst, 31, 1) << 20 |
extract32(inst, 21, 10) << 1 |
extract32(inst, 20, 1) << 11 |
extract32(inst, 12, 8) << 12;
}
static int32_t operand_simm12(rv_inst inst)
{
return sextract32(inst, 25, 7) << 5 |
extract32(inst, 7, 5);
}
static int32_t operand_sbimm12(rv_inst inst)
{
return sextract32(inst, 31, 1) << 12 |
extract32(inst, 25, 6) << 5 |
extract32(inst, 8, 4) << 1 |
extract32(inst, 7, 1) << 11;
}
static uint32_t operand_cimmshl6(rv_inst inst, rv_isa isa)
{
int imm = extract32(inst, 12, 1) << 5 |
extract32(inst, 2, 5);
if (isa == rv128) {
imm = imm ? imm : 64;
}
return imm;
}
static uint32_t operand_cimmshr6(rv_inst inst, rv_isa isa)
{
int imm = extract32(inst, 12, 1) << 5 |
extract32(inst, 2, 5);
if (isa == rv128) {
imm = imm | (imm & 32) << 1;
imm = imm ? imm : 64;
}
return imm;
}
static int32_t operand_cimmi(rv_inst inst)
{
return sextract32(inst, 12, 1) << 5 |
extract32(inst, 2, 5);
}
static int32_t operand_cimmui(rv_inst inst)
{
return sextract32(inst, 12, 1) << 17 |
extract32(inst, 2, 5) << 12;
}
static uint32_t operand_cimmlwsp(rv_inst inst)
{
return extract32(inst, 12, 1) << 5 |
extract32(inst, 4, 3) << 2 |
extract32(inst, 2, 2) << 6;
}
static uint32_t operand_cimmldsp(rv_inst inst)
{
return extract32(inst, 12, 1) << 5 |
extract32(inst, 5, 2) << 3 |
extract32(inst, 2, 3) << 6;
}
static uint32_t operand_cimmlqsp(rv_inst inst)
{
return extract32(inst, 12, 1) << 5 |
extract32(inst, 6, 1) << 4 |
extract32(inst, 2, 4) << 6;
}
static int32_t operand_cimm16sp(rv_inst inst)
{
return sextract32(inst, 12, 1) << 9 |
extract32(inst, 6, 1) << 4 |
extract32(inst, 5, 1) << 6 |
extract32(inst, 3, 2) << 7 |
extract32(inst, 2, 1) << 5;
}
static int32_t operand_cimmj(rv_inst inst)
{
return sextract32(inst, 12, 1) << 11 |
extract32(inst, 11, 1) << 4 |
extract32(inst, 9, 2) << 8 |
extract32(inst, 8, 1) << 10 |
extract32(inst, 7, 1) << 6 |
extract32(inst, 6, 1) << 7 |
extract32(inst, 3, 3) << 1 |
extract32(inst, 2, 1) << 5;
}
static int32_t operand_cimmb(rv_inst inst)
{
return sextract32(inst, 12, 1) << 8 |
extract32(inst, 10, 2) << 3 |
extract32(inst, 5, 2) << 6 |
extract32(inst, 3, 2) << 1 |
extract32(inst, 2, 1) << 5;
}
static uint32_t operand_cimmswsp(rv_inst inst)
{
return extract32(inst, 9, 4) << 2 |
extract32(inst, 7, 2) << 6;
}
static uint32_t operand_cimmsdsp(rv_inst inst)
{
return extract32(inst, 10, 3) << 3 |
extract32(inst, 7, 3) << 6;
}
static uint32_t operand_cimmsqsp(rv_inst inst)
{
return extract32(inst, 11, 2) << 4 |
extract32(inst, 7, 4) << 6;
}
static uint32_t operand_cimm4spn(rv_inst inst)
{
return extract32(inst, 11, 2) << 4 |
extract32(inst, 7, 4) << 6 |
extract32(inst, 6, 1) << 2 |
extract32(inst, 5, 1) << 3;
}
static uint32_t operand_cimmw(rv_inst inst)
{
return extract32(inst, 10, 3) << 3 |
extract32(inst, 6, 1) << 2 |
extract32(inst, 5, 1) << 6;
}
static uint32_t operand_cimmd(rv_inst inst)
{
return extract32(inst, 10, 3) << 3 |
extract32(inst, 5, 2) << 6;
}
static uint32_t operand_cimmq(rv_inst inst)
{
return extract32(inst, 11, 2) << 4 |
extract32(inst, 10, 1) << 8 |
extract32(inst, 5, 2) << 6;
}
static int32_t operand_vimm(rv_inst inst)
{
return sextract32(inst, 15, 5);
}
static uint32_t operand_vuimm(rv_inst inst)
{
return extract32(inst, 15, 5);
}
static uint32_t operand_vzimm11(rv_inst inst)
{
return extract32(inst, 20, 11);
}
static uint32_t operand_vzimm10(rv_inst inst)
{
return extract32(inst, 20, 10);
}
static uint32_t operand_vzimm6(rv_inst inst)
{
return extract32(inst, 26, 1) << 5 |
extract32(inst, 15, 5);
}
static uint32_t operand_bs(rv_inst inst)
{
return extract32(inst, 30, 2);
}
static uint32_t operand_rnum(rv_inst inst)
{
return extract32(inst, 20, 4);
}
static uint32_t operand_vm(rv_inst inst)
{
return extract32(inst, 25, 1);
}
static uint32_t operand_uimm_c_lb(rv_inst inst)
{
return extract32(inst, 5, 1) << 1 |
extract32(inst, 6, 1);
}
static uint32_t operand_uimm_c_lh(rv_inst inst)
{
return extract32(inst, 5, 1) << 1;
}
static uint32_t operand_zcmp_spimm(rv_inst inst)
{
return extract32(inst, 2, 2) << 4;
}
static uint32_t operand_zcmp_rlist(rv_inst inst)
{
return extract32(inst, 4, 4);
}
static uint32_t operand_imm6(rv_inst inst)
{
return extract32(inst, 20, 6);
}
static uint32_t operand_imm2(rv_inst inst)
{
return extract32(inst, 25, 2);
}
static uint32_t operand_immh(rv_inst inst)
{
return extract32(inst, 26, 6);
}
static uint32_t operand_imml(rv_inst inst)
{
return extract32(inst, 20, 6);
}
static uint32_t calculate_stack_adj(rv_isa isa, uint32_t rlist, uint32_t spimm)
{
int xlen_bytes_log2 = isa == rv64 ? 3 : 2;
int regs = rlist == 15 ? 13 : rlist - 3;
uint32_t stack_adj_base = ROUND_UP(regs << xlen_bytes_log2, 16);
return stack_adj_base + spimm;
}
static uint32_t operand_zcmp_stack_adj(rv_inst inst, rv_isa isa)
{
return calculate_stack_adj(isa, operand_zcmp_rlist(inst),
operand_zcmp_spimm(inst));
}
static uint32_t operand_tbl_index(rv_inst inst)
{
return extract32(inst, 2, 8);
}
static uint32_t operand_lpl(rv_inst inst)
{
return extract32(inst, 12, 20);
}
static uint32_t operand_cmop_imm(rv_inst inst)
{
return extract32(inst, 8, 3) * 2 + 1;
}
static uint32_t operand_mop_r_imm(rv_inst inst)
{
return (extract32(inst, 30, 1) << 4) |
(extract32(inst, 26, 2) << 2) |
extract32(inst, 20, 2);
}
static uint32_t operand_mop_rr_imm(rv_inst inst)
{
return (extract32(inst, 30, 1) << 2) | extract32(inst, 26, 2);
}
/* instruction metadata */
#define OP(N, ...) static const rv_opcode_data op_##N = { __VA_ARGS__ };
#include "riscv-op.c.inc"
#undef OP
/* CSR names */
static const char *csr_name(int csrno)
{
switch (csrno) {
case 0x0000: return "ustatus";
case 0x0001: return "fflags";
case 0x0002: return "frm";
case 0x0003: return "fcsr";
case 0x0004: return "uie";
case 0x0005: return "utvec";
case 0x0008: return "vstart";
case 0x0009: return "vxsat";
case 0x000a: return "vxrm";
case 0x000f: return "vcsr";
case 0x0011: return "ssp";
case 0x0015: return "seed";
case 0x0017: return "jvt";
case 0x0040: return "uscratch";
case 0x0041: return "uepc";
case 0x0042: return "ucause";
case 0x0043: return "utval";
case 0x0044: return "uip";
case 0x0100: return "sstatus";
case 0x0104: return "sie";
case 0x0105: return "stvec";
case 0x0106: return "scounteren";
case 0x0140: return "sscratch";
case 0x0141: return "sepc";
case 0x0142: return "scause";
case 0x0143: return "stval";
case 0x0144: return "sip";
case 0x0180: return "satp";
case 0x0200: return "hstatus";
case 0x0202: return "hedeleg";
case 0x0203: return "hideleg";
case 0x0204: return "hie";
case 0x0205: return "htvec";
case 0x0240: return "hscratch";
case 0x0241: return "hepc";
case 0x0242: return "hcause";
case 0x0243: return "hbadaddr";
case 0x0244: return "hip";
case 0x0300: return "mstatus";
case 0x0301: return "misa";
case 0x0302: return "medeleg";
case 0x0303: return "mideleg";
case 0x0304: return "mie";
case 0x0305: return "mtvec";
case 0x0306: return "mcounteren";
case 0x0320: return "mucounteren";
case 0x0321: return "mscounteren";
case 0x0322: return "mhcounteren";
case 0x0323: return "mhpmevent3";
case 0x0324: return "mhpmevent4";
case 0x0325: return "mhpmevent5";
case 0x0326: return "mhpmevent6";
case 0x0327: return "mhpmevent7";
case 0x0328: return "mhpmevent8";
case 0x0329: return "mhpmevent9";
case 0x032a: return "mhpmevent10";
case 0x032b: return "mhpmevent11";
case 0x032c: return "mhpmevent12";
case 0x032d: return "mhpmevent13";
case 0x032e: return "mhpmevent14";
case 0x032f: return "mhpmevent15";
case 0x0330: return "mhpmevent16";
case 0x0331: return "mhpmevent17";
case 0x0332: return "mhpmevent18";
case 0x0333: return "mhpmevent19";
case 0x0334: return "mhpmevent20";
case 0x0335: return "mhpmevent21";
case 0x0336: return "mhpmevent22";
case 0x0337: return "mhpmevent23";
case 0x0338: return "mhpmevent24";
case 0x0339: return "mhpmevent25";
case 0x033a: return "mhpmevent26";
case 0x033b: return "mhpmevent27";
case 0x033c: return "mhpmevent28";
case 0x033d: return "mhpmevent29";
case 0x033e: return "mhpmevent30";
case 0x033f: return "mhpmevent31";
case 0x0340: return "mscratch";
case 0x0341: return "mepc";
case 0x0342: return "mcause";
case 0x0343: return "mtval";
case 0x0344: return "mip";
case 0x0380: return "mbase";
case 0x0381: return "mbound";
case 0x0382: return "mibase";
case 0x0383: return "mibound";
case 0x0384: return "mdbase";
case 0x0385: return "mdbound";
case 0x03a0: return "pmpcfg0";
case 0x03a1: return "pmpcfg1";
case 0x03a2: return "pmpcfg2";
case 0x03a3: return "pmpcfg3";
case 0x03a4: return "pmpcfg4";
case 0x03a5: return "pmpcfg5";
case 0x03a6: return "pmpcfg6";
case 0x03a7: return "pmpcfg7";
case 0x03a8: return "pmpcfg8";
case 0x03a9: return "pmpcfg9";
case 0x03aa: return "pmpcfg10";
case 0x03ab: return "pmpcfg11";
case 0x03ac: return "pmpcfg12";
case 0x03ad: return "pmpcfg13";
case 0x03ae: return "pmpcfg14";
case 0x03af: return "pmpcfg15";
case 0x03b0: return "pmpaddr0";
case 0x03b1: return "pmpaddr1";
case 0x03b2: return "pmpaddr2";
case 0x03b3: return "pmpaddr3";
case 0x03b4: return "pmpaddr4";
case 0x03b5: return "pmpaddr5";
case 0x03b6: return "pmpaddr6";
case 0x03b7: return "pmpaddr7";
case 0x03b8: return "pmpaddr8";
case 0x03b9: return "pmpaddr9";
case 0x03ba: return "pmpaddr10";
case 0x03bb: return "pmpaddr11";
case 0x03bc: return "pmpaddr12";
case 0x03bd: return "pmpaddr13";
case 0x03be: return "pmpaddr14";
case 0x03bf: return "pmpaddr15";
case 0x03c0: return "pmpaddr16";
case 0x03c1: return "pmpaddr17";
case 0x03c2: return "pmpaddr18";
case 0x03c3: return "pmpaddr19";
case 0x03c4: return "pmpaddr20";
case 0x03c5: return "pmpaddr21";
case 0x03c6: return "pmpaddr22";
case 0x03c7: return "pmpaddr23";
case 0x03c8: return "pmpaddr24";
case 0x03c9: return "pmpaddr25";
case 0x03ca: return "pmpaddr26";
case 0x03cb: return "pmpaddr27";
case 0x03cc: return "pmpaddr28";
case 0x03cd: return "pmpaddr29";
case 0x03ce: return "pmpaddr30";
case 0x03cf: return "pmpaddr31";
case 0x03d0: return "pmpaddr32";
case 0x03d1: return "pmpaddr33";
case 0x03d2: return "pmpaddr34";
case 0x03d3: return "pmpaddr35";
case 0x03d4: return "pmpaddr36";
case 0x03d5: return "pmpaddr37";
case 0x03d6: return "pmpaddr38";
case 0x03d7: return "pmpaddr39";
case 0x03d8: return "pmpaddr40";
case 0x03d9: return "pmpaddr41";
case 0x03da: return "pmpaddr42";
case 0x03db: return "pmpaddr43";
case 0x03dc: return "pmpaddr44";
case 0x03dd: return "pmpaddr45";
case 0x03de: return "pmpaddr46";
case 0x03df: return "pmpaddr47";
case 0x03e0: return "pmpaddr48";
case 0x03e1: return "pmpaddr49";
case 0x03e2: return "pmpaddr50";
case 0x03e3: return "pmpaddr51";
case 0x03e4: return "pmpaddr52";
case 0x03e5: return "pmpaddr53";
case 0x03e6: return "pmpaddr54";
case 0x03e7: return "pmpaddr55";
case 0x03e8: return "pmpaddr56";
case 0x03e9: return "pmpaddr57";
case 0x03ea: return "pmpaddr58";
case 0x03eb: return "pmpaddr59";
case 0x03ec: return "pmpaddr60";
case 0x03ed: return "pmpaddr61";
case 0x03ee: return "pmpaddr62";
case 0x03ef: return "pmpaddr63";
case 0x0780: return "mtohost";
case 0x0781: return "mfromhost";
case 0x0782: return "mreset";
case 0x0783: return "mipi";
case 0x0784: return "miobase";
case 0x07a0: return "tselect";
case 0x07a1: return "tdata1";
case 0x07a2: return "tdata2";
case 0x07a3: return "tdata3";
case 0x07a4: return "tinfo";
case 0x07b0: return "dcsr";
case 0x07b1: return "dpc";
case 0x07b2: return "dscratch0";
case 0x07b3: return "dscratch1";
case 0x0b00: return "mcycle";
case 0x0b01: return "mtime";
case 0x0b02: return "minstret";
case 0x0b03: return "mhpmcounter3";
case 0x0b04: return "mhpmcounter4";
case 0x0b05: return "mhpmcounter5";
case 0x0b06: return "mhpmcounter6";
case 0x0b07: return "mhpmcounter7";
case 0x0b08: return "mhpmcounter8";
case 0x0b09: return "mhpmcounter9";
case 0x0b0a: return "mhpmcounter10";
case 0x0b0b: return "mhpmcounter11";
case 0x0b0c: return "mhpmcounter12";
case 0x0b0d: return "mhpmcounter13";
case 0x0b0e: return "mhpmcounter14";
case 0x0b0f: return "mhpmcounter15";
case 0x0b10: return "mhpmcounter16";
case 0x0b11: return "mhpmcounter17";
case 0x0b12: return "mhpmcounter18";
case 0x0b13: return "mhpmcounter19";
case 0x0b14: return "mhpmcounter20";
case 0x0b15: return "mhpmcounter21";
case 0x0b16: return "mhpmcounter22";
case 0x0b17: return "mhpmcounter23";
case 0x0b18: return "mhpmcounter24";
case 0x0b19: return "mhpmcounter25";
case 0x0b1a: return "mhpmcounter26";
case 0x0b1b: return "mhpmcounter27";
case 0x0b1c: return "mhpmcounter28";
case 0x0b1d: return "mhpmcounter29";
case 0x0b1e: return "mhpmcounter30";
case 0x0b1f: return "mhpmcounter31";
case 0x0b80: return "mcycleh";
case 0x0b81: return "mtimeh";
case 0x0b82: return "minstreth";
case 0x0b83: return "mhpmcounter3h";
case 0x0b84: return "mhpmcounter4h";
case 0x0b85: return "mhpmcounter5h";
case 0x0b86: return "mhpmcounter6h";
case 0x0b87: return "mhpmcounter7h";
case 0x0b88: return "mhpmcounter8h";
case 0x0b89: return "mhpmcounter9h";
case 0x0b8a: return "mhpmcounter10h";
case 0x0b8b: return "mhpmcounter11h";
case 0x0b8c: return "mhpmcounter12h";
case 0x0b8d: return "mhpmcounter13h";
case 0x0b8e: return "mhpmcounter14h";
case 0x0b8f: return "mhpmcounter15h";
case 0x0b90: return "mhpmcounter16h";
case 0x0b91: return "mhpmcounter17h";
case 0x0b92: return "mhpmcounter18h";
case 0x0b93: return "mhpmcounter19h";
case 0x0b94: return "mhpmcounter20h";
case 0x0b95: return "mhpmcounter21h";
case 0x0b96: return "mhpmcounter22h";
case 0x0b97: return "mhpmcounter23h";
case 0x0b98: return "mhpmcounter24h";
case 0x0b99: return "mhpmcounter25h";
case 0x0b9a: return "mhpmcounter26h";
case 0x0b9b: return "mhpmcounter27h";
case 0x0b9c: return "mhpmcounter28h";
case 0x0b9d: return "mhpmcounter29h";
case 0x0b9e: return "mhpmcounter30h";
case 0x0b9f: return "mhpmcounter31h";
case 0x0c00: return "cycle";
case 0x0c01: return "time";
case 0x0c02: return "instret";
case 0x0c20: return "vl";
case 0x0c21: return "vtype";
case 0x0c22: return "vlenb";
case 0x0c80: return "cycleh";
case 0x0c81: return "timeh";
case 0x0c82: return "instreth";
case 0x0d00: return "scycle";
case 0x0d01: return "stime";
case 0x0d02: return "sinstret";
case 0x0d80: return "scycleh";
case 0x0d81: return "stimeh";
case 0x0d82: return "sinstreth";
case 0x0e00: return "hcycle";
case 0x0e01: return "htime";
case 0x0e02: return "hinstret";
case 0x0e80: return "hcycleh";
case 0x0e81: return "htimeh";
case 0x0e82: return "hinstreth";
case 0x0f11: return "mvendorid";
case 0x0f12: return "marchid";
case 0x0f13: return "mimpid";
case 0x0f14: return "mhartid";
default: return NULL;
}
}
/* decode opcode */
static const rv_opcode_data *decode_inst_opcode(rv_decode *dec, rv_isa isa)
{
rv_inst inst = dec->inst;
switch ((inst >> 0) & 0b11) {
case 0:
switch ((inst >> 13) & 0b111) {
case 0:
if ((inst >> 5) & 0xff) {
return &op_c_addi4spn;
}
break;
case 1:
if (isa == rv128) {
return &op_c_lq;
}
return &op_c_fld;
case 2: return &op_c_lw;
case 3:
if (isa == rv32) {
return &op_c_flw;
}
return &op_c_ld;
case 4:
switch ((inst >> 10) & 0b111) {
case 0: return &op_c_lbu;
case 1:
if (((inst >> 6) & 1) == 0) {
return &op_c_lhu;
}
return &op_c_lh;
case 2: return &op_c_sb;
case 3:
if (((inst >> 6) & 1) == 0) {
return &op_c_sh;
}
break;
}
break;
case 5:
if (isa == rv128) {
return &op_c_sq;
}
return &op_c_fsd;
case 6: return &op_c_sw;
case 7:
if (isa == rv32) {
return &op_c_fsw;
}
return &op_c_sd;
}
break;
case 1:
switch ((inst >> 13) & 0b111) {
case 0:
return &op_c_addi; /* or unspecified HINT */
case 1:
if (isa == rv32) {
return &op_c_jal;
}
return &op_c_addiw;
case 2: return &op_c_li;
case 3:
if (dec->cfg
&& dec->cfg->ext_zcmop
&& ((inst >> 2) & 0b111111) == 0b100000
&& ((inst >> 11) & 0b11) == 0) {
if (dec->cfg->ext_zicfiss) {
switch (operand_cmop_imm(inst)) {
case 1: return &op_c_sspush;
case 5: return &op_c_sspopchk;
}
}
return &op_c_mop;
}
if (inst & ((1 << 12) | (0x1f << 2))) {
switch ((inst >> 7) & 0b11111) {
case 2: return &op_c_addi16sp;
default: return &op_c_lui;
}
}
break;
case 4:
switch ((inst >> 10) & 0b11) {
case 0:
/* For rv32, shamt[5]=1 is designated for custom extensions. */
if (isa != rv32 || (inst & 0x1000) == 0) {
return &op_c_srli; /* or unspecified HINT */
}
break;
case 1:
/* For rv32, shamt[5]=1 is designated for custom extensions. */
if (isa != rv32 || (inst & 0x1000) == 0) {
return &op_c_srai; /* or unspecified HINT */
}
break;
case 2: return &op_c_andi;
case 3:
switch (((inst >> 10) & 0b100) | ((inst >> 5) & 0b011)) {
case 0: return &op_c_sub;
case 1: return &op_c_xor;
case 2: return &op_c_or;
case 3: return &op_c_and;
case 4:
if (isa != rv32) {
return &op_c_subw;
}
break;
case 5:
if (isa != rv32) {
return &op_c_addw;
}
break;
case 6: return &op_c_mul;
case 7:
switch ((inst >> 2) & 0b111) {
case 0: return &op_c_zext_b;
case 1: return &op_c_sext_b;
case 2: return &op_c_zext_h;
case 3: return &op_c_sext_h;
case 4: return &op_c_zext_w;
case 5: return &op_c_not;
}
break;
}
break;
}
break;
case 5: return &op_c_j;
case 6: return &op_c_beqz;
case 7: return &op_c_bnez;
}
break;
case 2:
switch ((inst >> 13) & 0b111) {
case 0:
if (isa != rv32 || (inst & 0x1000) == 0) {
return &op_c_slli; /* or unspecified HINT */
}
break;
case 1:
if (isa == rv128) {
return &op_c_lqsp;
}
return &op_c_fldsp;
case 2: return &op_c_lwsp;
case 3:
if (isa == rv32) {
return &op_c_flwsp;
}
return &op_c_ldsp;
case 4:
switch ((inst >> 12) & 0b1) {
case 0:
switch ((inst >> 2) & 0b11111) {
case 0: return &op_c_jr;
default: return &op_c_mv;
}
break;
case 1:
switch ((inst >> 2) & 0b11111) {
case 0:
switch ((inst >> 7) & 0b11111) {
case 0: return &op_c_ebreak;
default: return &op_c_jalr;
}
break;
default: return &op_c_add;
}
break;
}
break;
case 5:
if (isa == rv128) {
return &op_c_sqsp;
}
if (dec->cfg) {
if (dec->cfg->ext_zcmp && ((inst >> 12) & 0b01)) {
switch ((inst >> 8) & 0b01111) {
case 8:
if (((inst >> 4) & 0b01111) >= 4) {
return &op_cm_push;
}
break;
case 10:
if (((inst >> 4) & 0b01111) >= 4) {
return &op_cm_pop;
}
break;
case 12:
if (((inst >> 4) & 0b01111) >= 4) {
return &op_cm_popretz;
}
break;
case 14:
if (((inst >> 4) & 0b01111) >= 4) {
return &op_cm_popret;
}
break;
}
}
switch ((inst >> 10) & 0b011) {
case 0:
if (!dec->cfg->ext_zcmt) {
break;
}
if (((inst >> 2) & 0xFF) >= 32) {
return &op_cm_jalt;
}
return &op_cm_jt;
case 3:
if (!dec->cfg->ext_zcmp) {
break;
}
switch ((inst >> 5) & 0b011) {
case 1: return &op_cm_mvsa01;
case 3: return &op_cm_mva01s;
}
break;
}
}
return &op_c_fsdsp;
case 6: return &op_c_swsp;
case 7:
if (isa == rv32) {
return &op_c_fswsp;
}
return &op_c_sdsp;
}
break;
case 3:
switch ((inst >> 2) & 0b11111) {
case 0:
switch ((inst >> 12) & 0b111) {
case 0: return &op_lb;
case 1: return &op_lh;
case 2: return &op_lw;
case 3: return &op_ld;
case 4: return &op_lbu;
case 5: return &op_lhu;
case 6: return &op_lwu;
case 7: return &op_ldu;
}
break;
case 1:
switch ((inst >> 12) & 0b111) {
case 0:
switch ((inst >> 20) & 0b111111111111) {
case 40: return &op_vl1re8_v;
case 552: return &op_vl2re8_v;
case 1576: return &op_vl4re8_v;
case 3624: return &op_vl8re8_v;
}
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vle8_v;
case 11: return &op_vlm_v;
case 16: return &op_vle8ff_v;
}
break;
case 1: return &op_vluxei8_v;
case 2: return &op_vlse8_v;
case 3: return &op_vloxei8_v;
}
break;
case 1: return &op_flh;
case 2: return &op_flw;
case 3: return &op_fld;
case 4: return &op_flq;
case 5:
switch ((inst >> 20) & 0b111111111111) {
case 40: return &op_vl1re16_v;
case 552: return &op_vl2re16_v;
case 1576: return &op_vl4re16_v;
case 3624: return &op_vl8re16_v;
}
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vle16_v;
case 16: return &op_vle16ff_v;
}
break;
case 1: return &op_vluxei16_v;
case 2: return &op_vlse16_v;
case 3: return &op_vloxei16_v;
}
break;
case 6:
switch ((inst >> 20) & 0b111111111111) {
case 40: return &op_vl1re32_v;
case 552: return &op_vl2re32_v;
case 1576: return &op_vl4re32_v;
case 3624: return &op_vl8re32_v;
}
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vle32_v;
case 16: return &op_vle32ff_v;
}
break;
case 1: return &op_vluxei32_v;
case 2: return &op_vlse32_v;
case 3: return &op_vloxei32_v;
}
break;
case 7:
switch ((inst >> 20) & 0b111111111111) {
case 40: return &op_vl1re64_v;
case 552: return &op_vl2re64_v;
case 1576: return &op_vl4re64_v;
case 3624: return &op_vl8re64_v;
}
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vle64_v;
case 16: return &op_vle64ff_v;
}
break;
case 1: return &op_vluxei64_v;
case 2: return &op_vlse64_v;
case 3: return &op_vloxei64_v;
}
break;
}
break;
case 3:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fence;
case 1: return &op_fence_i;
case 2:
/*
* 'lq' shares the "(...) 010 ..... 0001111" opcode space
* with 'cbo' insns. Check the next 5 bits to select
* what we want:
*
* cbo_inval 0000000 00000 ..... 010 00000 0001111
* cbo_clean 0000000 00001 ..... 010 00000 0001111
* cbo_flush 0000000 00010 ..... 010 00000 0001111
* cbo_zero 0000000 00100 ..... 010 00000 0001111
*
* Anything that doesn't match these will default to 'lq'.
*/
switch ((inst >> 17) & 0b11111) {
case 0: return &op_cbo_inval;
case 1: return &op_cbo_clean;
case 2: return &op_cbo_flush;
case 4: return &op_cbo_zero;
default: return &op_lq;
}
}
break;
case 4:
switch ((inst >> 12) & 0b111) {
case 0: return &op_addi;
case 1:
switch ((inst >> 27) & 0b11111) {
case 0b00000: return &op_slli;
case 0b00001:
switch ((inst >> 20) & 0b1111111) {
case 0b0001111: return &op_zip;
}
break;
case 0b00010:
switch ((inst >> 20) & 0b1111111) {
case 0b0000000: return &op_sha256sum0;
case 0b0000001: return &op_sha256sum1;
case 0b0000010: return &op_sha256sig0;
case 0b0000011: return &op_sha256sig1;
case 0b0000100: return &op_sha512sum0;
case 0b0000101: return &op_sha512sum1;
case 0b0000110: return &op_sha512sig0;
case 0b0000111: return &op_sha512sig1;
case 0b0001000: return &op_sm3p0;
case 0b0001001: return &op_sm3p1;
}
break;
case 0b00101: return &op_bseti;
case 0b00110:
switch ((inst >> 20) & 0b1111111) {
case 0b0000000: return &op_aes64im;
default:
if (((inst >> 24) & 0b0111) == 0b001) {
return &op_aes64ks1i;
}
break;
}
break;
case 0b01001: return &op_bclri;
case 0b01101: return &op_binvi;
case 0b01100:
switch ((inst >> 20) & 0b1111111) {
case 0b0000000: return &op_clz;
case 0b0000001: return &op_ctz;
case 0b0000010: return &op_cpop;
/* 0b0000011 */
case 0b0000100: return &op_sext_b;
case 0b0000101: return &op_sext_h;
}
break;
}
break;
case 2: return &op_slti;
case 3: return &op_sltiu;
case 4: return &op_xori;
case 5:
switch ((inst >> 27) & 0b11111) {
case 0b00000: return &op_srli;
case 0b00001:
switch ((inst >> 20) & 0b1111111) {
case 0b0001111: return &op_unzip;
}
break;
case 0b00101: return &op_orc_b;
case 0b01000: return &op_srai;
case 0b01001: return &op_bexti;
case 0b01100: return &op_rori;
case 0b01101:
switch ((inst >> 20) & 0b1111111) {
case 0b0011000:
if (isa == rv32) {
return &op_rev8;
}
break;
case 0b0111000:
if (isa == rv64) {
return &op_rev8;
}
break;
case 0b0000111: return &op_brev8;
}
break;
}
break;
case 6: return &op_ori;
case 7: return &op_andi;
}
break;
case 5:
if (dec->cfg && dec->cfg->ext_zicfilp &&
(((inst >> 7) & 0b11111) == 0b00000)) {
return &op_lpad;
}
return &op_auipc;
case 6:
/* OP-IMM-32 */
if (isa == rv32) {
break;
}
switch ((inst >> 12) & 0b111) {
case 0: return &op_addiw;
case 1:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_slliw;
case 2: return &op_slli_uw;
case 24:
switch ((inst >> 20) & 0b11111) {
case 0b00000: return &op_clzw;
case 0b00001: return &op_ctzw;
case 0b00010: return &op_cpopw;
}
break;
}
break;
case 5:
switch ((inst >> 25) & 0b1111111) {
case 0: return &op_srliw;
case 32: return &op_sraiw;
case 48: return &op_roriw;
}
break;
}
break;
case 8:
switch ((inst >> 12) & 0b111) {
case 0: return &op_sb;
case 1: return &op_sh;
case 2: return &op_sw;
case 3: return &op_sd;
case 4: return &op_sq;
}
break;
case 9:
switch ((inst >> 12) & 0b111) {
case 0:
switch ((inst >> 20) & 0b111111111111) {
case 40: return &op_vs1r_v;
case 552: return &op_vs2r_v;
case 1576: return &op_vs4r_v;
case 3624: return &op_vs8r_v;
}
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vse8_v;
case 11: return &op_vsm_v;
}
break;
case 1: return &op_vsuxei8_v;
case 2: return &op_vsse8_v;
case 3: return &op_vsoxei8_v;
}
break;
case 1: return &op_fsh;
case 2: return &op_fsw;
case 3: return &op_fsd;
case 4: return &op_fsq;
case 5:
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vse16_v;
}
break;
case 1: return &op_vsuxei16_v;
case 2: return &op_vsse16_v;
case 3: return &op_vsoxei16_v;
}
break;
case 6:
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vse32_v;
}
break;
case 1: return &op_vsuxei32_v;
case 2: return &op_vsse32_v;
case 3: return &op_vsoxei32_v;
}
break;
case 7:
switch ((inst >> 26) & 0b111) {
case 0:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_vse64_v;
}
break;
case 1: return &op_vsuxei64_v;
case 2: return &op_vsse64_v;
case 3: return &op_vsoxei64_v;
}
break;
}
break;
case 11:
switch (((inst >> 24) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_amoadd_b;
case 1: return &op_amoadd_h;
case 2: return &op_amoadd_w;
case 3: return &op_amoadd_d;
case 4: return &op_amoadd_q;
case 8: return &op_amoswap_b;
case 9: return &op_amoswap_h;
case 10: return &op_amoswap_w;
case 11: return &op_amoswap_d;
case 12: return &op_amoswap_q;
case 18:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_lr_w;
}
break;
case 19:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_lr_d;
}
break;
case 20:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_lr_q;
}
break;
case 26: return &op_sc_w;
case 27: return &op_sc_d;
case 28: return &op_sc_q;
case 32: return &op_amoxor_b;
case 33: return &op_amoxor_h;
case 34: return &op_amoxor_w;
case 35: return &op_amoxor_d;
case 36: return &op_amoxor_q;
case 40: return &op_amocas_b;
case 41: return &op_amocas_h;
case 42: return &op_amocas_w;
case 43: return &op_amocas_d;
case 44: return &op_amocas_q;
case 64: return &op_amoor_b;
case 65: return &op_amoor_h;
case 66: return &op_amoor_w;
case 67: return &op_amoor_d;
case 68: return &op_amoor_q;
case 74: return &op_ssamoswap_w;
case 75: return &op_ssamoswap_d;
case 96: return &op_amoand_b;
case 97: return &op_amoand_h;
case 98: return &op_amoand_w;
case 99: return &op_amoand_d;
case 100: return &op_amoand_q;
case 128: return &op_amomin_b;
case 129: return &op_amomin_h;
case 130: return &op_amomin_w;
case 131: return &op_amomin_d;
case 132: return &op_amomin_q;
case 160: return &op_amomax_b;
case 161: return &op_amomax_h;
case 162: return &op_amomax_w;
case 163: return &op_amomax_d;
case 164: return &op_amomax_q;
case 192: return &op_amominu_b;
case 193: return &op_amominu_h;
case 194: return &op_amominu_w;
case 195: return &op_amominu_d;
case 196: return &op_amominu_q;
case 224: return &op_amomaxu_b;
case 225: return &op_amomaxu_h;
case 226: return &op_amomaxu_w;
case 227: return &op_amomaxu_d;
case 228: return &op_amomaxu_q;
}
break;
case 12:
switch (((inst >> 22) & 0b1111111000) |
((inst >> 12) & 0b0000000111)) {
case 0: return &op_add;
case 1: return &op_sll;
case 2: return &op_slt;
case 3: return &op_sltu;
case 4: return &op_xor;
case 5: return &op_srl;
case 6: return &op_or;
case 7: return &op_and;
case 8: return &op_mul;
case 9: return &op_mulh;
case 10: return &op_mulhsu;
case 11: return &op_mulhu;
case 12: return &op_div;
case 13: return &op_divu;
case 14: return &op_rem;
case 15: return &op_remu;
case 36:
if (isa == rv32 && !((inst >> 20) & 0b11111)) {
return &op_zext_h;
}
return &op_pack;
case 39: return &op_packh;
case 41: return &op_clmul;
case 42: return &op_clmulr;
case 43: return &op_clmulh;
case 44: return &op_min;
case 45: return &op_minu;
case 46: return &op_max;
case 47: return &op_maxu;
case 075: return &op_czero_eqz;
case 077: return &op_czero_nez;
case 130: return &op_sh1add;
case 132: return &op_sh2add;
case 134: return &op_sh3add;
case 161: return &op_bset;
case 162: return &op_xperm4;
case 164: return &op_xperm8;
case 200: return &op_aes64es;
case 216: return &op_aes64esm;
case 232: return &op_aes64ds;
case 248: return &op_aes64dsm;
case 256: return &op_sub;
case 260: return &op_xnor;
case 261: return &op_sra;
case 262: return &op_orn;
case 263: return &op_andn;
case 289: return &op_bclr;
case 293: return &op_bext;
case 320: return &op_sha512sum0r;
case 328: return &op_sha512sum1r;
case 336: return &op_sha512sig0l;
case 344: return &op_sha512sig1l;
case 368: return &op_sha512sig0h;
case 376: return &op_sha512sig1h;
case 385: return &op_rol;
case 389: return &op_ror;
case 417: return &op_binv;
case 504: return &op_aes64ks2;
}
switch ((inst >> 25) & 0b0011111) {
case 17: return &op_aes32esi;
case 19: return &op_aes32esmi;
case 21: return &op_aes32dsi;
case 23: return &op_aes32dsmi;
case 24: return &op_sm4ed;
case 26: return &op_sm4ks;
}
break;
case 13: return &op_lui;
case 14:
/* OP-32 */
if (isa == rv32) {
break;
}
switch (((inst >> 22) & 0b1111111000) |
((inst >> 12) & 0b0000000111)) {
case 0: return &op_addw;
case 1: return &op_sllw;
case 5: return &op_srlw;
case 8: return &op_mulw;
case 12: return &op_divw;
case 13: return &op_divuw;
case 14: return &op_remw;
case 15: return &op_remuw;
case 32: return &op_add_uw;
case 36:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_zext_h;
default: return &op_packw;
}
break;
case 130: return &op_sh1add_uw;
case 132: return &op_sh2add_uw;
case 134: return &op_sh3add_uw;
case 256: return &op_subw;
case 261: return &op_sraw;
case 385: return &op_rolw;
case 389: return &op_rorw;
}
break;
case 16:
switch ((inst >> 25) & 0b11) {
case 0: return &op_fmadd_s;
case 1: return &op_fmadd_d;
case 3: return &op_fmadd_q;
}
break;
case 17:
switch ((inst >> 25) & 0b11) {
case 0: return &op_fmsub_s;
case 1: return &op_fmsub_d;
case 3: return &op_fmsub_q;
}
break;
case 18:
switch ((inst >> 25) & 0b11) {
case 0: return &op_fnmsub_s;
case 1: return &op_fnmsub_d;
case 3: return &op_fnmsub_q;
}
break;
case 19:
switch ((inst >> 25) & 0b11) {
case 0: return &op_fnmadd_s;
case 1: return &op_fnmadd_d;
case 3: return &op_fnmadd_q;
}
break;
case 20:
switch ((inst >> 25) & 0b1111111) {
case 0: return &op_fadd_s;
case 1: return &op_fadd_d;
case 3: return &op_fadd_q;
case 4: return &op_fsub_s;
case 5: return &op_fsub_d;
case 7: return &op_fsub_q;
case 8: return &op_fmul_s;
case 9: return &op_fmul_d;
case 11: return &op_fmul_q;
case 12: return &op_fdiv_s;
case 13: return &op_fdiv_d;
case 15: return &op_fdiv_q;
case 16:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fsgnj_s;
case 1: return &op_fsgnjn_s;
case 2: return &op_fsgnjx_s;
}
break;
case 17:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fsgnj_d;
case 1: return &op_fsgnjn_d;
case 2: return &op_fsgnjx_d;
}
break;
case 19:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fsgnj_q;
case 1: return &op_fsgnjn_q;
case 2: return &op_fsgnjx_q;
}
break;
case 20:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fmin_s;
case 1: return &op_fmax_s;
case 2: return &op_fminm_s;
case 3: return &op_fmaxm_s;
}
break;
case 21:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fmin_d;
case 1: return &op_fmax_d;
case 2: return &op_fminm_d;
case 3: return &op_fmaxm_d;
}
break;
case 22:
switch (((inst >> 12) & 0b111)) {
case 2: return &op_fminm_h;
case 3: return &op_fmaxm_h;
}
break;
case 23:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fmin_q;
case 1: return &op_fmax_q;
case 2: return &op_fminm_q;
case 3: return &op_fmaxm_q;
}
break;
case 32:
switch ((inst >> 20) & 0b11111) {
case 1: return &op_fcvt_s_d;
case 3: return &op_fcvt_s_q;
case 4: return &op_fround_s;
case 5: return &op_froundnx_s;
case 6: return &op_fcvt_s_bf16;
}
break;
case 33:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_d_s;
case 3: return &op_fcvt_d_q;
case 4: return &op_fround_d;
case 5: return &op_froundnx_d;
}
break;
case 34:
switch (((inst >> 20) & 0b11111)) {
case 4: return &op_fround_h;
case 5: return &op_froundnx_h;
case 8: return &op_fcvt_bf16_s;
}
break;
case 35:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_q_s;
case 1: return &op_fcvt_q_d;
case 4: return &op_fround_q;
case 5: return &op_froundnx_q;
}
break;
case 44:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fsqrt_s;
}
break;
case 45:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fsqrt_d;
}
break;
case 47:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fsqrt_q;
}
break;
case 80:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fle_s;
case 1: return &op_flt_s;
case 2: return &op_feq_s;
case 4: return &op_fleq_s;
case 5: return &op_fltq_s;
}
break;
case 81:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fle_d;
case 1: return &op_flt_d;
case 2: return &op_feq_d;
case 4: return &op_fleq_d;
case 5: return &op_fltq_d;
}
break;
case 82:
switch (((inst >> 12) & 0b111)) {
case 4: return &op_fleq_h;
case 5: return &op_fltq_h;
}
break;
case 83:
switch ((inst >> 12) & 0b111) {
case 0: return &op_fle_q;
case 1: return &op_flt_q;
case 2: return &op_feq_q;
case 4: return &op_fleq_q;
case 5: return &op_fltq_q;
}
break;
case 89:
switch (((inst >> 12) & 0b111)) {
case 0: return &op_fmvp_d_x;
}
break;
case 91:
switch (((inst >> 12) & 0b111)) {
case 0: return &op_fmvp_q_x;
}
break;
case 96:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_w_s;
case 1: return &op_fcvt_wu_s;
case 2: return &op_fcvt_l_s;
case 3: return &op_fcvt_lu_s;
}
break;
case 97:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_w_d;
case 1: return &op_fcvt_wu_d;
case 2: return &op_fcvt_l_d;
case 3: return &op_fcvt_lu_d;
case 8: return &op_fcvtmod_w_d;
}
break;
case 99:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_w_q;
case 1: return &op_fcvt_wu_q;
case 2: return &op_fcvt_l_q;
case 3: return &op_fcvt_lu_q;
}
break;
case 104:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_s_w;
case 1: return &op_fcvt_s_wu;
case 2: return &op_fcvt_s_l;
case 3: return &op_fcvt_s_lu;
}
break;
case 105:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_d_w;
case 1: return &op_fcvt_d_wu;
case 2: return &op_fcvt_d_l;
case 3: return &op_fcvt_d_lu;
}
break;
case 107:
switch ((inst >> 20) & 0b11111) {
case 0: return &op_fcvt_q_w;
case 1: return &op_fcvt_q_wu;
case 2: return &op_fcvt_q_l;
case 3: return &op_fcvt_q_lu;
}
break;
case 112:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_x_s;
case 1: return &op_fclass_s;
}
break;
case 113:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_x_d;
case 1: return &op_fclass_d;
case 8: return &op_fmvh_x_d;
}
break;
case 114:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_x_h;
}
break;
case 115:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_x_q;
case 1: return &op_fclass_q;
case 8: return &op_fmvh_x_q;
}
break;
case 120:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_s_x;
case 8: return &op_fli_s;
}
break;
case 121:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_d_x;
case 8: return &op_fli_d;
}
break;
case 122:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_h_x;
case 8: return &op_fli_h;
}
break;
case 123:
switch (((inst >> 17) & 0b11111000) |
((inst >> 12) & 0b00000111)) {
case 0: return &op_fmv_q_x;
case 8: return &op_fli_q;
}
break;
}
break;
case 21:
switch ((inst >> 12) & 0b111) {
case 0:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_vadd_vv;
case 1: return &op_vandn_vv;
case 2: return &op_vsub_vv;
case 4: return &op_vminu_vv;
case 5: return &op_vmin_vv;
case 6: return &op_vmaxu_vv;
case 7: return &op_vmax_vv;
case 9: return &op_vand_vv;
case 10: return &op_vor_vv;
case 11: return &op_vxor_vv;
case 12: return &op_vrgather_vv;
case 14: return &op_vrgatherei16_vv;
case 16:
if (((inst >> 25) & 1) == 0) {
return &op_vadc_vvm;
}
break;
case 17: return &op_vmadc_vvm;
case 18:
if (((inst >> 25) & 1) == 0) {
return &op_vsbc_vvm;
}
break;
case 19: return &op_vmsbc_vvm;
case 20: return &op_vror_vv;
case 21: return &op_vrol_vv;
case 23:
if (((inst >> 20) & 0b111111) == 32) {
return &op_vmv_v_v;
} else if (((inst >> 25) & 1) == 0) {
return &op_vmerge_vvm;
}
break;
case 24: return &op_vmseq_vv;
case 25: return &op_vmsne_vv;
case 26: return &op_vmsltu_vv;
case 27: return &op_vmslt_vv;
case 28: return &op_vmsleu_vv;
case 29: return &op_vmsle_vv;
case 32: return &op_vsaddu_vv;
case 33: return &op_vsadd_vv;
case 34: return &op_vssubu_vv;
case 35: return &op_vssub_vv;
case 37: return &op_vsll_vv;
case 39: return &op_vsmul_vv;
case 40: return &op_vsrl_vv;
case 41: return &op_vsra_vv;
case 42: return &op_vssrl_vv;
case 43: return &op_vssra_vv;
case 44: return &op_vnsrl_wv;
case 45: return &op_vnsra_wv;
case 46: return &op_vnclipu_wv;
case 47: return &op_vnclip_wv;
case 48: return &op_vwredsumu_vs;
case 49: return &op_vwredsum_vs;
case 53: return &op_vwsll_vv;
}
break;
case 1:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_vfadd_vv;
case 1: return &op_vfredusum_vs;
case 2: return &op_vfsub_vv;
case 3: return &op_vfredosum_vs;
case 4: return &op_vfmin_vv;
case 5: return &op_vfredmin_vs;
case 6: return &op_vfmax_vv;
case 7: return &op_vfredmax_vs;
case 8: return &op_vfsgnj_vv;
case 9: return &op_vfsgnjn_vv;
case 10: return &op_vfsgnjx_vv;
case 16:
switch ((inst >> 15) & 0b11111) {
case 0:
if ((inst >> 25) & 1) {
return &op_vfmv_f_s;
}
}
break;
case 18:
switch ((inst >> 15) & 0b11111) {
case 0: return &op_vfcvt_xu_f_v;
case 1: return &op_vfcvt_x_f_v;
case 2: return &op_vfcvt_f_xu_v;
case 3: return &op_vfcvt_f_x_v;
case 6: return &op_vfcvt_rtz_xu_f_v;
case 7: return &op_vfcvt_rtz_x_f_v;
case 8: return &op_vfwcvt_xu_f_v;
case 9: return &op_vfwcvt_x_f_v;
case 10: return &op_vfwcvt_f_xu_v;
case 11: return &op_vfwcvt_f_x_v;
case 12: return &op_vfwcvt_f_f_v;
case 13: return &op_vfwcvtbf16_f_f_v;
case 14: return &op_vfwcvt_rtz_xu_f_v;
case 15: return &op_vfwcvt_rtz_x_f_v;
case 16: return &op_vfncvt_xu_f_w;
case 17: return &op_vfncvt_x_f_w;
case 18: return &op_vfncvt_f_xu_w;
case 19: return &op_vfncvt_f_x_w;
case 20: return &op_vfncvt_f_f_w;
case 21: return &op_vfncvt_rod_f_f_w;
case 22: return &op_vfncvt_rtz_xu_f_w;
case 23: return &op_vfncvt_rtz_x_f_w;
case 29: return &op_vfncvtbf16_f_f_w;
}
break;
case 19:
switch ((inst >> 15) & 0b11111) {
case 0: return &op_vfsqrt_v;
case 4: return &op_vfrsqrt7_v;
case 5: return &op_vfrec7_v;
case 16: return &op_vfclass_v;
}
break;
case 24: return &op_vmfeq_vv;
case 25: return &op_vmfle_vv;
case 27: return &op_vmflt_vv;
case 28: return &op_vmfne_vv;
case 32: return &op_vfdiv_vv;
case 36: return &op_vfmul_vv;
case 40: return &op_vfmadd_vv;
case 41: return &op_vfnmadd_vv;
case 42: return &op_vfmsub_vv;
case 43: return &op_vfnmsub_vv;
case 44: return &op_vfmacc_vv;
case 45: return &op_vfnmacc_vv;
case 46: return &op_vfmsac_vv;
case 47: return &op_vfnmsac_vv;
case 48: return &op_vfwadd_vv;
case 49: return &op_vfwredusum_vs;
case 50: return &op_vfwsub_vv;
case 51: return &op_vfwredosum_vs;
case 52: return &op_vfwadd_wv;
case 54: return &op_vfwsub_wv;
case 56: return &op_vfwmul_vv;
case 59: return &op_vfwmaccbf16_vv;
case 60: return &op_vfwmacc_vv;
case 61: return &op_vfwnmacc_vv;
case 62: return &op_vfwmsac_vv;
case 63: return &op_vfwnmsac_vv;
}
break;
case 2:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_vredsum_vs;
case 1: return &op_vredand_vs;
case 2: return &op_vredor_vs;
case 3: return &op_vredxor_vs;
case 4: return &op_vredminu_vs;
case 5: return &op_vredmin_vs;
case 6: return &op_vredmaxu_vs;
case 7: return &op_vredmax_vs;
case 8: return &op_vaaddu_vv;
case 9: return &op_vaadd_vv;
case 10: return &op_vasubu_vv;
case 11: return &op_vasub_vv;
case 12: return &op_vclmul_vv;
case 13: return &op_vclmulh_vv;
case 16:
switch ((inst >> 15) & 0b11111) {
case 0:
if ((inst >> 25) & 1) {
return &op_vmv_x_s;
}
break;
case 16: return &op_vcpop_m;
case 17: return &op_vfirst_m;
}
break;
case 18:
switch ((inst >> 15) & 0b11111) {
case 2: return &op_vzext_vf8;
case 3: return &op_vsext_vf8;
case 4: return &op_vzext_vf4;
case 5: return &op_vsext_vf4;
case 6: return &op_vzext_vf2;
case 7: return &op_vsext_vf2;
case 8: return &op_vbrev8_v;
case 9: return &op_vrev8_v;
case 10: return &op_vbrev_v;
case 12: return &op_vclz_v;
case 13: return &op_vctz_v;
case 14: return &op_vcpop_v;
}
break;
case 20:
switch ((inst >> 15) & 0b11111) {
case 1: return &op_vmsbf_m; break;
case 2: return &op_vmsof_m;
case 3: return &op_vmsif_m;
case 16: return &op_viota_m;
case 17:
if (((inst >> 20) & 0b11111) == 0) {
return &op_vid_v;
}
break;
}
break;
case 23:
if ((inst >> 25) & 1) {
return &op_vcompress_vm;
}
break;
case 24:
if ((inst >> 25) & 1) {
return &op_vmandn_mm;
}
break;
case 25:
if ((inst >> 25) & 1) {
return &op_vmand_mm;
}
break;
case 26:
if ((inst >> 25) & 1) {
return &op_vmor_mm;
}
break;
case 27:
if ((inst >> 25) & 1) {
return &op_vmxor_mm;
}
break;
case 28:
if ((inst >> 25) & 1) {
return &op_vmorn_mm;
}
break;
case 29:
if ((inst >> 25) & 1) {
return &op_vmnand_mm;
}
break;
case 30:
if ((inst >> 25) & 1) {
return &op_vmnor_mm;
}
break;
case 31:
if ((inst >> 25) & 1) {
return &op_vmxnor_mm;
}
break;
case 32: return &op_vdivu_vv;
case 33: return &op_vdiv_vv;
case 34: return &op_vremu_vv;
case 35: return &op_vrem_vv;
case 36: return &op_vmulhu_vv;
case 37: return &op_vmul_vv;
case 38: return &op_vmulhsu_vv;
case 39: return &op_vmulh_vv;
case 41: return &op_vmadd_vv;
case 43: return &op_vnmsub_vv;
case 45: return &op_vmacc_vv;
case 47: return &op_vnmsac_vv;
case 48: return &op_vwaddu_vv;
case 49: return &op_vwadd_vv;
case 50: return &op_vwsubu_vv;
case 51: return &op_vwsub_vv;
case 52: return &op_vwaddu_wv;
case 53: return &op_vwadd_wv;
case 54: return &op_vwsubu_wv;
case 55: return &op_vwsub_wv;
case 56: return &op_vwmulu_vv;
case 58: return &op_vwmulsu_vv;
case 59: return &op_vwmul_vv;
case 60: return &op_vwmaccu_vv;
case 61: return &op_vwmacc_vv;
case 63: return &op_vwmaccsu_vv;
}
break;
case 3:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_vadd_vi;
case 3: return &op_vrsub_vi;
case 9: return &op_vand_vi;
case 10: return &op_vor_vi;
case 11: return &op_vxor_vi;
case 12: return &op_vrgather_vi;
case 14: return &op_vslideup_vi;
case 15: return &op_vslidedown_vi;
case 16:
if (((inst >> 25) & 1) == 0) {
return &op_vadc_vim;
}
break;
case 17: return &op_vmadc_vim;
case 20: case 21: return &op_vror_vi;
case 23:
if (((inst >> 20) & 0b111111) == 32) {
return &op_vmv_v_i;
} else if (((inst >> 25) & 1) == 0) {
return &op_vmerge_vim;
}
break;
case 24: return &op_vmseq_vi;
case 25: return &op_vmsne_vi;
case 28: return &op_vmsleu_vi;
case 29: return &op_vmsle_vi;
case 30: return &op_vmsgtu_vi;
case 31: return &op_vmsgt_vi;
case 32: return &op_vsaddu_vi;
case 33: return &op_vsadd_vi;
case 37: return &op_vsll_vi;
case 39:
switch ((inst >> 15) & 0b11111) {
case 0: return &op_vmv1r_v;
case 1: return &op_vmv2r_v;
case 3: return &op_vmv4r_v;
case 7: return &op_vmv8r_v;
}
break;
case 40: return &op_vsrl_vi;
case 41: return &op_vsra_vi;
case 42: return &op_vssrl_vi;
case 43: return &op_vssra_vi;
case 44: return &op_vnsrl_wi;
case 45: return &op_vnsra_wi;
case 46: return &op_vnclipu_wi;
case 47: return &op_vnclip_wi;
case 53: return &op_vwsll_vi;
}
break;
case 4:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_vadd_vx;
case 1: return &op_vandn_vx;
case 2: return &op_vsub_vx;
case 3: return &op_vrsub_vx;
case 4: return &op_vminu_vx;
case 5: return &op_vmin_vx;
case 6: return &op_vmaxu_vx;
case 7: return &op_vmax_vx;
case 9: return &op_vand_vx;
case 10: return &op_vor_vx;
case 11: return &op_vxor_vx;
case 12: return &op_vrgather_vx;
case 14: return &op_vslideup_vx;
case 15: return &op_vslidedown_vx;
case 16:
if (((inst >> 25) & 1) == 0) {
return &op_vadc_vxm;
}
break;
case 17: return &op_vmadc_vxm;
case 18:
if (((inst >> 25) & 1) == 0) {
return &op_vsbc_vxm;
}
break;
case 19: return &op_vmsbc_vxm;
case 20: return &op_vror_vx;
case 21: return &op_vrol_vx;
case 23:
if (((inst >> 20) & 0b111111) == 32) {
return &op_vmv_v_x;
} else if (((inst >> 25) & 1) == 0) {
return &op_vmerge_vxm;
}
break;
case 24: return &op_vmseq_vx;
case 25: return &op_vmsne_vx;
case 26: return &op_vmsltu_vx;
case 27: return &op_vmslt_vx;
case 28: return &op_vmsleu_vx;
case 29: return &op_vmsle_vx;
case 30: return &op_vmsgtu_vx;
case 31: return &op_vmsgt_vx;
case 32: return &op_vsaddu_vx;
case 33: return &op_vsadd_vx;
case 34: return &op_vssubu_vx;
case 35: return &op_vssub_vx;
case 37: return &op_vsll_vx;
case 39: return &op_vsmul_vx;
case 40: return &op_vsrl_vx;
case 41: return &op_vsra_vx;
case 42: return &op_vssrl_vx;
case 43: return &op_vssra_vx;
case 44: return &op_vnsrl_wx;
case 45: return &op_vnsra_wx;
case 46: return &op_vnclipu_wx;
case 47: return &op_vnclip_wx;
case 53: return &op_vwsll_vx;
}
break;
case 5:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_vfadd_vf;
case 2: return &op_vfsub_vf;
case 4: return &op_vfmin_vf;
case 6: return &op_vfmax_vf;
case 8: return &op_vfsgnj_vf;
case 9: return &op_vfsgnjn_vf;
case 10: return &op_vfsgnjx_vf;
case 14: return &op_vfslide1up_vf;
case 15: return &op_vfslide1down_vf;
case 16:
switch ((inst >> 20) & 0b11111) {
case 0:
if ((inst >> 25) & 1) {
return &op_vfmv_s_f;
}
}
break;
case 23:
if (((inst >> 25) & 1) == 0) {
return &op_vfmerge_vfm;
} else if (((inst >> 20) & 0b111111) == 32) {
return &op_vfmv_v_f;
}
break;
case 24: return &op_vmfeq_vf;
case 25: return &op_vmfle_vf;
case 27: return &op_vmflt_vf;
case 28: return &op_vmfne_vf;
case 29: return &op_vmfgt_vf;
case 31: return &op_vmfge_vf;
case 32: return &op_vfdiv_vf;
case 33: return &op_vfrdiv_vf;
case 36: return &op_vfmul_vf;
case 39: return &op_vfrsub_vf;
case 40: return &op_vfmadd_vf;
case 41: return &op_vfnmadd_vf;
case 42: return &op_vfmsub_vf;
case 43: return &op_vfnmsub_vf;
case 44: return &op_vfmacc_vf;
case 45: return &op_vfnmacc_vf;
case 46: return &op_vfmsac_vf;
case 47: return &op_vfnmsac_vf;
case 48: return &op_vfwadd_vf;
case 50: return &op_vfwsub_vf;
case 52: return &op_vfwadd_wf;
case 54: return &op_vfwsub_wf;
case 56: return &op_vfwmul_vf;
case 59: return &op_vfwmaccbf16_vf;
case 60: return &op_vfwmacc_vf;
case 61: return &op_vfwnmacc_vf;
case 62: return &op_vfwmsac_vf;
case 63: return &op_vfwnmsac_vf;
}
break;
case 6:
switch ((inst >> 26) & 0b111111) {
case 8: return &op_vaaddu_vx;
case 9: return &op_vaadd_vx;
case 10: return &op_vasubu_vx;
case 11: return &op_vasub_vx;
case 12: return &op_vclmul_vx;
case 13: return &op_vclmulh_vx;
case 14: return &op_vslide1up_vx;
case 15: return &op_vslide1down_vx;
case 16:
switch ((inst >> 20) & 0b11111) {
case 0:
if ((inst >> 25) & 1) {
return &op_vmv_s_x;
}
}
break;
case 32: return &op_vdivu_vx;
case 33: return &op_vdiv_vx;
case 34: return &op_vremu_vx;
case 35: return &op_vrem_vx;
case 36: return &op_vmulhu_vx;
case 37: return &op_vmul_vx;
case 38: return &op_vmulhsu_vx;
case 39: return &op_vmulh_vx;
case 41: return &op_vmadd_vx;
case 43: return &op_vnmsub_vx;
case 45: return &op_vmacc_vx;
case 47: return &op_vnmsac_vx;
case 48: return &op_vwaddu_vx;
case 49: return &op_vwadd_vx;
case 50: return &op_vwsubu_vx;
case 51: return &op_vwsub_vx;
case 52: return &op_vwaddu_wx;
case 53: return &op_vwadd_wx;
case 54: return &op_vwsubu_wx;
case 55: return &op_vwsub_wx;
case 56: return &op_vwmulu_vx;
case 58: return &op_vwmulsu_vx;
case 59: return &op_vwmul_vx;
case 60: return &op_vwmaccu_vx;
case 61: return &op_vwmacc_vx;
case 62: return &op_vwmaccus_vx;
case 63: return &op_vwmaccsu_vx;
}
break;
case 7:
if (((inst >> 31) & 1) == 0) {
return &op_vsetvli;
} else if ((inst >> 30) & 1) {
return &op_vsetivli;
} else if (((inst >> 25) & 0b11111) == 0) {
return &op_vsetvl;
}
break;
}
break;
case 22:
switch ((inst >> 12) & 0b111) {
case 0: return &op_addid;
case 1:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_sllid;
}
break;
case 5:
switch ((inst >> 26) & 0b111111) {
case 0: return &op_srlid;
case 16: return &op_sraid;
}
break;
}
break;
case 24:
switch ((inst >> 12) & 0b111) {
case 0: return &op_beq;
case 1: return &op_bne;
case 4: return &op_blt;
case 5: return &op_bge;
case 6: return &op_bltu;
case 7: return &op_bgeu;
}
break;
case 25:
switch ((inst >> 12) & 0b111) {
case 0: return &op_jalr;
}
break;
case 27: return &op_jal;
case 28:
switch ((inst >> 12) & 0b111) {
case 0:
switch (((inst >> 20) & 0b111111100000) |
((inst >> 7) & 0b000000011111)) {
case 0:
switch ((inst >> 15) & 0b1111111111) {
case 0: return &op_ecall;
case 32: return &op_ebreak;
case 64: return &op_uret;
case 416: return &op_wrs_nto;
case 928: return &op_wrs_sto;
}
break;
case 256:
switch ((inst >> 20) & 0b11111) {
case 2:
switch ((inst >> 15) & 0b11111) {
case 0: return &op_sret;
}
break;
case 4: return &op_sfence_vm;
case 5:
switch ((inst >> 15) & 0b11111) {
case 0: return &op_wfi;
}
break;
}
break;
case 288: return &op_sfence_vma;
case 512:
switch ((inst >> 15) & 0b1111111111) {
case 64: return &op_hret;
}
break;
case 768:
switch ((inst >> 15) & 0b1111111111) {
case 64: return &op_mret;
}
break;
case 1792:
switch ((inst >> 15) & 0b1111111111) {
case 64: return &op_mnret;
}
break;
case 1952:
switch ((inst >> 15) & 0b1111111111) {
case 576: return &op_dret;
}
break;
}
break;
case 1:
switch (operand_csr12(inst)) {
case 1: return &op_fsflags;
case 2: return &op_fsrm;
case 3: return &op_fscsr;
default: return &op_csrrw;
}
break;
case 2:
return &op_csrrs;
if (operand_rs1(inst) == 0) {
switch (operand_csr12(inst)) {
case 0x001: return &op_frflags;
case 0x002: return &op_frrm;
case 0x003: return &op_frcsr;
case 0xc00: return &op_rdcycle;
case 0xc01: return &op_rdtime;
case 0xc02: return &op_rdinstret;
case 0xc80: return &op_rdcycleh;
case 0xc81: return &op_rdtimeh;
case 0xc82: return &op_rdinstreth;
}
}
break;
case 3: return &op_csrrc;
case 4:
if (dec->cfg && dec->cfg->ext_zimop) {
if (((inst >> 22) & 0b1011001111) == 0b1000000111) {
if (dec->cfg->ext_zicfiss
&& operand_mop_r_imm(inst) == 28) {
switch (operand_rs1(inst)) {
case 0:
return &op_ssrdp;
case 1:
case 5:
if (operand_rd(inst) == 0) {
return &op_sspopchk;
}
}
}
return &op_mop_r;
}
if (((inst >> 25) & 0b1011001) == 0b1000001) {
if (dec->cfg->ext_zicfiss
&& operand_mop_rr_imm(inst) == 7
&& operand_rd(inst) == 0
&& operand_rs1(inst) == 0) {
switch (operand_rs2(inst)) {
case 1:
case 5:
return &op_sspush;
}
}
return &op_mop_rr;
}
}
break;
case 5:
switch (operand_csr12(inst)) {
case 1: return &op_fsflagsi;
case 2: return &op_fsrmi;
default: return &op_csrrwi;
}
break;
case 6: return &op_csrrsi;
case 7: return &op_csrrci;
}
break;
case 29:
if (((inst >> 25) & 1) == 1 && ((inst >> 12) & 0b111) == 2) {
switch ((inst >> 26) & 0b111111) {
case 32: return &op_vsm3me_vv;
case 33: return &op_vsm4k_vi;
case 34: return &op_vaeskf1_vi;
case 40:
switch ((inst >> 15) & 0b11111) {
case 0: return &op_vaesdm_vv;
case 1: return &op_vaesdf_vv;
case 2: return &op_vaesem_vv;
case 3: return &op_vaesef_vv;
case 16: return &op_vsm4r_vv;
case 17: return &op_vgmul_vv;
}
break;
case 41:
switch ((inst >> 15) & 0b11111) {
case 0: return &op_vaesdm_vs;
case 1: return &op_vaesdf_vs;
case 2: return &op_vaesem_vs;
case 3: return &op_vaesef_vs;
case 7: return &op_vaesz_vs;
case 16: return &op_vsm4r_vs;
}
break;
case 42: return &op_vaeskf2_vi;
case 43: return &op_vsm3c_vi;
case 44: return &op_vghsh_vv;
case 45: return &op_vsha2ms_vv;
case 46: return &op_vsha2ch_vv;
case 47: return &op_vsha2cl_vv;
}
}
break;
case 30:
switch (((inst >> 22) & 0b1111111000) |
((inst >> 12) & 0b0000000111)) {
case 0: return &op_addd;
case 1: return &op_slld;
case 5: return &op_srld;
case 8: return &op_muld;
case 12: return &op_divd;
case 13: return &op_divud;
case 14: return &op_remd;
case 15: return &op_remud;
case 256: return &op_subd;
case 261: return &op_srad;
}
break;
}
break;
}
return NULL;
}
/* decode operands */
static void decode_inst_operands(rv_decode *dec, rv_isa isa,
const rv_opcode_data *op)
{
rv_inst inst = dec->inst;
switch (op->codec) {
case rv_codec_none:
dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
dec->imm = 0;
break;
case rv_codec_u:
dec->rd = operand_rd(inst);
dec->rs1 = dec->rs2 = rv_ireg_zero;
dec->imm = operand_imm20(inst);
break;
case rv_codec_uj:
dec->rd = operand_rd(inst);
dec->rs1 = dec->rs2 = rv_ireg_zero;
dec->imm = operand_jimm20(inst);
break;
case rv_codec_i:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_imm12(inst);
break;
case rv_codec_i_sh5:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_shamt5(inst);
break;
case rv_codec_i_sh6:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_shamt6(inst);
break;
case rv_codec_i_sh7:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_shamt7(inst);
break;
case rv_codec_i_csr:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_csr12(inst);
break;
case rv_codec_s:
dec->rd = rv_ireg_zero;
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = operand_simm12(inst);
break;
case rv_codec_sb:
dec->rd = rv_ireg_zero;
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = operand_sbimm12(inst);
break;
case rv_codec_r:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = 0;
break;
case rv_codec_r_m:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = 0;
dec->rm = operand_rm(inst);
break;
case rv_codec_r4_m:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->rs3 = operand_rs3(inst);
dec->imm = 0;
dec->rm = operand_rm(inst);
break;
case rv_codec_r_a:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = 0;
dec->aq = operand_aq(inst);
dec->rl = operand_rl(inst);
break;
case rv_codec_r_l:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = 0;
dec->aq = operand_aq(inst);
dec->rl = operand_rl(inst);
break;
case rv_codec_r_f:
dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
dec->pred = operand_pred(inst);
dec->succ = operand_succ(inst);
dec->imm = 0;
break;
case rv_codec_cb:
dec->rd = rv_ireg_zero;
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmb(inst);
break;
case rv_codec_cb_imm:
dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmi(inst);
break;
case rv_codec_cb_sh5:
dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmsh5(inst);
break;
case rv_codec_cb_sh6:
dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmshr6(inst, isa);
break;
case rv_codec_ci:
dec->rd = dec->rs1 = operand_crs1rd(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmi(inst);
break;
case rv_codec_ci_sh5:
dec->rd = dec->rs1 = operand_crs1rd(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmsh5(inst);
break;
case rv_codec_ci_sh6:
dec->rd = dec->rs1 = operand_crs1rd(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmshl6(inst, isa);
break;
case rv_codec_ci_16sp:
dec->rd = rv_ireg_sp;
dec->rs1 = rv_ireg_sp;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimm16sp(inst);
break;
case rv_codec_ci_lwsp:
dec->rd = operand_crd(inst);
dec->rs1 = rv_ireg_sp;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmlwsp(inst);
break;
case rv_codec_ci_ldsp:
dec->rd = operand_crd(inst);
dec->rs1 = rv_ireg_sp;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmldsp(inst);
break;
case rv_codec_ci_lqsp:
dec->rd = operand_crd(inst);
dec->rs1 = rv_ireg_sp;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmlqsp(inst);
break;
case rv_codec_ci_li:
dec->rd = operand_crd(inst);
dec->rs1 = rv_ireg_zero;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmi(inst);
break;
case rv_codec_ci_lui:
dec->rd = operand_crd(inst);
dec->rs1 = rv_ireg_zero;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmui(inst);
break;
case rv_codec_ci_none:
dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
dec->imm = 0;
break;
case rv_codec_ciw_4spn:
dec->rd = operand_crdq(inst) + 8;
dec->rs1 = rv_ireg_sp;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimm4spn(inst);
break;
case rv_codec_cj:
dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmj(inst);
break;
case rv_codec_cj_jal:
dec->rd = rv_ireg_ra;
dec->rs1 = dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmj(inst);
break;
case rv_codec_cl_lw:
dec->rd = operand_crdq(inst) + 8;
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmw(inst);
break;
case rv_codec_cl_ld:
dec->rd = operand_crdq(inst) + 8;
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmd(inst);
break;
case rv_codec_cl_lq:
dec->rd = operand_crdq(inst) + 8;
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = rv_ireg_zero;
dec->imm = operand_cimmq(inst);
break;
case rv_codec_cr:
dec->rd = dec->rs1 = operand_crs1rd(inst);
dec->rs2 = operand_crs2(inst);
dec->imm = 0;
break;
case rv_codec_cr_mv:
dec->rd = operand_crd(inst);
dec->rs1 = operand_crs2(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = 0;
break;
case rv_codec_cr_jalr:
dec->rd = rv_ireg_ra;
dec->rs1 = operand_crs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = 0;
break;
case rv_codec_cr_jr:
dec->rd = rv_ireg_zero;
dec->rs1 = operand_crs1(inst);
dec->rs2 = rv_ireg_zero;
dec->imm = 0;
break;
case rv_codec_cs:
dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
dec->rs2 = operand_crs2q(inst) + 8;
dec->imm = 0;
break;
case rv_codec_cs_sw:
dec->rd = rv_ireg_zero;
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = operand_crs2q(inst) + 8;
dec->imm = operand_cimmw(inst);
break;
case rv_codec_cs_sd:
dec->rd = rv_ireg_zero;
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = operand_crs2q(inst) + 8;
dec->imm = operand_cimmd(inst);
break;
case rv_codec_cs_sq:
dec->rd = rv_ireg_zero;
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = operand_crs2q(inst) + 8;
dec->imm = operand_cimmq(inst);
break;
case rv_codec_css_swsp:
dec->rd = rv_ireg_zero;
dec->rs1 = rv_ireg_sp;
dec->rs2 = operand_crs2(inst);
dec->imm = operand_cimmswsp(inst);
break;
case rv_codec_css_sdsp:
dec->rd = rv_ireg_zero;
dec->rs1 = rv_ireg_sp;
dec->rs2 = operand_crs2(inst);
dec->imm = operand_cimmsdsp(inst);
break;
case rv_codec_css_sqsp:
dec->rd = rv_ireg_zero;
dec->rs1 = rv_ireg_sp;
dec->rs2 = operand_crs2(inst);
dec->imm = operand_cimmsqsp(inst);
break;
case rv_codec_k_bs:
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->bs = operand_bs(inst);
break;
case rv_codec_k_rnum:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rnum = operand_rnum(inst);
break;
case rv_codec_v_r:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->vm = operand_vm(inst);
break;
case rv_codec_v_ldst:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->vm = operand_vm(inst);
break;
case rv_codec_v_i:
dec->rd = operand_rd(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = operand_vimm(inst);
dec->vm = operand_vm(inst);
break;
case rv_codec_v_i_u:
dec->rd = operand_rd(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = operand_vuimm(inst);
dec->vm = operand_vm(inst);
break;
case rv_codec_vror_vi:
dec->rd = operand_rd(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = operand_vzimm6(inst);
dec->vm = operand_vm(inst);
break;
case rv_codec_vsetvli:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->vzimm = operand_vzimm11(inst);
break;
case rv_codec_vsetivli:
dec->rd = operand_rd(inst);
dec->imm = extract32(inst, 15, 5);
dec->vzimm = operand_vzimm10(inst);
break;
case rv_codec_zcb_lb:
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = operand_crs2q(inst) + 8;
dec->imm = operand_uimm_c_lb(inst);
break;
case rv_codec_zcb_lh:
dec->rs1 = operand_crs1q(inst) + 8;
dec->rs2 = operand_crs2q(inst) + 8;
dec->imm = operand_uimm_c_lh(inst);
break;
case rv_codec_zcb_ext:
dec->rd = operand_crs1q(inst) + 8;
break;
case rv_codec_zcb_mul:
dec->rd = operand_crs1rdq(inst) + 8;
dec->rs2 = operand_crs2q(inst) + 8;
break;
case rv_codec_zcmp_cm_pushpop:
dec->imm = operand_zcmp_stack_adj(inst, isa);
dec->rlist = operand_zcmp_rlist(inst);
break;
case rv_codec_zcmp_cm_mv:
dec->rd = operand_sreg1(inst);
dec->rs2 = operand_sreg2(inst);
break;
case rv_codec_zcmt_jt:
dec->imm = operand_tbl_index(inst);
break;
case rv_codec_fli:
dec->rd = operand_rd(inst);
dec->imm = operand_rs1(inst);
break;
case rv_codec_r2_imm5:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->imm = operand_rs2(inst);
break;
case rv_codec_r2:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
break;
case rv_codec_r2_imm6:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->imm = operand_imm6(inst);
break;
case rv_codec_r_imm2:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = operand_imm2(inst);
break;
case rv_codec_r2_immhl:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->imm = operand_immh(inst);
dec->imm1 = operand_imml(inst);
break;
case rv_codec_r2_imm2_imm5:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->imm = sextract32(operand_rs2(inst), 0, 5);
dec->imm1 = operand_imm2(inst);
break;
case rv_codec_lp:
dec->imm = operand_lpl(inst);
break;
case rv_codec_cmop:
dec->imm = operand_cmop_imm(inst);
break;
case rv_codec_cmop_ss:
dec->rd = rv_ireg_zero;
dec->rs1 = dec->rs2 = operand_crs1(inst);
dec->imm = 0;
break;
case rv_codec_mop_r:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->imm = operand_mop_r_imm(inst);
break;
case rv_codec_mop_rr:
dec->rd = operand_rd(inst);
dec->rs1 = operand_rs1(inst);
dec->rs2 = operand_rs2(inst);
dec->imm = operand_mop_rr_imm(inst);
break;
default:
g_assert_not_reached();
}
}
/* check constraint */
static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
{
int32_t imm = dec->imm;
uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
while (*c != rvc_end) {
switch (*c) {
case rvc_rd_eq_ra:
if (!(rd == 1)) {
return false;
}
break;
case rvc_rd_eq_x0:
if (!(rd == 0)) {
return false;
}
break;
case rvc_rs1_eq_x0:
if (!(rs1 == 0)) {
return false;
}
break;
case rvc_rs2_eq_x0:
if (!(rs2 == 0)) {
return false;
}
break;
case rvc_rs2_eq_rs1:
if (!(rs2 == rs1)) {
return false;
}
break;
case rvc_rs1_eq_ra:
if (!(rs1 == 1)) {
return false;
}
break;
case rvc_imm_eq_zero:
if (!(imm == 0)) {
return false;
}
break;
case rvc_imm_eq_n1:
if (!(imm == -1)) {
return false;
}
break;
case rvc_imm_eq_p1:
if (!(imm == 1)) {
return false;
}
break;
default: break;
}
c++;
}
return true;
}
/* Same as insn_len() from target/riscv/internals.h */
static size_t inst_length(rv_inst inst)
{
return (inst & 3) == 3 ? 4 : 2;
}
/* format instruction */
static GString *format_inst(size_t tab, rv_decode *dec,
const rv_opcode_data *op)
{
GString *buf = g_string_sized_new(64);
const char *fmt = op->format;
while (*fmt) {
switch (*fmt) {
case 'O':
g_string_append(buf, op->name);
break;
case '(':
case '.':
case ',':
case ')':
case '-':
g_string_append_c(buf, *fmt);
break;
case 'b':
g_string_append_printf(buf, "%d", dec->bs);
break;
case 'n':
g_string_append_printf(buf, "%d", dec->rnum);
break;
case '0':
g_string_append(buf, rv_ireg_name_sym[dec->rd]);
break;
case '1':
g_string_append(buf, rv_ireg_name_sym[dec->rs1]);
break;
case '2':
g_string_append(buf, rv_ireg_name_sym[dec->rs2]);
break;
case '3':
if (dec->cfg && dec->cfg->ext_zfinx) {
g_string_append(buf, rv_ireg_name_sym[dec->rd]);
} else {
g_string_append(buf, rv_freg_name_sym[dec->rd]);
}
break;
case '4':
if (dec->cfg && dec->cfg->ext_zfinx) {
g_string_append(buf, rv_ireg_name_sym[dec->rs1]);
} else {
g_string_append(buf, rv_freg_name_sym[dec->rs1]);
}
break;
case '5':
if (dec->cfg && dec->cfg->ext_zfinx) {
g_string_append(buf, rv_ireg_name_sym[dec->rs2]);
} else {
g_string_append(buf, rv_freg_name_sym[dec->rs2]);
}
break;
case '6':
if (dec->cfg && dec->cfg->ext_zfinx) {
g_string_append(buf, rv_ireg_name_sym[dec->rs3]);
} else {
g_string_append(buf, rv_freg_name_sym[dec->rs3]);
}
break;
case '7':
g_string_append_printf(buf, "%d", dec->rs1);
break;
case 'i':
g_string_append_printf(buf, "%d", dec->imm);
break;
case 'u':
g_string_append_printf(buf, "%u", ((uint32_t)dec->imm & 0b111111));
break;
case 'j':
g_string_append_printf(buf, "%d", dec->imm1);
break;
case 'o':
g_string_append_printf(buf, "%d", dec->imm);
while (buf->len < tab * 2) {
g_string_append_c(buf, ' ');
}
g_string_append_printf(buf, "# 0x%" PRIx64, dec->pc + dec->imm);
break;
case 'U':
fmt++;
g_string_append_printf(buf, "%d", dec->imm >> 12);
if (*fmt == 'o') {
while (buf->len < tab * 2) {
g_string_append_c(buf, ' ');
}
g_string_append_printf(buf, "# 0x%" PRIx64, dec->pc + dec->imm);
}
break;
case 'c': {
const char *name = csr_name(dec->imm & 0xfff);
if (name) {
g_string_append(buf, name);
} else {
g_string_append_printf(buf, "0x%03x", dec->imm & 0xfff);
}
break;
}
case 'r':
switch (dec->rm) {
case rv_rm_rne:
g_string_append(buf, "rne");
break;
case rv_rm_rtz:
g_string_append(buf, "rtz");
break;
case rv_rm_rdn:
g_string_append(buf, "rdn");
break;
case rv_rm_rup:
g_string_append(buf, "rup");
break;
case rv_rm_rmm:
g_string_append(buf, "rmm");
break;
case rv_rm_dyn:
g_string_append(buf, "dyn");
break;
default:
g_string_append(buf, "inv");
break;
}
break;
case 'p':
if (dec->pred & rv_fence_i) {
g_string_append_c(buf, 'i');
}
if (dec->pred & rv_fence_o) {
g_string_append_c(buf, 'o');
}
if (dec->pred & rv_fence_r) {
g_string_append_c(buf, 'r');
}
if (dec->pred & rv_fence_w) {
g_string_append_c(buf, 'w');
}
break;
case 's':
if (dec->succ & rv_fence_i) {
g_string_append_c(buf, 'i');
}
if (dec->succ & rv_fence_o) {
g_string_append_c(buf, 'o');
}
if (dec->succ & rv_fence_r) {
g_string_append_c(buf, 'r');
}
if (dec->succ & rv_fence_w) {
g_string_append_c(buf, 'w');
}
break;
case '\t':
while (buf->len < tab) {
g_string_append_c(buf, ' ');
}
break;
case 'A':
if (dec->aq) {
g_string_append(buf, ".aq");
}
break;
case 'R':
if (dec->rl) {
g_string_append(buf, ".rl");
}
break;
case 'l':
g_string_append(buf, ",v0");
break;
case 'm':
if (dec->vm == 0) {
g_string_append(buf, ",v0.t");
}
break;
case 'D':
g_string_append(buf, rv_vreg_name_sym[dec->rd]);
break;
case 'E':
g_string_append(buf, rv_vreg_name_sym[dec->rs1]);
break;
case 'F':
g_string_append(buf, rv_vreg_name_sym[dec->rs2]);
break;
case 'G':
g_string_append(buf, rv_vreg_name_sym[dec->rs3]);
break;
case 'v': {
const int sew = 1 << (((dec->vzimm >> 3) & 0b111) + 3);
const int lmul = dec->vzimm & 0b11;
const int flmul = (dec->vzimm >> 2) & 1;
const char *vta = (dec->vzimm >> 6) & 1 ? "ta" : "tu";
const char *vma = (dec->vzimm >> 7) & 1 ? "ma" : "mu";
g_string_append_printf(buf, "e%d,m", sew);
if (flmul) {
switch (lmul) {
case 3:
g_string_append(buf, "f2");
break;
case 2:
g_string_append(buf, "f4");
break;
case 1:
g_string_append(buf, "f8");
break;
}
} else {
g_string_append_printf(buf, "%d", 1 << lmul);
}
g_string_append_c(buf, ',');
g_string_append(buf, vta);
g_string_append_c(buf, ',');
g_string_append(buf, vma);
break;
}
case 'x': {
switch (dec->rlist) {
case 4:
g_string_append(buf, "{ra}");
break;
case 5:
g_string_append(buf, "{ra, s0}");
break;
case 15:
g_string_append(buf, "{ra, s0-s11}");
break;
default:
g_string_append_printf(buf, "{ra, s0-s%d}", dec->rlist - 5);
break;
}
break;
}
case 'h':
g_string_append(buf, rv_fli_name_const[dec->imm]);
break;
default:
break;
}
fmt++;
}
return buf;
}
/* lift instruction to pseudo-instruction */
static const rv_opcode_data *decode_inst_lift_pseudo(rv_decode *dec,
const rv_opcode_data *op)
{
const rv_comp_data *comp_data = op->pseudo;
if (comp_data) {
while (comp_data->constraints) {
if (check_constraints(dec, comp_data->constraints)) {
assert(op != comp_data->op);
return decode_inst_lift_pseudo(dec, comp_data->op);
}
comp_data++;
}
}
return op;
}
/* disassemble instruction */
static GString *disasm_inst(rv_isa isa, uint64_t pc, rv_inst inst,
const RISCVCPUConfig *cfg)
{
rv_decode dec = {
.pc = pc,
.inst = inst,
.cfg = cfg,
};
const rv_opcode_data *op = decode_inst_opcode(&dec, isa);
if (!op && cfg) {
static const struct {
bool (*guard_func)(const RISCVCPUConfig *);
const rv_opcode_data *(*decode_func)(rv_decode *, rv_isa);
} decoders[] = {
{ has_xtheadba_p, decode_xtheadba },
{ has_xtheadbb_p, decode_xtheadbb },
{ has_xtheadbs_p, decode_xtheadbs },
{ has_xtheadcmo_p, decode_xtheadcmo },
{ has_xtheadcondmov_p, decode_xtheadcondmov },
{ has_xtheadfmemidx_p, decode_xtheadfmemidx },
{ has_xtheadfmv_p, decode_xtheadfmv },
{ has_xtheadmac_p, decode_xtheadmac },
{ has_xtheadmemidx_p, decode_xtheadmemidx },
{ has_xtheadmempair_p, decode_xtheadmempair },
{ has_xtheadsync_p, decode_xtheadsync },
{ has_XVentanaCondOps_p, decode_xventanacondops },
{ has_xlrbr_p, decode_xlrbr },
};
for (size_t i = 0; i < ARRAY_SIZE(decoders); i++) {
if (decoders[i].guard_func(cfg)) {
op = decoders[i].decode_func(&dec, isa);
if (op) {
break;
}
}
}
}
if (op) {
decode_inst_operands(&dec, isa, op);
op = decode_inst_lift_pseudo(&dec, op);
} else {
op = &op_illegal;
}
return format_inst(24, &dec, op);
}
#define INST_FMT_2 "%04x "
#define INST_FMT_4 "%08x "
static int
print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
{
bfd_byte packet[2];
rv_inst inst = 0;
size_t len = 2;
bfd_vma n;
int status;
/* Instructions are made of 2-byte packets in little-endian order */
for (n = 0; n < len; n += 2) {
status = (*info->read_memory_func)(memaddr + n, packet, 2, info);
if (status != 0) {
/* Don't fail just because we fell off the end. */
if (n > 0) {
break;
}
(*info->memory_error_func)(status, memaddr, info);
return status;
}
inst |= ((rv_inst) bfd_getl16(packet)) << (8 * n);
if (n == 0) {
len = inst_length(inst);
}
}
if (info->show_opcodes) {
switch (len) {
case 2:
(*info->fprintf_func)(info->stream, INST_FMT_2, inst);
break;
case 4:
(*info->fprintf_func)(info->stream, INST_FMT_4, inst);
break;
default:
g_assert_not_reached();
}
}
g_autoptr(GString) str =
disasm_inst(isa, memaddr, inst,
(const RISCVCPUConfig *)info->target_info);
(*info->fprintf_func)(info->stream, "%s", str->str);
return len;
}
int print_insn_riscv32(bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_riscv(memaddr, info, rv32);
}
int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_riscv(memaddr, info, rv64);
}
int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_riscv(memaddr, info, rv128);
}