use super::riscv_register_info::*;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RiscVOpcode {
LUI,
AUIPC,
JAL,
JALR,
BEQ,
BNE,
BLT,
BGE,
BLTU,
BGEU,
LB,
LH,
LW,
LBU,
LHU,
LD,
LWU,
SB,
SH,
SW,
SD,
ADDI,
SLTI,
SLTIU,
XORI,
ORI,
ANDI,
SLLI,
SRLI,
SRAI,
ADD,
SUB,
SLL,
SLT,
SLTU,
XOR,
SRL,
SRA,
OR,
AND,
ADDIW,
SLLIW,
SRLIW,
SRAIW,
ADDW,
SUBW,
SLLW,
SRLW,
SRAW,
FENCE,
FENCE_I,
FENCE_TSO,
PAUSE,
ECALL,
EBREAK,
CSRRW,
CSRRS,
CSRRC,
CSRRWI,
CSRRSI,
CSRRCI,
MUL,
MULH,
MULHSU,
MULHU,
DIV,
DIVU,
REM,
REMU,
MULW,
DIVW,
DIVUW,
REMW,
REMUW,
LR_W,
SC_W,
LR_D,
SC_D,
AMOSWAP_W,
AMOADD_W,
AMOXOR_W,
AMOAND_W,
AMOOR_W,
AMOMIN_W,
AMOMAX_W,
AMOMINU_W,
AMOMAXU_W,
AMOSWAP_D,
AMOADD_D,
AMOXOR_D,
AMOAND_D,
AMOOR_D,
AMOMIN_D,
AMOMAX_D,
AMOMINU_D,
AMOMAXU_D,
FLW,
FSW,
FMADD_S,
FMSUB_S,
FNMSUB_S,
FNMADD_S,
FADD_S,
FSUB_S,
FMUL_S,
FDIV_S,
FSQRT_S,
FSGNJ_S,
FSGNJN_S,
FSGNJX_S,
FMIN_S,
FMAX_S,
FCVT_W_S,
FCVT_WU_S,
FMV_X_W,
FEQ_S,
FLT_S,
FLE_S,
FCLASS_S,
FCVT_S_W,
FCVT_S_WU,
FMV_W_X,
FCVT_L_S,
FCVT_LU_S,
FCVT_S_L,
FCVT_S_LU,
FLD,
FSD,
FMADD_D,
FMSUB_D,
FNMSUB_D,
FNMADD_D,
FADD_D,
FSUB_D,
FMUL_D,
FDIV_D,
FSQRT_D,
FSGNJ_D,
FSGNJN_D,
FSGNJX_D,
FMIN_D,
FMAX_D,
FCVT_W_D,
FCVT_WU_D,
FMV_X_D,
FEQ_D,
FLT_D,
FLE_D,
FCLASS_D,
FCVT_D_W,
FCVT_D_WU,
FMV_D_X,
FCVT_L_D,
FCVT_LU_D,
FCVT_D_L,
FCVT_D_LU,
FCVT_S_D,
FCVT_D_S,
C_ADDI4SPN,
C_LW,
C_LD,
C_FLW,
C_FLD,
C_SW,
C_SD,
C_FSW,
C_FSD,
C_NOP,
C_ADDI,
C_ADDIW,
C_ADDI16SP,
C_LI,
C_LUI,
C_SLLI,
C_SRAI,
C_SRLI,
C_MISC_ALU,
C_J,
C_JAL,
C_BEQZ,
C_BNEZ,
C_MV,
C_ADD,
C_JR,
C_JALR,
C_EBREAK,
C_SWSP,
C_SDSP,
C_FSWSP,
C_FSDSP,
C_LWSP,
C_LDSP,
C_FLWSP,
C_FLDSP,
C_SUB,
C_XOR,
C_OR,
C_AND,
C_ANDI,
NOP,
MV,
NOT,
NEG,
NEGW,
SEQZ,
SNEZ,
SLTZ,
SGTZ,
BEQZ,
BNEZ,
BLEZ,
BGEZ,
BLTZ,
BGTZ,
J,
JR,
RET,
CALL,
TAIL,
LI,
LA,
SH1ADD,
SH2ADD,
SH3ADD,
ANDN,
ORN,
XNOR,
CLZ,
CTZ,
CPOP,
MAX,
MAXU,
MIN,
MINU,
SEXT_B,
SEXT_H,
ZEXT_H,
ROL,
ROR,
RORI,
ORC_B,
REV8,
CLZW,
CTZW,
CPOPW,
ROLW,
RORW,
RORIW,
REV8_64,
CLMUL,
CLMULH,
CLMULR,
BCLR,
BCLRI,
BSET,
BSETI,
BINV,
BINVI,
BEXT,
BEXTI,
AES32ESMI,
AES32ESI,
AES32DSMI,
AES32DSI,
SHA256SIG0,
SHA256SIG1,
SHA256SUM0,
SHA256SUM1,
SM4ED,
SM4KS,
SM3P0,
SM3P1,
SM3P0_SM3,
SM3P1_SM3,
AES64DSM,
AES64DS,
AES64ESM,
AES64ES,
AES64IM,
SHA512SIG0,
SHA512SIG1,
SHA512SUM0,
SHA512SUM1,
SHA512SIG0L,
SHA512SIG0H,
SHA512SIG1L,
SHA512SIG1H,
SHA512SUM0R,
SHA512SUM1R,
SM4ED_32,
SM4KS_32,
SM3P0_ZKSH,
SM3P1_ZKSH,
FLH,
FSH,
FMADD_H,
FMSUB_H,
FNMSUB_H,
FNMADD_H,
FADD_H,
FSUB_H,
FMUL_H,
FDIV_H,
FSQRT_H,
FSGNJ_H,
FSGNJN_H,
FSGNJX_H,
FMIN_H,
FMAX_H,
FCVT_W_H,
FCVT_WU_H,
FCVT_H_W,
FCVT_H_WU,
FMV_X_H,
FMV_H_X,
FEQ_H,
FLT_H,
FLE_H,
FCLASS_H,
FCVT_S_H,
FCVT_H_S,
FCVT_D_H,
FCVT_H_D,
FCVT_L_H,
FCVT_LU_H,
FCVT_H_L,
FCVT_H_LU,
FLI_S,
FLI_D,
FLI_H,
FMINM_S,
FMAXM_S,
FMINM_D,
FMAXM_D,
FMINM_H,
FMAXM_H,
FROUND_S,
FROUNDNX_S,
FROUND_D,
FROUNDNX_D,
FROUND_H,
FROUNDNX_H,
FCVTMOD_W_D,
FMVH_X_D,
FMVP_D_X,
FMVP_Q_X,
PACK,
PACKH,
PACKW,
BREV8,
UNZIP,
ZIP,
XPERM4,
XPERM8,
SEED,
CZERO_EQZ,
CZERO_NEZ,
CM_PUSH,
CM_POP,
CM_POPRET,
CM_POPRETZ,
CM_MVA01S,
CM_MVSA01,
CM_JT,
CM_JALT,
CM_BEQZ,
CM_BNEZ,
CM_MV,
CM_ADD,
CM_ADDI,
CM_SLLI,
VSETVLI,
VSETIVLI,
VSETVL,
VADD_VV,
VADD_VX,
VADD_VI,
VSUB_VV,
VSUB_VX,
VRSUB_VX,
VRSUB_VI,
VMINU_VV,
VMINU_VX,
VMIN_VV,
VMIN_VX,
VMAXU_VV,
VMAXU_VX,
VMAX_VV,
VMAX_VX,
VAND_VV,
VAND_VX,
VAND_VI,
VOR_VV,
VOR_VX,
VOR_VI,
VXOR_VV,
VXOR_VX,
VXOR_VI,
VRGATHER_VV,
VRGATHER_VX,
VRGATHER_VI,
VRGATHEREI16_VV,
VSLL_VV,
VSLL_VX,
VSLL_VI,
VSRL_VV,
VSRL_VX,
VSRL_VI,
VSRA_VV,
VSRA_VX,
VSRA_VI,
VMUL_VV,
VMUL_VX,
VMULH_VV,
VMULH_VX,
VMULHU_VV,
VMULHU_VX,
VMULHSU_VV,
VMULHSU_VX,
VDIVU_VV,
VDIVU_VX,
VDIV_VV,
VDIV_VX,
VREMU_VV,
VREMU_VX,
VREM_VV,
VREM_VX,
VWADDU_VV,
VWADDU_VX,
VWADD_VV,
VWADD_VX,
VWSUBU_VV,
VWSUBU_VX,
VWSUB_VV,
VWSUB_VX,
VWMULU_VV,
VWMULU_VX,
VWMULSU_VV,
VWMULSU_VX,
VWMUL_VV,
VWMUL_VX,
VNSRL_WV,
VNSRL_WX,
VNSRL_WI,
VNSRA_WV,
VNSRA_WX,
VNSRA_WI,
VNCVT_X_X_W,
VMAND_MM,
VMNAND_MM,
VMANDN_MM,
VMXOR_MM,
VMOR_MM,
VMNOR_MM,
VMORN_MM,
VMXNOR_MM,
VMMV_M,
VMCLR_M,
VMSET_M,
VMNOT_M,
VCPOP_M,
VFIRST_M,
VMSBF_M,
VMSIF_M,
VMSOF_M,
VIOTA_M,
VID_V,
VMSEQ_VV,
VMSEQ_VX,
VMSEQ_VI,
VMSNE_VV,
VMSNE_VX,
VMSNE_VI,
VMSLTU_VV,
VMSLTU_VX,
VMSLT_VV,
VMSLT_VX,
VMSLEU_VV,
VMSLEU_VX,
VMSLE_VV,
VMSLE_VX,
VMSGTU_VX,
VMSGTU_VI,
VMSGT_VX,
VMSGT_VI,
VMERGE_VVM,
VMERGE_VXM,
VMERGE_VIM,
VMV_V_V,
VMV_V_X,
VMV_V_I,
VMV_X_S,
VMV_S_X,
VFMV_F_S,
VFMV_S_F,
VSLIDEUP_VX,
VSLIDEUP_VI,
VSLIDEDOWN_VX,
VSLIDEDOWN_VI,
VSLIDE1UP_VX,
VSLIDE1DOWN_VX,
VRGATHER_VV_V,
VRGATHER_VX_V,
VCOMPRESS_VM,
VREDSUM_VS,
VREDMAXU_VS,
VREDMAX_VS,
VREDMINU_VS,
VREDMIN_VS,
VREDAND_VS,
VREDOR_VS,
VREDXOR_VS,
VWREDSUMU_VS,
VWREDSUM_VS,
VLE8_V,
VLE16_V,
VLE32_V,
VLE64_V,
VSE8_V,
VSE16_V,
VSE32_V,
VSE64_V,
VLM_V,
VSM_V,
VLOXEI8_V,
VLOXEI16_V,
VLOXEI32_V,
VLOXEI64_V,
VLUXEI8_V,
VLUXEI16_V,
VLUXEI32_V,
VLUXEI64_V,
VSOXEI8_V,
VSOXEI16_V,
VSOXEI32_V,
VSOXEI64_V,
VSUXEI8_V,
VSUXEI16_V,
VSUXEI32_V,
VSUXEI64_V,
VLSEG2E8_V,
VLSEG2E16_V,
VLSEG2E32_V,
VSSEG2E8_V,
VSSEG2E16_V,
VSSEG2E32_V,
VLSEG3E8_V,
VSSEG3E8_V,
VLSEG4E8_V,
VSSEG4E8_V,
VLSEG5E8_V,
VSSEG5E8_V,
VLSEG6E8_V,
VSSEG6E8_V,
VLSEG7E8_V,
VSSEG7E8_V,
VLSEG8E8_V,
VSSEG8E8_V,
VLSEGNF_V,
VSSEGNF_V,
VMV1R_V,
VMV2R_V,
VMV4R_V,
VMV8R_V,
VFADD_VV,
VFADD_VF,
VFSUB_VV,
VFSUB_VF,
VFRSUB_VF,
VFMUL_VV,
VFMUL_VF,
VFDIV_VV,
VFDIV_VF,
VFMADD_VV,
VFMADD_VF,
VFNMADD_VV,
VFNMADD_VF,
VFMSUB_VV,
VFMSUB_VF,
VFNMSUB_VV,
VFNMSUB_VF,
VFWMUL_VV,
VFWMUL_VF,
VFWADD_VV,
VFWADD_VF,
VFWSUB_VV,
VFWSUB_VF,
VFWMACC_VV,
VFWMACC_VF,
VFWNMACC_VV,
VFWNMACC_VF,
VFWMSAC_VV,
VFWMSAC_VF,
VFWNMSAC_VV,
VFWNMSAC_VF,
VFSQRT_V,
VFRSQRT7_V,
VFREC7_V,
VFMIN_VV,
VFMIN_VF,
VFMAX_VV,
VFMAX_VF,
VFSGNJ_VV,
VFSGNJ_VF,
VFSGNJN_VV,
VFSGNJN_VF,
VFSGNJX_VV,
VFSGNJX_VF,
VMFEQ_VV,
VMFEQ_VF,
VMFNE_VV,
VMFNE_VF,
VMFLT_VV,
VMFLT_VF,
VMFLE_VV,
VMFLE_VF,
VMFGT_VF,
VMFGE_VF,
VFCLASS_V,
VFNCVT_F_F_W,
VFNCVT_X_F_W,
VFWCVT_F_X_V,
VFWCVT_F_F_V,
VFCVT_X_F_V,
VFCVT_F_X_V,
VFCVT_RTZ_X_F_V,
VFREDUSUM_VS,
VFREDOSUM_VS,
VFREDMAX_VS,
VFREDMIN_VS,
VFWCVT_XU_F_V,
VFWCVT_X_F_V,
VFNCVT_XU_F_W,
VFNCVT_F_XU_W,
VFNCVT_F_X_W,
VFWCVT_F_XU_V,
VFNCVT_ROD_F_F_W,
VFWCVT_F_X_V_W,
VFWCVT_F_XU_V_W,
VFWCVT_X_F_V_W,
VFWCVT_XU_F_V_W,
VFNCVT_F_F_W_W,
VFNCVT_X_F_W_W,
VFNCVT_XU_F_W_W,
VFNCVT_F_X_W_W,
VFNCVT_F_XU_W_W,
VFMERGE_VFM,
VFMV_V_F,
VLSEG2E64_V,
VSSEG2E64_V,
VLSEG3E16_V,
VLSEG3E32_V,
VLSEG3E64_V,
VSSEG3E16_V,
VSSEG3E32_V,
VSSEG3E64_V,
VLSEG4E16_V,
VLSEG4E32_V,
VLSEG4E64_V,
VSSEG4E16_V,
VSSEG4E32_V,
VSSEG4E64_V,
VANDN_VV,
VANDN_VX,
VBREV_V,
VBREV8_V,
VREV8_V,
VCLZ_V,
VCTZ_V,
VCPOP_V,
VROL_VV,
VROL_VX,
VROR_VV,
VROR_VX,
VROR_VI,
VWSLL_VV,
VWSLL_VX,
VWSLL_VI,
VCLMUL_VV,
VCLMUL_VX,
VCLMULH_VV,
VCLMULH_VX,
VGHSH_VV,
VGMUL_VV,
VAES128E_VV,
VAES128D_VV,
VAES256E_VV,
VAES256D_VV,
VAES128E_VI,
VAES128D_VI,
VAES256E_VI,
VAES256D_VI,
VSHA256MS_VV,
VSHA256CH_VV,
VSHA256CL_VV,
VSM4E_VV,
VSM4E_VI,
VSM4D_VV,
VSM4D_VI,
VSM3ME_VV,
VSM3C_VI,
VSHA512MS_VV,
VSHA512CH_VV,
VSHA512CL_VV,
VSHA512SUM0_V,
VSHA512SUM1_V,
VSHA512SIG0_V,
VSHA512SIG1_V,
FCVT_BF16_S,
FCVT_S_BF16,
LPAD,
SSRDPOP,
SSRDPOP_CHK,
SSRDADDI,
SSAMOSWAP_W,
SSAMOSWAP_D,
SDEXT,
SRMTRR,
SMCSRIND,
SSCSRIND,
SVVPTC,
HFENCE_VVMA,
HFENCE_GVMA,
HLV_B,
HLV_H,
HLV_W,
HLV_D,
HLVX_HU,
HLVX_WU,
HSV_B,
HSV_H,
HSV_W,
HSV_D,
}
impl RiscVOpcode {
pub fn as_u32(self) -> u32 {
self as u32
}
pub fn is_conditional_branch(self) -> bool {
matches!(
self,
RiscVOpcode::BEQ
| RiscVOpcode::BNE
| RiscVOpcode::BLT
| RiscVOpcode::BGE
| RiscVOpcode::BLTU
| RiscVOpcode::BGEU
| RiscVOpcode::BEQZ
| RiscVOpcode::BNEZ
| RiscVOpcode::BLEZ
| RiscVOpcode::BGEZ
| RiscVOpcode::BLTZ
| RiscVOpcode::BGTZ
)
}
pub fn is_unconditional_jump(self) -> bool {
matches!(
self,
RiscVOpcode::JAL
| RiscVOpcode::JALR
| RiscVOpcode::J
| RiscVOpcode::JR
| RiscVOpcode::RET
| RiscVOpcode::TAIL
)
}
pub fn is_fp_opcode(self) -> bool {
use RiscVOpcode::*;
matches!(
self,
FLW | FSW
| FMADD_S
| FMSUB_S
| FNMSUB_S
| FNMADD_S
| FADD_S
| FSUB_S
| FMUL_S
| FDIV_S
| FSQRT_S
| FSGNJ_S
| FSGNJN_S
| FSGNJX_S
| FMIN_S
| FMAX_S
| FCVT_W_S
| FCVT_WU_S
| FCVT_L_S
| FCVT_LU_S
| FMV_X_W
| FEQ_S
| FLT_S
| FLE_S
| FCLASS_S
| FCVT_S_W
| FCVT_S_WU
| FCVT_S_L
| FCVT_S_LU
| FMV_W_X
| FLD
| FSD
| FMADD_D
| FMSUB_D
| FNMSUB_D
| FNMADD_D
| FADD_D
| FSUB_D
| FMUL_D
| FDIV_D
| FSQRT_D
| FSGNJ_D
| FSGNJN_D
| FSGNJX_D
| FMIN_D
| FMAX_D
| FCVT_W_D
| FCVT_WU_D
| FCVT_L_D
| FCVT_LU_D
| FMV_X_D
| FEQ_D
| FLT_D
| FLE_D
| FCLASS_D
| FCVT_D_W
| FCVT_D_WU
| FCVT_D_L
| FCVT_D_LU
| FMV_D_X
| FCVT_S_D
| FCVT_D_S
)
}
pub fn is_compressed(self) -> bool {
use RiscVOpcode::*;
matches!(
self,
C_ADDI4SPN
| C_LW
| C_LD
| C_FLW
| C_FLD
| C_SW
| C_SD
| C_FSW
| C_FSD
| C_NOP
| C_ADDI
| C_ADDIW
| C_ADDI16SP
| C_LI
| C_LUI
| C_SLLI
| C_SRAI
| C_SRLI
| C_MISC_ALU
| C_J
| C_JAL
| C_BEQZ
| C_BNEZ
| C_MV
| C_ADD
| C_JR
| C_JALR
| C_EBREAK
| C_SWSP
| C_SDSP
| C_FSWSP
| C_FSDSP
| C_LWSP
| C_LDSP
| C_FLWSP
| C_FLDSP
| C_SUB
| C_XOR
| C_OR
| C_AND
| C_ANDI
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RiscVOperandType {
GPR,
FPR,
FPR32,
FPR64,
Imm12,
Imm20,
Imm5,
Simm5,
Imm3,
Simm12,
Simm13,
Simm21,
Simm26,
CSR,
FencePredSucc,
VR,
VMask,
VFPR32,
VFPR64,
VGroup,
VSEW,
VLMul,
}
impl RiscVOperandType {
pub fn is_register(self) -> bool {
matches!(
self,
RiscVOperandType::GPR
| RiscVOperandType::FPR
| RiscVOperandType::FPR32
| RiscVOperandType::FPR64
| RiscVOperandType::VR
| RiscVOperandType::VFPR32
| RiscVOperandType::VFPR64
| RiscVOperandType::VMask
)
}
pub fn is_immediate(self) -> bool {
matches!(
self,
RiscVOperandType::Imm12
| RiscVOperandType::Imm20
| RiscVOperandType::Imm5
| RiscVOperandType::Imm3
| RiscVOperandType::Simm12
| RiscVOperandType::Simm13
| RiscVOperandType::Simm21
| RiscVOperandType::Simm26
| RiscVOperandType::CSR
| RiscVOperandType::VGroup
| RiscVOperandType::VSEW
| RiscVOperandType::VLMul
)
}
}
#[derive(Debug, Clone)]
pub struct RiscVInstrDesc {
pub opcode: RiscVOpcode,
pub mnemonic: &'static str,
pub num_operands: u8,
pub is_terminator: bool,
pub is_branch: bool,
pub is_call: bool,
pub is_return: bool,
pub is_compare: bool,
pub is_load: bool,
pub is_store: bool,
pub is_commutative: bool,
pub has_side_effects: bool,
pub is_rv32: bool,
pub is_rv64: bool,
pub operand_types: &'static [RiscVOperandType],
pub implicit_defs: &'static [u16],
pub implicit_uses: &'static [u16],
}
const FPR32_FPR32_FPR32_FPR32: &[RiscVOperandType] = &[
RiscVOperandType::FPR32,
RiscVOperandType::FPR32,
RiscVOperandType::FPR32,
RiscVOperandType::FPR32,
];
const FPR32_FPR32_FPR32: &[RiscVOperandType] = &[
RiscVOperandType::FPR32,
RiscVOperandType::FPR32,
RiscVOperandType::FPR32,
];
const FPR32_FPR32: &[RiscVOperandType] = &[RiscVOperandType::FPR32, RiscVOperandType::FPR32];
const GPR_FPR32_FPR32: &[RiscVOperandType] = &[
RiscVOperandType::GPR,
RiscVOperandType::FPR32,
RiscVOperandType::FPR32,
];
const GPR_FPR32: &[RiscVOperandType] = &[RiscVOperandType::GPR, RiscVOperandType::FPR32];
const FPR32_GPR: &[RiscVOperandType] = &[RiscVOperandType::FPR32, RiscVOperandType::GPR];
const FPR64_FPR64_FPR64_FPR64: &[RiscVOperandType] = &[
RiscVOperandType::FPR64,
RiscVOperandType::FPR64,
RiscVOperandType::FPR64,
RiscVOperandType::FPR64,
];
const FPR64_FPR64_FPR64: &[RiscVOperandType] = &[
RiscVOperandType::FPR64,
RiscVOperandType::FPR64,
RiscVOperandType::FPR64,
];
const FPR64_FPR64: &[RiscVOperandType] = &[RiscVOperandType::FPR64, RiscVOperandType::FPR64];
const GPR_FPR64_FPR64: &[RiscVOperandType] = &[
RiscVOperandType::GPR,
RiscVOperandType::FPR64,
RiscVOperandType::FPR64,
];
const GPR_FPR64: &[RiscVOperandType] = &[RiscVOperandType::GPR, RiscVOperandType::FPR64];
const FPR64_GPR: &[RiscVOperandType] = &[RiscVOperandType::FPR64, RiscVOperandType::GPR];
pub struct RiscVInstrInfo {
descriptors: HashMap<RiscVOpcode, RiscVInstrDesc>,
by_mnemonic: HashMap<String, RiscVOpcode>,
}
impl RiscVInstrInfo {
pub fn new() -> Self {
let mut info = RiscVInstrInfo {
descriptors: HashMap::with_capacity(300),
by_mnemonic: HashMap::with_capacity(300),
};
info.init_descriptors();
info
}
fn init_descriptors(&mut self) {
use RiscVOpcode::*;
use RiscVOperandType::*;
self.add(
InstrBuilder::new(LUI, "lui", 2)
.operands(&[GPR, Imm20])
.build(),
);
self.add(
InstrBuilder::new(AUIPC, "auipc", 2)
.operands(&[GPR, Imm20])
.build(),
);
self.add(
InstrBuilder::new(JAL, "jal", 2)
.operands(&[GPR, Simm21])
.is_terminator()
.is_branch()
.is_call()
.implicit_defs(&[RA])
.build(),
);
self.add(
InstrBuilder::new(JALR, "jalr", 3)
.operands(&[GPR, GPR, Simm12])
.is_terminator()
.is_branch()
.implicit_defs(&[RA])
.build(),
);
self.add(
InstrBuilder::new(BEQ, "beq", 3)
.operands(&[GPR, GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BNE, "bne", 3)
.operands(&[GPR, GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BLT, "blt", 3)
.operands(&[GPR, GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BGE, "bge", 3)
.operands(&[GPR, GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BLTU, "bltu", 3)
.operands(&[GPR, GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BGEU, "bgeu", 3)
.operands(&[GPR, GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(LB, "lb", 3)
.operands(&[GPR, Simm12, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(LH, "lh", 3)
.operands(&[GPR, Simm12, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(LW, "lw", 3)
.operands(&[GPR, Simm12, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(LBU, "lbu", 3)
.operands(&[GPR, Simm12, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(LHU, "lhu", 3)
.operands(&[GPR, Simm12, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(LD, "ld", 3)
.operands(&[GPR, Simm12, GPR])
.is_load()
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(LWU, "lwu", 3)
.operands(&[GPR, Simm12, GPR])
.is_load()
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SB, "sb", 3)
.operands(&[GPR, Simm12, GPR])
.is_store()
.build(),
);
self.add(
InstrBuilder::new(SH, "sh", 3)
.operands(&[GPR, Simm12, GPR])
.is_store()
.build(),
);
self.add(
InstrBuilder::new(SW, "sw", 3)
.operands(&[GPR, Simm12, GPR])
.is_store()
.build(),
);
self.add(
InstrBuilder::new(SD, "sd", 3)
.operands(&[GPR, Simm12, GPR])
.is_store()
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(ADDI, "addi", 3)
.operands(&[GPR, GPR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(SLTI, "slti", 3)
.operands(&[GPR, GPR, Simm12])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(SLTIU, "sltiu", 3)
.operands(&[GPR, GPR, Simm12])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(XORI, "xori", 3)
.operands(&[GPR, GPR, Simm12])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(ORI, "ori", 3)
.operands(&[GPR, GPR, Simm12])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(ANDI, "andi", 3)
.operands(&[GPR, GPR, Simm12])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(SLLI, "slli", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(SRLI, "srli", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(SRAI, "srai", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(ADD, "add", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(SUB, "sub", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SLL, "sll", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SLT, "slt", 3)
.operands(&[GPR, GPR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(SLTU, "sltu", 3)
.operands(&[GPR, GPR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(XOR, "xor", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(SRL, "srl", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SRA, "sra", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(OR, "or", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(AND, "and", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(ADDIW, "addiw", 3)
.operands(&[GPR, GPR, Simm12])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SLLIW, "slliw", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SRLIW, "srliw", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SRAIW, "sraiw", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(ADDW, "addw", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SUBW, "subw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SLLW, "sllw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SRLW, "srlw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SRAW, "sraw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(FENCE, "fence", 2)
.operands(&[FencePredSucc, FencePredSucc])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(FENCE_I, "fence.i", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(FENCE_TSO, "fence.tso", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(PAUSE, "pause", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(ECALL, "ecall", 0)
.has_side_effects()
.is_terminator()
.build(),
);
self.add(
InstrBuilder::new(EBREAK, "ebreak", 0)
.has_side_effects()
.is_terminator()
.build(),
);
self.add(
InstrBuilder::new(CSRRW, "csrrw", 3)
.operands(&[GPR, CSR, GPR])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CSRRS, "csrrs", 3)
.operands(&[GPR, CSR, GPR])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CSRRC, "csrrc", 3)
.operands(&[GPR, CSR, GPR])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CSRRWI, "csrrwi", 3)
.operands(&[GPR, CSR, Imm5])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CSRRSI, "csrrsi", 3)
.operands(&[GPR, CSR, Imm5])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CSRRCI, "csrrci", 3)
.operands(&[GPR, CSR, Imm5])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(MUL, "mul", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(MULH, "mulh", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(MULHSU, "mulhsu", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(MULHU, "mulhu", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(DIV, "div", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(DIVU, "divu", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(REM, "rem", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(REMU, "remu", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(MULW, "mulw", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(DIVW, "divw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(DIVUW, "divuw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(REMW, "remw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(REMUW, "remuw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(LR_W, "lr.w", 2)
.operands(&[GPR, GPR])
.is_load()
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SC_W, "sc.w", 3)
.operands(&[GPR, GPR, GPR])
.is_store()
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(LR_D, "lr.d", 2)
.operands(&[GPR, GPR])
.is_load()
.has_side_effects()
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SC_D, "sc.d", 3)
.operands(&[GPR, GPR, GPR])
.is_store()
.has_side_effects()
.is_rv64()
.build(),
);
self.add_amo(AMOSWAP_W, "amoswap.w");
self.add_amo(AMOADD_W, "amoadd.w");
self.add_amo(AMOXOR_W, "amoxor.w");
self.add_amo(AMOAND_W, "amoand.w");
self.add_amo(AMOOR_W, "amoor.w");
self.add_amo(AMOMIN_W, "amomin.w");
self.add_amo(AMOMAX_W, "amomax.w");
self.add_amo(AMOMINU_W, "amominu.w");
self.add_amo(AMOMAXU_W, "amomaxu.w");
self.add_amo_rv64(AMOSWAP_D, "amoswap.d");
self.add_amo_rv64(AMOADD_D, "amoadd.d");
self.add_amo_rv64(AMOXOR_D, "amoxor.d");
self.add_amo_rv64(AMOAND_D, "amoand.d");
self.add_amo_rv64(AMOOR_D, "amoor.d");
self.add_amo_rv64(AMOMIN_D, "amomin.d");
self.add_amo_rv64(AMOMAX_D, "amomax.d");
self.add_amo_rv64(AMOMINU_D, "amominu.d");
self.add_amo_rv64(AMOMAXU_D, "amomaxu.d");
self.add(
InstrBuilder::new(FLW, "flw", 3)
.operands(&[FPR32, GPR, Simm12])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(FSW, "fsw", 3)
.operands(&[FPR32, GPR, Simm12])
.is_store()
.build(),
);
self.add_fp_fma(FMADD_S, "fmadd.s", FPR32_FPR32_FPR32_FPR32);
self.add_fp_fma(FMSUB_S, "fmsub.s", FPR32_FPR32_FPR32_FPR32);
self.add_fp_fma(FNMSUB_S, "fnmsub.s", FPR32_FPR32_FPR32_FPR32);
self.add_fp_fma(FNMADD_S, "fnmadd.s", FPR32_FPR32_FPR32_FPR32);
self.add_fp_binop(FADD_S, "fadd.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FSUB_S, "fsub.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FMUL_S, "fmul.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FDIV_S, "fdiv.s", FPR32_FPR32_FPR32);
self.add_fp_unop(FSQRT_S, "fsqrt.s", FPR32_FPR32);
self.add_fp_binop(FSGNJ_S, "fsgnj.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FSGNJN_S, "fsgnjn.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FSGNJX_S, "fsgnjx.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FMIN_S, "fmin.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FMAX_S, "fmax.s", FPR32_FPR32_FPR32);
self.add_fp_to_int(FCVT_W_S, "fcvt.w.s", GPR_FPR32);
self.add_fp_to_int(FCVT_WU_S, "fcvt.wu.s", GPR_FPR32);
self.add_fp_to_int_rv64(FCVT_L_S, "fcvt.l.s", GPR_FPR32);
self.add_fp_to_int_rv64(FCVT_LU_S, "fcvt.lu.s", GPR_FPR32);
self.add(
InstrBuilder::new(FMV_X_W, "fmv.x.w", 2)
.operands(&[GPR, FPR32])
.build(),
);
self.add_fp_compare(FEQ_S, "feq.s", GPR_FPR32_FPR32);
self.add_fp_compare(FLT_S, "flt.s", GPR_FPR32_FPR32);
self.add_fp_compare(FLE_S, "fle.s", GPR_FPR32_FPR32);
self.add(
InstrBuilder::new(FCLASS_S, "fclass.s", 2)
.operands(&[GPR, FPR32])
.build(),
);
self.add_int_to_fp(FCVT_S_W, "fcvt.s.w", FPR32_GPR);
self.add_int_to_fp(FCVT_S_WU, "fcvt.s.wu", FPR32_GPR);
self.add_int_to_fp_rv64(FCVT_S_L, "fcvt.s.l", FPR32_GPR);
self.add_int_to_fp_rv64(FCVT_S_LU, "fcvt.s.lu", FPR32_GPR);
self.add(
InstrBuilder::new(FMV_W_X, "fmv.w.x", 2)
.operands(&[FPR32, GPR])
.build(),
);
self.add(
InstrBuilder::new(FLD, "fld", 3)
.operands(&[FPR64, GPR, Simm12])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(FSD, "fsd", 3)
.operands(&[FPR64, GPR, Simm12])
.is_store()
.build(),
);
self.add_fp_fma(FMADD_D, "fmadd.d", FPR64_FPR64_FPR64_FPR64);
self.add_fp_fma(FMSUB_D, "fmsub.d", FPR64_FPR64_FPR64_FPR64);
self.add_fp_fma(FNMSUB_D, "fnmsub.d", FPR64_FPR64_FPR64_FPR64);
self.add_fp_fma(FNMADD_D, "fnmadd.d", FPR64_FPR64_FPR64_FPR64);
self.add_fp_binop(FADD_D, "fadd.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FSUB_D, "fsub.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FMUL_D, "fmul.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FDIV_D, "fdiv.d", FPR64_FPR64_FPR64);
self.add_fp_unop(FSQRT_D, "fsqrt.d", FPR64_FPR64);
self.add_fp_binop(FSGNJ_D, "fsgnj.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FSGNJN_D, "fsgnjn.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FSGNJX_D, "fsgnjx.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FMIN_D, "fmin.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FMAX_D, "fmax.d", FPR64_FPR64_FPR64);
self.add_fp_to_int(FCVT_W_D, "fcvt.w.d", GPR_FPR64);
self.add_fp_to_int(FCVT_WU_D, "fcvt.wu.d", GPR_FPR64);
self.add_fp_to_int_rv64(FCVT_L_D, "fcvt.l.d", GPR_FPR64);
self.add_fp_to_int_rv64(FCVT_LU_D, "fcvt.lu.d", GPR_FPR64);
self.add(
InstrBuilder::new(FMV_X_D, "fmv.x.d", 2)
.operands(&[GPR, FPR64])
.build(),
);
self.add_fp_compare(FEQ_D, "feq.d", GPR_FPR64_FPR64);
self.add_fp_compare(FLT_D, "flt.d", GPR_FPR64_FPR64);
self.add_fp_compare(FLE_D, "fle.d", GPR_FPR64_FPR64);
self.add(
InstrBuilder::new(FCLASS_D, "fclass.d", 2)
.operands(&[GPR, FPR64])
.build(),
);
self.add_int_to_fp(FCVT_D_W, "fcvt.d.w", FPR64_GPR);
self.add_int_to_fp(FCVT_D_WU, "fcvt.d.wu", FPR64_GPR);
self.add_int_to_fp_rv64(FCVT_D_L, "fcvt.d.l", FPR64_GPR);
self.add_int_to_fp_rv64(FCVT_D_LU, "fcvt.d.lu", FPR64_GPR);
self.add(
InstrBuilder::new(FMV_D_X, "fmv.d.x", 2)
.operands(&[FPR64, GPR])
.build(),
);
self.add(
InstrBuilder::new(FCVT_S_D, "fcvt.s.d", 2)
.operands(&[FPR32, FPR64])
.build(),
);
self.add(
InstrBuilder::new(FCVT_D_S, "fcvt.d.s", 2)
.operands(&[FPR64, FPR32])
.build(),
);
self.add_compressed(C_ADDI4SPN, "c.addi4spn");
self.add_compressed(C_LW, "c.lw");
self.add_compressed(C_LD, "c.ld");
self.add_compressed(C_FLW, "c.flw");
self.add_compressed(C_FLD, "c.fld");
self.add_compressed(C_SW, "c.sw");
self.add_compressed(C_SD, "c.sd");
self.add_compressed(C_FSW, "c.fsw");
self.add_compressed(C_FSD, "c.fsd");
self.add_compressed(C_NOP, "c.nop");
self.add_compressed(C_ADDI, "c.addi");
self.add_compressed(C_ADDIW, "c.addiw");
self.add_compressed(C_ADDI16SP, "c.addi16sp");
self.add_compressed(C_LI, "c.li");
self.add_compressed(C_LUI, "c.lui");
self.add_compressed(C_SLLI, "c.slli");
self.add_compressed(C_SRAI, "c.srai");
self.add_compressed(C_SRLI, "c.srli");
self.add_compressed(C_MISC_ALU, "c.misc.alu");
self.add_compressed(C_J, "c.j");
self.add_compressed(C_JAL, "c.jal");
self.add_compressed(C_BEQZ, "c.beqz");
self.add_compressed(C_BNEZ, "c.bnez");
self.add_compressed(C_MV, "c.mv");
self.add_compressed(C_ADD, "c.add");
self.add_compressed(C_JR, "c.jr");
self.add_compressed(C_JALR, "c.jalr");
self.add_compressed(C_EBREAK, "c.ebreak");
self.add_compressed(C_SWSP, "c.swsp");
self.add_compressed(C_SDSP, "c.sdsp");
self.add_compressed(C_FSWSP, "c.fswsp");
self.add_compressed(C_FSDSP, "c.fsdsp");
self.add_compressed(C_LWSP, "c.lwsp");
self.add_compressed(C_LDSP, "c.ldsp");
self.add_compressed(C_FLWSP, "c.flwsp");
self.add_compressed(C_FLDSP, "c.fldsp");
self.add_compressed(C_SUB, "c.sub");
self.add_compressed(C_XOR, "c.xor");
self.add_compressed(C_OR, "c.or");
self.add_compressed(C_AND, "c.and");
self.add_compressed(C_ANDI, "c.andi");
self.add(
InstrBuilder::new(SH1ADD, "sh1add", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SH2ADD, "sh2add", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SH3ADD, "sh3add", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(ANDN, "andn", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(ORN, "orn", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(XNOR, "xnor", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(CLZ, "clz", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CTZ, "ctz", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CPOP, "cpop", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(MAX, "max", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(MAXU, "maxu", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(MIN, "min", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(MINU, "minu", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SEXT_B, "sext.b", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SEXT_H, "sext.h", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(ZEXT_H, "zext.h", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(ROL, "rol", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(ROR, "ror", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(RORI, "rori", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(ORC_B, "orc.b", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(REV8, "rev8", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CLZW, "clzw", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(CTZW, "ctzw", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(CPOPW, "cpopw", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(ROLW, "rolw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(RORW, "rorw", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(RORIW, "roriw", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(REV8_64, "rev8", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(CLMUL, "clmul", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(CLMULH, "clmulh", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(CLMULR, "clmulr", 3)
.operands(&[GPR, GPR, GPR])
.is_commutative()
.build(),
);
self.add(
InstrBuilder::new(BCLR, "bclr", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(BCLRI, "bclri", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(BSET, "bset", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(BSETI, "bseti", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(BINV, "binv", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(BINVI, "binvi", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(BEXT, "bext", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(BEXTI, "bexti", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(AES32ESMI, "aes32esmi", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(AES32ESI, "aes32esi", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(AES32DSMI, "aes32dsmi", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(AES32DSI, "aes32dsi", 3)
.operands(&[GPR, GPR, Imm5])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SHA256SIG0, "sha256sig0", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SHA256SIG1, "sha256sig1", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SHA256SUM0, "sha256sum0", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SHA256SUM1, "sha256sum1", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SM4ED, "sm4ed", 4)
.operands(&[GPR, GPR, Imm5, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SM4KS, "sm4ks", 4)
.operands(&[GPR, GPR, Imm5, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SM3P0, "sm3p0", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SM3P1, "sm3p1", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(AES64DSM, "aes64dsm", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(AES64DS, "aes64ds", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(AES64ESM, "aes64esm", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(AES64ES, "aes64es", 3)
.operands(&[GPR, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(AES64IM, "aes64im", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SHA512SIG0, "sha512sig0", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SHA512SIG1, "sha512sig1", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SHA512SUM0, "sha512sum0", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SHA512SUM1, "sha512sum1", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SHA512SIG0L, "sha512sig0l", 2)
.operands(&[GPR, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SHA512SIG0H, "sha512sig0h", 2)
.operands(&[GPR, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SHA512SIG1L, "sha512sig1l", 2)
.operands(&[GPR, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SHA512SIG1H, "sha512sig1h", 2)
.operands(&[GPR, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SHA512SUM0R, "sha512sum0r", 2)
.operands(&[GPR, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SHA512SUM1R, "sha512sum1r", 2)
.operands(&[GPR, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SM4ED_32, "sm4ed", 4)
.operands(&[GPR, GPR, Imm5, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SM4KS_32, "sm4ks", 4)
.operands(&[GPR, GPR, Imm5, GPR])
.is_rv32()
.build(),
);
self.add(
InstrBuilder::new(SM3P0_ZKSH, "sm3p0", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(SM3P1_ZKSH, "sm3p1", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(FLH, "flh", 3)
.operands(&[FPR32, GPR, Simm12])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(FSH, "fsh", 3)
.operands(&[FPR32, GPR, Simm12])
.is_store()
.build(),
);
self.add_fp_fma(FMADD_H, "fmadd.h", FPR32_FPR32_FPR32_FPR32);
self.add_fp_fma(FMSUB_H, "fmsub.h", FPR32_FPR32_FPR32_FPR32);
self.add_fp_fma(FNMSUB_H, "fnmsub.h", FPR32_FPR32_FPR32_FPR32);
self.add_fp_fma(FNMADD_H, "fnmadd.h", FPR32_FPR32_FPR32_FPR32);
self.add_fp_binop(FADD_H, "fadd.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FSUB_H, "fsub.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FMUL_H, "fmul.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FDIV_H, "fdiv.h", FPR32_FPR32_FPR32);
self.add_fp_unop(FSQRT_H, "fsqrt.h", FPR32_FPR32);
self.add_fp_binop(FSGNJ_H, "fsgnj.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FSGNJN_H, "fsgnjn.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FSGNJX_H, "fsgnjx.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FMIN_H, "fmin.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FMAX_H, "fmax.h", FPR32_FPR32_FPR32);
self.add_fp_to_int(FCVT_W_H, "fcvt.w.h", GPR_FPR32);
self.add_fp_to_int(FCVT_WU_H, "fcvt.wu.h", GPR_FPR32);
self.add_int_to_fp(FCVT_H_W, "fcvt.h.w", FPR32_GPR);
self.add_int_to_fp(FCVT_H_WU, "fcvt.h.wu", FPR32_GPR);
self.add(
InstrBuilder::new(FMV_X_H, "fmv.x.h", 2)
.operands(&[GPR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FMV_H_X, "fmv.h.x", 2)
.operands(&[FPR32, GPR])
.build(),
);
self.add_fp_compare(FEQ_H, "feq.h", GPR_FPR32_FPR32);
self.add_fp_compare(FLT_H, "flt.h", GPR_FPR32_FPR32);
self.add_fp_compare(FLE_H, "fle.h", GPR_FPR32_FPR32);
self.add(
InstrBuilder::new(FCLASS_H, "fclass.h", 2)
.operands(&[GPR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FCVT_S_H, "fcvt.s.h", 2)
.operands(&[FPR32, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FCVT_H_S, "fcvt.h.s", 2)
.operands(&[FPR32, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FCVT_D_H, "fcvt.d.h", 2)
.operands(&[FPR64, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FCVT_H_D, "fcvt.h.d", 2)
.operands(&[FPR32, FPR64])
.build(),
);
self.add_fp_to_int_rv64(FCVT_L_H, "fcvt.l.h", GPR_FPR32);
self.add_fp_to_int_rv64(FCVT_LU_H, "fcvt.lu.h", GPR_FPR32);
self.add_int_to_fp_rv64(FCVT_H_L, "fcvt.h.l", FPR32_GPR);
self.add_int_to_fp_rv64(FCVT_H_LU, "fcvt.h.lu", FPR32_GPR);
self.add(
InstrBuilder::new(FLI_S, "fli.s", 2)
.operands(&[FPR32, Imm5])
.build(),
);
self.add(
InstrBuilder::new(FLI_D, "fli.d", 2)
.operands(&[FPR64, Imm5])
.build(),
);
self.add(
InstrBuilder::new(FLI_H, "fli.h", 2)
.operands(&[FPR32, Imm5])
.build(),
);
self.add_fp_binop(FMINM_S, "fminm.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FMAXM_S, "fmaxm.s", FPR32_FPR32_FPR32);
self.add_fp_binop(FMINM_D, "fminm.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FMAXM_D, "fmaxm.d", FPR64_FPR64_FPR64);
self.add_fp_binop(FMINM_H, "fminm.h", FPR32_FPR32_FPR32);
self.add_fp_binop(FMAXM_H, "fmaxm.h", FPR32_FPR32_FPR32);
self.add(
InstrBuilder::new(FROUND_S, "fround.s", 2)
.operands(&[FPR32, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FROUNDNX_S, "froundnx.s", 2)
.operands(&[FPR32, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FROUND_D, "fround.d", 2)
.operands(&[FPR64, FPR64])
.build(),
);
self.add(
InstrBuilder::new(FROUNDNX_D, "froundnx.d", 2)
.operands(&[FPR64, FPR64])
.build(),
);
self.add(
InstrBuilder::new(FROUND_H, "fround.h", 2)
.operands(&[FPR32, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FROUNDNX_H, "froundnx.h", 2)
.operands(&[FPR32, FPR32])
.build(),
);
self.add(
InstrBuilder::new(FCVTMOD_W_D, "fcvtmod.w.d", 2)
.operands(&[GPR, FPR64])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(FMVH_X_D, "fmvh.x.d", 2)
.operands(&[GPR, FPR64])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(FMVP_D_X, "fmvp.d.x", 3)
.operands(&[FPR64, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(FMVP_Q_X, "fmvp.q.x", 3)
.operands(&[FPR64, GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(CZERO_EQZ, "czero.eqz", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CZERO_NEZ, "czero.nez", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CM_PUSH, "cm.push", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CM_POP, "cm.pop", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CM_POPRET, "cm.popret", 0)
.is_terminator()
.is_branch()
.is_return()
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CM_POPRETZ, "cm.popretz", 0)
.is_terminator()
.is_branch()
.is_return()
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(CM_MVA01S, "cm.mva01s", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CM_MVSA01, "cm.mvsa01", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CM_JT, "cm.jt", 1)
.operands(&[GPR])
.is_terminator()
.is_branch()
.build(),
);
self.add(
InstrBuilder::new(CM_JALT, "cm.jalt", 1)
.operands(&[GPR])
.is_terminator()
.is_branch()
.is_call()
.implicit_defs(&[RA])
.build(),
);
self.add(
InstrBuilder::new(CM_BEQZ, "cm.beqz", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(CM_BNEZ, "cm.bnez", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(CM_MV, "cm.mv", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CM_ADD, "cm.add", 3)
.operands(&[GPR, GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(CM_ADDI, "cm.addi", 3)
.operands(&[GPR, GPR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(CM_SLLI, "cm.slli", 3)
.operands(&[GPR, GPR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VSETVLI, "vsetvli", 3)
.operands(&[GPR, GPR, VSEW])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(VSETIVLI, "vsetivli", 3)
.operands(&[GPR, Imm5, VSEW])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(VSETVL, "vsetvl", 3)
.operands(&[GPR, GPR, GPR])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(VADD_VV, "vadd.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VADD_VX, "vadd.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VADD_VI, "vadd.vi", 3)
.operands(&[VR, VR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(VSUB_VV, "vsub.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSUB_VX, "vsub.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VRSUB_VX, "vrsub.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VRSUB_VI, "vrsub.vi", 3)
.operands(&[VR, VR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(VMINU_VV, "vminu.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMINU_VX, "vminu.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMIN_VV, "vmin.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMIN_VX, "vmin.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMAXU_VV, "vmaxu.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMAXU_VX, "vmaxu.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMAX_VV, "vmax.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMAX_VX, "vmax.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VAND_VV, "vand.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VAND_VX, "vand.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VAND_VI, "vand.vi", 3)
.operands(&[VR, VR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(VOR_VV, "vor.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VOR_VX, "vor.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VOR_VI, "vor.vi", 3)
.operands(&[VR, VR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(VXOR_VV, "vxor.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VXOR_VX, "vxor.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VXOR_VI, "vxor.vi", 3)
.operands(&[VR, VR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(VRGATHER_VV, "vrgather.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VRGATHER_VX, "vrgather.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VRGATHER_VI, "vrgather.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VRGATHEREI16_VV, "vrgatherei16.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSLL_VV, "vsll.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSLL_VX, "vsll.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VSLL_VI, "vsll.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VSRL_VV, "vsrl.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSRL_VX, "vsrl.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VSRL_VI, "vsrl.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VSRA_VV, "vsra.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSRA_VX, "vsra.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VSRA_VI, "vsra.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VMUL_VV, "vmul.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMUL_VX, "vmul.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMULH_VV, "vmulh.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMULH_VX, "vmulh.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMULHU_VV, "vmulhu.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMULHU_VX, "vmulhu.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMULHSU_VV, "vmulhsu.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMULHSU_VX, "vmulhsu.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VDIVU_VV, "vdivu.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VDIVU_VX, "vdivu.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VDIV_VV, "vdiv.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VDIV_VX, "vdiv.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VREMU_VV, "vremu.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREMU_VX, "vremu.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VREM_VV, "vrem.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREM_VX, "vrem.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMAND_MM, "vmand.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMNAND_MM, "vmnand.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMANDN_MM, "vmandn.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMXOR_MM, "vmxor.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMOR_MM, "vmor.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMNOR_MM, "vmnor.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMORN_MM, "vmorn.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMXNOR_MM, "vmxnor.mm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMMV_M, "vmmv.m", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMCLR_M, "vmclr.m", 1)
.operands(&[VR])
.build(),
);
self.add(
InstrBuilder::new(VMSET_M, "vmset.m", 1)
.operands(&[VR])
.build(),
);
self.add(
InstrBuilder::new(VMNOT_M, "vmnot.m", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VCPOP_M, "vcpop.m", 2)
.operands(&[GPR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFIRST_M, "vfirst.m", 2)
.operands(&[GPR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMSBF_M, "vmsbf.m", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMSIF_M, "vmsif.m", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMSOF_M, "vmsof.m", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VIOTA_M, "viota.m", 2)
.operands(&[VR, VR])
.build(),
);
self.add(InstrBuilder::new(VID_V, "vid.v", 1).operands(&[VR]).build());
self.add(
InstrBuilder::new(VMSEQ_VV, "vmseq.vv", 3)
.operands(&[VR, VR, VR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMSEQ_VX, "vmseq.vx", 3)
.operands(&[VR, VR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMSEQ_VI, "vmseq.vi", 3)
.operands(&[VR, VR, Simm12])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMSNE_VV, "vmsne.vv", 3)
.operands(&[VR, VR, VR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMSNE_VX, "vmsne.vx", 3)
.operands(&[VR, VR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMSNE_VI, "vmsne.vi", 3)
.operands(&[VR, VR, Simm12])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMSLTU_VV, "vmsltu.vv", 3)
.operands(&[VR, VR, VR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMSLTU_VX, "vmsltu.vx", 3)
.operands(&[VR, VR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMERGE_VVM, "vmerge.vvm", 4)
.operands(&[VR, VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMERGE_VXM, "vmerge.vxm", 4)
.operands(&[VR, VR, GPR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMERGE_VIM, "vmerge.vim", 4)
.operands(&[VR, VR, Simm12, VR])
.build(),
);
self.add(
InstrBuilder::new(VMV_V_V, "vmv.v.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMV_V_X, "vmv.v.x", 2)
.operands(&[VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMV_V_I, "vmv.v.i", 2)
.operands(&[VR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(VMV_X_S, "vmv.x.s", 2)
.operands(&[GPR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMV_S_X, "vmv.s.x", 2)
.operands(&[VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VSLIDEUP_VX, "vslideup.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VSLIDEUP_VI, "vslideup.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VSLIDEDOWN_VX, "vslidedown.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VSLIDEDOWN_VI, "vslidedown.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VSLIDE1UP_VX, "vslide1up.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VSLIDE1DOWN_VX, "vslide1down.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VREDSUM_VS, "vredsum.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREDMAXU_VS, "vredmaxu.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREDMAX_VS, "vredmax.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREDMINU_VS, "vredminu.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREDMIN_VS, "vredmin.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREDAND_VS, "vredand.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREDOR_VS, "vredor.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREDXOR_VS, "vredxor.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VWREDSUMU_VS, "vwredsumu.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VWREDSUM_VS, "vwredsum.vs", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VLE8_V, "vle8.v", 2)
.operands(&[VR, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(VLE16_V, "vle16.v", 2)
.operands(&[VR, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(VLE32_V, "vle32.v", 2)
.operands(&[VR, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(VLE64_V, "vle64.v", 2)
.operands(&[VR, GPR])
.is_load()
.build(),
);
self.add(
InstrBuilder::new(VSE8_V, "vse8.v", 2)
.operands(&[VR, GPR])
.is_store()
.build(),
);
self.add(
InstrBuilder::new(VSE16_V, "vse16.v", 2)
.operands(&[VR, GPR])
.is_store()
.build(),
);
self.add(
InstrBuilder::new(VSE32_V, "vse32.v", 2)
.operands(&[VR, GPR])
.is_store()
.build(),
);
self.add(
InstrBuilder::new(VSE64_V, "vse64.v", 2)
.operands(&[VR, GPR])
.is_store()
.build(),
);
self.add(
InstrBuilder::new(VFADD_VV, "vfadd.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFADD_VF, "vfadd.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFSUB_VV, "vfsub.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFSUB_VF, "vfsub.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFMUL_VV, "vfmul.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFMUL_VF, "vfmul.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFDIV_VV, "vfdiv.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFDIV_VF, "vfdiv.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFSQRT_V, "vfsqrt.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFRSQRT7_V, "vfrsqrt7.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFREC7_V, "vfrec7.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFMIN_VV, "vfmin.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFMIN_VF, "vfmin.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFMAX_VV, "vfmax.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFMAX_VF, "vfmax.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFSGNJ_VV, "vfsgnj.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFSGNJ_VF, "vfsgnj.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFSGNJN_VV, "vfsgnjn.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFSGNJN_VF, "vfsgnjn.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VFSGNJX_VV, "vfsgnjx.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFSGNJX_VF, "vfsgnjx.vf", 3)
.operands(&[VR, VR, FPR32])
.build(),
);
self.add(
InstrBuilder::new(VMFEQ_VV, "vmfeq.vv", 3)
.operands(&[VR, VR, VR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMFEQ_VF, "vmfeq.vf", 3)
.operands(&[VR, VR, FPR32])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMFNE_VV, "vmfne.vv", 3)
.operands(&[VR, VR, VR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMFNE_VF, "vmfne.vf", 3)
.operands(&[VR, VR, FPR32])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMFLT_VV, "vmflt.vv", 3)
.operands(&[VR, VR, VR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMFLT_VF, "vmflt.vf", 3)
.operands(&[VR, VR, FPR32])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMFLE_VV, "vmfle.vv", 3)
.operands(&[VR, VR, VR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VMFLE_VF, "vmfle.vf", 3)
.operands(&[VR, VR, FPR32])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(VFCLASS_V, "vfclass.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFCVT_X_F_V, "vfcvt.x.f.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFCVT_F_X_V, "vfcvt.f.x.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFCVT_RTZ_X_F_V, "vfcvt.rtz.x.f.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(InstrBuilder::new(NOP, "nop", 0).build());
self.add(InstrBuilder::new(MV, "mv", 2).operands(&[GPR, GPR]).build());
self.add(
InstrBuilder::new(NOT, "not", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(NEG, "neg", 2)
.operands(&[GPR, GPR])
.build(),
);
self.add(
InstrBuilder::new(NEGW, "negw", 2)
.operands(&[GPR, GPR])
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SEQZ, "seqz", 2)
.operands(&[GPR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(SNEZ, "snez", 2)
.operands(&[GPR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(SLTZ, "sltz", 2)
.operands(&[GPR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(SGTZ, "sgtz", 2)
.operands(&[GPR, GPR])
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BEQZ, "beqz", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BNEZ, "bnez", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BLEZ, "blez", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BGEZ, "bgez", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BLTZ, "bltz", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(BGTZ, "bgtz", 2)
.operands(&[GPR, Simm13])
.is_terminator()
.is_branch()
.is_compare()
.build(),
);
self.add(
InstrBuilder::new(J, "j", 1)
.operands(&[Simm21])
.is_terminator()
.is_branch()
.build(),
);
self.add(
InstrBuilder::new(JR, "jr", 1)
.operands(&[GPR])
.is_terminator()
.is_branch()
.is_return()
.build(),
);
self.add(
InstrBuilder::new(RET, "ret", 0)
.is_terminator()
.is_branch()
.is_return()
.implicit_uses(&[RA])
.build(),
);
self.add(
InstrBuilder::new(CALL, "call", 1)
.operands(&[Simm21])
.is_terminator()
.is_branch()
.is_call()
.implicit_defs(&[RA])
.implicit_uses(&[SP])
.build(),
);
self.add(
InstrBuilder::new(TAIL, "tail", 1)
.operands(&[Simm21])
.is_terminator()
.is_branch()
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(LI, "li", 2)
.operands(&[GPR, Simm12])
.build(),
);
self.add(
InstrBuilder::new(LA, "la", 2)
.operands(&[GPR, Simm21])
.build(),
);
self.add(
InstrBuilder::new(VMV_S_X, "vmv.s.x", 2)
.operands(&[VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMV_X_S, "vmv.x.s", 2)
.operands(&[GPR, VR])
.build(),
);
self.add(
InstrBuilder::new(VMV_V_I, "vmv.v.i", 2)
.operands(&[VR, Simm5])
.build(),
);
self.add(
InstrBuilder::new(VMV_V_X, "vmv.v.x", 2)
.operands(&[VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMV_V_V, "vmv.v.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VIOTA_M, "viota.m", 2)
.operands(&[VR, VR])
.build(),
);
self.add(InstrBuilder::new(VID_V, "vid.v", 1).operands(&[VR]).build());
self.add(
InstrBuilder::new(VMERGE_VIM, "vmerge.vim", 3)
.operands(&[VR, VR, Simm5])
.build(),
);
self.add(
InstrBuilder::new(VMERGE_VXM, "vmerge.vxm", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VMERGE_VVM, "vmerge.vvm", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFMERGE_VFM, "vfmerge.vfm", 3)
.operands(&[VR, VR, FPR])
.build(),
);
self.add(
InstrBuilder::new(VFMV_F_S, "vfmv.f.s", 2)
.operands(&[FPR, VR])
.build(),
);
self.add(
InstrBuilder::new(VFMV_S_F, "vfmv.s.f", 2)
.operands(&[VR, FPR])
.build(),
);
self.add(
InstrBuilder::new(VFMV_V_F, "vfmv.v.f", 2)
.operands(&[VR, FPR])
.build(),
);
self.add(
InstrBuilder::new(VSETVL, "vsetvl", 2)
.operands(&[GPR, GPR])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(VSETVLI, "vsetvli", 2)
.operands(&[GPR, Imm12])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(VSETIVLI, "vsetivli", 2)
.operands(&[GPR, Imm5])
.has_side_effects()
.build(),
);
for (mn, op) in &[
("vlseg2e64.v", VLSEG2E64_V),
("vsseg2e64.v", VSSEG2E64_V),
("vlseg3e16.v", VLSEG3E16_V),
("vlseg3e32.v", VLSEG3E32_V),
("vlseg3e64.v", VLSEG3E64_V),
("vsseg3e16.v", VSSEG3E16_V),
("vsseg3e32.v", VSSEG3E32_V),
("vsseg3e64.v", VSSEG3E64_V),
("vlseg4e16.v", VLSEG4E16_V),
("vlseg4e32.v", VLSEG4E32_V),
("vlseg4e64.v", VLSEG4E64_V),
("vsseg4e16.v", VSSEG4E16_V),
("vsseg4e32.v", VSSEG4E32_V),
("vsseg4e64.v", VSSEG4E64_V),
] {
self.add(
InstrBuilder::new(*op, mn, 2)
.operands(&[VR, GPR])
.is_load()
.is_store()
.build(),
);
}
self.add(
InstrBuilder::new(VANDN_VV, "vandn.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VANDN_VX, "vandn.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VBREV_V, "vbrev.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VBREV8_V, "vbrev8.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VREV8_V, "vrev8.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VCLZ_V, "vclz.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VCTZ_V, "vctz.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VCPOP_V, "vcpop.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VROL_VV, "vrol.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VROL_VX, "vrol.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VROR_VV, "vror.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VROR_VX, "vror.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VROR_VI, "vror.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VWSLL_VV, "vwsll.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VWSLL_VX, "vwsll.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VWSLL_VI, "vwsll.vi", 3)
.operands(&[VR, VR, Imm5])
.build(),
);
self.add(
InstrBuilder::new(VCLMUL_VV, "vclmul.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VCLMUL_VX, "vclmul.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VCLMULH_VV, "vclmulh.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VCLMULH_VX, "vclmulh.vx", 3)
.operands(&[VR, VR, GPR])
.build(),
);
self.add(
InstrBuilder::new(VGHSH_VV, "vghsh.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VGMUL_VV, "vgmul.vv", 2)
.operands(&[VR, VR])
.build(),
);
for (mn, op) in &[
("vaes128e.vv", VAES128E_VV),
("vaes128d.vv", VAES128D_VV),
("vaes256e.vv", VAES256E_VV),
("vaes256d.vv", VAES256D_VV),
("vaes128e.vi", VAES128E_VI),
("vaes128d.vi", VAES128D_VI),
("vaes256e.vi", VAES256E_VI),
("vaes256d.vi", VAES256D_VI),
] {
self.add(InstrBuilder::new(*op, mn, 2).operands(&[VR, VR]).build());
}
self.add(
InstrBuilder::new(VSHA256MS_VV, "vsha256ms.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA256CH_VV, "vsha256ch.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA256CL_VV, "vsha256cl.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSM4E_VV, "vsm4e.vv", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSM4E_VI, "vsm4e.vi", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSM4D_VV, "vsm4d.vv", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSM4D_VI, "vsm4d.vi", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSM3ME_VV, "vsm3me.vv", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSM3C_VI, "vsm3c.vi", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA512MS_VV, "vsha512ms.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA512CH_VV, "vsha512ch.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA512CL_VV, "vsha512cl.vv", 3)
.operands(&[VR, VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA512SUM0_V, "vsha512sum0.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA512SUM1_V, "vsha512sum1.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA512SIG0_V, "vsha512sig0.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(VSHA512SIG1_V, "vsha512sig1.v", 2)
.operands(&[VR, VR])
.build(),
);
self.add(
InstrBuilder::new(FCVT_BF16_S, "fcvt.bf16.s", 2)
.operands(&[FPR, FPR])
.build(),
);
self.add(
InstrBuilder::new(FCVT_S_BF16, "fcvt.s.bf16", 2)
.operands(&[FPR, FPR])
.build(),
);
self.add(
InstrBuilder::new(LPAD, "lpad", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SSRDPOP, "ssrdpop", 2)
.operands(&[GPR, GPR])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SSRDPOP_CHK, "ssrdpop.chk", 2)
.operands(&[GPR, GPR])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SSRDADDI, "ssrdaddi", 3)
.operands(&[GPR, GPR, Simm12])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SSAMOSWAP_W, "ssamoswap.w", 3)
.operands(&[GPR, GPR, GPR])
.is_load()
.is_store()
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SSAMOSWAP_D, "ssamoswap.d", 3)
.operands(&[GPR, GPR, GPR])
.is_load()
.is_store()
.has_side_effects()
.is_rv64()
.build(),
);
self.add(
InstrBuilder::new(SDEXT, "sdext", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SRMTRR, "srmtrr", 0)
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SMCSRIND, "smcsrind", 2)
.operands(&[GPR, Imm12])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SSCSRIND, "sscsrind", 2)
.operands(&[GPR, Imm12])
.has_side_effects()
.build(),
);
self.add(
InstrBuilder::new(SVVPTC, "svvptc", 0)
.has_side_effects()
.build(),
);
}
fn add(&mut self, desc: RiscVInstrDesc) {
let mnemonic = desc.mnemonic.to_string();
self.by_mnemonic.insert(mnemonic, desc.opcode);
self.descriptors.insert(desc.opcode, desc);
}
fn add_amo(&mut self, opcode: RiscVOpcode, mnemonic: &'static str) {
self.add(
InstrBuilder::new(opcode, mnemonic, 3)
.operands(&[
RiscVOperandType::GPR,
RiscVOperandType::GPR,
RiscVOperandType::GPR,
])
.is_load()
.is_store()
.has_side_effects()
.build(),
);
}
fn add_amo_rv64(&mut self, opcode: RiscVOpcode, mnemonic: &'static str) {
self.add(
InstrBuilder::new(opcode, mnemonic, 3)
.operands(&[
RiscVOperandType::GPR,
RiscVOperandType::GPR,
RiscVOperandType::GPR,
])
.is_load()
.is_store()
.has_side_effects()
.is_rv64()
.build(),
);
}
fn add_fp_fma(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(InstrBuilder::new(opcode, mnemonic, 4).operands(ops).build());
}
fn add_fp_binop(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(InstrBuilder::new(opcode, mnemonic, 3).operands(ops).build());
}
fn add_fp_unop(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(InstrBuilder::new(opcode, mnemonic, 2).operands(ops).build());
}
fn add_fp_compare(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(
InstrBuilder::new(opcode, mnemonic, 3)
.operands(ops)
.is_compare()
.build(),
);
}
fn add_fp_to_int(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(InstrBuilder::new(opcode, mnemonic, 2).operands(ops).build());
}
fn add_fp_to_int_rv64(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(
InstrBuilder::new(opcode, mnemonic, 2)
.operands(ops)
.is_rv64()
.build(),
);
}
fn add_int_to_fp(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(InstrBuilder::new(opcode, mnemonic, 2).operands(ops).build());
}
fn add_int_to_fp_rv64(
&mut self,
opcode: RiscVOpcode,
mnemonic: &'static str,
ops: &'static [RiscVOperandType],
) {
self.add(
InstrBuilder::new(opcode, mnemonic, 2)
.operands(ops)
.is_rv64()
.build(),
);
}
fn add_compressed(&mut self, opcode: RiscVOpcode, mnemonic: &'static str) {
self.add(
InstrBuilder::new(opcode, mnemonic, 0)
.has_side_effects()
.build(),
);
}
pub fn get(&self, opcode: RiscVOpcode) -> &RiscVInstrDesc {
self.descriptors
.get(&opcode)
.unwrap_or_else(|| panic!("No descriptor for opcode {:?}", opcode))
}
pub fn get_mnemonic(&self, opcode: RiscVOpcode) -> &str {
self.get(opcode).mnemonic
}
pub fn find_by_mnemonic(&self, name: &str) -> Option<RiscVOpcode> {
self.by_mnemonic.get(name).copied()
}
pub fn is_terminator(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_terminator
}
pub fn is_branch(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_branch
}
pub fn is_call(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_call
}
pub fn is_return(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_return
}
pub fn is_commutative(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_commutative
}
pub fn is_compare(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_compare
}
pub fn may_load(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_load
}
pub fn may_store(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_store
}
pub fn has_side_effects(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).has_side_effects
}
pub fn get_num_operands(&self, opcode: RiscVOpcode) -> u8 {
self.get(opcode).num_operands
}
pub fn get_operand_types(&self, opcode: RiscVOpcode) -> &[RiscVOperandType] {
self.get(opcode).operand_types
}
pub fn get_implicit_defs(&self, opcode: RiscVOpcode) -> &[u16] {
self.get(opcode).implicit_defs
}
pub fn get_implicit_uses(&self, opcode: RiscVOpcode) -> &[u16] {
self.get(opcode).implicit_uses
}
pub fn is_rv32_only(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_rv32
}
pub fn is_rv64_only(&self, opcode: RiscVOpcode) -> bool {
self.get(opcode).is_rv64
}
pub fn get_rv32_opcodes(&self) -> Vec<RiscVOpcode> {
self.descriptors
.values()
.filter(|d| !d.is_rv64)
.map(|d| d.opcode)
.collect()
}
pub fn get_rv64_opcodes(&self) -> Vec<RiscVOpcode> {
self.descriptors
.values()
.filter(|d| !d.is_rv32)
.map(|d| d.opcode)
.collect()
}
}
impl Default for RiscVInstrInfo {
fn default() -> Self {
RiscVInstrInfo::new()
}
}
struct InstrBuilder {
desc: RiscVInstrDesc,
}
impl InstrBuilder {
fn new(opcode: RiscVOpcode, mnemonic: &'static str, num_operands: u8) -> Self {
InstrBuilder {
desc: RiscVInstrDesc {
opcode,
mnemonic,
num_operands,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[],
},
}
}
fn operands(mut self, types: &'static [RiscVOperandType]) -> Self {
self.desc.operand_types = types;
self
}
fn is_terminator(mut self) -> Self {
self.desc.is_terminator = true;
self
}
fn is_branch(mut self) -> Self {
self.desc.is_branch = true;
self
}
fn is_call(mut self) -> Self {
self.desc.is_call = true;
self
}
fn is_return(mut self) -> Self {
self.desc.is_return = true;
self
}
fn is_compare(mut self) -> Self {
self.desc.is_compare = true;
self
}
fn is_load(mut self) -> Self {
self.desc.is_load = true;
self
}
fn is_store(mut self) -> Self {
self.desc.is_store = true;
self
}
fn is_commutative(mut self) -> Self {
self.desc.is_commutative = true;
self
}
fn has_side_effects(mut self) -> Self {
self.desc.has_side_effects = true;
self
}
fn is_rv32(mut self) -> Self {
self.desc.is_rv32 = true;
self
}
fn is_rv64(mut self) -> Self {
self.desc.is_rv64 = true;
self
}
fn implicit_defs(mut self, defs: &'static [u16]) -> Self {
self.desc.implicit_defs = defs;
self
}
fn implicit_uses(mut self, uses: &'static [u16]) -> Self {
self.desc.implicit_uses = uses;
self
}
fn build(self) -> RiscVInstrDesc {
self.desc
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_info() -> RiscVInstrInfo {
RiscVInstrInfo::new()
}
#[test]
fn test_opcode_count_at_least_200() {
let info = make_info();
let count = info.descriptors.len();
assert!(count >= 200, "Expected at least 200 opcodes, got {}", count);
}
#[test]
fn test_opcode_is_conditional_branch() {
assert!(RiscVOpcode::BEQ.is_conditional_branch());
assert!(RiscVOpcode::BNE.is_conditional_branch());
assert!(RiscVOpcode::BLT.is_conditional_branch());
assert!(RiscVOpcode::BGE.is_conditional_branch());
assert!(RiscVOpcode::BLTU.is_conditional_branch());
assert!(RiscVOpcode::BGEU.is_conditional_branch());
assert!(RiscVOpcode::BEQZ.is_conditional_branch());
assert!(RiscVOpcode::BNEZ.is_conditional_branch());
assert!(!RiscVOpcode::ADD.is_conditional_branch());
assert!(!RiscVOpcode::JAL.is_conditional_branch());
}
#[test]
fn test_opcode_is_unconditional_jump() {
assert!(RiscVOpcode::JAL.is_unconditional_jump());
assert!(RiscVOpcode::JALR.is_unconditional_jump());
assert!(RiscVOpcode::J.is_unconditional_jump());
assert!(RiscVOpcode::JR.is_unconditional_jump());
assert!(RiscVOpcode::RET.is_unconditional_jump());
assert!(!RiscVOpcode::BEQ.is_unconditional_jump());
}
#[test]
fn test_opcode_is_fp_opcode() {
assert!(RiscVOpcode::FADD_S.is_fp_opcode());
assert!(RiscVOpcode::FADD_D.is_fp_opcode());
assert!(RiscVOpcode::FMUL_S.is_fp_opcode());
assert!(RiscVOpcode::FCVT_S_D.is_fp_opcode());
assert!(!RiscVOpcode::ADD.is_fp_opcode());
assert!(!RiscVOpcode::LW.is_fp_opcode());
}
#[test]
fn test_operand_type_is_register() {
assert!(RiscVOperandType::GPR.is_register());
assert!(RiscVOperandType::FPR32.is_register());
assert!(RiscVOperandType::FPR64.is_register());
assert!(!RiscVOperandType::Simm12.is_register());
assert!(!RiscVOperandType::Imm20.is_register());
}
#[test]
fn test_operand_type_is_immediate() {
assert!(RiscVOperandType::Imm12.is_immediate());
assert!(RiscVOperandType::Simm12.is_immediate());
assert!(RiscVOperandType::Simm21.is_immediate());
assert!(RiscVOperandType::CSR.is_immediate());
assert!(!RiscVOperandType::GPR.is_immediate());
}
#[test]
fn test_instr_info_get() {
let info = make_info();
let desc = info.get(RiscVOpcode::ADD);
assert_eq!(desc.mnemonic, "add");
assert_eq!(desc.num_operands, 3);
assert!(desc.is_commutative);
}
#[test]
fn test_instr_info_get_mnemonic() {
let info = make_info();
assert_eq!(info.get_mnemonic(RiscVOpcode::LUI), "lui");
assert_eq!(info.get_mnemonic(RiscVOpcode::BEQ), "beq");
assert_eq!(info.get_mnemonic(RiscVOpcode::JAL), "jal");
assert_eq!(info.get_mnemonic(RiscVOpcode::LW), "lw");
assert_eq!(info.get_mnemonic(RiscVOpcode::FADD_S), "fadd.s");
}
#[test]
fn test_find_by_mnemonic() {
let info = make_info();
assert_eq!(info.find_by_mnemonic("add"), Some(RiscVOpcode::ADD));
assert_eq!(info.find_by_mnemonic("lw"), Some(RiscVOpcode::LW));
assert_eq!(info.find_by_mnemonic("jal"), Some(RiscVOpcode::JAL));
assert_eq!(info.find_by_mnemonic("ecall"), Some(RiscVOpcode::ECALL));
assert_eq!(info.find_by_mnemonic("nonexistent"), None);
}
#[test]
fn test_instr_info_is_terminator() {
let info = make_info();
assert!(info.is_terminator(RiscVOpcode::JAL));
assert!(info.is_terminator(RiscVOpcode::JALR));
assert!(info.is_terminator(RiscVOpcode::BEQ));
assert!(info.is_terminator(RiscVOpcode::RET));
assert!(info.is_terminator(RiscVOpcode::ECALL));
assert!(!info.is_terminator(RiscVOpcode::ADD));
assert!(!info.is_terminator(RiscVOpcode::LW));
}
#[test]
fn test_instr_info_is_branch() {
let info = make_info();
assert!(info.is_branch(RiscVOpcode::JAL));
assert!(info.is_branch(RiscVOpcode::BEQ));
assert!(info.is_branch(RiscVOpcode::BNE));
assert!(info.is_branch(RiscVOpcode::RET));
assert!(!info.is_branch(RiscVOpcode::ADD));
}
#[test]
fn test_instr_info_is_call() {
let info = make_info();
assert!(info.is_call(RiscVOpcode::JAL));
assert!(info.is_call(RiscVOpcode::CALL));
assert!(!info.is_call(RiscVOpcode::ADD));
assert!(!info.is_call(RiscVOpcode::BEQ));
}
#[test]
fn test_instr_info_is_return() {
let info = make_info();
assert!(info.is_return(RiscVOpcode::JR));
assert!(info.is_return(RiscVOpcode::RET));
assert!(!info.is_return(RiscVOpcode::JAL));
assert!(!info.is_return(RiscVOpcode::ADD));
}
#[test]
fn test_instr_info_is_commutative() {
let info = make_info();
assert!(info.is_commutative(RiscVOpcode::ADD));
assert!(info.is_commutative(RiscVOpcode::MUL));
assert!(info.is_commutative(RiscVOpcode::XOR));
assert!(info.is_commutative(RiscVOpcode::AND));
assert!(!info.is_commutative(RiscVOpcode::SUB));
assert!(!info.is_commutative(RiscVOpcode::SLL));
}
#[test]
fn test_instr_info_is_compare() {
let info = make_info();
assert!(info.is_compare(RiscVOpcode::SLT));
assert!(info.is_compare(RiscVOpcode::BEQ));
assert!(info.is_compare(RiscVOpcode::SEQZ));
assert!(info.is_compare(RiscVOpcode::FEQ_S));
assert!(!info.is_compare(RiscVOpcode::ADD));
assert!(!info.is_compare(RiscVOpcode::LW));
}
#[test]
fn test_instr_info_may_load() {
let info = make_info();
assert!(info.may_load(RiscVOpcode::LB));
assert!(info.may_load(RiscVOpcode::LW));
assert!(info.may_load(RiscVOpcode::LD));
assert!(info.may_load(RiscVOpcode::FLW));
assert!(info.may_load(RiscVOpcode::FLD));
assert!(!info.may_load(RiscVOpcode::ADD));
assert!(!info.may_load(RiscVOpcode::SW));
}
#[test]
fn test_instr_info_may_store() {
let info = make_info();
assert!(info.may_store(RiscVOpcode::SB));
assert!(info.may_store(RiscVOpcode::SW));
assert!(info.may_store(RiscVOpcode::SD));
assert!(info.may_store(RiscVOpcode::FSW));
assert!(info.may_store(RiscVOpcode::FSD));
assert!(!info.may_store(RiscVOpcode::ADD));
assert!(!info.may_store(RiscVOpcode::LW));
}
#[test]
fn test_instr_info_has_side_effects() {
let info = make_info();
assert!(info.has_side_effects(RiscVOpcode::ECALL));
assert!(info.has_side_effects(RiscVOpcode::EBREAK));
assert!(info.has_side_effects(RiscVOpcode::FENCE));
assert!(info.has_side_effects(RiscVOpcode::CSRRW));
assert!(!info.has_side_effects(RiscVOpcode::ADD));
assert!(!info.has_side_effects(RiscVOpcode::LW));
}
#[test]
fn test_instr_info_get_num_operands() {
let info = make_info();
assert_eq!(info.get_num_operands(RiscVOpcode::LUI), 2);
assert_eq!(info.get_num_operands(RiscVOpcode::ADD), 3);
assert_eq!(info.get_num_operands(RiscVOpcode::JAL), 2);
assert_eq!(info.get_num_operands(RiscVOpcode::NOP), 0);
assert_eq!(info.get_num_operands(RiscVOpcode::RET), 0);
assert_eq!(info.get_num_operands(RiscVOpcode::FMADD_S), 4);
}
#[test]
fn test_instr_info_rv32_rv64() {
let info = make_info();
assert!(info.is_rv64_only(RiscVOpcode::LD));
assert!(info.is_rv64_only(RiscVOpcode::LWU));
assert!(info.is_rv64_only(RiscVOpcode::ADDW));
assert!(info.is_rv64_only(RiscVOpcode::MULW));
assert!(!info.is_rv64_only(RiscVOpcode::ADD));
assert!(!info.is_rv32_only(RiscVOpcode::ADD));
assert!(!info.is_rv64_only(RiscVOpcode::ADD));
}
#[test]
fn test_get_rv32_opcodes() {
let info = make_info();
let rv32 = info.get_rv32_opcodes();
assert!(rv32.contains(&RiscVOpcode::ADD));
assert!(rv32.contains(&RiscVOpcode::LW));
assert!(!rv32.contains(&RiscVOpcode::LD));
assert!(!rv32.contains(&RiscVOpcode::ADDW));
}
#[test]
fn test_get_rv64_opcodes() {
let info = make_info();
let rv64 = info.get_rv64_opcodes();
assert!(rv64.contains(&RiscVOpcode::ADD));
assert!(rv64.contains(&RiscVOpcode::LD));
assert!(rv64.contains(&RiscVOpcode::ADDW));
assert!(rv64.contains(&RiscVOpcode::LW));
}
#[test]
fn test_find_by_mnemonic_pseudo() {
let info = make_info();
assert_eq!(info.find_by_mnemonic("nop"), Some(RiscVOpcode::NOP));
assert_eq!(info.find_by_mnemonic("mv"), Some(RiscVOpcode::MV));
assert_eq!(info.find_by_mnemonic("ret"), Some(RiscVOpcode::RET));
assert_eq!(info.find_by_mnemonic("call"), Some(RiscVOpcode::CALL));
assert_eq!(info.find_by_mnemonic("li"), Some(RiscVOpcode::LI));
assert_eq!(info.find_by_mnemonic("la"), Some(RiscVOpcode::LA));
}
#[test]
fn test_find_by_mnemonic_fp() {
let info = make_info();
assert_eq!(info.find_by_mnemonic("fadd.s"), Some(RiscVOpcode::FADD_S));
assert_eq!(info.find_by_mnemonic("fmul.d"), Some(RiscVOpcode::FMUL_D));
assert_eq!(
info.find_by_mnemonic("fcvt.s.d"),
Some(RiscVOpcode::FCVT_S_D)
);
assert_eq!(
info.find_by_mnemonic("fcvt.d.s"),
Some(RiscVOpcode::FCVT_D_S)
);
}
#[test]
fn test_implicit_defs_uses() {
let info = make_info();
let jal = info.get(RiscVOpcode::JAL);
assert!(jal.implicit_defs.contains(&RA));
let ret = info.get(RiscVOpcode::RET);
assert!(ret.implicit_uses.contains(&RA));
let call = info.get(RiscVOpcode::CALL);
assert!(call.implicit_defs.contains(&RA));
assert!(call.implicit_uses.contains(&SP));
}
#[test]
fn test_get_operand_types() {
let info = make_info();
let add = info.get_operand_types(RiscVOpcode::ADD);
assert_eq!(add.len(), 3);
assert_eq!(add[0], RiscVOperandType::GPR);
let lw = info.get_operand_types(RiscVOpcode::LW);
assert_eq!(lw.len(), 3);
assert_eq!(lw[0], RiscVOperandType::GPR);
assert_eq!(lw[1], RiscVOperandType::Simm12);
assert_eq!(lw[2], RiscVOperandType::GPR);
}
#[test]
fn test_find_by_mnemonic_atomics() {
let info = make_info();
assert_eq!(info.find_by_mnemonic("lr.w"), Some(RiscVOpcode::LR_W));
assert_eq!(info.find_by_mnemonic("sc.w"), Some(RiscVOpcode::SC_W));
assert_eq!(
info.find_by_mnemonic("amoswap.w"),
Some(RiscVOpcode::AMOSWAP_W)
);
assert_eq!(
info.find_by_mnemonic("amoadd.d"),
Some(RiscVOpcode::AMOADD_D)
);
}
#[test]
fn test_find_by_mnemonic_compressed() {
let info = make_info();
assert_eq!(info.find_by_mnemonic("c.addi"), Some(RiscVOpcode::C_ADDI));
assert_eq!(info.find_by_mnemonic("c.mv"), Some(RiscVOpcode::C_MV));
assert_eq!(info.find_by_mnemonic("c.j"), Some(RiscVOpcode::C_J));
assert_eq!(info.find_by_mnemonic("c.nop"), Some(RiscVOpcode::C_NOP));
}
#[test]
fn test_all_opcodes_have_descriptor() {
let info = make_info();
assert!(info.find_by_mnemonic("add").is_some());
assert!(info.find_by_mnemonic("addi").is_some());
assert!(info.find_by_mnemonic("sub").is_some());
assert!(info.find_by_mnemonic("lui").is_some());
assert!(info.find_by_mnemonic("auipc").is_some());
assert!(info.find_by_mnemonic("lw").is_some());
assert!(info.find_by_mnemonic("sw").is_some());
assert!(info.find_by_mnemonic("beq").is_some());
assert!(info.find_by_mnemonic("jal").is_some());
assert!(info.find_by_mnemonic("jalr").is_some());
assert!(info.find_by_mnemonic("mul").is_some());
assert!(info.find_by_mnemonic("div").is_some());
assert!(info.find_by_mnemonic("rem").is_some());
assert!(info.find_by_mnemonic("ecall").is_some());
assert!(info.find_by_mnemonic("csrrw").is_some());
}
#[test]
fn test_default_creates_valid_instance() {
let info = RiscVInstrInfo::default();
assert!(info.descriptors.len() >= 200);
}
#[test]
fn test_rv64_only_opcodes_not_in_rv32() {
let info = make_info();
let rv32 = info.get_rv32_opcodes();
assert!(!rv32.contains(&RiscVOpcode::LD));
assert!(!rv32.contains(&RiscVOpcode::SD));
assert!(!rv32.contains(&RiscVOpcode::ADDW));
assert!(!rv32.contains(&RiscVOpcode::SUBW));
assert!(!rv32.contains(&RiscVOpcode::MULW));
assert!(!rv32.contains(&RiscVOpcode::DIVW));
assert!(!rv32.contains(&RiscVOpcode::LR_D));
assert!(!rv32.contains(&RiscVOpcode::SC_D));
assert!(!rv32.contains(&RiscVOpcode::LWU));
}
#[test]
fn test_branch_opcodes_are_terminators() {
let info = make_info();
let branches = [
RiscVOpcode::BEQ,
RiscVOpcode::BNE,
RiscVOpcode::BLT,
RiscVOpcode::BGE,
RiscVOpcode::BLTU,
RiscVOpcode::BGEU,
RiscVOpcode::BEQZ,
RiscVOpcode::BNEZ,
RiscVOpcode::BLEZ,
RiscVOpcode::BGEZ,
RiscVOpcode::BLTZ,
RiscVOpcode::BGTZ,
];
for op in &branches {
assert!(
info.is_terminator(*op),
"Expected {:?} to be a terminator",
op
);
assert!(info.is_branch(*op), "Expected {:?} to be a branch", op);
}
}
#[test]
fn test_load_store_mutual_exclusivity() {
let info = make_info();
let loads = [RiscVOpcode::LB, RiscVOpcode::LW, RiscVOpcode::LD];
for op in &loads {
assert!(info.may_load(*op));
assert!(!info.may_store(*op));
}
let stores = [RiscVOpcode::SB, RiscVOpcode::SW, RiscVOpcode::SD];
for op in &stores {
assert!(info.may_store(*op));
assert!(!info.may_load(*op));
}
let amos = [RiscVOpcode::AMOSWAP_W, RiscVOpcode::AMOADD_D];
for op in &amos {
assert!(info.may_load(*op));
assert!(info.may_store(*op));
}
}
#[test]
fn test_fp_opcodes_have_correct_mnemonics() {
let info = make_info();
assert_eq!(info.get_mnemonic(RiscVOpcode::FADD_S), "fadd.s");
assert_eq!(info.get_mnemonic(RiscVOpcode::FADD_D), "fadd.d");
assert_eq!(info.get_mnemonic(RiscVOpcode::FMUL_S), "fmul.s");
assert_eq!(info.get_mnemonic(RiscVOpcode::FCVT_S_D), "fcvt.s.d");
assert_eq!(info.get_mnemonic(RiscVOpcode::FCVT_D_S), "fcvt.d.s");
assert_eq!(info.get_mnemonic(RiscVOpcode::FMADD_S), "fmadd.s");
assert_eq!(info.get_mnemonic(RiscVOpcode::FNMADD_D), "fnmadd.d");
}
#[test]
fn test_operand_type_is_register_both() {
assert!(RiscVOperandType::GPR.is_register());
assert!(RiscVOperandType::FPR32.is_register());
assert!(RiscVOperandType::FPR64.is_register());
assert!(!RiscVOperandType::Imm12.is_register());
}
}