/* * QEMU RISC-V Disassembler * * Copyright (c) 2016-2017 Michael Clark * 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 . */ #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); }