use crate::codegen::{MachineInstr, MachineOperand, VirtReg};
use crate::riscv::riscv_register_info::{
A0, A1, A2, A3, A4, A5, A6, A7, F0, F1, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F2,
F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F3, F30, F31, F4, F5, F6, F7, F8, F9, FA0,
FA1, FA2, FA3, FA4, FA5, FA6, FA7, FP, FS0, FS1, FS10, FS11, FS2, FS3, FS4, FS5, FS6, FS7, FS8,
FS9, FT0, FT1, FT10, FT11, FT2, FT3, FT4, FT5, FT6, FT7, FT8, FT9, GP, RA, S0, S1, S10, S11, S2,
S3, S4, S5, S6, S7, S8, S9, SP, T0, T1, T2, T3, T4, T5, T6, TP, X0, X1, X10, X11, X12, X13,
X14, X15, X16, X17, X18, X19, X2, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X3, X30,
X31, X4, X5, X6, X7, X8, X9, ZERO,
};
use std::collections::HashMap;
pub const DEEP_GPR_BASE: u16 = 3000;
pub const DEEP_FPR_BASE: u16 = 3050;
pub const DEEP_VR_BASE: u16 = 3100;
pub const DEEP_GPR_COUNT: usize = 32;
pub const DEEP_FPR_COUNT: usize = 32;
pub const DEEP_VR_COUNT: usize = 32;
pub const V0: u16 = 3100;
pub const V1: u16 = 3101;
pub const V2: u16 = 3102;
pub const V3: u16 = 3103;
pub const V4: u16 = 3104;
pub const V5: u16 = 3105;
pub const V6: u16 = 3106;
pub const V7: u16 = 3107;
pub const V8: u16 = 3108;
pub const V9: u16 = 3109;
pub const V10: u16 = 3110;
pub const V11: u16 = 3111;
pub const V12: u16 = 3112;
pub const V13: u16 = 3113;
pub const V14: u16 = 3114;
pub const V15: u16 = 3115;
pub const V16: u16 = 3116;
pub const V17: u16 = 3117;
pub const V18: u16 = 3118;
pub const V19: u16 = 3119;
pub const V20: u16 = 3120;
pub const V21: u16 = 3121;
pub const V22: u16 = 3122;
pub const V23: u16 = 3123;
pub const V24: u16 = 3124;
pub const V25: u16 = 3125;
pub const V26: u16 = 3126;
pub const V27: u16 = 3127;
pub const V28: u16 = 3128;
pub const V29: u16 = 3129;
pub const V30: u16 = 3130;
pub const V31: u16 = 3131;
pub const DEEP_GPR_NAMES: [&str; 32] = [
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0/fp", "s1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3",
"t4", "t5", "t6",
];
pub const DEEP_FPR_NAMES: [&str; 32] = [
"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",
];
pub const DEEP_VR_NAMES: [&str; 32] = [
"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",
];
pub const DEEP_GPR_IDS: [u16; 32] = [
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31,
];
pub const DEEP_FPR_IDS: [u16; 32] = [
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19,
F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31,
];
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepRegClass {
GPR,
FPR32,
FPR64,
VR,
VMask,
}
impl std::fmt::Display for DeepRegClass {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DeepRegClass::GPR => write!(f, "GPR"),
DeepRegClass::FPR32 => write!(f, "FPR32"),
DeepRegClass::FPR64 => write!(f, "FPR64"),
DeepRegClass::VR => write!(f, "VR"),
DeepRegClass::VMask => write!(f, "VMask"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepOperandType {
GPR,
FPR,
FPR32,
FPR64,
VR,
VMask,
Simm12,
Uimm12,
Uimm20,
Uimm5,
Uimm3,
Simm6,
Simm13,
Simm21,
Simm26,
CSR,
FenceField,
VSEW,
VLMul,
AmoOrder,
}
impl DeepOperandType {
pub fn is_register(&self) -> bool {
matches!(
self,
DeepOperandType::GPR
| DeepOperandType::FPR
| DeepOperandType::FPR32
| DeepOperandType::FPR64
| DeepOperandType::VR
| DeepOperandType::VMask
)
}
pub fn is_immediate(&self) -> bool {
matches!(
self,
DeepOperandType::Simm12
| DeepOperandType::Uimm12
| DeepOperandType::Uimm20
| DeepOperandType::Uimm5
| DeepOperandType::Uimm3
| DeepOperandType::Simm6
| DeepOperandType::Simm13
| DeepOperandType::Simm21
| DeepOperandType::Simm26
| DeepOperandType::CSR
| DeepOperandType::FenceField
| DeepOperandType::VSEW
| DeepOperandType::VLMul
| DeepOperandType::AmoOrder
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RISCVDeepOpcode {
LUI,
AUIPC,
JAL,
JALR,
BEQ,
BNE,
BLT,
BGE,
BLTU,
BGEU,
LB,
LH,
LW,
LBU,
LHU,
LWU,
LD,
SB,
SH,
SW,
SD,
ADDI,
SLTI,
SLTIU,
XORI,
ORI,
ANDI,
SLLI,
SRLI,
SRAI,
ADD,
SUB,
SLL,
SLT,
SLTU,
XOR,
SRL,
SRA,
OR,
AND,
FENCE,
FENCE_I,
FENCE_TSO,
PAUSE,
ECALL,
EBREAK,
CSRRW,
CSRRS,
CSRRC,
CSRRWI,
CSRRSI,
CSRRCI,
ADDIW,
SLLIW,
SRLIW,
SRAIW,
ADDW,
SUBW,
SLLW,
SRLW,
SRAW,
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,
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_S_D,
FCVT_D_S,
FCVT_L_S,
FCVT_LU_S,
FCVT_S_L,
FCVT_S_LU,
FCVT_L_D,
FCVT_LU_D,
FCVT_D_L,
FCVT_D_LU,
C_ADDI4SPN,
C_FLD,
C_LW,
C_FLW,
C_LD,
C_FSD,
C_SW,
C_FSW,
C_SD,
C_NOP,
C_ADDI,
C_JAL,
C_ADDIW,
C_LI,
C_ADDI16SP,
C_LUI,
C_SRLI,
C_SRAI,
C_ANDI,
C_SUB,
C_XOR,
C_OR,
C_AND,
C_SUBW,
C_ADDW,
C_J,
C_BEQZ,
C_BNEZ,
C_SLLI,
C_FLDSP,
C_LWSP,
C_FLWSP,
C_LDSP,
C_JR,
C_MV,
C_EBREAK,
C_JALR,
C_ADD,
C_FSDSP,
C_SWSP,
C_FSWSP,
C_SDSP,
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,
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,
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,
VFNCVT_XU_F_W,
VFNCVT_F_XU_W,
VFNCVT_F_X_W,
VFNCVT_ROD_F_F_W,
VFWCVT_F_X_V,
VFWCVT_F_F_V,
VFWCVT_XU_F_V,
VFWCVT_X_F_V,
VFWCVT_F_XU_V,
VFCVT_X_F_V,
VFCVT_F_X_V,
VFCVT_RTZ_X_F_V,
VFREDUSUM_VS,
VFREDOSUM_VS,
VFREDMAX_VS,
VFREDMIN_VS,
VFMERGE_VFM,
VFMV_V_F,
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,
PACK,
PACKH,
PACKW,
BREV8,
UNZIP,
ZIP,
CLMUL,
CLMULH,
CLMULR,
XPERM4,
XPERM8,
BCLR,
BCLRI,
BSET,
BSETI,
BINV,
BINVI,
BEXT,
BEXTI,
AES32ESMI,
AES32ESI,
AES32DSMI,
AES32DSI,
SHA256SIG0,
SHA256SIG1,
SHA256SUM0,
SHA256SUM1,
SM4ED,
SM4KS,
SM3P0,
SM3P1,
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,
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,
HLV_B,
HLV_H,
HLV_W,
HLV_D,
HLVX_HU,
HLVX_WU,
HSV_B,
HSV_H,
HSV_W,
HSV_D,
HFENCE_VVMA,
HFENCE_GVMA,
NOP,
MV,
NOT,
NEG,
NEGW,
SEQZ,
SNEZ,
SLTZ,
SGTZ,
BEQZ,
BNEZ,
BLEZ,
BGEZ,
BLTZ,
BGTZ,
J,
JR,
RET,
CALL,
TAIL,
LI,
LA,
}
#[derive(Debug, Clone)]
pub struct RISCVInstrDescDeep {
pub opcode: RISCVDeepOpcode,
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 is_fp: bool,
pub is_compressed: bool,
pub is_vector: bool,
pub operand_types: &'static [DeepOperandType],
pub implicit_defs: &'static [u16],
pub implicit_uses: &'static [u16],
}
pub struct RISCVInstrInfoDeep {
pub descriptors: HashMap<RISCVDeepOpcode, RISCVInstrDescDeep>,
pub by_mnemonic: HashMap<&'static str, RISCVDeepOpcode>,
}
fn build_deep_instr_table() -> Vec<RISCVInstrDescDeep> {
use DeepOperandType::*;
use RISCVDeepOpcode::*;
vec![
RISCVInstrDescDeep {
opcode: LUI,
mnemonic: "lui",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, Uimm20],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AUIPC,
mnemonic: "auipc",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, Uimm20],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: JAL,
mnemonic: "jal",
num_operands: 2,
is_terminator: true,
is_branch: false,
is_call: true,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, Simm21],
implicit_defs: &[RA],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: JALR,
mnemonic: "jalr",
num_operands: 3,
is_terminator: true,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[RA],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BEQ,
mnemonic: "beq",
num_operands: 3,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm13],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BNE,
mnemonic: "bne",
num_operands: 3,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm13],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BLT,
mnemonic: "blt",
num_operands: 3,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm13],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BGE,
mnemonic: "bge",
num_operands: 3,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm13],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BLTU,
mnemonic: "bltu",
num_operands: 3,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm13],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BGEU,
mnemonic: "bgeu",
num_operands: 3,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm13],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LB,
mnemonic: "lb",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LH,
mnemonic: "lh",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LW,
mnemonic: "lw",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LBU,
mnemonic: "lbu",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LHU,
mnemonic: "lhu",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LWU,
mnemonic: "lwu",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LD,
mnemonic: "ld",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SB,
mnemonic: "sb",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SH,
mnemonic: "sh",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SW,
mnemonic: "sw",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SD,
mnemonic: "sd",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ADDI,
mnemonic: "addi",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLTI,
mnemonic: "slti",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLTIU,
mnemonic: "sltiu",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: XORI,
mnemonic: "xori",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ORI,
mnemonic: "ori",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ANDI,
mnemonic: "andi",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLLI,
mnemonic: "slli",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRLI,
mnemonic: "srli",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRAI,
mnemonic: "srai",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ADD,
mnemonic: "add",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SUB,
mnemonic: "sub",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLL,
mnemonic: "sll",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLT,
mnemonic: "slt",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLTU,
mnemonic: "sltu",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: XOR,
mnemonic: "xor",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRL,
mnemonic: "srl",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRA,
mnemonic: "sra",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: OR,
mnemonic: "or",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AND,
mnemonic: "and",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FENCE,
mnemonic: "fence",
num_operands: 2,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[FenceField, FenceField],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FENCE_I,
mnemonic: "fence.i",
num_operands: 0,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ECALL,
mnemonic: "ecall",
num_operands: 0,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: EBREAK,
mnemonic: "ebreak",
num_operands: 0,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CSRRW,
mnemonic: "csrrw",
num_operands: 3,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, CSR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CSRRS,
mnemonic: "csrrs",
num_operands: 3,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, CSR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CSRRC,
mnemonic: "csrrc",
num_operands: 3,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, CSR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CSRRWI,
mnemonic: "csrrwi",
num_operands: 3,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, CSR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CSRRSI,
mnemonic: "csrrsi",
num_operands: 3,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, CSR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CSRRCI,
mnemonic: "csrrci",
num_operands: 3,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, CSR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ADDIW,
mnemonic: "addiw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLLIW,
mnemonic: "slliw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRLIW,
mnemonic: "srliw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRAIW,
mnemonic: "sraiw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ADDW,
mnemonic: "addw",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SUBW,
mnemonic: "subw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SLLW,
mnemonic: "sllw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRLW,
mnemonic: "srlw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SRAW,
mnemonic: "sraw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: MUL,
mnemonic: "mul",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: MULH,
mnemonic: "mulh",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: MULHSU,
mnemonic: "mulhsu",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: MULHU,
mnemonic: "mulhu",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: DIV,
mnemonic: "div",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: DIVU,
mnemonic: "divu",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: REM,
mnemonic: "rem",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: REMU,
mnemonic: "remu",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: MULW,
mnemonic: "mulw",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: DIVW,
mnemonic: "divw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: DIVUW,
mnemonic: "divuw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: REMW,
mnemonic: "remw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: REMUW,
mnemonic: "remuw",
num_operands: 3,
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: true,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LR_W,
mnemonic: "lr.w",
num_operands: 2,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SC_W,
mnemonic: "sc.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOSWAP_W,
mnemonic: "amoswap.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOADD_W,
mnemonic: "amoadd.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOXOR_W,
mnemonic: "amoxor.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOAND_W,
mnemonic: "amoand.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOOR_W,
mnemonic: "amoor.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOMIN_W,
mnemonic: "amomin.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOMAX_W,
mnemonic: "amomax.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOMINU_W,
mnemonic: "amominu.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: AMOMAXU_W,
mnemonic: "amomaxu.w",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: true,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FLW,
mnemonic: "flw",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSW,
mnemonic: "fsw",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMADD_S,
mnemonic: "fmadd.s",
num_operands: 4,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMSUB_S,
mnemonic: "fmsub.s",
num_operands: 4,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FNMSUB_S,
mnemonic: "fnmsub.s",
num_operands: 4,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FNMADD_S,
mnemonic: "fnmadd.s",
num_operands: 4,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FADD_S,
mnemonic: "fadd.s",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSUB_S,
mnemonic: "fsub.s",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMUL_S,
mnemonic: "fmul.s",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FDIV_S,
mnemonic: "fdiv.s",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSQRT_S,
mnemonic: "fsqrt.s",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSGNJ_S,
mnemonic: "fsgnj.s",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSGNJN_S,
mnemonic: "fsgnjn.s",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSGNJX_S,
mnemonic: "fsgnjx.s",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMIN_S,
mnemonic: "fmin.s",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMAX_S,
mnemonic: "fmax.s",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCVT_W_S,
mnemonic: "fcvt.w.s",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCVT_WU_S,
mnemonic: "fcvt.wu.s",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMV_X_W,
mnemonic: "fmv.x.w",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FEQ_S,
mnemonic: "feq.s",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FLT_S,
mnemonic: "flt.s",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FLE_S,
mnemonic: "fle.s",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR32, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCLASS_S,
mnemonic: "fclass.s",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCVT_S_W,
mnemonic: "fcvt.s.w",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCVT_S_WU,
mnemonic: "fcvt.s.wu",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMV_W_X,
mnemonic: "fmv.w.x",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FLD,
mnemonic: "fld",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSD,
mnemonic: "fsd",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR, GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FADD_D,
mnemonic: "fadd.d",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSUB_D,
mnemonic: "fsub.d",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMUL_D,
mnemonic: "fmul.d",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FDIV_D,
mnemonic: "fdiv.d",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSQRT_D,
mnemonic: "fsqrt.d",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSGNJ_D,
mnemonic: "fsgnj.d",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSGNJN_D,
mnemonic: "fsgnjn.d",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FSGNJX_D,
mnemonic: "fsgnjx.d",
num_operands: 3,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMIN_D,
mnemonic: "fmin.d",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FMAX_D,
mnemonic: "fmax.d",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCVT_S_D,
mnemonic: "fcvt.s.d",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR32, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCVT_D_S,
mnemonic: "fcvt.d.s",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[FPR64, FPR32],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FEQ_D,
mnemonic: "feq.d",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FLT_D,
mnemonic: "flt.d",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FLE_D,
mnemonic: "fle.d",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR64, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: FCLASS_D,
mnemonic: "fclass.d",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, FPR64],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_NOP,
mnemonic: "c.nop",
num_operands: 0,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_ADDI,
mnemonic: "c.addi",
num_operands: 2,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Simm6],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_LI,
mnemonic: "c.li",
num_operands: 2,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Simm6],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_LUI,
mnemonic: "c.lui",
num_operands: 2,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Simm6],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_SLLI,
mnemonic: "c.slli",
num_operands: 2,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_ADDI16SP,
mnemonic: "c.addi16sp",
num_operands: 1,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[Simm6],
implicit_defs: &[SP],
implicit_uses: &[SP],
},
RISCVInstrDescDeep {
opcode: C_MV,
mnemonic: "c.mv",
num_operands: 2,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_ADD,
mnemonic: "c.add",
num_operands: 2,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_JR,
mnemonic: "c.jr",
num_operands: 1,
is_terminator: true,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_J,
mnemonic: "c.j",
num_operands: 1,
is_terminator: true,
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,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_BEQZ,
mnemonic: "c.beqz",
num_operands: 2,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Simm6],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_BNEZ,
mnemonic: "c.bnez",
num_operands: 2,
is_terminator: true,
is_branch: true,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Simm6],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_EBREAK,
mnemonic: "c.ebreak",
num_operands: 0,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: C_LWSP,
mnemonic: "c.lwsp",
num_operands: 2,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: true,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[SP],
},
RISCVInstrDescDeep {
opcode: C_SWSP,
mnemonic: "c.swsp",
num_operands: 2,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: true,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: true,
is_vector: false,
operand_types: &[GPR, Uimm5],
implicit_defs: &[],
implicit_uses: &[SP],
},
RISCVInstrDescDeep {
opcode: VSETVLI,
mnemonic: "vsetvli",
num_operands: 3,
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: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[GPR, GPR, VSEW],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VADD_VV,
mnemonic: "vadd.vv",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VSUB_VV,
mnemonic: "vsub.vv",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VMUL_VV,
mnemonic: "vmul.vv",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VDIV_VV,
mnemonic: "vdiv.vv",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VFADD_VV,
mnemonic: "vfadd.vv",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VFMUL_VV,
mnemonic: "vfmul.vv",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: true,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VFNCVT_F_F_W,
mnemonic: "vfncvt.f.f.w",
num_operands: 2,
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,
is_fp: true,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VNSRL_WV,
mnemonic: "vnsrl.wv",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VSLIDEUP_VX,
mnemonic: "vslideup.vx",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VSLIDEDOWN_VX,
mnemonic: "vslidedown.vx",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VRGATHER_VV,
mnemonic: "vrgather.vv",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: VCOMPRESS_VM,
mnemonic: "vcompress.vm",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: true,
operand_types: &[VR, VR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ANDN,
mnemonic: "andn",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ORN,
mnemonic: "orn",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: XNOR,
mnemonic: "xnor",
num_operands: 3,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: true,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CLZ,
mnemonic: "clz",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CTZ,
mnemonic: "ctz",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: CPOP,
mnemonic: "cpop",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ROL,
mnemonic: "rol",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: ROR,
mnemonic: "ror",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BCLR,
mnemonic: "bclr",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: BSET,
mnemonic: "bset",
num_operands: 3,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: NOP,
mnemonic: "nop",
num_operands: 0,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: MV,
mnemonic: "mv",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: NOT,
mnemonic: "not",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: NEG,
mnemonic: "neg",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SEQZ,
mnemonic: "seqz",
num_operands: 2,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: SNEZ,
mnemonic: "snez",
num_operands: 2,
is_terminator: false,
is_branch: false,
is_call: false,
is_return: false,
is_compare: true,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: false,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: RET,
mnemonic: "ret",
num_operands: 0,
is_terminator: true,
is_branch: false,
is_call: false,
is_return: true,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[],
implicit_defs: &[],
implicit_uses: &[RA],
},
RISCVInstrDescDeep {
opcode: J,
mnemonic: "j",
num_operands: 1,
is_terminator: true,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[Simm21],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: JR,
mnemonic: "jr",
num_operands: 1,
is_terminator: true,
is_branch: false,
is_call: false,
is_return: false,
is_compare: false,
is_load: false,
is_store: false,
is_commutative: false,
has_side_effects: true,
is_rv32: false,
is_rv64: false,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LI,
mnemonic: "li",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
RISCVInstrDescDeep {
opcode: LA,
mnemonic: "la",
num_operands: 2,
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,
is_fp: false,
is_compressed: false,
is_vector: false,
operand_types: &[GPR, Simm12],
implicit_defs: &[],
implicit_uses: &[],
},
]
}
impl RISCVInstrInfoDeep {
pub fn new() -> Self {
let table = build_deep_instr_table();
let mut descriptors = HashMap::new();
let mut by_mnemonic = HashMap::new();
for desc in &table {
descriptors.insert(desc.opcode, desc.clone());
by_mnemonic.insert(desc.mnemonic, desc.opcode);
}
RISCVInstrInfoDeep {
descriptors,
by_mnemonic,
}
}
pub fn get(&self, opcode: RISCVDeepOpcode) -> Option<&RISCVInstrDescDeep> {
self.descriptors.get(&opcode)
}
pub fn get_mnemonic(&self, opcode: RISCVDeepOpcode) -> Option<&'static str> {
self.descriptors.get(&opcode).map(|d| d.mnemonic)
}
pub fn find_by_mnemonic(&self, mnemonic: &str) -> Option<RISCVDeepOpcode> {
self.by_mnemonic.get(mnemonic).copied()
}
pub fn all_opcodes(&self) -> Vec<RISCVDeepOpcode> {
self.descriptors.keys().copied().collect()
}
pub fn len(&self) -> usize {
self.descriptors.len()
}
pub fn is_empty(&self) -> bool {
self.descriptors.is_empty()
}
pub fn is_terminator(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_terminator)
}
pub fn is_branch(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_branch)
}
pub fn is_call(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_call)
}
pub fn is_return(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_return)
}
pub fn is_commutative(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_commutative)
}
pub fn is_compare(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_compare)
}
pub fn may_load(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_load)
}
pub fn may_store(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_store)
}
pub fn has_side_effects(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.has_side_effects)
}
pub fn is_fp(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_fp)
}
pub fn is_compressed(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_compressed)
}
pub fn is_vector(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_vector)
}
pub fn is_rv32_only(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_rv32 && !d.is_rv64)
}
pub fn is_rv64_only(&self, op: RISCVDeepOpcode) -> bool {
self.get(op).map_or(false, |d| d.is_rv64 && !d.is_rv32)
}
pub fn get_num_operands(&self, op: RISCVDeepOpcode) -> u8 {
self.get(op).map_or(0, |d| d.num_operands)
}
pub fn get_operand_types(&self, op: RISCVDeepOpcode) -> &[DeepOperandType] {
self.get(op).map_or(&[], |d| d.operand_types)
}
pub fn get_implicit_defs(&self, op: RISCVDeepOpcode) -> &[u16] {
self.get(op).map_or(&[], |d| d.implicit_defs)
}
pub fn get_implicit_uses(&self, op: RISCVDeepOpcode) -> &[u16] {
self.get(op).map_or(&[], |d| d.implicit_uses)
}
pub fn get_rv32_opcodes(&self) -> Vec<RISCVDeepOpcode> {
self.descriptors
.iter()
.filter_map(|(op, d)| if d.is_rv32 && !d.is_rv64 { Some(*op) } else { None })
.collect()
}
pub fn get_rv64_opcodes(&self) -> Vec<RISCVDeepOpcode> {
self.descriptors
.iter()
.filter_map(|(op, d)| if d.is_rv64 && !d.is_rv32 { Some(*op) } else { None })
.collect()
}
}
impl Default for RISCVInstrInfoDeep {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct RISCVRegisterInfoDeep {}
impl RISCVRegisterInfoDeep {
pub fn new() -> Self {
RISCVRegisterInfoDeep {}
}
pub fn get_asm_name(&self, reg_id: u16) -> Option<&'static str> {
if (X0..=X31).contains(®_id) {
let idx = (reg_id - X0) as usize;
Some(match idx {
0 => "x0", 1 => "x1", 2 => "x2", 3 => "x3", 4 => "x4",
5 => "x5", 6 => "x6", 7 => "x7", 8 => "x8", 9 => "x9",
10 => "x10", 11 => "x11", 12 => "x12", 13 => "x13", 14 => "x14",
15 => "x15", 16 => "x16", 17 => "x17", 18 => "x18", 19 => "x19",
20 => "x20", 21 => "x21", 22 => "x22", 23 => "x23", 24 => "x24",
25 => "x25", 26 => "x26", 27 => "x27", 28 => "x28", 29 => "x29",
30 => "x30", 31 => "x31",
_ => return None,
})
} else if (F0..=F31).contains(®_id) {
let idx = (reg_id - F0) as usize;
Some(match idx {
0 => "f0", 1 => "f1", 2 => "f2", 3 => "f3", 4 => "f4",
5 => "f5", 6 => "f6", 7 => "f7", 8 => "f8", 9 => "f9",
10 => "f10", 11 => "f11", 12 => "f12", 13 => "f13", 14 => "f14",
15 => "f15", 16 => "f16", 17 => "f17", 18 => "f18", 19 => "f19",
20 => "f20", 21 => "f21", 22 => "f22", 23 => "f23", 24 => "f24",
25 => "f25", 26 => "f26", 27 => "f27", 28 => "f28", 29 => "f29",
30 => "f30", 31 => "f31",
_ => return None,
})
} else if (V0..=V31).contains(®_id) {
let idx = (reg_id - V0) as usize;
Some(DEEP_VR_NAMES.get(idx).copied().unwrap_or("v?"))
} else {
None
}
}
pub fn get_abi_name(&self, reg_id: u16) -> Option<&'static str> {
if (X0..=X31).contains(®_id) {
let idx = (reg_id - X0) as usize;
DEEP_GPR_NAMES.get(idx).copied()
} else if (F0..=F31).contains(®_id) {
let idx = (reg_id - F0) as usize;
DEEP_FPR_NAMES.get(idx).copied()
} else if (V0..=V31).contains(®_id) {
let idx = (reg_id - V0) as usize;
DEEP_VR_NAMES.get(idx).copied()
} else {
None
}
}
pub fn get_reg_class(&self, reg_id: u16) -> DeepRegClass {
if (X0..=X31).contains(®_id) {
DeepRegClass::GPR
} else if (F0..=F31).contains(®_id) {
DeepRegClass::FPR64
} else if (V0..=V31).contains(®_id) {
DeepRegClass::VR
} else {
DeepRegClass::GPR
}
}
pub fn get_reg_width(&self, reg_id: u16, is_64bit: bool) -> u32 {
if (X0..=X31).contains(®_id) {
if is_64bit { 64 } else { 32 }
} else if (F0..=F31).contains(®_id) {
64
} else if (V0..=V31).contains(®_id) {
0 } else {
0
}
}
pub fn is_callee_saved(&self, reg_id: u16) -> bool {
matches!(
reg_id,
S0 | S1
| S2
| S3
| S4
| S5
| S6
| S7
| S8
| S9
| S10
| S11
| FS0
| FS1
| FS2
| FS3
| FS4
| FS5
| FS6
| FS7
| FS8
| FS9
| FS10
| FS11
)
}
pub fn is_caller_saved(&self, reg_id: u16) -> bool {
matches!(
reg_id,
RA | T0
| T1
| T2
| T3
| T4
| T5
| T6
| A0
| A1
| A2
| A3
| A4
| A5
| A6
| A7
| FT0
| FT1
| FT2
| FT3
| FT4
| FT5
| FT6
| FT7
| FT8
| FT9
| FT10
| FT11
| FA0
| FA1
| FA2
| FA3
| FA4
| FA5
| FA6
| FA7
)
}
pub fn is_reserved(&self, reg_id: u16) -> bool {
matches!(reg_id, ZERO | SP | GP | TP)
}
pub fn get_allocatable_gprs(&self) -> Vec<u16> {
vec![
T0, T1, T2, A0, A1, A2, A3, A4, A5, A6, A7, T3, T4, T5, T6,
]
}
pub fn get_allocatable_fprs(&self) -> Vec<u16> {
vec![
FT0, FT1, FT2, FT3, FT4, FT5, FT6, FT7, FT8, FT9, FT10, FT11,
FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7,
]
}
pub fn get_argument_regs(&self) -> Vec<u16> {
vec![A0, A1, A2, A3, A4, A5, A6, A7]
}
pub fn get_fp_argument_regs(&self) -> Vec<u16> {
vec![FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7]
}
pub fn get_return_regs(&self) -> Vec<u16> {
vec![A0, A1]
}
pub fn get_fp_return_regs(&self) -> Vec<u16> {
vec![FA0, FA1]
}
pub fn get_frame_pointer_reg(&self) -> u16 {
S0
}
pub fn get_return_address_reg(&self) -> u16 {
RA
}
pub fn get_stack_pointer_reg(&self) -> u16 {
SP
}
pub fn get_global_pointer_reg(&self) -> u16 {
GP
}
pub fn get_thread_pointer_reg(&self) -> u16 {
TP
}
pub fn get_zero_reg(&self) -> u16 {
ZERO
}
pub fn is_gpr(&self, reg_id: u16) -> bool {
(X0..=X31).contains(®_id)
}
pub fn is_fpr(&self, reg_id: u16) -> bool {
(F0..=F31).contains(®_id)
}
pub fn is_vr(&self, reg_id: u16) -> bool {
(V0..=V31).contains(®_id)
}
pub fn get_gpr_index(&self, reg_id: u16) -> Option<usize> {
if (X0..=X31).contains(®_id) {
Some((reg_id - X0) as usize)
} else {
None
}
}
pub fn get_fpr_index(&self, reg_id: u16) -> Option<usize> {
if (F0..=F31).contains(®_id) {
Some((reg_id - F0) as usize)
} else {
None
}
}
}
impl Default for RISCVRegisterInfoDeep {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct RISCvFrameInfoDeep {
pub frame_size: i64,
pub has_frame_pointer: bool,
pub has_calls: bool,
pub saved_regs: Vec<u16>,
pub saved_ra_offset: i64,
pub saved_fp_offset: i64,
pub is_64bit: bool,
}
impl RISCvFrameInfoDeep {
pub fn new(is_64bit: bool) -> Self {
RISCvFrameInfoDeep {
frame_size: 0,
has_frame_pointer: false,
has_calls: false,
saved_regs: Vec::new(),
saved_ra_offset: 0,
saved_fp_offset: 0,
is_64bit,
}
}
pub fn reg_width(&self) -> i64 {
if self.is_64bit { 8 } else { 4 }
}
}
impl Default for RISCvFrameInfoDeep {
fn default() -> Self {
Self::new(true)
}
}
#[derive(Debug, Clone)]
pub struct RISCVFrameLoweringDeep {
pub is_64bit: bool,
}
impl RISCVFrameLoweringDeep {
pub fn new(is_64bit: bool) -> Self {
RISCVFrameLoweringDeep { is_64bit }
}
pub fn emit_prologue(&self, info: &RISCvFrameInfoDeep) -> Vec<MachineInstr> {
let mut instrs = Vec::new();
let frame_size = info.frame_size;
if frame_size == 0 && info.saved_regs.is_empty() && !info.has_calls {
return instrs;
}
if frame_size > 0 {
instrs.push(self.make_addi(SP, SP, -frame_size));
}
if info.has_calls {
let ra_offset = info.saved_ra_offset;
instrs.push(self.make_store(RA, SP, ra_offset));
}
if info.has_frame_pointer {
let fp_offset = info.saved_fp_offset;
instrs.push(self.make_store(S0, SP, fp_offset));
instrs.push(self.make_addi(S0, SP, frame_size));
}
for &(reg, offset) in &self.assign_spill_slots(info) {
instrs.push(self.make_store(reg, SP, offset));
}
instrs
}
pub fn emit_epilogue(&self, info: &RISCvFrameInfoDeep) -> Vec<MachineInstr> {
let mut instrs = Vec::new();
let frame_size = info.frame_size;
if frame_size == 0 && info.saved_regs.is_empty() && !info.has_calls {
instrs.push(self.make_ret());
return instrs;
}
let spill_slots = self.assign_spill_slots(info);
for &(reg, offset) in spill_slots.iter().rev() {
instrs.push(self.make_load(reg, SP, offset));
}
if info.has_frame_pointer {
instrs.push(self.make_load(S0, SP, info.saved_fp_offset));
}
if info.has_calls {
instrs.push(self.make_load(RA, SP, info.saved_ra_offset));
}
if frame_size > 0 {
instrs.push(self.make_addi(SP, SP, frame_size));
}
instrs.push(self.make_ret());
instrs
}
fn make_addi(&self, rd: u16, rs1: u16, imm: i64) -> MachineInstr {
let mut instr = MachineInstr::new(0); instr.operands.push(MachineOperand::PhysReg(rd as u32));
instr.operands.push(MachineOperand::PhysReg(rs1 as u32));
instr.operands.push(MachineOperand::Imm(imm));
instr
}
fn make_store(&self, src: u16, base: u16, offset: i64) -> MachineInstr {
let mut instr = MachineInstr::new(0); instr.operands.push(MachineOperand::PhysReg(src as u32));
instr.operands.push(MachineOperand::PhysReg(base as u32));
instr.operands.push(MachineOperand::Imm(offset));
instr
}
fn make_load(&self, dst: u16, base: u16, offset: i64) -> MachineInstr {
let mut instr = MachineInstr::new(0); instr.operands.push(MachineOperand::PhysReg(dst as u32));
instr.operands.push(MachineOperand::PhysReg(base as u32));
instr.operands.push(MachineOperand::Imm(offset));
instr
}
fn make_ret(&self) -> MachineInstr {
MachineInstr::new(0) }
fn assign_spill_slots(&self, info: &RISCvFrameInfoDeep) -> Vec<(u16, i64)> {
let rw = info.reg_width();
let mut slots = Vec::new();
let mut offset = -rw; let mut current_offset = info.saved_ra_offset;
for ® in &info.saved_regs {
offset -= rw;
slots.push((reg, offset));
}
let _ = current_offset;
slots
}
pub fn needs_frame_pointer(&self, frame_size: i64, has_variable_sized_objects: bool) -> bool {
has_variable_sized_objects || frame_size > 2048
}
pub fn calculate_frame_size(
&self,
local_size: i64,
saved_reg_count: usize,
has_calls: bool,
) -> i64 {
let rw = if self.is_64bit { 8 } else { 4 };
let saved_size = saved_reg_count as i64 * rw;
let ra_size = if has_calls { rw } else { 0 };
let total = local_size + saved_size + ra_size;
((total + 15) / 16) * 16
}
}
impl Default for RISCVFrameLoweringDeep {
fn default() -> Self {
Self::new(true)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DeepCallingConvention {
LP64,
LP64D,
LP64F,
ILP32,
ILP32D,
ILP32F,
}
impl DeepCallingConvention {
pub fn name(&self) -> &'static str {
match self {
DeepCallingConvention::LP64 => "LP64",
DeepCallingConvention::LP64D => "LP64D",
DeepCallingConvention::LP64F => "LP64F",
DeepCallingConvention::ILP32 => "ILP32",
DeepCallingConvention::ILP32D => "ILP32D",
DeepCallingConvention::ILP32F => "ILP32F",
}
}
pub fn is_64bit(&self) -> bool {
matches!(
self,
DeepCallingConvention::LP64
| DeepCallingConvention::LP64D
| DeepCallingConvention::LP64F
)
}
pub fn xlen_bits(&self) -> u32 {
if self.is_64bit() { 64 } else { 32 }
}
pub fn xlen_bytes(&self) -> u32 {
self.xlen_bits() / 8
}
pub fn uses_fp_regs(&self) -> bool {
matches!(
self,
DeepCallingConvention::LP64D
| DeepCallingConvention::LP64F
| DeepCallingConvention::ILP32D
| DeepCallingConvention::ILP32F
)
}
pub fn get_int_param_regs(&self) -> Vec<u16> {
vec![A0, A1, A2, A3, A4, A5, A6, A7]
}
pub fn get_fp_param_regs(&self) -> Vec<u16> {
if self.uses_fp_regs() {
vec![FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7]
} else {
vec![]
}
}
pub fn get_stack_alignment(&self) -> u32 {
16
}
pub fn get_red_zone_size(&self) -> u32 {
0
}
pub fn get_frame_pointer_reg(&self) -> u16 {
S0
}
pub fn get_return_address_reg(&self) -> u16 {
RA
}
pub fn get_stack_pointer_reg(&self) -> u16 {
SP
}
pub fn get_return_regs(&self, size_bytes: u32, is_fp: bool) -> Vec<u16> {
let xlen = self.xlen_bytes();
if is_fp {
if size_bytes <= 8 { vec![FA0] } else { vec![FA0, FA1] }
} else if size_bytes <= xlen {
vec![A0]
} else if size_bytes <= 2 * xlen {
vec![A0, A1]
} else {
vec![A0] }
}
}
#[derive(Debug, Clone)]
pub struct RISCVCallingConventionDeep {
pub abi: DeepCallingConvention,
}
impl RISCVCallingConventionDeep {
pub fn new(abi: DeepCallingConvention) -> Self {
RISCVCallingConventionDeep { abi }
}
pub fn int_arg_regs(&self) -> Vec<u16> {
self.abi.get_int_param_regs()
}
pub fn fp_arg_regs(&self) -> Vec<u16> {
self.abi.get_fp_param_regs()
}
pub fn int_return_regs(&self) -> Vec<u16> {
vec![A0, A1]
}
pub fn fp_return_regs(&self) -> Vec<u16> {
vec![FA0, FA1]
}
pub fn stack_alignment(&self) -> u32 {
self.abi.get_stack_alignment()
}
pub fn xlen_bytes(&self) -> u32 {
self.abi.xlen_bytes()
}
pub fn uses_fp_regs(&self) -> bool {
self.abi.uses_fp_regs()
}
pub fn is_64bit(&self) -> bool {
self.abi.is_64bit()
}
}
impl Default for RISCVCallingConventionDeep {
fn default() -> Self {
Self::new(DeepCallingConvention::LP64D)
}
}
#[derive(Debug, Clone)]
pub struct RISCVDeep {
pub instr_info: RISCVInstrInfoDeep,
pub reg_info: RISCVRegisterInfoDeep,
pub frame_lowering: RISCVFrameLoweringDeep,
pub calling_convention: RISCVCallingConventionDeep,
pub is_64bit: bool,
pub triple: String,
pub cpu: String,
pub extensions: Vec<String>,
}
impl RISCVDeep {
pub fn new(is_64bit: bool, triple: &str, cpu: &str) -> Self {
let abi = if is_64bit {
DeepCallingConvention::LP64D
} else {
DeepCallingConvention::ILP32D
};
RISCVDeep {
instr_info: RISCVInstrInfoDeep::new(),
reg_info: RISCVRegisterInfoDeep::new(),
frame_lowering: RISCVFrameLoweringDeep::new(is_64bit),
calling_convention: RISCVCallingConventionDeep::new(abi),
is_64bit,
triple: triple.to_string(),
cpu: cpu.to_string(),
extensions: Vec::new(),
}
}
pub fn enable_extension(&mut self, ext: &str) {
if !self.extensions.contains(&ext.to_string()) {
self.extensions.push(ext.to_string());
}
}
pub fn has_extension(&self, ext: &str) -> bool {
self.extensions.contains(&ext.to_string())
}
pub fn rv64gc(triple: &str, cpu: &str) -> Self {
let mut backend = Self::new(true, triple, cpu);
for ext in &["m", "a", "f", "d", "c"] {
backend.enable_extension(ext);
}
backend
}
pub fn rv32imac(triple: &str, cpu: &str) -> Self {
let mut backend = Self::new(false, triple, cpu);
for ext in &["m", "a", "c"] {
backend.enable_extension(ext);
}
backend
}
pub fn rv64gcv(triple: &str, cpu: &str) -> Self {
let mut backend = Self::rv64gc(triple, cpu);
backend.enable_extension("v");
backend
}
pub fn get_triple(&self) -> &str {
&self.triple
}
pub fn get_cpu(&self) -> &str {
&self.cpu
}
pub fn get_isa_string(&self) -> String {
let mut isa = if self.is_64bit {
String::from("rv64")
} else {
String::from("rv32")
};
isa.push('i');
for ext in &self.extensions {
isa.push_str(ext);
}
isa
}
pub fn xlen_bits(&self) -> u32 {
if self.is_64bit { 64 } else { 32 }
}
pub fn emit_prologue(&self, info: &RISCvFrameInfoDeep) -> Vec<MachineInstr> {
self.frame_lowering.emit_prologue(info)
}
pub fn emit_epilogue(&self, info: &RISCvFrameInfoDeep) -> Vec<MachineInstr> {
self.frame_lowering.emit_epilogue(info)
}
}
impl Default for RISCVDeep {
fn default() -> Self {
Self::rv64gc("riscv64-unknown-linux-gnu", "generic-rv64")
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_rv64_backend() -> RISCVDeep {
RISCVDeep::rv64gc("riscv64-unknown-linux-gnu", "generic-rv64")
}
fn make_rv32_backend() -> RISCVDeep {
RISCVDeep::rv32imac("riscv32-unknown-elf", "generic-rv32")
}
fn make_rv64gc_backend() -> RISCVDeep {
make_rv64_backend()
}
fn make_instr_info() -> RISCVInstrInfoDeep {
RISCVInstrInfoDeep::new()
}
fn make_reg_info() -> RISCVRegisterInfoDeep {
RISCVRegisterInfoDeep::new()
}
#[test]
fn test_instr_info_has_at_least_120_core_instructions() {
let info = make_instr_info();
let count = info.len();
assert!(
count >= 120,
"Expected at least 120 instruction descriptors, got {}",
count
);
}
#[test]
fn test_instr_info_non_empty() {
let info = make_instr_info();
assert!(!info.is_empty(), "Instruction info should not be empty");
}
#[test]
fn test_instr_info_get_add() {
let info = make_instr_info();
let desc = info.get(RISCVDeepOpcode::ADD);
assert!(desc.is_some(), "ADD should have a descriptor");
let desc = desc.unwrap();
assert_eq!(desc.mnemonic, "add");
assert_eq!(desc.num_operands, 3);
assert!(desc.is_commutative);
assert!(!desc.is_terminator);
assert!(!desc.is_branch);
}
#[test]
fn test_instr_info_get_sub() {
let info = make_instr_info();
let desc = info.get(RISCVDeepOpcode::SUB).unwrap();
assert_eq!(desc.mnemonic, "sub");
assert!(!desc.is_commutative);
}
#[test]
fn test_instr_info_get_lui() {
let info = make_instr_info();
let desc = info.get(RISCVDeepOpcode::LUI).unwrap();
assert_eq!(desc.mnemonic, "lui");
assert_eq!(desc.num_operands, 2);
}
#[test]
fn test_instr_info_get_auipc() {
let info = make_instr_info();
let desc = info.get(RISCVDeepOpcode::AUIPC).unwrap();
assert_eq!(desc.mnemonic, "auipc");
assert_eq!(desc.num_operands, 2);
}
#[test]
fn test_instr_info_get_jal() {
let info = make_instr_info();
let desc = info.get(RISCVDeepOpcode::JAL).unwrap();
assert_eq!(desc.mnemonic, "jal");
assert!(desc.is_terminator);
assert!(desc.is_call);
assert!(desc.has_side_effects);
}
#[test]
fn test_instr_info_get_jalr() {
let info = make_instr_info();
let desc = info.get(RISCVDeepOpcode::JALR).unwrap();
assert_eq!(desc.mnemonic, "jalr");
assert!(desc.is_terminator);
assert!(desc.has_side_effects);
}
#[test]
fn test_instr_info_branches() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::BEQ,
RISCVDeepOpcode::BNE,
RISCVDeepOpcode::BLT,
RISCVDeepOpcode::BGE,
RISCVDeepOpcode::BLTU,
RISCVDeepOpcode::BGEU,
] {
let desc = info.get(*op).unwrap();
assert!(desc.is_terminator, "{:?} should be terminator", op);
assert!(desc.is_branch, "{:?} should be branch", op);
assert!(desc.is_compare, "{:?} should be compare", op);
}
}
#[test]
fn test_instr_info_branch_commutativity() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::BEQ).unwrap().is_commutative);
assert!(info.get(RISCVDeepOpcode::BNE).unwrap().is_commutative);
assert!(!info.get(RISCVDeepOpcode::BLT).unwrap().is_commutative);
assert!(!info.get(RISCVDeepOpcode::BGE).unwrap().is_commutative);
}
#[test]
fn test_instr_info_loads() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::LB,
RISCVDeepOpcode::LH,
RISCVDeepOpcode::LW,
RISCVDeepOpcode::LBU,
RISCVDeepOpcode::LHU,
RISCVDeepOpcode::LD,
RISCVDeepOpcode::LWU,
] {
let desc = info.get(*op).unwrap();
assert!(desc.is_load, "{:?} should be a load", op);
assert!(!desc.is_store, "{:?} should not be a store", op);
}
}
#[test]
fn test_instr_info_stores() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::SB,
RISCVDeepOpcode::SH,
RISCVDeepOpcode::SW,
RISCVDeepOpcode::SD,
] {
let desc = info.get(*op).unwrap();
assert!(desc.is_store, "{:?} should be a store", op);
assert!(!desc.is_load, "{:?} should not be a load", op);
}
}
#[test]
fn test_instr_info_alu_immediate() {
let info = make_instr_info();
let desc = info.get(RISCVDeepOpcode::ADDI).unwrap();
assert_eq!(desc.mnemonic, "addi");
assert_eq!(desc.num_operands, 3);
assert!(!desc.is_commutative);
}
#[test]
fn test_instr_info_slti_is_compare() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::SLTI).unwrap().is_compare);
assert!(info.get(RISCVDeepOpcode::SLTIU).unwrap().is_compare);
}
#[test]
fn test_instr_info_shift_immediate() {
let info = make_instr_info();
for op in &[RISCVDeepOpcode::SLLI, RISCVDeepOpcode::SRLI, RISCVDeepOpcode::SRAI] {
let desc = info.get(*op).unwrap();
assert_eq!(desc.num_operands, 3);
}
}
#[test]
fn test_instr_info_alu_commutative() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::ADD).unwrap().is_commutative);
assert!(info.get(RISCVDeepOpcode::XOR).unwrap().is_commutative);
assert!(info.get(RISCVDeepOpcode::OR).unwrap().is_commutative);
assert!(info.get(RISCVDeepOpcode::AND).unwrap().is_commutative);
assert!(!info.get(RISCVDeepOpcode::SUB).unwrap().is_commutative);
assert!(!info.get(RISCVDeepOpcode::SLL).unwrap().is_commutative);
}
#[test]
fn test_instr_info_compare_ops() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::SLT).unwrap().is_compare);
assert!(info.get(RISCVDeepOpcode::SLTU).unwrap().is_compare);
}
#[test]
fn test_instr_info_fence_has_side_effects() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::FENCE).unwrap().has_side_effects);
assert!(info.get(RISCVDeepOpcode::FENCE_I).unwrap().has_side_effects);
assert!(info.get(RISCVDeepOpcode::ECALL).unwrap().has_side_effects);
assert!(info.get(RISCVDeepOpcode::EBREAK).unwrap().has_side_effects);
}
#[test]
fn test_instr_info_csr_has_side_effects() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::CSRRW,
RISCVDeepOpcode::CSRRS,
RISCVDeepOpcode::CSRRC,
RISCVDeepOpcode::CSRRWI,
RISCVDeepOpcode::CSRRSI,
RISCVDeepOpcode::CSRRCI,
] {
assert!(
info.get(*op).unwrap().has_side_effects,
"{:?} should have side effects",
op
);
}
}
#[test]
fn test_instr_info_rv64_specific() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::LWU,
RISCVDeepOpcode::LD,
RISCVDeepOpcode::SD,
RISCVDeepOpcode::ADDIW,
RISCVDeepOpcode::SLLIW,
RISCVDeepOpcode::SRLIW,
RISCVDeepOpcode::SRAIW,
RISCVDeepOpcode::ADDW,
RISCVDeepOpcode::SUBW,
RISCVDeepOpcode::SLLW,
RISCVDeepOpcode::SRLW,
RISCVDeepOpcode::SRAW,
RISCVDeepOpcode::MULW,
RISCVDeepOpcode::DIVW,
RISCVDeepOpcode::DIVUW,
RISCVDeepOpcode::REMW,
RISCVDeepOpcode::REMUW,
] {
let desc = info.get(*op).unwrap();
assert!(desc.is_rv64, "{:?} should be RV64-only", op);
assert!(!desc.is_rv32, "{:?} should not be RV32", op);
}
}
#[test]
fn test_get_rv64_opcodes() {
let info = make_instr_info();
let rv64_ops = info.get_rv64_opcodes();
assert!(!rv64_ops.is_empty(), "Should have RV64-only opcodes");
for op in &rv64_ops {
assert!(
info.is_rv64_only(*op),
"{:?} should be RV64-only",
op
);
}
}
#[test]
fn test_instr_info_m_extension() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::MUL,
RISCVDeepOpcode::MULH,
RISCVDeepOpcode::MULHSU,
RISCVDeepOpcode::MULHU,
RISCVDeepOpcode::DIV,
RISCVDeepOpcode::DIVU,
RISCVDeepOpcode::REM,
RISCVDeepOpcode::REMU,
] {
let desc = info.get(*op).unwrap();
assert_eq!(desc.num_operands, 3, "{:?} should have 3 operands", op);
}
}
#[test]
fn test_instr_info_mul_is_commutative() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::MUL).unwrap().is_commutative);
assert!(info.get(RISCVDeepOpcode::MULH).unwrap().is_commutative);
assert!(!info.get(RISCVDeepOpcode::MULHSU).unwrap().is_commutative);
}
#[test]
fn test_instr_info_a_extension() {
let info = make_instr_info();
let lr = info.get(RISCVDeepOpcode::LR_W).unwrap();
assert!(lr.is_load);
assert!(lr.has_side_effects);
let sc = info.get(RISCVDeepOpcode::SC_W).unwrap();
assert!(sc.is_store);
assert!(sc.has_side_effects);
let amo = info.get(RISCVDeepOpcode::AMOSWAP_W).unwrap();
assert!(amo.is_load && amo.is_store);
assert!(amo.has_side_effects);
}
#[test]
fn test_instr_info_f_extension_load_store() {
let info = make_instr_info();
let flw = info.get(RISCVDeepOpcode::FLW).unwrap();
assert!(flw.is_load);
assert!(flw.is_fp);
let fsw = info.get(RISCVDeepOpcode::FSW).unwrap();
assert!(fsw.is_store);
assert!(fsw.is_fp);
}
#[test]
fn test_instr_info_fadd_is_commutative() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::FADD_S).unwrap().is_commutative);
assert!(info.get(RISCVDeepOpcode::FADD_D).unwrap().is_commutative);
assert!(!info.get(RISCVDeepOpcode::FSUB_S).unwrap().is_commutative);
assert!(!info.get(RISCVDeepOpcode::FSUB_D).unwrap().is_commutative);
}
#[test]
fn test_instr_info_fp_compare_returns_gpr() {
let info = make_instr_info();
let feq = info.get(RISCVDeepOpcode::FEQ_S).unwrap();
assert!(feq.is_compare);
assert_eq!(feq.operand_types[0], DeepOperandType::GPR);
assert_eq!(feq.operand_types[1], DeepOperandType::FPR32);
}
#[test]
fn test_instr_info_c_extension() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::C_NOP,
RISCVDeepOpcode::C_ADDI,
RISCVDeepOpcode::C_LI,
RISCVDeepOpcode::C_LUI,
RISCVDeepOpcode::C_SLLI,
RISCVDeepOpcode::C_MV,
RISCVDeepOpcode::C_ADD,
RISCVDeepOpcode::C_BEQZ,
RISCVDeepOpcode::C_BNEZ,
RISCVDeepOpcode::C_J,
RISCVDeepOpcode::C_JR,
] {
let desc = info.get(*op).unwrap();
assert!(desc.is_compressed, "{:?} should be compressed", op);
}
}
#[test]
fn test_instr_info_c_branch() {
let info = make_instr_info();
for op in &[RISCVDeepOpcode::C_BEQZ, RISCVDeepOpcode::C_BNEZ] {
let desc = info.get(*op).unwrap();
assert!(desc.is_terminator);
assert!(desc.is_branch);
assert!(desc.is_compare);
}
}
#[test]
fn test_instr_info_v_extension() {
let info = make_instr_info();
for op in &[
RISCVDeepOpcode::VADD_VV,
RISCVDeepOpcode::VSUB_VV,
RISCVDeepOpcode::VMUL_VV,
RISCVDeepOpcode::VDIV_VV,
] {
let desc = info.get(*op).unwrap();
assert!(desc.is_vector, "{:?} should be vector", op);
}
}
#[test]
fn test_instr_info_vfadd_is_fp_and_vector() {
let info = make_instr_info();
let vfadd = info.get(RISCVDeepOpcode::VFADD_VV).unwrap();
assert!(vfadd.is_fp);
assert!(vfadd.is_vector);
assert!(vfadd.is_commutative);
}
#[test]
fn test_instr_info_zb_extensions() {
let info = make_instr_info();
assert!(info.get(RISCVDeepOpcode::ANDN).is_some());
assert!(info.get(RISCVDeepOpcode::ORN).is_some());
assert!(info.get(RISCVDeepOpcode::XNOR).unwrap().is_commutative);
assert_eq!(info.get(RISCVDeepOpcode::CLZ).unwrap().num_operands, 2);
assert_eq!(info.get(RISCVDeepOpcode::CTZ).unwrap().num_operands, 2);
}
#[test]
fn test_instr_info_pseudos() {
let info = make_instr_info();
let nop = info.get(RISCVDeepOpcode::NOP).unwrap();
assert_eq!(nop.num_operands, 0);
let mv = info.get(RISCVDeepOpcode::MV).unwrap();
assert_eq!(mv.num_operands, 2);
let ret = info.get(RISCVDeepOpcode::RET).unwrap();
assert!(ret.is_terminator);
assert!(ret.is_return);
assert!(info.get(RISCVDeepOpcode::LI).is_some());
}
#[test]
fn test_find_by_mnemonic() {
let info = make_instr_info();
assert_eq!(
info.find_by_mnemonic("add"),
Some(RISCVDeepOpcode::ADD)
);
assert_eq!(
info.find_by_mnemonic("lui"),
Some(RISCVDeepOpcode::LUI)
);
assert_eq!(
info.find_by_mnemonic("beq"),
Some(RISCVDeepOpcode::BEQ)
);
assert_eq!(
info.find_by_mnemonic("jal"),
Some(RISCVDeepOpcode::JAL)
);
assert_eq!(
info.find_by_mnemonic("ret"),
Some(RISCVDeepOpcode::RET)
);
assert_eq!(info.find_by_mnemonic("nonexistent"), None);
}
#[test]
fn test_get_mnemonic() {
let info = make_instr_info();
assert_eq!(info.get_mnemonic(RISCVDeepOpcode::ADD), Some("add"));
assert_eq!(info.get_mnemonic(RISCVDeepOpcode::LW), Some("lw"));
}
#[test]
fn test_is_terminator() {
let info = make_instr_info();
assert!(info.is_terminator(RISCVDeepOpcode::JAL));
assert!(info.is_terminator(RISCVDeepOpcode::BEQ));
assert!(info.is_terminator(RISCVDeepOpcode::RET));
assert!(!info.is_terminator(RISCVDeepOpcode::ADD));
}
#[test]
fn test_is_branch() {
let info = make_instr_info();
assert!(info.is_branch(RISCVDeepOpcode::BEQ));
assert!(!info.is_branch(RISCVDeepOpcode::JAL));
}
#[test]
fn test_is_call() {
let info = make_instr_info();
assert!(info.is_call(RISCVDeepOpcode::JAL));
assert!(!info.is_call(RISCVDeepOpcode::JALR));
}
#[test]
fn test_is_return() {
let info = make_instr_info();
assert!(info.is_return(RISCVDeepOpcode::RET));
assert!(!info.is_return(RISCVDeepOpcode::JALR));
}
#[test]
fn test_is_compare() {
let info = make_instr_info();
assert!(info.is_compare(RISCVDeepOpcode::SLT));
assert!(info.is_compare(RISCVDeepOpcode::FEQ_S));
assert!(!info.is_compare(RISCVDeepOpcode::ADD));
}
#[test]
fn test_may_load() {
let info = make_instr_info();
assert!(info.may_load(RISCVDeepOpcode::LW));
assert!(info.may_load(RISCVDeepOpcode::LD));
assert!(info.may_load(RISCVDeepOpcode::FLW));
assert!(!info.may_load(RISCVDeepOpcode::SW));
}
#[test]
fn test_may_store() {
let info = make_instr_info();
assert!(info.may_store(RISCVDeepOpcode::SW));
assert!(info.may_store(RISCVDeepOpcode::SD));
assert!(info.may_store(RISCVDeepOpcode::FSW));
assert!(!info.may_store(RISCVDeepOpcode::LW));
}
#[test]
fn test_has_side_effects() {
let info = make_instr_info();
assert!(info.has_side_effects(RISCVDeepOpcode::ECALL));
assert!(info.has_side_effects(RISCVDeepOpcode::CSRRW));
assert!(!info.has_side_effects(RISCVDeepOpcode::ADD));
}
#[test]
fn test_is_fp() {
let info = make_instr_info();
assert!(info.is_fp(RISCVDeepOpcode::FADD_S));
assert!(info.is_fp(RISCVDeepOpcode::FADD_D));
assert!(!info.is_fp(RISCVDeepOpcode::ADD));
}
#[test]
fn test_is_compressed() {
let info = make_instr_info();
assert!(info.is_compressed(RISCVDeepOpcode::C_ADD));
assert!(info.is_compressed(RISCVDeepOpcode::C_NOP));
assert!(!info.is_compressed(RISCVDeepOpcode::ADD));
}
#[test]
fn test_is_vector() {
let info = make_instr_info();
assert!(info.is_vector(RISCVDeepOpcode::VADD_VV));
assert!(!info.is_vector(RISCVDeepOpcode::ADD));
}
#[test]
fn test_get_num_operands() {
let info = make_instr_info();
assert_eq!(info.get_num_operands(RISCVDeepOpcode::ADD), 3);
assert_eq!(info.get_num_operands(RISCVDeepOpcode::LUI), 2);
assert_eq!(info.get_num_operands(RISCVDeepOpcode::NOP), 0);
}
#[test]
fn test_get_operand_types() {
let info = make_instr_info();
let types = info.get_operand_types(RISCVDeepOpcode::ADD);
assert_eq!(types.len(), 3);
assert_eq!(types[0], DeepOperandType::GPR);
assert_eq!(types[1], DeepOperandType::GPR);
assert_eq!(types[2], DeepOperandType::GPR);
}
#[test]
fn test_get_implicit_defs() {
let info = make_instr_info();
let defs = info.get_implicit_defs(RISCVDeepOpcode::JAL);
assert_eq!(defs, &[RA]);
}
#[test]
fn test_get_implicit_uses() {
let info = make_instr_info();
let uses = info.get_implicit_uses(RISCVDeepOpcode::RET);
assert_eq!(uses, &[RA]);
}
#[test]
fn test_all_opcodes() {
let info = make_instr_info();
let all = info.all_opcodes();
assert!(all.contains(&RISCVDeepOpcode::ADD));
assert!(all.contains(&RISCVDeepOpcode::NOP));
}
#[test]
fn test_default_creates_valid_instance() {
let info = RISCVInstrInfoDeep::default();
assert!(info.len() > 0);
assert!(info.get(RISCVDeepOpcode::ADD).is_some());
}
#[test]
fn test_register_counts() {
let ri = make_reg_info();
assert_eq!(
ri.get_allocatable_gprs().len(),
15,
"15 allocatable GPRs (t0-t2, a0-a7, t3-t6)"
);
assert_eq!(
ri.get_allocatable_fprs().len(),
20,
"20 allocatable FPRs (ft0-ft11, fa0-fa7)"
);
}
#[test]
fn test_register_asm_names() {
let ri = make_reg_info();
assert_eq!(ri.get_asm_name(X0), Some("x0"));
assert_eq!(ri.get_asm_name(X1), Some("x1"));
assert_eq!(ri.get_asm_name(X31), Some("x31"));
assert_eq!(ri.get_asm_name(F0), Some("f0"));
assert_eq!(ri.get_asm_name(F31), Some("f31"));
}
#[test]
fn test_register_abi_names() {
let ri = make_reg_info();
assert_eq!(ri.get_abi_name(ZERO), Some("zero"));
assert_eq!(ri.get_abi_name(RA), Some("ra"));
assert_eq!(ri.get_abi_name(SP), Some("sp"));
assert_eq!(ri.get_abi_name(GP), Some("gp"));
assert_eq!(ri.get_abi_name(TP), Some("tp"));
assert_eq!(ri.get_abi_name(T0), Some("t0"));
assert_eq!(ri.get_abi_name(S0), Some("s0/fp"));
assert_eq!(ri.get_abi_name(A0), Some("a0"));
assert_eq!(ri.get_abi_name(FT0), Some("ft0"));
assert_eq!(ri.get_abi_name(FA0), Some("fa0"));
assert_eq!(ri.get_abi_name(FS0), Some("fs0"));
}
#[test]
fn test_register_classes() {
let ri = make_reg_info();
assert_eq!(ri.get_reg_class(X0), DeepRegClass::GPR);
assert_eq!(ri.get_reg_class(F0), DeepRegClass::FPR64);
assert_eq!(ri.get_reg_class(V0), DeepRegClass::VR);
}
#[test]
fn test_register_widths() {
let ri = make_reg_info();
assert_eq!(ri.get_reg_width(X0, true), 64);
assert_eq!(ri.get_reg_width(X0, false), 32);
assert_eq!(ri.get_reg_width(F0, true), 64);
}
#[test]
fn test_is_callee_saved() {
let ri = make_reg_info();
assert!(ri.is_callee_saved(S0));
assert!(ri.is_callee_saved(S1));
assert!(ri.is_callee_saved(S2));
assert!(!ri.is_callee_saved(T0));
assert!(!ri.is_callee_saved(A0));
assert!(ri.is_callee_saved(FS0));
assert!(!ri.is_callee_saved(FT0));
}
#[test]
fn test_is_caller_saved() {
let ri = make_reg_info();
assert!(ri.is_caller_saved(RA));
assert!(ri.is_caller_saved(T0));
assert!(ri.is_caller_saved(A0));
assert!(!ri.is_caller_saved(S0));
assert!(ri.is_caller_saved(FT0));
assert!(!ri.is_caller_saved(FS0));
}
#[test]
fn test_is_reserved() {
let ri = make_reg_info();
assert!(ri.is_reserved(ZERO));
assert!(ri.is_reserved(SP));
assert!(ri.is_reserved(GP));
assert!(ri.is_reserved(TP));
assert!(!ri.is_reserved(T0));
}
#[test]
fn test_argument_regs() {
let ri = make_reg_info();
let args = ri.get_argument_regs();
assert_eq!(args, vec![A0, A1, A2, A3, A4, A5, A6, A7]);
}
#[test]
fn test_fp_argument_regs() {
let ri = make_reg_info();
let args = ri.get_fp_argument_regs();
assert_eq!(args, vec![FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7]);
}
#[test]
fn test_return_regs() {
let ri = make_reg_info();
assert_eq!(ri.get_return_regs(), vec![A0, A1]);
assert_eq!(ri.get_fp_return_regs(), vec![FA0, FA1]);
}
#[test]
fn test_special_regs() {
let ri = make_reg_info();
assert_eq!(ri.get_frame_pointer_reg(), S0);
assert_eq!(ri.get_return_address_reg(), RA);
assert_eq!(ri.get_stack_pointer_reg(), SP);
assert_eq!(ri.get_global_pointer_reg(), GP);
assert_eq!(ri.get_thread_pointer_reg(), TP);
assert_eq!(ri.get_zero_reg(), ZERO);
}
#[test]
fn test_is_gpr_fpr_vr() {
let ri = make_reg_info();
assert!(ri.is_gpr(X5));
assert!(!ri.is_gpr(F5));
assert!(ri.is_fpr(F5));
assert!(!ri.is_fpr(X5));
assert!(ri.is_vr(V5));
assert!(!ri.is_vr(X5));
}
#[test]
fn test_get_gpr_index() {
let ri = make_reg_info();
assert_eq!(ri.get_gpr_index(X0), Some(0));
assert_eq!(ri.get_gpr_index(X15), Some(15));
assert_eq!(ri.get_gpr_index(X31), Some(31));
assert_eq!(ri.get_gpr_index(F0), None);
}
#[test]
fn test_get_fpr_index() {
let ri = make_reg_info();
assert_eq!(ri.get_fpr_index(F0), Some(0));
assert_eq!(ri.get_fpr_index(F15), Some(15));
assert_eq!(ri.get_fpr_index(F31), Some(31));
assert_eq!(ri.get_fpr_index(X0), None);
}
#[test]
fn test_vr_names() {
let ri = make_reg_info();
assert_eq!(ri.get_asm_name(V0), Some("v0"));
assert_eq!(ri.get_asm_name(V15), Some("v15"));
assert_eq!(ri.get_asm_name(V31), Some("v31"));
assert_eq!(ri.get_abi_name(V0), Some("v0"));
}
#[test]
fn test_register_info_default() {
let ri = RISCVRegisterInfoDeep::default();
assert!(ri.get_asm_name(X0).is_some());
}
#[test]
fn test_frame_lowering_new_rv64() {
let fl = RISCVFrameLoweringDeep::new(true);
assert!(fl.is_64bit);
}
#[test]
fn test_frame_lowering_new_rv32() {
let fl = RISCVFrameLoweringDeep::new(false);
assert!(!fl.is_64bit);
}
#[test]
fn test_frame_info_default() {
let fi = RISCvFrameInfoDeep::default();
assert_eq!(fi.frame_size, 0);
assert!(!fi.has_frame_pointer);
assert!(!fi.has_calls);
assert!(fi.is_64bit);
}
#[test]
fn test_frame_info_rv32() {
let fi = RISCvFrameInfoDeep::new(false);
assert_eq!(fi.reg_width(), 4);
}
#[test]
fn test_frame_info_rv64_reg_width() {
let fi = RISCvFrameInfoDeep::new(true);
assert_eq!(fi.reg_width(), 8);
}
#[test]
fn test_prologue_empty_leaf() {
let fl = RISCVFrameLoweringDeep::new(true);
let info = RISCvFrameInfoDeep::new(true);
let instrs = fl.emit_prologue(&info);
assert!(instrs.is_empty());
}
#[test]
fn test_prologue_with_frame() {
let fl = RISCVFrameLoweringDeep::new(true);
let mut info = RISCvFrameInfoDeep::new(true);
info.frame_size = 32;
info.has_calls = true;
info.saved_ra_offset = 24;
info.has_frame_pointer = true;
info.saved_fp_offset = 16;
info.saved_regs = vec![S1, S2];
let instrs = fl.emit_prologue(&info);
assert!(instrs.len() >= 4, "Expected at least 4 prologue instructions, got {}", instrs.len());
}
#[test]
fn test_epilogue_empty_leaf() {
let fl = RISCVFrameLoweringDeep::new(true);
let info = RISCvFrameInfoDeep::new(true);
let instrs = fl.emit_epilogue(&info);
assert_eq!(instrs.len(), 1);
}
#[test]
fn test_epilogue_with_frame() {
let fl = RISCVFrameLoweringDeep::new(true);
let mut info = RISCvFrameInfoDeep::new(true);
info.frame_size = 32;
info.has_calls = true;
info.saved_ra_offset = 24;
info.has_frame_pointer = true;
info.saved_fp_offset = 16;
info.saved_regs = vec![S1, S2];
let instrs = fl.emit_epilogue(&info);
assert!(instrs.len() >= 4, "Expected at least 4 epilogue instructions, got {}", instrs.len());
}
#[test]
fn test_needs_frame_pointer() {
let fl = RISCVFrameLoweringDeep::new(true);
assert!(!fl.needs_frame_pointer(256, false));
assert!(fl.needs_frame_pointer(4096, false));
assert!(fl.needs_frame_pointer(0, true)); }
#[test]
fn test_calculate_frame_size() {
let fl = RISCVFrameLoweringDeep::new(true);
let size = fl.calculate_frame_size(8, 2, true);
assert_eq!(size, 32);
let size2 = fl.calculate_frame_size(1, 0, false);
assert_eq!(size2, 16);
}
#[test]
fn test_calculate_frame_size_rv32() {
let fl = RISCVFrameLoweringDeep::new(false);
let size = fl.calculate_frame_size(4, 1, true);
assert_eq!(size, 16);
}
#[test]
fn test_frame_lowering_default() {
let fl = RISCVFrameLoweringDeep::default();
assert!(fl.is_64bit);
}
#[test]
fn test_cc_lp64d_name() {
let cc = DeepCallingConvention::LP64D;
assert_eq!(cc.name(), "LP64D");
}
#[test]
fn test_cc_ilp32_name() {
let cc = DeepCallingConvention::ILP32;
assert_eq!(cc.name(), "ILP32");
}
#[test]
fn test_cc_is_64bit() {
assert!(DeepCallingConvention::LP64.is_64bit());
assert!(DeepCallingConvention::LP64D.is_64bit());
assert!(DeepCallingConvention::LP64F.is_64bit());
assert!(!DeepCallingConvention::ILP32.is_64bit());
assert!(!DeepCallingConvention::ILP32D.is_64bit());
assert!(!DeepCallingConvention::ILP32F.is_64bit());
}
#[test]
fn test_cc_xlen() {
assert_eq!(DeepCallingConvention::LP64.xlen_bits(), 64);
assert_eq!(DeepCallingConvention::ILP32.xlen_bits(), 32);
assert_eq!(DeepCallingConvention::LP64.xlen_bytes(), 8);
assert_eq!(DeepCallingConvention::ILP32.xlen_bytes(), 4);
}
#[test]
fn test_cc_uses_fp_regs() {
assert!(DeepCallingConvention::LP64D.uses_fp_regs());
assert!(DeepCallingConvention::LP64F.uses_fp_regs());
assert!(!DeepCallingConvention::LP64.uses_fp_regs());
assert!(!DeepCallingConvention::ILP32.uses_fp_regs());
}
#[test]
fn test_cc_int_param_regs() {
for cc in &[
DeepCallingConvention::LP64,
DeepCallingConvention::LP64D,
DeepCallingConvention::ILP32,
] {
assert_eq!(
cc.get_int_param_regs(),
vec![A0, A1, A2, A3, A4, A5, A6, A7]
);
}
}
#[test]
fn test_cc_fp_param_regs() {
assert_eq!(
DeepCallingConvention::LP64D.get_fp_param_regs(),
vec![FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7]
);
assert!(DeepCallingConvention::LP64.get_fp_param_regs().is_empty());
}
#[test]
fn test_cc_return_regs_int() {
let cc = DeepCallingConvention::LP64;
assert_eq!(cc.get_return_regs(4, false), vec![A0]);
assert_eq!(cc.get_return_regs(8, false), vec![A0]);
assert_eq!(cc.get_return_regs(16, false), vec![A0]);
}
#[test]
fn test_cc_return_regs_fp() {
let cc = DeepCallingConvention::LP64D;
assert_eq!(cc.get_return_regs(4, true), vec![FA0]);
assert_eq!(cc.get_return_regs(8, true), vec![FA0]);
assert_eq!(cc.get_return_regs(12, true), vec![FA0, FA1]);
}
#[test]
fn test_cc_return_regs_ilp32() {
let cc = DeepCallingConvention::ILP32;
assert_eq!(cc.get_return_regs(4, false), vec![A0]);
assert_eq!(cc.get_return_regs(8, false), vec![A0, A1]);
assert_eq!(cc.get_return_regs(16, false), vec![A0]); }
#[test]
fn test_cc_stack_alignment() {
for cc in &[
DeepCallingConvention::LP64,
DeepCallingConvention::ILP32,
] {
assert_eq!(cc.get_stack_alignment(), 16);
}
}
#[test]
fn test_cc_special_regs() {
for cc in &[
DeepCallingConvention::LP64,
DeepCallingConvention::ILP32,
] {
assert_eq!(cc.get_frame_pointer_reg(), S0);
assert_eq!(cc.get_return_address_reg(), RA);
assert_eq!(cc.get_stack_pointer_reg(), SP);
}
}
#[test]
fn test_calling_convention_deep_new() {
let cc = RISCVCallingConventionDeep::new(DeepCallingConvention::LP64D);
assert!(cc.is_64bit());
assert!(cc.uses_fp_regs());
assert_eq!(cc.xlen_bytes(), 8);
assert_eq!(cc.stack_alignment(), 16);
}
#[test]
fn test_calling_convention_deep_int_args() {
let cc = RISCVCallingConventionDeep::new(DeepCallingConvention::LP64);
assert_eq!(
cc.int_arg_regs(),
vec![A0, A1, A2, A3, A4, A5, A6, A7]
);
}
#[test]
fn test_calling_convention_deep_return_regs() {
let cc = RISCVCallingConventionDeep::new(DeepCallingConvention::LP64D);
assert_eq!(cc.int_return_regs(), vec![A0, A1]);
assert_eq!(cc.fp_return_regs(), vec![FA0, FA1]);
}
#[test]
fn test_calling_convention_deep_default() {
let cc = RISCVCallingConventionDeep::default();
assert!(cc.is_64bit());
}
#[test]
fn test_backend_new_rv64() {
let be = RISCVDeep::new(true, "riscv64-unknown-linux-gnu", "generic");
assert!(be.is_64bit);
assert_eq!(be.xlen_bits(), 64);
assert_eq!(be.get_triple(), "riscv64-unknown-linux-gnu");
assert_eq!(be.get_cpu(), "generic");
}
#[test]
fn test_backend_new_rv32() {
let be = RISCVDeep::new(false, "riscv32-unknown-elf", "generic-rv32");
assert!(!be.is_64bit);
assert_eq!(be.xlen_bits(), 32);
}
#[test]
fn test_backend_rv64gc() {
let be = make_rv64gc_backend();
assert!(be.is_64bit);
assert!(be.has_extension("m"));
assert!(be.has_extension("a"));
assert!(be.has_extension("f"));
assert!(be.has_extension("d"));
assert!(be.has_extension("c"));
assert!(!be.has_extension("v"));
}
#[test]
fn test_backend_rv32imac() {
let be = make_rv32_backend();
assert!(!be.is_64bit);
assert!(be.has_extension("m"));
assert!(be.has_extension("a"));
assert!(be.has_extension("c"));
assert!(!be.has_extension("f"));
assert!(!be.has_extension("d"));
}
#[test]
fn test_backend_rv64gcv() {
let be = RISCVDeep::rv64gcv("riscv64-unknown-linux-gnu", "generic");
assert!(be.has_extension("v"));
assert!(be.has_extension("c"));
}
#[test]
fn test_backend_enable_extension() {
let mut be = make_rv64_backend();
assert!(!be.has_extension("zbkb"));
be.enable_extension("zbkb");
assert!(be.has_extension("zbkb"));
}
#[test]
fn test_backend_duplicate_extension() {
let mut be = make_rv64_backend();
be.enable_extension("m");
be.enable_extension("m");
assert_eq!(be.extensions.iter().filter(|e| *e == "m").count(), 1);
}
#[test]
fn test_backend_isa_string() {
let be = make_rv64gc_backend();
let isa = be.get_isa_string();
assert!(isa.starts_with("rv64i"));
assert!(isa.contains('m'));
assert!(isa.contains('a'));
assert!(isa.contains('f'));
assert!(isa.contains('d'));
assert!(isa.contains('c'));
}
#[test]
fn test_backend_isa_string_rv32() {
let be = make_rv32_backend();
let isa = be.get_isa_string();
assert!(isa.starts_with("rv32i"));
}
#[test]
fn test_backend_emit_prologue() {
let be = make_rv64_backend();
let mut info = RISCvFrameInfoDeep::new(true);
info.frame_size = 32;
info.has_calls = true;
info.saved_ra_offset = 24;
let instrs = be.emit_prologue(&info);
assert!(!instrs.is_empty());
}
#[test]
fn test_backend_emit_epilogue() {
let be = make_rv64_backend();
let mut info = RISCvFrameInfoDeep::new(true);
info.frame_size = 32;
info.has_calls = true;
info.saved_ra_offset = 24;
let instrs = be.emit_epilogue(&info);
assert!(!instrs.is_empty());
}
#[test]
fn test_backend_default() {
let be = RISCVDeep::default();
assert!(be.is_64bit);
assert!(be.instr_info.len() > 0);
}
#[test]
fn test_operand_type_is_register() {
assert!(DeepOperandType::GPR.is_register());
assert!(DeepOperandType::FPR.is_register());
assert!(DeepOperandType::VR.is_register());
assert!(!DeepOperandType::Simm12.is_register());
assert!(!DeepOperandType::Uimm20.is_register());
}
#[test]
fn test_operand_type_is_immediate() {
assert!(DeepOperandType::Simm12.is_immediate());
assert!(DeepOperandType::Uimm12.is_immediate());
assert!(DeepOperandType::Uimm20.is_immediate());
assert!(DeepOperandType::Uimm5.is_immediate());
assert!(!DeepOperandType::GPR.is_immediate());
assert!(!DeepOperandType::FPR.is_immediate());
}
#[test]
fn test_reg_class_display() {
assert_eq!(format!("{}", DeepRegClass::GPR), "GPR");
assert_eq!(format!("{}", DeepRegClass::FPR32), "FPR32");
assert_eq!(format!("{}", DeepRegClass::FPR64), "FPR64");
assert_eq!(format!("{}", DeepRegClass::VR), "VR");
assert_eq!(format!("{}", DeepRegClass::VMask), "VMask");
}
#[test]
fn test_deep_constants() {
assert_eq!(DEEP_GPR_COUNT, 32);
assert_eq!(DEEP_FPR_COUNT, 32);
assert_eq!(DEEP_VR_COUNT, 32);
assert_eq!(DEEP_GPR_BASE, 3000);
assert_eq!(DEEP_FPR_BASE, 3050);
assert_eq!(DEEP_VR_BASE, 3100);
}
#[test]
fn test_vr_id_range() {
assert_eq!(V0, 3100);
assert_eq!(V31, 3131);
for i in 0..32 {
let id = V0 + i;
assert!((3100..=3131).contains(&id));
}
}
#[test]
fn test_gpr_names_count() {
assert_eq!(DEEP_GPR_NAMES.len(), 32);
}
#[test]
fn test_fpr_names_count() {
assert_eq!(DEEP_FPR_NAMES.len(), 32);
}
#[test]
fn test_vr_names_count() {
assert_eq!(DEEP_VR_NAMES.len(), 32);
}
#[test]
fn test_roundtrip_prologue_epilogue_rv64() {
let be = make_rv64_backend();
let mut info = RISCvFrameInfoDeep::new(true);
info.frame_size = 64;
info.has_calls = true;
info.saved_ra_offset = 56;
info.has_frame_pointer = true;
info.saved_fp_offset = 48;
info.saved_regs = vec![S1, S2, S3];
let prologue = be.emit_prologue(&info);
let epilogue = be.emit_epilogue(&info);
assert!(!prologue.is_empty());
assert!(!epilogue.is_empty());
assert!(epilogue.len() >= 2, "Epilogue should have multiple instructions");
}
#[test]
fn test_roundtrip_leaf_function() {
let be = make_rv64_backend();
let info = RISCvFrameInfoDeep::new(true);
let prologue = be.emit_prologue(&info);
let epilogue = be.emit_epilogue(&info);
assert!(prologue.is_empty(), "Leaf fn should have empty prologue");
assert_eq!(epilogue.len(), 1, "Leaf fn epilogue should be just RET");
}
#[test]
fn test_roundtrip_rv32() {
let be = make_rv32_backend();
let mut info = RISCvFrameInfoDeep::new(false);
info.frame_size = 16;
info.has_calls = true;
info.saved_ra_offset = 12;
let prologue = be.emit_prologue(&info);
let epilogue = be.emit_epilogue(&info);
assert!(!prologue.is_empty());
assert!(!epilogue.is_empty());
}
#[test]
fn test_all_opcodes_have_valid_mnemonics() {
let info = make_instr_info();
for op in info.all_opcodes() {
let desc = info.get(op).unwrap();
assert!(!desc.mnemonic.is_empty(), "{:?} has empty mnemonic", op);
}
}
#[test]
fn test_no_opcode_is_both_load_and_store() {
let info = make_instr_info();
for op in info.all_opcodes() {
let desc = info.get(op).unwrap();
if !desc.mnemonic.starts_with("amo") && !desc.mnemonic.starts_with("lr") && !desc.mnemonic.starts_with("sc") {
assert!(
!(desc.is_load && desc.is_store),
"{:?} should not be both load and store unless atomic",
op
);
}
}
}
#[test]
fn test_terminators_are_not_regular_alu() {
let info = make_instr_info();
for op in info.all_opcodes() {
let desc = info.get(op).unwrap();
if desc.is_terminator {
assert!(
desc.is_branch || desc.is_return || desc.is_call || desc.has_side_effects,
"{:?} is terminator but has no distinguishing feature",
op
);
}
}
}
#[test]
fn test_all_commutative_ops_have_at_least_2_operands() {
let info = make_instr_info();
for op in info.all_opcodes() {
let desc = info.get(op).unwrap();
if desc.is_commutative {
assert!(
desc.num_operands >= 2,
"Commutative op {:?} has only {} operands",
op,
desc.num_operands
);
}
}
}
#[test]
fn test_find_by_mnemonic_returns_correct_opcode_for_each_descriptor() {
let info = make_instr_info();
for op in info.all_opcodes() {
let mnemonic = info.get_mnemonic(op).unwrap();
let found = info.find_by_mnemonic(mnemonic);
assert!(
found.is_some(),
"Could not find {} by mnemonic '{}'",
mnemonic,
mnemonic
);
}
}
}