use super::arm_instr_info::ArmOpcode;
use crate::codegen::{MachineInstr, MachineOperand};
use std::collections::HashMap;
const OP_ADD: u32 = ArmOpcode::ADD as u32;
const OP_SUB: u32 = ArmOpcode::SUB as u32;
const _OP_MUL: u32 = ArmOpcode::MUL as u32;
const OP_SDIV: u32 = ArmOpcode::SDIV as u32;
const OP_UDIV: u32 = ArmOpcode::UDIV as u32;
const OP_AND: u32 = ArmOpcode::AND as u32;
const OP_ORR: u32 = ArmOpcode::ORR as u32;
const OP_EOR: u32 = ArmOpcode::EOR as u32;
const OP_ADDS: u32 = ArmOpcode::ADDS as u32;
const OP_SUBS: u32 = ArmOpcode::SUBS as u32;
const OP_MADD: u32 = ArmOpcode::MADD as u32;
const OP_MSUB: u32 = ArmOpcode::MSUB as u32;
const OP_MOV: u32 = ArmOpcode::MOV as u32;
const OP_MOVZ: u32 = ArmOpcode::MOVZ as u32;
const OP_MOVK: u32 = ArmOpcode::MOVK as u32;
const OP_MOVN: u32 = ArmOpcode::MOVN as u32;
const OP_LDR: u32 = ArmOpcode::LDR as u32;
const OP_STR: u32 = ArmOpcode::STR as u32;
const OP_LDP: u32 = ArmOpcode::LDP as u32;
const OP_STP: u32 = ArmOpcode::STP as u32;
const OP_B: u32 = ArmOpcode::B as u32;
const OP_BL: u32 = ArmOpcode::BL as u32;
const OP_BR: u32 = ArmOpcode::BR as u32;
const OP_BLR: u32 = ArmOpcode::BLR as u32;
const OP_RET: u32 = ArmOpcode::RET as u32;
const OP_CBZ: u32 = ArmOpcode::CBZ as u32;
const OP_CBNZ: u32 = ArmOpcode::CBNZ as u32;
const OP_B_COND: u32 = ArmOpcode::B_COND as u32;
const OP_CMP: u32 = ArmOpcode::CMP as u32;
const _OP_TST: u32 = ArmOpcode::TST as u32;
const OP_CSEL: u32 = ArmOpcode::CSEL as u32;
const OP_BFM: u32 = ArmOpcode::BFM as u32;
const OP_SBFM: u32 = ArmOpcode::SBFM as u32;
const OP_UBFM: u32 = ArmOpcode::UBFM as u32;
const OP_NOP: u32 = ArmOpcode::NOP as u32;
const OP_ARM_ADD: u32 = ArmOpcode::ARM_ADD as u32;
const OP_ARM_SUB: u32 = ArmOpcode::ARM_SUB as u32;
const OP_ARM_MOV: u32 = ArmOpcode::ARM_MOV as u32;
const OP_ARM_AND: u32 = ArmOpcode::ARM_AND as u32;
const OP_ARM_ORR: u32 = ArmOpcode::ARM_ORR as u32;
const OP_ARM_EOR: u32 = ArmOpcode::ARM_EOR as u32;
const OP_ARM_CMP: u32 = ArmOpcode::ARM_CMP as u32;
const OP_ARM_B: u32 = ArmOpcode::ARM_B as u32;
const OP_ARM_BL: u32 = ArmOpcode::ARM_BL as u32;
const OP_ARM_LDR: u32 = ArmOpcode::ARM_LDR as u32;
const OP_ARM_STR: u32 = ArmOpcode::ARM_STR as u32;
const OP_ARM_PUSH: u32 = ArmOpcode::ARM_PUSH as u32;
const OP_ARM_POP: u32 = ArmOpcode::ARM_POP as u32;
const OP_SVC: u32 = ArmOpcode::SVC as u32;
const OP_HVC: u32 = ArmOpcode::HVC as u32;
const OP_SMC: u32 = ArmOpcode::SMC as u32;
const OP_BRK: u32 = ArmOpcode::BRK as u32;
const OP_MSR: u32 = ArmOpcode::MSR as u32;
const OP_MRS: u32 = ArmOpcode::MRS as u32;
const OP_SYS: u32 = ArmOpcode::SYS as u32;
const OP_SYSL: u32 = ArmOpcode::SYSL as u32;
const OP_ADR: u32 = ArmOpcode::ADR as u32;
const OP_ADRP: u32 = ArmOpcode::ADRP as u32;
const OP_TBNZ: u32 = ArmOpcode::TBNZ as u32;
const OP_TBZ: u32 = ArmOpcode::TBZ as u32;
const OP_LDRB: u32 = ArmOpcode::LDRB as u32;
const OP_LDRH: u32 = ArmOpcode::LDRH as u32;
const OP_LDRSB: u32 = ArmOpcode::LDRSB as u32;
const OP_LDRSH: u32 = ArmOpcode::LDRSH as u32;
const OP_LDRSW: u32 = ArmOpcode::LDRSW as u32;
const OP_STRB: u32 = ArmOpcode::STRB as u32;
const OP_STRH: u32 = ArmOpcode::STRH as u32;
const OP_LDUR: u32 = ArmOpcode::LDUR as u32;
const OP_LDURB: u32 = ArmOpcode::LDURB as u32;
const OP_LDURH: u32 = ArmOpcode::LDURH as u32;
const OP_STUR: u32 = ArmOpcode::STUR as u32;
const OP_STURB: u32 = ArmOpcode::STURB as u32;
const OP_STURH: u32 = ArmOpcode::STURH as u32;
const OP_LDXR: u32 = 1000;
const OP_LDXRB: u32 = 1001;
const OP_LDXRH: u32 = 1002;
const OP_STXR: u32 = 1003;
const OP_STXRB: u32 = 1004;
const OP_STXRH: u32 = 1005;
const OP_LDAXR: u32 = 1006;
const OP_STLXR: u32 = 1007;
const OP_PRFM: u32 = ArmOpcode::PRFM as u32;
const OP_CLREX: u32 = ArmOpcode::CLREX_A64 as u32;
const OP_DMB: u32 = ArmOpcode::DMB as u32;
const OP_DSB: u32 = ArmOpcode::DSB as u32;
const OP_ISB: u32 = ArmOpcode::ISB as u32;
const OP_CCMN: u32 = ArmOpcode::CCMN as u32;
const OP_CCMP: u32 = ArmOpcode::CCMP as u32;
const OP_RBIT: u32 = ArmOpcode::RBIT as u32;
const OP_REV: u32 = ArmOpcode::REV as u32;
const OP_REV16: u32 = ArmOpcode::REV16 as u32;
const OP_REV32: u32 = ArmOpcode::REV32 as u32;
const OP_CLZ: u32 = ArmOpcode::CLZ as u32;
const OP_CLS: u32 = ArmOpcode::CLS as u32;
const OP_MVN: u32 = 1010;
const OP_NEG: u32 = 1011;
const OP_NEGS: u32 = 1012;
const OP_NGC: u32 = 1013;
const OP_NGCS: u32 = 1014;
const OP_ADC: u32 = 1015;
const OP_ADCS: u32 = 1016;
const OP_SBC: u32 = 1017;
const OP_SBCS: u32 = 1018;
const OP_ORN: u32 = ArmOpcode::ORN as u32;
const OP_BIC: u32 = ArmOpcode::BIC as u32;
const OP_BICS: u32 = 1019;
const OP_EON: u32 = 1020;
const OP_TST: u32 = ArmOpcode::TST as u32;
const OP_ANDS_IMPLICIT: u32 = 1021;
const OP_UBFIZ: u32 = 1022;
const OP_SBFIZ: u32 = 1023;
const OP_UBFX: u32 = ArmOpcode::UBFX as u32;
const OP_SBFX: u32 = ArmOpcode::SBFX as u32;
const OP_EXTR: u32 = ArmOpcode::EXTR as u32;
const OP_LSLV: u32 = 1024;
const OP_LSRV: u32 = 1025;
const OP_ASRV: u32 = 1026;
const OP_RORV: u32 = 1027;
const OP_CRC32B: u32 = 1028;
const OP_CRC32H: u32 = 1029;
const OP_CRC32W: u32 = 1030;
const OP_CRC32X: u32 = 1031;
const OP_CRC32CB: u32 = 1032;
const OP_CRC32CH: u32 = 1033;
const OP_CRC32CW: u32 = 1034;
const OP_CRC32CX: u32 = 1035;
const OP_FADD: u32 = ArmOpcode::FADD as u32;
const OP_FSUB: u32 = ArmOpcode::FSUB as u32;
const OP_FMUL: u32 = ArmOpcode::FMUL as u32;
const OP_FDIV: u32 = ArmOpcode::FDIV as u32;
const OP_FNEG: u32 = ArmOpcode::FNEG as u32;
const OP_FABS: u32 = ArmOpcode::FABS as u32;
const OP_FSQRT: u32 = ArmOpcode::FSQRT as u32;
const OP_FMOV: u32 = ArmOpcode::FMOV as u32;
const OP_FCVT: u32 = ArmOpcode::FCVT as u32;
const OP_FCVTZS: u32 = ArmOpcode::FCVTZS as u32;
const OP_FCVTZU: u32 = ArmOpcode::FCVTZU as u32;
const OP_SCVTF: u32 = ArmOpcode::SCVTF as u32;
const OP_UCVTF: u32 = ArmOpcode::UCVTF as u32;
const OP_FCMP: u32 = ArmOpcode::FCMP as u32;
const OP_FCMPE: u32 = 1040;
const OP_FCCMP: u32 = ArmOpcode::FCCMP as u32;
const OP_FCCMPE: u32 = 1041;
const OP_FCSEL: u32 = ArmOpcode::FCSEL as u32;
const OP_FMADD: u32 = 1042;
const OP_FMSUB: u32 = 1043;
const OP_FNMADD: u32 = 1044;
const OP_FNMSUB: u32 = 1045;
const OP_FMIN: u32 = ArmOpcode::FMIN as u32;
const OP_FMAX: u32 = ArmOpcode::FMAX as u32;
const OP_FRINTN: u32 = ArmOpcode::FRINTN as u32;
const OP_FRINTP: u32 = ArmOpcode::FRINTP as u32;
const OP_FRINTM: u32 = ArmOpcode::FRINTM as u32;
const OP_FRINTZ: u32 = ArmOpcode::FRINTZ as u32;
const OP_FRINTA: u32 = ArmOpcode::FRINTA as u32;
const OP_FRINTX: u32 = ArmOpcode::FRINTX as u32;
const OP_FRINTI: u32 = ArmOpcode::FRINTI as u32;
const OP_ADDV: u32 = 1050;
const OP_SADDLV: u32 = ArmOpcode::SADDLV as u32;
const OP_UADDLV: u32 = ArmOpcode::UADDLV as u32;
const OP_SMAXV: u32 = ArmOpcode::SMAXV as u32;
const OP_UMAXV: u32 = ArmOpcode::UMAXV as u32;
const OP_SMINV: u32 = ArmOpcode::SMINV as u32;
const OP_UMINV: u32 = ArmOpcode::UMINV as u32;
const OP_FMAXV: u32 = ArmOpcode::FMAXV as u32;
const OP_FMINV: u32 = ArmOpcode::FMINV as u32;
const OP_FADDP: u32 = ArmOpcode::FADDP as u32;
const OP_DUP: u32 = ArmOpcode::DUP as u32;
const OP_INS: u32 = ArmOpcode::INS as u32;
const OP_UMOV: u32 = ArmOpcode::UMOV as u32;
const OP_SMOV: u32 = ArmOpcode::SMOV as u32;
const OP_MOVI: u32 = ArmOpcode::MOVI as u32;
const OP_MVNI: u32 = 1051;
const OP_BIC_V: u32 = ArmOpcode::BIC_V as u32;
const OP_ORR_V: u32 = ArmOpcode::ORR_V as u32;
const OP_AND_V: u32 = ArmOpcode::AND_V as u32;
const OP_EOR_V: u32 = ArmOpcode::EOR_V as u32;
const OP_BSL: u32 = ArmOpcode::BSL as u32;
const OP_BIT: u32 = ArmOpcode::BIT as u32;
const OP_BIF: u32 = ArmOpcode::BIF as u32;
const OP_ADD_V: u32 = ArmOpcode::ADD_V as u32;
const OP_SUB_V: u32 = ArmOpcode::SUB_V as u32;
const OP_MUL_V: u32 = ArmOpcode::MUL_V as u32;
const OP_MLA_V: u32 = ArmOpcode::MLA_V as u32;
const OP_MLS_V: u32 = ArmOpcode::MLS_V as u32;
const OP_SHL: u32 = 1052;
const OP_SSHL: u32 = ArmOpcode::SSHL as u32;
const OP_USHL: u32 = ArmOpcode::USHL as u32;
const OP_CMEQ: u32 = ArmOpcode::CMEQ as u32;
const OP_CMGT: u32 = ArmOpcode::CMGT as u32;
const OP_CMGE: u32 = ArmOpcode::CMGE as u32;
const OP_CMHI: u32 = ArmOpcode::CMHI as u32;
const OP_CMHS: u32 = ArmOpcode::CMHS as u32;
const OP_CMTST: u32 = ArmOpcode::CMTST as u32;
const OP_FADD_V: u32 = 1053;
const OP_FSUB_V: u32 = 1054;
const OP_FMUL_V: u32 = 1055;
const OP_FDIV_V: u32 = 1056;
const OP_FCMLA: u32 = 1057;
const OP_FCADD: u32 = 1058;
const OP_EXT: u32 = ArmOpcode::EXT as u32;
const OP_TBL: u32 = ArmOpcode::TBL as u32;
const OP_TBX: u32 = ArmOpcode::TBX as u32;
const OP_ZIP1: u32 = ArmOpcode::ZIP1 as u32;
const OP_ZIP2: u32 = ArmOpcode::ZIP2 as u32;
const OP_UZP1: u32 = ArmOpcode::UZP1 as u32;
const OP_UZP2: u32 = ArmOpcode::UZP2 as u32;
const OP_TRN1: u32 = ArmOpcode::TRN1 as u32;
const OP_TRN2: u32 = ArmOpcode::TRN2 as u32;
const OP_REV64: u32 = ArmOpcode::REV64 as u32;
const OP_REV32_V: u32 = ArmOpcode::REV32_V as u32;
const OP_REV16_V: u32 = ArmOpcode::REV16_V as u32;
const OP_SADDLP: u32 = ArmOpcode::SADDLP as u32;
const OP_UADDLP: u32 = ArmOpcode::UADDLP as u32;
const OP_XTN: u32 = ArmOpcode::XTN as u32;
const OP_SQXTN: u32 = ArmOpcode::SQXTN as u32;
const OP_UQXTN: u32 = ArmOpcode::UQXTN as u32;
const OP_FCVTN: u32 = 1060;
const OP_FCVTL: u32 = 1061;
const OP_SCVTF_V: u32 = ArmOpcode::SCVTF_V as u32;
const OP_UCVTF_V: u32 = ArmOpcode::UCVTF_V as u32;
const OP_FCVTZS_V: u32 = ArmOpcode::FCVTZS_V as u32;
const OP_FCVTZU_V: u32 = ArmOpcode::FCVTZU_V as u32;
const OP_LD1: u32 = 1070;
const OP_LD2: u32 = ArmOpcode::LD2 as u32;
const OP_LD3: u32 = ArmOpcode::LD3 as u32;
const OP_LD4: u32 = ArmOpcode::LD4 as u32;
const OP_ST1: u32 = 1071;
const OP_ST2: u32 = ArmOpcode::ST2 as u32;
const OP_ST3: u32 = ArmOpcode::ST3 as u32;
const OP_ST4: u32 = ArmOpcode::ST4 as u32;
const OP_LDR_QIMM: u32 = 1072;
const OP_STR_QIMM: u32 = 1073;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArmCond {
EQ = 0b0000,
NE = 0b0001,
CS = 0b0010, CC = 0b0011, MI = 0b0100,
PL = 0b0101,
VS = 0b0110,
VC = 0b0111,
HI = 0b1000,
LS = 0b1001,
GE = 0b1010,
LT = 0b1011,
GT = 0b1100,
LE = 0b1101,
AL = 0b1110,
}
impl ArmCond {
pub fn from_mnemonic(s: &str) -> Option<ArmCond> {
match s.to_lowercase().as_str() {
"eq" => Some(ArmCond::EQ),
"ne" => Some(ArmCond::NE),
"cs" | "hs" => Some(ArmCond::CS),
"cc" | "lo" => Some(ArmCond::CC),
"mi" => Some(ArmCond::MI),
"pl" => Some(ArmCond::PL),
"vs" => Some(ArmCond::VS),
"vc" => Some(ArmCond::VC),
"hi" => Some(ArmCond::HI),
"ls" => Some(ArmCond::LS),
"ge" => Some(ArmCond::GE),
"lt" => Some(ArmCond::LT),
"gt" => Some(ArmCond::GT),
"le" => Some(ArmCond::LE),
"al" => Some(ArmCond::AL),
_ => None,
}
}
pub fn invert(self) -> ArmCond {
match self {
ArmCond::EQ => ArmCond::NE,
ArmCond::NE => ArmCond::EQ,
ArmCond::CS => ArmCond::CC,
ArmCond::CC => ArmCond::CS,
ArmCond::MI => ArmCond::PL,
ArmCond::PL => ArmCond::MI,
ArmCond::VS => ArmCond::VC,
ArmCond::VC => ArmCond::VS,
ArmCond::HI => ArmCond::LS,
ArmCond::LS => ArmCond::HI,
ArmCond::GE => ArmCond::LT,
ArmCond::LT => ArmCond::GE,
ArmCond::GT => ArmCond::LE,
ArmCond::LE => ArmCond::GT,
ArmCond::AL => ArmCond::AL,
}
}
}
pub struct ArmMCEncoder {
pub is_64bit: bool,
pub output: Vec<u8>,
pub label_offsets: HashMap<String, u64>,
}
impl ArmMCEncoder {
pub fn new(is_64bit: bool) -> Self {
Self {
is_64bit,
output: Vec::new(),
label_offsets: HashMap::new(),
}
}
pub fn encode_instruction(&self, mi: &MachineInstr) -> Vec<u8> {
if self.is_64bit {
let word = self.encode_aarch64(mi);
word.to_le_bytes().to_vec()
} else {
let word = self.encode_arm32_instruction(mi);
word.to_le_bytes().to_vec()
}
}
pub fn record_label(&mut self, label: &str, offset: u64) {
self.label_offsets.insert(label.to_string(), offset);
}
pub fn len(&self) -> usize {
self.output.len()
}
pub fn is_empty(&self) -> bool {
self.output.is_empty()
}
fn encode_aarch64(&self, mi: &MachineInstr) -> u32 {
let op = mi.opcode;
if op == OP_ADD || op == OP_SUB || op == OP_ADDS || op == OP_SUBS {
self.encode_add_sub(mi)
} else if op == OP_ADC || op == OP_ADCS || op == OP_SBC || op == OP_SBCS {
self.encode_add_sub(mi) } else if op == OP_MOVZ {
self.encode_movz(mi)
} else if op == OP_MOVK {
self.encode_movk(mi)
} else if op == OP_MOVN {
self.encode_movn(mi)
} else if op == OP_MOV {
self.encode_mov(mi)
} else if op == OP_MVN {
self.encode_mvn(mi)
} else if op == OP_NEG || op == OP_NEGS || op == OP_NGC || op == OP_NGCS {
self.encode_neg(mi)
}
else if op == OP_LDR || op == OP_STR {
self.encode_ldr_str(mi)
} else if op == OP_LDP || op == OP_STP {
self.encode_ldp_stp(mi)
} else if op == OP_LDRB {
self.encode_ldrb_imm(mi)
} else if op == OP_STRB {
self.encode_strb_imm(mi)
} else if op == OP_LDRH {
self.encode_ldrh_imm(mi)
} else if op == OP_STRH {
self.encode_strh_imm(mi)
} else if op == OP_LDRSB {
self.encode_ldrsb_imm(mi)
} else if op == OP_LDRSH {
self.encode_ldrsh_imm(mi)
} else if op == OP_LDRSW {
self.encode_ldrsw_imm(mi)
} else if op == OP_LDUR {
self.encode_ldur(mi)
} else if op == OP_STUR {
self.encode_stur(mi)
} else if op == OP_LDURB {
self.encode_ldurb(mi)
} else if op == OP_LDURH {
self.encode_ldurh(mi)
} else if op == OP_STURB {
self.encode_sturb(mi)
} else if op == OP_STURH {
self.encode_sturh(mi)
} else if op == OP_LDXR || op == OP_LDXRB || op == OP_LDXRH {
self.encode_ldxr(mi)
} else if op == OP_STXR || op == OP_STXRB || op == OP_STXRH {
self.encode_stxr(mi)
} else if op == OP_LDAXR {
self.encode_ldaxr(mi)
} else if op == OP_STLXR {
self.encode_stlxr(mi)
}
else if op == OP_B || op == OP_BL {
self.encode_b_bl(mi)
} else if op == OP_CBZ || op == OP_CBNZ {
self.encode_cbz_cbnz(mi)
} else if op == OP_RET {
self.encode_ret(mi)
} else if op == OP_BR {
self.encode_br(mi)
} else if op == OP_BLR {
self.encode_blr(mi)
} else if op == OP_B_COND {
self.encode_b_cond(mi)
} else if op == OP_TBNZ || op == OP_TBZ {
self.encode_tbz_tbnz(mi)
}
else if op == OP_NOP {
self.encode_nop()
} else if op == OP_SVC {
self.encode_svc(mi)
} else if op == OP_HVC {
self.encode_hvc(mi)
} else if op == OP_SMC {
self.encode_smc(mi)
} else if op == OP_BRK {
self.encode_brk(mi)
} else if op == OP_MSR {
self.encode_msr(mi)
} else if op == OP_MRS {
self.encode_mrs(mi)
} else if op == OP_SYS {
self.encode_sys(mi)
} else if op == OP_SYSL {
self.encode_sysl(mi)
} else if op == OP_DMB {
self.encode_dmb(mi)
} else if op == OP_DSB {
self.encode_dsb(mi)
} else if op == OP_ISB {
self.encode_isb(mi)
} else if op == OP_CLREX {
self.encode_clrex(mi)
}
else if op == OP_ADR {
self.encode_adr(mi)
} else if op == OP_ADRP {
self.encode_adrp(mi)
}
else if op == OP_CMP {
self.encode_cmp(mi)
} else if op == OP_CCMN || op == OP_CCMP {
self.encode_ccmp_ccmn(mi)
} else if op == OP_CSEL {
self.encode_csel(mi)
} else if op == OP_RBIT {
self.encode_rbit(mi)
} else if op == OP_REV || op == OP_REV16 || op == OP_REV32 {
self.encode_rev(mi)
} else if op == OP_CLZ || op == OP_CLS {
self.encode_clz(mi)
} else if op == OP_BFM || op == OP_SBFM || op == OP_UBFM {
self.encode_bfm(mi)
} else if op == OP_UBFIZ || op == OP_SBFIZ {
self.encode_ubfiz(mi)
} else if op == OP_UBFX {
self.encode_ubfx(mi)
} else if op == OP_SBFX {
self.encode_sbfx(mi)
} else if op == OP_EXTR {
self.encode_extr(mi)
} else if op == OP_SDIV || op == OP_UDIV {
self.encode_sdiv_udiv(mi)
} else if op == OP_MADD || op == OP_MSUB {
self.encode_madd_msub(mi)
} else if op == OP_LSLV {
self.encode_lslv(mi)
} else if op == OP_LSRV {
self.encode_lsrv(mi)
} else if op == OP_ASRV {
self.encode_asrv(mi)
} else if op == OP_RORV {
self.encode_rorv(mi)
}
else if op == OP_AND || op == OP_ORR || op == OP_EOR {
self.encode_aarch64_logical(mi)
} else if op == OP_BIC || op == OP_BICS {
self.encode_bic(mi)
} else if op == OP_ORN {
self.encode_aarch64_logical(mi) } else if op == OP_EON {
self.encode_aarch64_logical(mi)
} else if op == OP_TST || op == OP_ANDS_IMPLICIT {
self.encode_aarch64_logical(mi)
}
else if op >= OP_CRC32B && op <= OP_CRC32CX {
self.encode_crc32(mi)
}
else if op == OP_FADD {
self.encode_fadd(mi)
} else if op == OP_FSUB {
self.encode_fsub(mi)
} else if op == OP_FMUL {
self.encode_fmul(mi)
} else if op == OP_FDIV {
self.encode_fdiv(mi)
} else if op == OP_FNEG {
self.encode_fneg(mi)
} else if op == OP_FABS {
self.encode_fabs(mi)
} else if op == OP_FSQRT {
self.encode_fsqrt(mi)
} else if op == OP_FCVT {
self.encode_fcvt(mi)
} else if op == OP_FMOV {
self.encode_fmov(mi)
} else if op == OP_FCMP {
self.encode_fcmp(mi)
} else if op == OP_FCMPE {
self.encode_fcmpe(mi)
} else if op == OP_FCSEL {
self.encode_fcsel(mi)
} else if op == OP_FMADD || op == OP_FMSUB || op == OP_FNMADD || op == OP_FNMSUB {
self.encode_fmadd(mi)
} else if op == OP_FMIN || op == OP_FMAX {
self.encode_fminmax(mi)
} else if op >= OP_FRINTN && op <= OP_FRINTI {
self.encode_frint(mi)
} else if op == OP_FCVTZS || op == OP_FCVTZU || op == OP_SCVTF || op == OP_UCVTF {
self.encode_fcvt_int_fp(mi)
}
else if op == OP_ADD_V {
self.encode_add_v(mi)
} else if op == OP_SUB_V {
self.encode_sub_v(mi)
} else if op == OP_MUL_V {
self.encode_mul_v(mi)
} else if op == OP_MLA_V {
self.encode_mla_v(mi)
} else if op == OP_MLS_V {
self.encode_mls_v(mi)
} else if op == OP_AND_V {
self.encode_and_v(mi)
} else if op == OP_ORR_V {
self.encode_orr_v(mi)
} else if op == OP_EOR_V {
self.encode_eor_v(mi)
} else if op == OP_BIC_V {
self.encode_bic_v(mi)
} else if op == OP_BSL || op == OP_BIT || op == OP_BIF {
self.encode_bsl(mi)
} else if op == OP_SHL || op == OP_SSHL || op == OP_USHL {
self.encode_simd_shift(mi)
} else if op == OP_CMEQ
|| op == OP_CMGT
|| op == OP_CMGE
|| op == OP_CMHI
|| op == OP_CMHS
|| op == OP_CMTST
{
self.encode_simd_compare(mi)
} else if op == OP_FADD_V
|| op == OP_FSUB_V
|| op == OP_FMUL_V
|| op == OP_FDIV_V
|| op == OP_FCMLA
|| op == OP_FCADD
{
self.encode_simd_fp_three_same(mi)
} else if op >= OP_ADDV && op <= OP_FADDP {
self.encode_simd_across(mi)
} else if op == OP_DUP {
self.encode_dup(mi)
} else if op == OP_MOVI || op == OP_MVNI {
self.encode_movi(mi)
} else if op == OP_EXT {
self.encode_ext(mi)
} else if op >= OP_ZIP1 && op <= OP_TRN2 {
self.encode_simd_permute(mi)
} else if op >= OP_REV64 && op <= OP_REV16_V {
self.encode_simd_permute(mi)
} else if op >= OP_SADDLP && op <= OP_UADDLP {
self.encode_simd_across(mi)
} else if op >= OP_XTN && op <= OP_FCVTL {
self.encode_simd_narrow(mi)
} else if op >= OP_LD1 && op <= OP_LD4 {
self.encode_simd_ldst_single(mi)
} else if op >= OP_ST1 && op <= OP_ST4 {
self.encode_simd_ldst_single(mi)
} else if op == OP_LDR_QIMM {
self.encode_simd_ldr_str_imm(mi, false)
} else if op == OP_STR_QIMM {
self.encode_simd_ldr_str_imm(mi, true)
} else {
0xD503201F
}
}
fn encode_add_sub(&self, mi: &MachineInstr) -> u32 {
let op = mi.opcode;
let is_sub = op == OP_SUB || op == OP_SUBS;
let set_flags = op == OP_ADDS || op == OP_SUBS;
let sf: u32 = 1;
if mi.operands.len() >= 3 {
if let MachineOperand::Imm(imm_val) = mi.operands[2] {
return self.encode_add_sub_imm(mi, is_sub, set_flags, sf, imm_val);
}
}
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
self.encode_add_sub_reg(is_sub, set_flags, sf, rd, rn, rm, 0, 0) }
fn encode_add_sub_imm(
&self,
mi: &MachineInstr,
is_sub: bool,
set_flags: bool,
sf: u32,
imm: i64,
) -> u32 {
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm_u = imm as u64;
let (imm12, shift) = if imm_u <= 0xFFF {
(imm_u as u32 & 0xFFF, 0u32)
} else if imm_u & 0xFFF == 0 && (imm_u >> 12) <= 0xFFF {
((imm_u >> 12) as u32 & 0xFFF, 1u32)
} else {
(imm_u as u32 & 0xFFF, 0u32)
};
let mut word: u32 = 0;
word |= sf << 31;
word |= (is_sub as u32) << 30;
word |= (set_flags as u32) << 29;
word |= 0b10001 << 24;
word |= shift << 22;
word |= (imm12 & 0xFFF) << 10;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
fn encode_add_sub_reg(
&self,
is_sub: bool,
set_flags: bool,
sf: u32,
rd: u8,
rn: u8,
rm: u8,
shift: u32,
amount: u32,
) -> u32 {
let mut word: u32 = 0;
word |= sf << 31;
word |= (is_sub as u32) << 30;
word |= (set_flags as u32) << 29;
word |= 0b01011 << 24;
word |= (shift & 0x3) << 22;
word |= (rm as u32) << 16;
word |= (amount & 0x3F) << 10;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
fn encode_movz(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let imm = self.get_imm_from_operand(mi.operands.get(1));
let hw = self.get_hw_from_operand(mi.operands.get(2));
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b10 << 29;
word |= 0b100101 << 23;
word |= (hw & 0x3) << 21;
word |= (imm as u32 & 0xFFFF) << 5;
word |= rd as u32;
word
}
fn encode_movk(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let imm = self.get_imm_from_operand(mi.operands.get(1));
let hw = self.get_hw_from_operand(mi.operands.get(2));
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b11 << 29;
word |= 0b100101 << 23;
word |= (hw & 0x3) << 21;
word |= (imm as u32 & 0xFFFF) << 5;
word |= rd as u32;
word
}
fn encode_movn(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let imm = self.get_imm_from_operand(mi.operands.get(1));
let hw = self.get_hw_from_operand(mi.operands.get(2));
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b00 << 29;
word |= 0b100101 << 23;
word |= (hw & 0x3) << 21;
word |= (imm as u32 & 0xFFFF) << 5;
word |= rd as u32;
word
}
fn encode_mov(&self, mi: &MachineInstr) -> u32 {
if mi.operands.len() < 2 {
return self.encode_nop();
}
match &mi.operands[1] {
MachineOperand::Reg(_) | MachineOperand::PhysReg(_) => self.encode_mov_reg(mi),
MachineOperand::Imm(_) => self.encode_mov_imm(mi),
_ => self.encode_nop(),
}
}
fn encode_mov_reg(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rm = self.get_reg_field_from_operand(mi.operands.get(1));
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b01 << 29;
word |= 0b01010 << 24;
word |= 31u32 << 5;
word |= (rm as u32) << 16;
word |= rd as u32;
word
}
fn encode_mov_imm(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let imm_val = self.get_imm_from_operand(mi.operands.get(1)) as u64;
if let Some((immr, imms, n)) = encode_bitmask_imm(imm_val, 64) {
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b01 << 29;
word |= 0b100100 << 23;
word |= n << 22;
word |= (immr & 0x3F) << 16;
word |= (imms & 0x3F) << 10;
word |= 31u32 << 5; word |= rd as u32;
word
} else {
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b10 << 29; word |= 0b100101 << 23;
word |= (imm_val as u32 & 0xFFFF) << 5;
word |= rd as u32;
word
}
}
fn encode_ldr_str(&self, mi: &MachineInstr) -> u32 {
let is_store = mi.opcode == OP_STR;
let size: u32 = 0b11;
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2));
let scaled_imm = (imm as u64 / 8) as u32;
let mut word: u32 = 0;
word |= size << 30; if is_store {
word |= 0b11100100 << 22;
} else {
word |= 0b11100101 << 22;
}
word |= (scaled_imm & 0x1FF) << 12; word |= 0b01 << 10;
word |= (rn as u32) << 5;
word |= rt as u32;
word
}
fn encode_ldp_stp(&self, mi: &MachineInstr) -> u32 {
let is_store = mi.opcode == OP_STP;
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rt2 = self.get_reg_field_from_operand(mi.operands.get(1));
let rn = self.get_reg_field_from_operand(mi.operands.get(2));
let imm = self.get_imm_from_operand(mi.operands.get(3));
let scaled_imm = (imm / 8) as i32;
let mut word: u32 = 0;
if is_store {
word |= 0b11 << 30; } else {
word |= 0b10 << 30; }
word |= 0b10100101 << 22; word |= ((scaled_imm as u32) & 0x7F) << 15; word |= (rt2 as u32) << 10; word |= (rn as u32) << 5;
word |= rt as u32;
word
}
fn encode_b_bl(&self, mi: &MachineInstr) -> u32 {
let is_call = mi.opcode == OP_BL;
let offset = self.get_branch_offset(mi);
let imm26 = (offset as u32) & 0x3FFFFFF;
let mut word: u32 = 0;
if is_call {
word |= 0b100101 << 26;
} else {
word |= 0b000101 << 26;
}
word |= imm26;
word
}
fn encode_b_cond(&self, mi: &MachineInstr) -> u32 {
let cond = self.get_cond_from_operand(mi.operands.first());
let offset = self.get_branch_offset_19bit(mi);
let mut word: u32 = 0;
word |= 0b01010100 << 24;
word |= (offset & 0x7FFFF) << 5;
word |= cond as u32;
word
}
fn encode_cbz_cbnz(&self, mi: &MachineInstr) -> u32 {
let is_nonzero = mi.opcode == OP_CBNZ;
let rt = self.get_reg_field_from_operand(mi.operands.first());
let offset = self.get_branch_offset_19bit(mi);
let mut word: u32 = 0;
if is_nonzero {
word |= 0xB5 << 24; } else {
word |= 0xB4 << 24; }
word |= (offset & 0x7FFFF) << 5;
word |= rt as u32;
word
}
fn encode_ret(&self, mi: &MachineInstr) -> u32 {
let rn = if let Some(op) = mi.operands.first() {
self.get_reg_field_from_operand(Some(op))
} else {
30 };
let mut word: u32 = 0xD65F0000;
word |= (rn as u32) << 5;
word
}
fn encode_br(&self, mi: &MachineInstr) -> u32 {
let rn = self.get_reg_field_from_operand(mi.operands.first());
0xD61F0000 | ((rn as u32) << 5)
}
fn encode_blr(&self, mi: &MachineInstr) -> u32 {
let rn = self.get_reg_field_from_operand(mi.operands.first());
0xD63F0000 | ((rn as u32) << 5)
}
fn encode_nop(&self) -> u32 {
0xD503201F
}
fn encode_cmp(&self, mi: &MachineInstr) -> u32 {
let rn = self.get_reg_field_from_operand(mi.operands.first());
let op2 = mi.operands.get(1);
match op2 {
Some(MachineOperand::Imm(imm)) => {
let rd: u8 = 31; let imm_u = *imm as u64;
let (imm12, shift) = if imm_u <= 0xFFF {
(imm_u as u32 & 0xFFF, 0u32)
} else if imm_u & 0xFFF == 0 && (imm_u >> 12) <= 0xFFF {
((imm_u >> 12) as u32 & 0xFFF, 1u32)
} else {
(imm_u as u32 & 0xFFF, 0u32)
};
let mut word: u32 = 0;
word |= 1 << 31; word |= 1 << 30; word |= 1 << 29; word |= 0b10001 << 24;
word |= shift << 22;
word |= (imm12 & 0xFFF) << 10;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
_ => {
let rm = self.get_reg_field_from_operand(op2);
self.encode_add_sub_reg(true, true, 1, 31, rn, rm, 0, 0)
}
}
}
fn encode_csel(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
let cond = self.get_cond_from_operand(mi.operands.get(3));
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b11010100 << 21;
word |= (rm as u32) << 16;
word |= (cond as u32) << 12;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
fn encode_bfm(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let op = mi.opcode;
let opc: u32 = if op == OP_BFM {
0b01
} else if op == OP_SBFM {
0b00
} else {
0b10 };
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let immr = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let imms = self.get_imm_from_operand(mi.operands.get(3)) as u32;
let n: u32 = if sf == 1 && imms >= 32 { 1 } else { 0 };
let mut word: u32 = 0;
word |= sf << 31;
word |= opc << 29;
word |= 0b100110 << 23;
word |= n << 22;
word |= (immr & 0x3F) << 16;
word |= (imms & 0x3F) << 10;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
fn encode_sdiv_udiv(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let is_udiv = mi.opcode == OP_UDIV;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
let opcode: u32 = if is_udiv { 0b000010 } else { 0b000011 };
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b11010110 << 21;
word |= (rm as u32) << 16;
word |= opcode << 10;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
fn encode_madd_msub(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let is_msub = mi.opcode == OP_MSUB;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
let ra = self.get_reg_field_from_operand(mi.operands.get(3));
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b11011 << 24;
word |= (rm as u32) << 16;
word |= (is_msub as u32) << 15;
word |= (ra as u32) << 10;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
fn encode_svc(&self, mi: &MachineInstr) -> u32 {
let imm16 = self.get_imm_from_operand(mi.operands.first()) as u32 & 0xFFFF;
0xD4000001u32 | (imm16 << 5)
}
fn encode_hvc(&self, mi: &MachineInstr) -> u32 {
let imm16 = self.get_imm_from_operand(mi.operands.first()) as u32 & 0xFFFF;
0xD4000002u32 | (imm16 << 5)
}
fn encode_smc(&self, mi: &MachineInstr) -> u32 {
let imm16 = self.get_imm_from_operand(mi.operands.first()) as u32 & 0xFFFF;
0xD4000003u32 | (imm16 << 5)
}
fn encode_brk(&self, mi: &MachineInstr) -> u32 {
let imm16 = self.get_imm_from_operand(mi.operands.first()) as u32 & 0xFFFF;
0xD4200000u32 | (imm16 << 5)
}
fn encode_msr(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let sr = self.get_imm_from_operand(mi.operands.get(1)) as u32;
let op0 = (sr >> 14) & 0x3;
let op1 = (sr >> 11) & 0x7;
let crn = (sr >> 7) & 0xF;
let crm = (sr >> 3) & 0xF;
let op2 = sr & 0x7;
let mut word: u32 = 0xD5100000u32;
word |= op0 << 19;
word |= op1 << 16;
word |= crn << 12;
word |= crm << 8;
word |= op2 << 5;
word |= rt as u32;
word
}
fn encode_msr_imm(&self, mi: &MachineInstr) -> u32 {
let field = self.get_imm_from_operand(mi.operands.first()) as u32;
let imm = self.get_imm_from_operand(mi.operands.get(1)) as u32;
let op1 = (field >> 3) & 0x7;
let op2 = field & 0x7;
let mut word: u32 = 0xD500401Fu32;
word |= op1 << 16;
word |= (imm & 0xF) << 8;
word |= op2 << 5;
word
}
fn encode_mrs(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let sr = self.get_imm_from_operand(mi.operands.get(1)) as u32;
let op0 = (sr >> 14) & 0x3;
let op1 = (sr >> 11) & 0x7;
let crn = (sr >> 7) & 0xF;
let crm = (sr >> 3) & 0xF;
let op2 = sr & 0x7;
let mut word: u32 = 0xD5300000u32;
word |= op0 << 19;
word |= op1 << 16;
word |= crn << 12;
word |= crm << 8;
word |= op2 << 5;
word |= rt as u32;
word
}
fn encode_sys(&self, mi: &MachineInstr) -> u32 {
let imm = self.get_imm_from_operand(mi.operands.first()) as u32;
let op1 = (imm >> 14) & 0x7;
let crn = (imm >> 10) & 0xF;
let crm = (imm >> 6) & 0xF;
let op2 = (imm >> 3) & 0x7;
let rt = self.get_reg_field_from_operand(mi.operands.get(1));
let mut word: u32 = 0xD5080000u32;
word |= op1 << 16;
word |= crn << 12;
word |= crm << 8;
word |= op2 << 5;
word |= rt as u32;
word
}
fn encode_sysl(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let imm = self.get_imm_from_operand(mi.operands.get(1)) as u32;
let op1 = (imm >> 14) & 0x7;
let crn = (imm >> 10) & 0xF;
let crm = (imm >> 6) & 0xF;
let op2 = (imm >> 3) & 0x7;
let mut word: u32 = 0xD5280000u32;
word |= op1 << 16;
word |= crn << 12;
word |= crm << 8;
word |= op2 << 5;
word |= rt as u32;
word
}
fn encode_adr(&self, mi: &MachineInstr) -> u32 {
let rd = self.get_reg_field_from_operand(mi.operands.first());
let offset = self.get_branch_offset(mi) as i64;
let imm = (offset & 0x1FFFFF) as u32;
let immlo = imm & 0x3;
let immhi = (imm >> 2) & 0x7FFFF;
(immlo << 29) | (0b10000 << 24) | (immhi << 5) | (rd as u32)
}
fn encode_adrp(&self, mi: &MachineInstr) -> u32 {
let rd = self.get_reg_field_from_operand(mi.operands.first());
let offset = self.get_branch_offset(mi) as i64;
let imm = (offset & 0x1FFFFF) as u32;
let immlo = imm & 0x3;
let immhi = (imm >> 2) & 0x7FFFF;
(1u32 << 31) | (immlo << 29) | (0b10000 << 24) | (immhi << 5) | (rd as u32)
}
fn encode_tbz_tbnz(&self, mi: &MachineInstr) -> u32 {
let is_tbnz = mi.opcode == OP_TBNZ;
let sf: u32 = 1;
let rt = self.get_reg_field_from_operand(mi.operands.first());
let bit = self.get_imm_from_operand(mi.operands.get(1)) as u32;
let imm14 = self.get_branch_offset(mi) & 0x3FFF;
let b5 = (bit >> 5) & 1;
let b40 = (bit & 0x1F) | ((rt as u32) << 5);
let mut word: u32 = 0;
word |= sf << 31;
word |= 0b011011 << 25;
word |= b5 << 24;
word |= imm14 << 5;
word |= b40 & 0x1F;
word
}
fn encode_ldrb_imm(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 0; let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
(sf << 31) | (0b0011100001 << 22) | (imm << 10) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_strb_imm(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
(0b0011100000 << 22) | (imm << 10) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_ldrh_imm(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 0;
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
(sf << 31) | (0b0111100001 << 22) | (imm << 10) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_strh_imm(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
(0b0111100000 << 22) | (imm << 10) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_ldrsb_imm(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let opc: u32 = if sf == 1 { 0b11 } else { 0b10 };
(sf << 31) | (opc << 22) | (imm << 10) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_ldrsh_imm(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let opc: u32 = if sf == 1 { 0b11 } else { 0b10 };
(sf << 31)
| (0b0100000000u32 << 22)
| (opc << 22)
| (imm << 10)
| ((rn as u32) << 5)
| (rt as u32)
}
fn encode_ldrsw_imm(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
(1u32 << 31) | (0b1011100010u32 << 22) | (imm << 10) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_ldur(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let simm9 = (self.get_imm_from_operand(mi.operands.get(2)) as i32) & 0x1FF;
let size: u32 = if sf == 1 { 0b11 } else { 0b10 };
(sf << 31)
| (size << 30)
| (0b11100010u32 << 22)
| ((simm9 as u32) << 12)
| ((rn as u32) << 5)
| (rt as u32)
}
fn encode_stur(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let simm9 = (self.get_imm_from_operand(mi.operands.get(2)) as i32) & 0x1FF;
let size: u32 = if sf == 1 { 0b11 } else { 0b10 };
(sf << 31)
| (size << 30)
| (0b11100000u32 << 22)
| ((simm9 as u32) << 12)
| ((rn as u32) << 5)
| (rt as u32)
}
fn encode_ldurb(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let simm9 = (self.get_imm_from_operand(mi.operands.get(2)) as i32) & 0x1FF;
(0b0011100010u32 << 22) | ((simm9 as u32) << 12) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_ldurh(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let simm9 = (self.get_imm_from_operand(mi.operands.get(2)) as i32) & 0x1FF;
(0b0111100010u32 << 22) | ((simm9 as u32) << 12) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_sturb(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let simm9 = (self.get_imm_from_operand(mi.operands.get(2)) as i32) & 0x1FF;
(0b0011100000u32 << 22) | ((simm9 as u32) << 12) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_sturh(&self, mi: &MachineInstr) -> u32 {
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let simm9 = (self.get_imm_from_operand(mi.operands.get(2)) as i32) & 0x1FF;
(0b0111100000u32 << 22) | ((simm9 as u32) << 12) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_ldxr(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
(sf << 31) | (1u32 << 30) | (0b011111111111u32 << 10) | ((rn as u32) << 5) | (rt as u32)
}
fn encode_ldaxr(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
(sf << 31)
| (1u32 << 30)
| (1u32 << 11)
| (0b011111111111u32 << 10)
| ((rn as u32) << 5)
| (rt as u32)
}
fn encode_stxr(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let ws = self.get_reg_field_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.get(1));
let rn = self.get_reg_field_from_operand(mi.operands.get(2));
(sf << 31)
| (0b00000000111111111u32 << 10)
| ((ws as u32) << 16)
| ((rn as u32) << 5)
| (rt as u32)
}
fn encode_stlxr(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let ws = self.get_reg_field_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.get(1));
let rn = self.get_reg_field_from_operand(mi.operands.get(2));
(sf << 31)
| (1u32 << 11)
| (0b00000000111111111u32 << 10)
| ((ws as u32) << 16)
| ((rn as u32) << 5)
| (rt as u32)
}
fn encode_dmb(&self, mi: &MachineInstr) -> u32 {
let option = self.get_imm_from_operand(mi.operands.first()) as u32 & 0xF;
0xD50330BFu32 | (option << 8)
}
fn encode_dsb(&self, mi: &MachineInstr) -> u32 {
let option = self.get_imm_from_operand(mi.operands.first()) as u32 & 0xF;
0xD503309Fu32 | (option << 8)
}
fn encode_isb(&self, mi: &MachineInstr) -> u32 {
let option = self.get_imm_from_operand(mi.operands.first()) as u32 & 0xF;
0xD50330DFu32 | (option << 8)
}
fn encode_clrex(&self, _mi: &MachineInstr) -> u32 {
0xD503305Fu32
}
fn encode_ccmp_ccmn(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let is_ccmp = mi.opcode == OP_CCMP;
let rn = self.get_reg_field_from_operand(mi.operands.first());
let imm5 = self.get_imm_from_operand(mi.operands.get(1)) as u32 & 0x1F;
let nzcv = self.get_imm_from_operand(mi.operands.get(2)) as u32 & 0xF;
let cond = self.get_cond_from_operand(mi.operands.get(3));
let mut word: u32 = 0;
word |= sf << 31;
word |= (is_ccmp as u32) << 30;
word |= 1u32 << 29;
word |= 0b11010010u32 << 21;
word |= imm5 << 16;
word |= cond << 12;
word |= (rn as u32) << 5;
word |= nzcv;
word
}
fn encode_rbit(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
(sf << 31)
| (1u32 << 30)
| (0b11010110000000u32 << 10)
| (0b000000u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_rev(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let opcode: u32 = if sf == 1 { 0b000011 } else { 0b000010 };
(sf << 31)
| (1u32 << 30)
| (0b11010110000000u32 << 10)
| (opcode << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_clz(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let opcode: u32 = if sf == 1 { 0b000100 } else { 0b000100 };
(sf << 31)
| (1u32 << 30)
| (0b11010110000000u32 << 10)
| (opcode << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_mvn(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rm = self.get_reg_field_from_operand(mi.operands.get(1));
(sf << 31)
| (0b01u32 << 29)
| (0b01010u32 << 24)
| ((rm as u32) << 16)
| (31u32 << 5)
| (rd as u32)
}
fn encode_neg(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rm = self.get_reg_field_from_operand(mi.operands.get(1));
(sf << 31)
| (1u32 << 30)
| (0b01011u32 << 24)
| ((rm as u32) << 16)
| (31u32 << 5)
| (rd as u32)
}
fn encode_bic(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
(sf << 31)
| (0b01010u32 << 24)
| (1u32 << 21)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_ubfiz(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let lsb = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let width = self.get_imm_from_operand(mi.operands.get(3)) as u32;
let immr = ((-(lsb as i32)) as u32) & 0x3F;
let imms = (width - 1) & 0x3F;
(sf << 31)
| (0b10u32 << 29)
| (0b100110u32 << 23)
| (immr << 16)
| (imms << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_ubfx(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let lsb = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let width = self.get_imm_from_operand(mi.operands.get(3)) as u32;
let immr = lsb & 0x3F;
let imms = (lsb + width - 1) & 0x3F;
(sf << 31)
| (0b10u32 << 29)
| (0b100110u32 << 23)
| (immr << 16)
| (imms << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_sbfx(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let lsb = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let width = self.get_imm_from_operand(mi.operands.get(3)) as u32;
let immr = lsb & 0x3F;
let imms = (lsb + width - 1) & 0x3F;
(sf << 31)
| (0b00u32 << 29)
| (0b100110u32 << 23)
| (immr << 16)
| (imms << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_extr(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
let lsb = self.get_imm_from_operand(mi.operands.get(3)) as u32;
(sf << 31)
| (1u32 << 30)
| (0b00100111u32 << 22)
| (0u32 << 21)
| ((rm as u32) << 16)
| (lsb << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_lslv(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
(sf << 31)
| (0b11010110u32 << 21)
| (0b001000u32 << 16)
| ((rm as u32) << 16)
| (0b001000u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_lsrv(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
(sf << 31)
| (0b11010110u32 << 21)
| ((rm as u32) << 16)
| (0b001001u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_asrv(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
(sf << 31)
| (0b11010110u32 << 21)
| ((rm as u32) << 16)
| (0b001010u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_rorv(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
(sf << 31)
| (0b11010110u32 << 21)
| ((rm as u32) << 16)
| (0b001011u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_crc32(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
let sz: u32 = match mi.opcode {
OP_CRC32B => 0b00,
OP_CRC32H => 0b01,
OP_CRC32W => 0b10,
OP_CRC32X => 0b11,
OP_CRC32CB => 0b00,
OP_CRC32CH => 0b01,
OP_CRC32CW => 0b10,
OP_CRC32CX => 0b11,
_ => 0b11,
};
let c: u32 = if mi.opcode >= OP_CRC32CB { 1 } else { 0 };
(sf << 31)
| (0b11011010110u32 << 21)
| (c << 20)
| (sz << 12)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn get_simd_size(&self, op: Option<&MachineOperand>) -> u32 {
match op {
Some(MachineOperand::PhysReg(pr)) => {
if *pr >= 2340 && *pr < 2360 {
0b10
}
else if *pr >= 2360 && *pr < 2380 {
0b11
}
else if *pr >= 2320 && *pr < 2340 {
0b01
}
else {
0b00
} }
_ => 0b11, }
}
fn get_simd_reg_field(&self, op: Option<&MachineOperand>) -> u8 {
match op {
Some(MachineOperand::PhysReg(pr)) => {
if *pr >= 2300 && *pr < 2400 {
((*pr - 2300) % 32) as u8
} else {
0
}
}
Some(MachineOperand::Reg(vr)) => (*vr % 32) as u8,
_ => 0,
}
}
fn encode_fadd(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
(sz << 22)
| (0b00011110u32 << 24)
| (0b001010u32 << 10)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fsub(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
(sz << 22)
| (0b00011110u32 << 24)
| (0b001110u32 << 10)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fmul(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
(sz << 22)
| (0b00011110u32 << 24)
| (0b000010u32 << 10)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fdiv(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
(sz << 22)
| (0b00011110u32 << 24)
| (0b000110u32 << 10)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fneg(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
(sz << 22)
| (0b00011110u32 << 24)
| (0b100001010000u32 << 12)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fabs(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
(sz << 22)
| (0b00011110u32 << 24)
| (0b100001100000u32 << 12)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fsqrt(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
(sz << 22)
| (0b00011110u32 << 24)
| (0b100001110000u32 << 12)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fcvt(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let ftype: u32 = if sz == 1 { 0b01 } else { 0b10 };
(0b00011110u32 << 24)
| (ftype << 22)
| (1u32 << 21)
| (0b00010010000u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fmov(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
(sz << 22)
| (0b00011110u32 << 24)
| (0b00000010000u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fcmp(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.first());
let rm = self.get_simd_reg_field(mi.operands.get(1));
(sz << 22)
| (0b00011110u32 << 24)
| (0b001000u32 << 10)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
}
fn encode_fcmpe(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.first());
let rm = self.get_simd_reg_field(mi.operands.get(1));
(sz << 22)
| (0b00011110u32 << 24)
| (0b001001u32 << 10)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
}
fn encode_fmov_tofrom_gen(&self, mi: &MachineInstr, to_simd: bool) -> u32 {
let sf: u32 = self.get_sf_from_operand(mi.operands.first());
let rt = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
if to_simd {
(sf << 31)
| (0b00011110111u32 << 21)
| (0b100111000000u32 << 10)
| ((rt as u32) << 5)
| (rn as u32)
} else {
(sf << 31)
| (0b00011110110u32 << 21)
| (0b100111000000u32 << 10)
| ((rn as u32) << 5)
| (rt as u32)
}
}
fn encode_fcsel(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
let cond = self.get_cond_from_operand(mi.operands.get(3));
(sz << 22)
| (0b00011110u32 << 24)
| (cond << 12)
| (0b11u32 << 10)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fmadd(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
let ra = self.get_simd_reg_field(mi.operands.get(3));
let op: u32 = match mi.opcode {
OP_FMADD => 0b0,
OP_FMSUB => 0b1,
OP_FNMADD => 0b0,
OP_FNMSUB => 0b1,
_ => 0b0,
};
let neg: u32 = if mi.opcode == OP_FNMADD || mi.opcode == OP_FNMSUB {
0b10
} else {
0b00
};
(sz << 22)
| (neg << 21)
| (op << 15)
| (0b11111u32 << 24)
| ((rm as u32) << 16)
| ((ra as u32) << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fminmax(&self, mi: &MachineInstr) -> u32 {
let is_max = mi.opcode == OP_FMAX;
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
(sz << 22)
| (0b00011110u32 << 24)
| ((is_max as u32) << 14)
| (0b0110u32 << 12)
| ((rm as u32) << 16)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_frint(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let opcode: u32 = match mi.opcode {
OP_FRINTN => 0b1000,
OP_FRINTP => 0b1001,
OP_FRINTM => 0b1010,
OP_FRINTZ => 0b1011,
OP_FRINTA => 0b1100,
OP_FRINTX => 0b1110,
OP_FRINTI => 0b1111,
_ => 0b1000,
};
(sz << 22)
| (0b00011110u32 << 24)
| (1u32 << 21)
| (opcode << 17)
| (0b10000u32 << 12)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_fcvt_int_fp(&self, mi: &MachineInstr) -> u32 {
let sz = self.get_simd_size(mi.operands.first());
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let (sf, ftype, opcode): (u32, u32, u32) = match mi.opcode {
OP_FCVTZS => (1, 0b11, 0b00),
OP_FCVTZU => (1, 0b11, 0b01),
OP_SCVTF => (1, 0b00, 0b10),
OP_UCVTF => (1, 0b00, 0b11),
_ => (1, 0b11, 0b00),
};
(sf << 31)
| (ftype << 22)
| (0b00011110u32 << 24)
| (1u32 << 21)
| (opcode << 16)
| (0b0000000000u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_simd_arrangement(&self, mi: &MachineInstr) -> (u32, u32) {
let op = mi.operands.first();
let q: u32 = match op {
Some(MachineOperand::PhysReg(pr)) => {
if *pr >= 2380 && *pr < 2400 {
1
} else {
0
}
}
_ => 0,
};
let size = self.get_simd_size(op);
(q, size)
}
fn encode_simd_three_same(&self, mi: &MachineInstr, u: u32, opcode: u32) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
(q << 30)
| (u << 29)
| (size << 22)
| (0b01110u32 << 24)
| ((rm as u32) << 16)
| (opcode << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_add_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 0, 0b100001)
}
fn encode_sub_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 1, 0b100001)
}
fn encode_mul_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 0, 0b100111)
}
fn encode_mla_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 0, 0b100101)
}
fn encode_mls_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 1, 0b100101)
}
fn encode_and_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 0, 0b000111)
}
fn encode_orr_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 0, 0b000111) | (1u32 << 22) }
fn encode_eor_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 1, 0b000111)
}
fn encode_bic_v(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 0, 0b000111) | (1u32 << 22)
}
fn encode_bsl(&self, mi: &MachineInstr) -> u32 {
self.encode_simd_three_same(mi, 1, 0b000111) | (1u32 << 22)
}
fn encode_simd_shift(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let shift = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let u: u32 = match mi.opcode {
OP_SHL => 0,
OP_SSHL => 0,
OP_USHL => 1,
_ => 0,
};
(q << 30)
| (u << 29)
| (size << 22)
| (0b01110u32 << 24)
| (shift << 16)
| (0b010101u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_simd_compare(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
let (u, opcode): (u32, u32) = match mi.opcode {
OP_CMEQ => (1, 0b100011),
OP_CMGT => (0, 0b001101),
OP_CMGE => (0, 0b001111),
OP_CMHI => (1, 0b001101),
OP_CMHS => (1, 0b001111),
OP_CMTST => (0, 0b100011),
_ => (0, 0b100011),
};
(q << 30)
| (u << 29)
| (size << 22)
| (0b01110u32 << 24)
| ((rm as u32) << 16)
| (opcode << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_simd_fp_three_same(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
let (u, opcode): (u32, u32) = match mi.opcode {
OP_FADD_V => (0, 0b110101),
OP_FSUB_V => (0, 0b110101),
OP_FMUL_V => (1, 0b110111),
OP_FDIV_V => (1, 0b111111),
_ => (0, 0b110101),
};
(q << 30)
| (u << 29)
| (size << 22)
| (0b01110u32 << 24)
| ((rm as u32) << 16)
| (opcode << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_simd_across(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let (u, opcode): (u32, u32) = match mi.opcode {
OP_ADDV => (0, 0b110111011),
OP_SADDLV => (0, 0b000111011),
OP_UADDLV => (1, 0b000111011),
OP_SMAXV => (0, 0b001101011),
OP_UMAXV => (1, 0b001101011),
OP_SMINV => (0, 0b001101011), OP_UMINV => (1, 0b001101011),
OP_FMAXV => (0, 0b011111111),
OP_FMINV => (0, 0b011111111),
_ => (0, 0b110111011),
};
(q << 30)
| (u << 29)
| (size << 22)
| (0b01110u32 << 24)
| (opcode << 12)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_dup(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
(q << 30)
| (0b0111000000u32 << 22)
| (size << 22)
| (0b000011u32 << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_movi(&self, mi: &MachineInstr) -> u32 {
let (q, _size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let imm = self.get_imm_from_operand(mi.operands.get(1)) as u32;
let op: u32 = if mi.opcode == OP_MVNI { 1 } else { 0 };
(q << 30)
| (op << 29)
| (0b0111100000u32 << 22)
| (0b111001u32 << 12)
| (imm & 0xFF) << 5
| (rd as u32)
}
fn encode_ext(&self, mi: &MachineInstr) -> u32 {
let (q, _size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
let index = self.get_imm_from_operand(mi.operands.get(3)) as u32;
(q << 30)
| (0b101110000u32 << 22)
| ((rm as u32) << 16)
| (index << 11)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_simd_permute(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let rm = self.get_simd_reg_field(mi.operands.get(2));
let opcode: u32 = match mi.opcode {
OP_ZIP1 => 0b001110,
OP_ZIP2 => 0b001111,
OP_UZP1 => 0b000110,
OP_UZP2 => 0b000111,
OP_TRN1 => 0b001010,
OP_TRN2 => 0b001011,
_ => 0b001110,
};
(q << 30)
| (size << 22)
| (0b01110u32 << 24)
| ((rm as u32) << 16)
| (opcode << 10)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_simd_narrow(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rd = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let (u, opcode): (u32, u32) = match mi.opcode {
OP_XTN => (0, 0b100101),
OP_SQXTN => (0, 0b101001),
OP_UQXTN => (1, 0b101001),
OP_FCVTN => (0, 0b101101),
_ => (0, 0b100101),
};
(q << 30)
| (u << 29)
| (size << 22)
| (0b01110u32 << 24)
| (opcode << 12)
| ((rn as u32) << 5)
| (rd as u32)
}
fn encode_simd_ldst_single(&self, mi: &MachineInstr) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rt = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let is_store: bool = matches!(mi.opcode, OP_ST1 | OP_ST2 | OP_ST3 | OP_ST4);
let num_regs: u32 = match mi.opcode {
OP_LD1 | OP_ST1 => 0b0111,
OP_LD2 | OP_ST2 => 0b1010,
OP_LD3 | OP_ST3 => 0b0110,
OP_LD4 | OP_ST4 => 0b0010,
_ => 0b0111,
};
let l_flag: u32 = if is_store { 0 } else { 1 };
(q << 30)
| (l_flag << 22)
| (0b001100u32 << 24)
| (num_regs << 12)
| (size << 10)
| ((rn as u32) << 5)
| (rt as u32)
}
fn encode_simd_ldr_str_imm(&self, mi: &MachineInstr, is_store: bool) -> u32 {
let (q, size) = self.encode_simd_arrangement(mi);
let rt = self.get_simd_reg_field(mi.operands.first());
let rn = self.get_simd_reg_field(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let l: u32 = if is_store { 0 } else { 1 };
let opc: u32 = (q << 1) | l;
(size << 30)
| (0b1111u32 << 26)
| (opc << 22)
| (imm << 10)
| ((rn as u32) << 5)
| (rt as u32)
}
const _OP_NV: u32 = 0xF;
fn get_sf_from_operand(&self, op: Option<&MachineOperand>) -> u32 {
match op {
Some(MachineOperand::PhysReg(pr)) => {
if *pr >= 2000 && *pr <= 2033 {
1
} else if *pr >= 2040 && *pr <= 2072 {
0
} else {
1
} }
_ => 1,
}
}
fn encode_aarch64_logical(&self, mi: &MachineInstr) -> u32 {
let sf: u32 = 1;
let op = mi.opcode;
let opc: u32 = if op == OP_AND {
0b00
} else if op == OP_ORR {
0b01
} else if op == OP_EOR {
0b10
} else {
0b00
};
let rd = self.get_reg_field_from_operand(mi.operands.first());
let rn = self.get_reg_field_from_operand(mi.operands.get(1));
let rm = self.get_reg_field_from_operand(mi.operands.get(2));
let mut word: u32 = 0;
word |= sf << 31;
word |= opc << 29;
word |= 0b01010 << 24;
word |= (rm as u32) << 16;
word |= (rn as u32) << 5;
word |= rd as u32;
word
}
fn encode_arm32_instruction(&self, mi: &MachineInstr) -> u32 {
let op = mi.opcode;
if op == OP_ARM_ADD
|| op == OP_ARM_SUB
|| op == OP_ARM_MOV
|| op == OP_ARM_AND
|| op == OP_ARM_ORR
|| op == OP_ARM_EOR
|| op == OP_ARM_CMP
{
self.encode_arm32_data_proc(mi)
} else if op == OP_ARM_LDR || op == OP_ARM_STR {
self.encode_arm32_ldr_str(mi)
} else if op == OP_ARM_B || op == OP_ARM_BL {
self.encode_arm32_b_bl(mi)
} else if op == OP_ARM_PUSH || op == OP_ARM_POP {
self.encode_arm32_push_pop(mi)
} else {
0xE1A00000 }
}
fn encode_arm32_data_proc(&self, mi: &MachineInstr) -> u32 {
let op = mi.opcode;
let cond: u32 = 0xE; let set_flags = op == OP_ARM_CMP;
let opcode: u32 = match op {
OP_ARM_ADD => 0b0100,
OP_ARM_SUB => 0b0010,
OP_ARM_MOV => 0b1101,
OP_ARM_AND => 0b0000,
OP_ARM_ORR => 0b1100,
OP_ARM_EOR => 0b0001,
OP_ARM_CMP => 0b1010,
_ => 0b0000,
};
let rd = self.get_arm32_reg_field_from_operand(mi.operands.first());
let rn = if op == OP_ARM_MOV {
0 } else {
self.get_arm32_reg_field_from_operand(mi.operands.get(1))
};
let (i_flag, operand2) =
if mi.operands.len() >= 3 || (op == OP_ARM_MOV && mi.operands.len() >= 2) {
let src_idx = if op == OP_ARM_MOV { 1 } else { 2 };
match mi.operands.get(src_idx) {
Some(MachineOperand::Imm(imm)) => {
let imm8 = *imm as u32 & 0xFF;
(1u32, ((0u32) << 8) | imm8)
}
_ => {
let rm = self.get_arm32_reg_field_from_operand(mi.operands.get(src_idx));
(0u32, rm)
}
}
} else {
(0u32, 0u32)
};
let mut word: u32 = 0;
word |= cond << 28;
word |= i_flag << 25;
word |= opcode << 21;
word |= (set_flags as u32) << 20;
word |= rn << 16;
word |= rd << 12;
word |= operand2 & 0xFFF;
word
}
fn encode_arm32_ldr_str(&self, mi: &MachineInstr) -> u32 {
let is_load = mi.opcode == OP_ARM_LDR;
let cond: u32 = 0xE;
let rd = self.get_arm32_reg_field_from_operand(mi.operands.first());
let rn = self.get_arm32_reg_field_from_operand(mi.operands.get(1));
let imm = self.get_imm_from_operand(mi.operands.get(2)) as u32;
let mut word: u32 = 0;
word |= cond << 28;
word |= 0b01 << 26; word |= 0b01 << 24; word |= 1 << 23; word |= (is_load as u32) << 20;
word |= rn << 16;
word |= rd << 12;
word |= imm & 0xFFF;
word
}
fn encode_arm32_b_bl(&self, mi: &MachineInstr) -> u32 {
let is_call = mi.opcode == OP_ARM_BL;
let cond: u32 = 0xE;
let offset = self.get_branch_offset(mi) & 0xFFFFFF;
let mut word: u32 = 0;
word |= cond << 28;
word |= 0b101 << 25;
word |= (is_call as u32) << 24;
word |= offset;
word
}
fn encode_arm32_push_pop(&self, mi: &MachineInstr) -> u32 {
let is_pop = mi.opcode == OP_ARM_POP;
let cond: u32 = 0xE;
let mut reg_list: u32 = 0;
for op in &mi.operands {
let reg = self.get_arm32_reg_field_from_operand(Some(op));
if reg < 16 {
reg_list |= 1u32 << reg;
}
}
let mut word: u32 = 0;
word |= cond << 28;
if is_pop {
word |= 0b10001001 << 20; } else {
word |= 0b10010010 << 20; }
word |= 0b1101 << 16; word |= reg_list & 0xFFFF;
word
}
pub fn get_reg_field(reg_id: u16) -> u8 {
use super::arm_register_info::*;
match reg_id {
X0..=X30 => (reg_id - X0) as u8,
SP => 31,
XZR => 31,
W0..=W30 => (reg_id - W0) as u8,
WSP => 31,
WZR => 31,
R0..=R15 => (reg_id - R0) as u8,
_ if reg_id < 32 => reg_id as u8,
_ => 0,
}
}
fn get_reg_field_from_operand(&self, op: Option<&MachineOperand>) -> u8 {
match op {
Some(MachineOperand::Reg(vr)) => {
(*vr as u16 % 32) as u8
}
Some(MachineOperand::PhysReg(pr)) => Self::get_reg_field(*pr as u16),
_ => 31, }
}
fn get_arm32_reg_field_from_operand(&self, op: Option<&MachineOperand>) -> u32 {
match op {
Some(MachineOperand::Reg(vr)) => (*vr % 16) as u32,
Some(MachineOperand::PhysReg(pr)) => {
if *pr >= 2100 && *pr <= 2115 {
(*pr - 2100) as u32
} else {
*pr % 16
}
}
_ => 0,
}
}
fn get_imm_from_operand(&self, op: Option<&MachineOperand>) -> i64 {
match op {
Some(MachineOperand::Imm(v)) => *v,
_ => 0,
}
}
fn get_hw_from_operand(&self, op: Option<&MachineOperand>) -> u32 {
match op {
Some(MachineOperand::Imm(v)) => {
match *v {
0 => 0,
16 => 1,
32 => 2,
48 => 3,
_ => 0,
}
}
_ => 0,
}
}
fn get_cond_from_operand(&self, op: Option<&MachineOperand>) -> u32 {
match op {
Some(MachineOperand::Imm(v)) => *v as u32 & 0xF,
Some(MachineOperand::Label(s)) => {
ArmCond::from_mnemonic(s).map(|c| c as u32).unwrap_or(0xE)
}
_ => 0xE, }
}
fn get_branch_offset(&self, mi: &MachineInstr) -> u32 {
for op in &mi.operands {
if let MachineOperand::Label(label) = op {
if let Some(&target_off) = self.label_offsets.get(label) {
return (target_off as u32) / 4;
}
}
if let MachineOperand::Imm(offset) = op {
return (*offset as u32) / 4;
}
}
0
}
fn get_branch_offset_19bit(&self, mi: &MachineInstr) -> u32 {
self.get_branch_offset(mi) & 0x7FFFF
}
pub fn encode_sve_pred_and(&self, pd: u32, pg: u32, pn: u32, pm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00100101 << 24;
w |= 0b00 << 22;
w |= (pm & 0xF) << 16;
w |= (pg & 0xF) << 10;
w |= (pn & 0xF) << 5;
w |= (pd & 0xF);
w
}
pub fn encode_sve_pred_orr(&self, pd: u32, pg: u32, pn: u32, pm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00100101 << 24;
w |= 0b01 << 22;
w |= (pm & 0xF) << 16;
w |= (pg & 0xF) << 10;
w |= (pn & 0xF) << 5;
w |= (pd & 0xF);
w
}
pub fn encode_sve_pred_eor(&self, pd: u32, pg: u32, pn: u32, pm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00100101 << 24;
w |= 0b10 << 22;
w |= (pm & 0xF) << 16;
w |= (pg & 0xF) << 10;
w |= (pn & 0xF) << 5;
w |= (pd & 0xF);
w
}
pub fn encode_sve_pred_nand(&self, pd: u32, pg: u32, pn: u32, pm: u32) -> u32 {
self.encode_sve_pred_and(pd, pg, pn, pm) ^ (1 << 23)
}
pub fn encode_sve_pred_nor(&self, pd: u32, pg: u32, pn: u32, pm: u32) -> u32 {
self.encode_sve_pred_orr(pd, pg, pn, pm) ^ (1 << 23)
}
pub fn encode_sve_pred_orn(&self, pd: u32, pg: u32, pn: u32, pm: u32) -> u32 {
self.encode_sve_pred_eor(pd, pg, pn, pm) ^ (1 << 23)
}
pub fn encode_sve_ptrue(&self, pd: u32, pattern: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00100101 << 24;
w |= 0b01 << 22; w |= 0b1 << 21;
w |= 0b10 << 10;
w |= (pattern & 0x1F) << 5;
w |= (pd & 0xF);
w
}
pub fn encode_sve_pfirst(&self, pd: u32, pg: u32, pn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00100101 << 24;
w |= 0b00 << 22;
w |= 0b1 << 21;
w |= 0b00000 << 16;
w |= (pg & 0xF) << 10;
w |= (pn & 0xF) << 5;
w |= 0b1 << 4;
w |= (pd & 0xF);
w
}
pub fn encode_sve_pnext(&self, pd: u32, pg: u32, pn: u32) -> u32 {
self.encode_sve_pfirst(pd, pg, pn) | (1 << 13)
}
pub fn encode_sve_plast(&self, pd: u32, pg: u32, pn: u32) -> u32 {
self.encode_sve_pfirst(pd, pg, pn) | (1 << 14)
}
pub fn encode_sve_add_z(&self, zd: u32, pg: u32, zn: u32, size: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00000100 << 24;
w |= (size & 0x3) << 22;
w |= 0b1 << 21;
w |= 0b0 << 20; w |= (zd & 0x1) << 16; w |= (zd >> 1) << 14;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sve_sub_z(&self, zd: u32, pg: u32, zn: u32, size: u32) -> u32 {
let w = self.encode_sve_add_z(zd, pg, zn, size);
w | (1 << 13)
}
pub fn encode_sve_mul_z(&self, zd: u32, pg: u32, zn: u32, zm: u32, size: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00000100 << 24;
w |= (size & 0x3) << 22;
w |= 0b1 << 21;
w |= (zm & 0x1F) << 16;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w |= 0b1 << 12; w
}
pub fn encode_sve_mla_z(&self, zd: u32, pg: u32, zn: u32, zm: u32, size: u32) -> u32 {
self.encode_sve_mul_z(zd, pg, zn, zm, size) | (1 << 11)
}
pub fn encode_sve_mls_z(&self, zd: u32, pg: u32, zn: u32, zm: u32, size: u32) -> u32 {
self.encode_sve_mla_z(zd, pg, zn, zm, size) | (1 << 13)
}
pub fn encode_sve_fadd_z(&self, zd: u32, pg: u32, zn: u32, size: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b01100101 << 24;
w |= (size & 0x3) << 22;
w |= 0b0 << 21;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sve_fsub_z(&self, zd: u32, pg: u32, zn: u32, size: u32) -> u32 {
self.encode_sve_fadd_z(zd, pg, zn, size) | (1 << 13)
}
pub fn encode_sve_fmul_z(&self, zd: u32, pg: u32, zn: u32, zm: u32, size: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b01100101 << 24;
w |= (size & 0x3) << 22;
w |= 0b0 << 21;
w |= (zm & 0x1F) << 16;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w |= 0b1 << 12;
w
}
pub fn encode_sve_fdiv_z(&self, zd: u32, pg: u32, zn: u32, zm: u32, size: u32) -> u32 {
self.encode_sve_fmul_z(zd, pg, zn, zm, size) | (1 << 11)
}
pub fn encode_sve_ld1b_z(&self, zt: u32, pg: u32, zn: u32, xm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10100101 << 24;
w |= 0b0 << 23;
w |= 0b0 << 22;
w |= 0b0 << 21;
w |= 0b0 << 20;
w |= 0b10 << 18;
w |= (xm & 0x1F) << 16;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zt & 0x1F);
w
}
pub fn encode_sve_st1b_z(&self, zt: u32, pg: u32, zn: u32, xm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11100101 << 24;
w |= 0b0 << 23;
w |= 0b0 << 22;
w |= 0b0 << 21;
w |= 0b0 << 20;
w |= 0b10 << 18;
w |= (xm & 0x1F) << 16;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zt & 0x1F);
w
}
pub fn encode_sve_ld1w_gather(&self, zt: u32, pg: u32, zn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10000101 << 24;
w |= 0b0 << 23; w |= 0b10 << 21;
w |= (zm & 0x1F) << 16;
w |= 0b0 << 15;
w |= 0b10 << 13; w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zt & 0x1F);
w
}
pub fn encode_sve_ld1d_gather(&self, zt: u32, pg: u32, zn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000101 << 24;
w |= 0b0 << 23; w |= 0b10 << 21;
w |= (zm & 0x1F) << 16;
w |= 0b0 << 15;
w |= 0b11 << 13; w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zt & 0x1F);
w
}
pub fn encode_sve_st1w_scatter(&self, zt: u32, pg: u32, zn: u32, zm: u32) -> u32 {
let w = self.encode_sve_ld1w_gather(zt, pg, zn, zm);
w | (1 << 26) }
pub fn encode_sve_st1d_scatter(&self, zt: u32, pg: u32, zn: u32, zm: u32) -> u32 {
let w = self.encode_sve_ld1d_gather(zt, pg, zn, zm);
w | (1 << 26)
}
pub fn encode_sme_addha(&self, zdn: u32, pm: u32, pn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b00 << 22;
w |= (zm & 0x1F) << 16;
w |= (pn & 0xF) << 10;
w |= (pm & 0xF) << 5;
w |= (zdn & 0x1F);
w
}
pub fn encode_sme_addva(&self, zdn: u32, pm: u32, pn: u32, zm: u32) -> u32 {
self.encode_sme_addha(zdn, pm, pn, zm) | (1 << 12)
}
pub fn encode_sme_ldr_za(&self, rn: u32, offset: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11100001 << 24;
w |= 0b11 << 22;
w |= (rn & 0x1F) << 5;
w |= (offset & 0x3FF) >> 6;
w
}
pub fn encode_sme_str_za(&self, rn: u32, offset: u32) -> u32 {
let mut w = self.encode_sme_ldr_za(rn, offset);
w ^= 1 << 22; w
}
pub fn encode_sme_mova_za_to_z(&self, zd: u32, slice: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b00 << 22;
w |= (slice & 0x7) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme_mova_z_to_za(&self, zn: u32, slice: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b01 << 22;
w |= (slice & 0x7) << 5;
w |= (zn & 0x1F);
w
}
pub fn encode_sme_zero_za(&self) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b11 << 22;
w |= 0b1 << 21;
w
}
pub fn encode_sme2_fmla_multi(&self, zdn: u32, zm: u32, zn: u32, pn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b10 << 22;
w |= (zm & 0x1F) << 16;
w |= (zn & 0x1F) << 5;
w |= (pn & 0xF) << 10;
w |= (zdn & 0x1F);
w
}
pub fn encode_sme2_fmls_multi(&self, zdn: u32, zm: u32, zn: u32, pn: u32) -> u32 {
self.encode_sme2_fmla_multi(zdn, zm, zn, pn) | (1 << 12)
}
pub fn encode_sme2_ld1b_multi(&self, zt: u32, pn: u32, xm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b00 << 22;
w |= 0b11 << 20; w |= (xm & 0x1F) << 5;
w |= (pn & 0xF) << 10;
w |= (zt & 0x1F);
w
}
pub fn encode_sme2_st1b_multi(&self, zt: u32, pn: u32, xm: u32) -> u32 {
let mut w = self.encode_sme2_ld1b_multi(zt, pn, xm);
w ^= 1 << 22;
w
}
pub fn encode_mte_stg(&self, xt: u32, xn: u32, simm: i32) -> u32 {
let s = simm as u32 & 0x3FF;
let s9_4 = (s >> 4) & 0x3F;
let s3_0 = s & 0xF;
let mut w: u32 = 0;
w |= 0b11011001 << 24;
w |= 0b0 << 23;
w |= 0b1 << 22;
w |= s9_4 << 16;
w |= 0b0 << 15;
w |= (s3_0 >> 3) << 14;
w |= (xt & 0x1F) << 10;
w |= (s3_0 & 0x7) << 8;
w |= 0b1 << 7;
w |= (xn & 0x1F);
w
}
pub fn encode_mte_stzg(&self, xt: u32, xn: u32, simm: i32) -> u32 {
self.encode_mte_stg(xt, xn, simm) | (1 << 23)
}
pub fn encode_mte_st2g(&self, xt: u32, xn: u32, simm: i32) -> u32 {
self.encode_mte_stg(xt, xn, simm) | (1 << 21)
}
pub fn encode_mte_stz2g(&self, xt: u32, xn: u32, simm: i32) -> u32 {
self.encode_mte_st2g(xt, xn, simm) | (1 << 23)
}
pub fn encode_mte_ldg(&self, xt: u32, xn: u32, simm: i32) -> u32 {
let mut w = self.encode_mte_stg(xt, xn, simm);
w |= 1 << 23; w
}
pub fn encode_mte_stgm(&self, xt: u32, xn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11011001 << 24;
w |= 0b0 << 23;
w |= 0b1 << 22;
w |= (xt & 0x1F) << 10;
w |= 0b1 << 7;
w |= (xn & 0x1F);
w
}
pub fn encode_mte_stzgm(&self, xt: u32, xn: u32) -> u32 {
self.encode_mte_stgm(xt, xn) | (1 << 23)
}
pub fn encode_mte_ldgm(&self, xt: u32, xn: u32) -> u32 {
let mut w = self.encode_mte_stgm(xt, xn);
w |= 1 << 23;
w
}
pub fn encode_mte_irg(&self, xd: u32, xn: u32, xm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11011001 << 24;
w |= (xm & 0x1F) << 16;
w |= (xn & 0x1F) << 5;
w |= (xd & 0x1F);
w
}
pub fn encode_mte_addg(&self, xd: u32, xn: u32, uimm6: u32, uimm4: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10010001 << 24;
w |= 0b1 << 23;
w |= (uimm6 & 0x3F) << 16;
w |= (uimm4 & 0xF) << 10;
w |= (xn & 0x1F) << 5;
w |= (xd & 0x1F);
w
}
pub fn encode_mte_subg(&self, xd: u32, xn: u32, uimm6: u32, uimm4: u32) -> u32 {
self.encode_mte_addg(xd, xn, uimm6, uimm4) | (1 << 22)
}
pub fn encode_mte_gmi(&self, xd: u32, xn: u32, xm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10011001 << 24;
w |= (xm & 0x1F) << 16;
w |= (xn & 0x1F) << 5;
w |= (xd & 0x1F);
w
}
pub fn encode_mte_subp(&self, xd: u32, xn: u32, xm: u32) -> u32 {
let mut w = self.encode_mte_gmi(xd, xn, xm);
w ^= 1 << 22;
w
}
pub fn encode_mte_subps(&self, xd: u32, xn: u32, xm: u32) -> u32 {
self.encode_mte_subp(xd, xn, xm) | (1 << 22)
}
pub fn encode_sme2_ld1_multi(&self, zt: u32, pg: u32, xn: u32, xm: u32, num_regs: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10100101 << 24;
w |= (num_regs & 0x3) << 22;
w |= 0b1 << 21;
w |= (xm & 0x1F) << 16;
w |= (pg & 0xF) << 10;
w |= (xn & 0x1F) << 5;
w |= (zt & 0x1F);
w
}
pub fn encode_sme2_st1_multi(&self, zt: u32, pg: u32, xn: u32, xm: u32, num_regs: u32) -> u32 {
self.encode_sme2_ld1_multi(zt, pg, xn, xm, num_regs) | (1 << 24)
}
pub fn encode_sme2_bfmopa(&self, zd: u32, zn: u32, zm: u32, za: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10100001 << 24;
w |= 0b00 << 23;
w |= (zm & 0x1F) << 16;
w |= (za & 0x7) << 13;
w |= 0b1 << 12;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_bfmops(&self, zd: u32, zn: u32, zm: u32, za: u32) -> u32 {
self.encode_sme2_bfmopa(zd, zn, zm, za) ^ (1 << 23)
}
pub fn encode_f8_f1cvt(&self, vd: u32, vn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b01001110 << 24;
w |= 0b0 << 23;
w |= 0b0011111 << 16;
w |= 0b100001 << 10;
w |= (vn & 0x1F) << 5;
w |= (vd & 0x1F);
w
}
pub fn encode_f8_f2cvt(&self, vd: u32, vn: u32) -> u32 {
let mut w = self.encode_f8_f1cvt(vd, vn);
w ^= 1 << 23;
w
}
pub fn encode_f8_bf1cvt(&self, vd: u32, vn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b01001110 << 24;
w |= 0b1 << 23;
w |= 0b0011111 << 16;
w |= 0b100001 << 10;
w |= (vn & 0x1F) << 5;
w |= (vd & 0x1F);
w
}
pub fn encode_lut_luti2(&self, zd: u32, zn: u32, zm: u32, table_idx: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b01000101 << 24;
w |= table_idx << 20;
w |= (zm & 0x1F) << 16;
w |= 0b001 << 13;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_lut_luti4(&self, zd: u32, zn: u32, zm: u32, table_idx: u32) -> u32 {
self.encode_lut_luti2(zd, zn, zm, table_idx) ^ (1 << 23)
}
pub fn encode_faminmax_famin(&self, vd: u32, vn: u32, vm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b0 << 31;
w |= 0b0 << 30;
w |= 0b01110 << 25;
w |= 0b1 << 24;
w |= (vm & 0x1F) << 16;
w |= 0b0100 << 12;
w |= 0b1 << 10;
w |= (vn & 0x1F) << 5;
w |= (vd & 0x1F);
w
}
pub fn encode_faminmax_famax(&self, vd: u32, vn: u32, vm: u32) -> u32 {
self.encode_faminmax_famin(vd, vn, vm) ^ (1 << 30)
}
pub fn encode_sve2_cmla(
&self,
zda: u32,
pg: u32,
zn: u32,
zm: u32,
rot: u32,
size: u32,
) -> u32 {
let mut w: u32 = 0;
w |= 0b01000100 << 24;
w |= (size & 0x3) << 22;
w |= 0b1 << 21;
w |= (zm & 0x1F) << 16;
w |= (rot & 0x3) << 14;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zda & 0x1F);
w
}
pub fn encode_sve2_sdot(&self, zda: u32, pg: u32, zn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b01000100 << 24;
w |= 0b00 << 22;
w |= 0b1 << 21;
w |= (zm & 0x1F) << 16;
w |= 0b0001 << 10;
w |= (pg & 0xF) << 10;
w |= (zn & 0x1F) << 5;
w |= (zda & 0x1F);
w
}
pub fn encode_brb_iall(&self) -> u32 {
0b1101010100 << 22
}
pub fn encode_brb_inj(&self, xt: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b1101010100 << 22;
w |= 0b000100 << 16;
w |= 0b0000 << 12;
w |= 0b001 << 9;
w |= 0b11111 << 5;
w |= (xt & 0x1F);
w
}
pub fn encode_lrcpc3_ldiapp(&self, rt1: u32, rt2: u32, rn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11001000 << 24;
w |= 0b010 << 21;
w |= 0b0000111111 << 10;
w |= (rn & 0x1F) << 5;
w |= (rt2 & 0x1F) << 10;
w |= (rt1 & 0x1F);
w
}
pub fn encode_lrcpc3_stilp(&self, rt1: u32, rt2: u32, rn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11001000 << 24;
w |= 0b000 << 21;
w |= 0b0000111111 << 10;
w |= (rn & 0x1F) << 5;
w |= (rt2 & 0x1F) << 10;
w |= (rt1 & 0x1F);
w
}
pub fn encode_the_rctx(&self, xt: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11010101 << 24;
w |= 0b0000 << 20;
w |= 0b000011 << 14;
w |= 0b0010 << 10;
w |= 0b11111 << 5;
w |= (xt & 0x1F);
w
}
pub fn encode_chkfeat(&self, xt: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11010101 << 24;
w |= 0b0011 << 20;
w |= 0b0000 << 16;
w |= 0b0100 << 12;
w |= 0b101 << 9;
w |= 0b11111 << 5;
w |= (xt & 0x1F);
w
}
pub fn encode_gcs_gcspushx(&self, xt: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11010101 << 24;
w |= 0b0001 << 20;
w |= 0b0000 << 16;
w |= 0b0101 << 12;
w |= 0b100 << 9;
w |= 0b11111 << 5;
w |= (xt & 0x1F);
w
}
pub fn encode_gcs_gcspopx(&self, xt: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11010101 << 24;
w |= 0b0001 << 20;
w |= 0b0000 << 16;
w |= 0b0101 << 12;
w |= 0b101 << 9;
w |= 0b11111 << 5;
w |= (xt & 0x1F);
w
}
pub fn encode_cpd(&self, xd: u32, xn: u32, xm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10011010 << 24;
w |= (xm & 0x1F) << 16;
w |= 0b01 << 12;
w |= (xn & 0x1F) << 5;
w |= (xd & 0x1F);
w
}
pub fn encode_cpyfp(&self, xd: u32, xn: u32, xm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10011011 << 24;
w |= (xm & 0x1F) << 16;
w |= 0b000 << 12;
w |= (xn & 0x1F) << 5;
w |= (xd & 0x1F);
w
}
pub fn encode_cpyfm(&self, xd: u32, xn: u32, xm: u32) -> u32 {
let mut w = self.encode_cpyfp(xd, xn, xm);
w ^= 1 << 9;
w
}
pub fn encode_cpyfe(&self, xd: u32, xn: u32, xm: u32) -> u32 {
let mut w = self.encode_cpyfp(xd, xn, xm);
w ^= 2 << 9;
w
}
pub fn encode_setfp(&self, xd: u32, xn: u32, xm: u32) -> u32 {
self.encode_cpyfp(xd, xn, xm) ^ (1 << 24)
}
pub fn encode_setfm(&self, xd: u32, xn: u32, xm: u32) -> u32 {
self.encode_cpyfm(xd, xn, xm) ^ (1 << 24)
}
pub fn encode_setfe(&self, xd: u32, xn: u32, xm: u32) -> u32 {
self.encode_cpyfe(xd, xn, xm) ^ (1 << 24)
}
pub fn encode_pacm(&self, xd: u32, xn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11010101 << 24;
w |= 0b0000 << 20;
w |= 0b0011 << 16;
w |= 0b0000 << 12;
w |= 0b01 << 10;
w |= (xn & 0x1F) << 5;
w |= (xd & 0x1F);
w
}
pub fn encode_sme2_fmla_2z(&self, zd: u32, zn: u32, za_w: u32) -> u32 {
self.encode_sme2_fmla_multi(zd, zn, za_w, 0)
}
pub fn encode_sme2_fmla_4z(&self, zd: u32, zn: u32, za_w: u32) -> u32 {
self.encode_sme2_fmla_multi(zd, zn, za_w, 1)
}
pub fn encode_sme2_fmls_2z(&self, zd: u32, zn: u32, za_w: u32) -> u32 {
self.encode_sme2_fmls_multi(zd, zn, za_w, 0)
}
pub fn encode_sme2_fmls_4z(&self, zd: u32, zn: u32, za_w: u32) -> u32 {
self.encode_sme2_fmls_multi(zd, zn, za_w, 1)
}
pub fn encode_sve2_udot(&self, zda: u32, pg: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sve2_sdot(zda, pg, zn, zm);
w ^= 1 << 23;
w
}
pub fn encode_sve2_bdot(&self, zda: u32, pg: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sve2_sdot(zda, pg, zn, zm);
w ^= 2 << 23;
w
}
pub fn encode_faminmax_famin_vec(&self, vd: u32, vn: u32, vm: u32) -> u32 {
let mut w = self.encode_faminmax_famin(vd, vn, vm);
w |= 0b1 << 30;
w
}
pub fn encode_faminmax_famax_vec(&self, vd: u32, vn: u32, vm: u32) -> u32 {
let mut w = self.encode_faminmax_famin_vec(vd, vn, vm);
w ^= 1 << 24;
w
}
pub fn encode_sme2_fmla_mv(&self, zd: u32, zn: u32, zm: u32, num_vecs: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b01 << 22;
w |= ((num_vecs - 1) & 0x3) << 20;
w |= (zm & 0x1F) << 16;
w |= 0b0 << 15;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_fmla_mv_idx(&self, zd: u32, zn: u32, zm: u32, idx: u32) -> u32 {
let mut w = self.encode_sme2_fmla_mv(zd, zn, zm, 1);
w |= (idx & 0x3) << 13;
w
}
pub fn encode_sme2_smlal_mv(&self, zd: u32, zn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b10 << 22;
w |= (zm & 0x1F) << 16;
w |= 0b0 << 15;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_sdot_mv(&self, zd: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sme2_smlal_mv(zd, zn, zm);
w |= 0b01 << 22;
w
}
pub fn encode_sme2_udot_mv(&self, zd: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sme2_smlal_mv(zd, zn, zm);
w |= 0b10 << 22;
w
}
pub fn encode_sme2_bfmopa_pred(&self, zd: u32, pm: u32, zn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b10000001 << 24;
w |= 0b1 << 23;
w |= (pm & 0xF) << 19;
w |= (zm & 0x1F) << 16;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_fmopa(&self, zd: u32, pm: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sme2_bfmopa_pred(zd, pm, zn, zm);
w ^= 1 << 22;
w
}
pub fn encode_sme2_smopa(&self, zd: u32, pm: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sme2_bfmopa_pred(zd, pm, zn, zm);
w ^= 3 << 22;
w
}
pub fn encode_sme2_umopa(&self, zd: u32, pm: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sme2_bfmopa_pred(zd, pm, zn, zm);
w ^= 2 << 22;
w
}
pub fn encode_sme2_zero_mv(&self, zt: u32, num_regs: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b11 << 22;
w |= ((num_regs - 1) & 0x3) << 20;
w |= 0b1 << 21;
w |= 0b0 << 15;
w |= (zt & 0x1F);
w
}
pub fn encode_sme2_movprfx_mv(&self, zd: u32, pm: u32, zn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b0 << 23;
w |= (pm & 0xF) << 17;
w |= (zm & 0x1F) << 16;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_luti2(&self, zt: u32, zm: u32, idx: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b10 << 22;
w |= (zm & 0x1F) << 16;
w |= (idx & 0x3) << 13;
w |= (zt & 0x1F);
w
}
pub fn encode_sme2_luti4(&self, zt: u32, zm: u32, idx: u32) -> u32 {
let mut w = self.encode_sme2_luti2(zt, zm, idx);
w |= 0b01 << 20;
w
}
pub fn encode_sme2_f1cvt(&self, zd: u32, zn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b01 << 22;
w |= 0b1 << 15;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_f1cvtl(&self, zd: u32, zn: u32, imm: u32) -> u32 {
let mut w = self.encode_sme2_f1cvt(zd, zn);
w |= (imm & 0x1) << 14;
w
}
pub fn encode_sme2_bf1cvt(&self, zd: u32, zn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b01 << 22;
w |= 0b0 << 15;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_bf1cvtl(&self, zd: u32, zn: u32) -> u32 {
let mut w = self.encode_sme2_bf1cvt(zd, zn);
w |= 0b1 << 14;
w
}
pub fn encode_sme2_f2cvt(&self, zd: u32, zn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b11 << 22;
w |= 0b0 << 21;
w |= (zn & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_ldr_mv_strided(&self, zt: u32, xn: u32, imm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000101 << 24;
w |= 0b1 << 22;
w |= ((imm >> 3) & 0x7) << 17;
w |= (xn & 0x1F) << 5;
w |= (zt & 0x1F);
w
}
pub fn encode_sme2_str_mv_strided(&self, zt: u32, xn: u32, imm: u32) -> u32 {
let mut w = self.encode_sme2_ldr_mv_strided(zt, xn, imm);
w ^= 1 << 22;
w
}
pub fn encode_sme2_ldr_mv_contig(&self, zt: u32, xn: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000101 << 24;
w |= 0b0 << 22;
w |= (xn & 0x1F) << 5;
w |= (zt & 0x1F);
w
}
pub fn encode_sme2_str_mv_contig(&self, zt: u32, xn: u32) -> u32 {
let mut w = self.encode_sme2_ldr_mv_contig(zt, xn);
w ^= 1 << 22;
w
}
pub fn encode_sme2_psel(&self, pd: u32, pn: u32, pm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b11000001 << 24;
w |= 0b0 << 23;
w |= (pn & 0xF) << 19;
w |= 0b1 << 18;
w |= (pm & 0xF) << 14;
w |= (pd & 0xF) << 5;
w
}
pub fn encode_sme2_revd(&self, zd: u32, pn: u32, zm: u32) -> u32 {
let mut w: u32 = 0;
w |= 0b00000101 << 24;
w |= 0b1 << 23;
w |= (pn & 0xF) << 19;
w |= 0b1 << 18;
w |= (zm & 0x1F) << 5;
w |= (zd & 0x1F);
w
}
pub fn encode_sme2_sclamp(&self, zd: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sme2_revd(zd, 0, zm);
w |= (zn & 0x1F) << 16;
w
}
pub fn encode_sme2_uclamp(&self, zd: u32, zn: u32, zm: u32) -> u32 {
let mut w = self.encode_sme2_sclamp(zd, zn, zm);
w ^= 1 << 23;
w
}
}
pub fn encode_bitmask_imm(value: u64, size: u8) -> Option<(u32, u32, u32)> {
match size {
32 => encode_bitmask_imm_32(value as u32),
64 => encode_bitmask_imm_64(value),
_ => None,
}
}
fn encode_bitmask_imm_32(value: u32) -> Option<(u32, u32, u32)> {
let v = value;
if v == 0 || v == 0xFFFFFFFF {
let imms = if v == 0 {
0x1F } else {
0x20 };
return Some((0, imms, 0));
}
for rotation in 0..32 {
let rotated = v.rotate_right(rotation);
if let Some(run_len) = find_contiguous_ones_32(rotated) {
let imms = encode_imms_32(run_len, rotation);
if imms < 32 {
return Some((rotation, imms, 0));
}
}
}
None
}
fn encode_bitmask_imm_64(value: u64) -> Option<(u32, u32, u32)> {
let v = value;
let lo = v as u32;
let hi = (v >> 32) as u32;
if lo == hi {
if let Some((immr, imms, _)) = encode_bitmask_imm_32(lo) {
return Some((immr, imms, 0));
}
}
if v == 0 || v == 0xFFFFFFFFFFFFFFFF {
let imms = if v == 0 { 0x3F } else { 0x40 };
return Some((0, imms, 1));
}
for rotation in 0..64 {
let rotated = v.rotate_right(rotation as u32);
if let Some(run_len) = find_contiguous_ones_64(rotated) {
let (immr_val, imms_val) = encode_imms_64(run_len, rotation);
if imms_val < 64 {
return Some((immr_val as u32, imms_val, 1));
}
}
}
None
}
fn find_contiguous_ones_32(v: u32) -> Option<u32> {
if v == 0 {
return Some(0);
}
let tz = v.trailing_ones();
let mask = (1u64 << tz) - 1;
let remaining = v as u64 & !mask;
if remaining == 0 {
Some(tz)
} else {
None
}
}
fn find_contiguous_ones_64(v: u64) -> Option<u32> {
if v == 0 {
return Some(0);
}
let tz = v.trailing_ones() as u32;
let mask = (1u64 << tz) - 1;
let remaining = v & !mask;
if remaining == 0 {
Some(tz)
} else {
None
}
}
fn encode_imms_32(run_len: u32, _immr: u32) -> u32 {
if run_len == 0 {
return 0;
}
run_len.wrapping_sub(1) & 0x1F
}
fn encode_imms_64(run_len: u32, immr: u32) -> (u32, u32) {
if run_len == 0 {
return (0, 0);
}
let imms = run_len.wrapping_sub(1) & 0x3F;
(immr & 0x3F, imms)
}
pub fn encode_immediate_aarch64(value: u64, size: u8) -> (u32, u32) {
if let Some((immr, imms, n)) = encode_bitmask_imm(value, size) {
let encoded = (n << 12) | (immr << 6) | imms;
(encoded, immr)
} else {
(0, 0)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_instr(op: u32) -> MachineInstr {
MachineInstr::new(op)
}
fn make_instr_imm(op: u32, rd: u32, rn: u32, imm: i64) -> MachineInstr {
let mut mi = MachineInstr::new(op);
mi.operands.push(MachineOperand::PhysReg(rd));
mi.operands.push(MachineOperand::PhysReg(rn));
mi.operands.push(MachineOperand::Imm(imm));
mi
}
fn make_instr_reg(op: u32, rd: u32, rn: u32, rm: u32) -> MachineInstr {
let mut mi = MachineInstr::new(op);
mi.operands.push(MachineOperand::PhysReg(rd));
mi.operands.push(MachineOperand::PhysReg(rn));
mi.operands.push(MachineOperand::PhysReg(rm));
mi
}
fn make_instr_two_reg(op: u32, r1: u32, r2: u32) -> MachineInstr {
let mut mi = MachineInstr::new(op);
mi.operands.push(MachineOperand::PhysReg(r1));
mi.operands.push(MachineOperand::PhysReg(r2));
mi
}
fn make_instr_one_reg(op: u32, r: u32) -> MachineInstr {
let mut mi = MachineInstr::new(op);
mi.operands.push(MachineOperand::PhysReg(r));
mi
}
#[test]
fn test_get_reg_field_x0() {
assert_eq!(ArmMCEncoder::get_reg_field(2000), 0); assert_eq!(ArmMCEncoder::get_reg_field(2030), 30); }
#[test]
fn test_get_reg_field_sp_xzr() {
assert_eq!(ArmMCEncoder::get_reg_field(2031), 31); assert_eq!(ArmMCEncoder::get_reg_field(2032), 31); }
#[test]
fn test_get_reg_field_w_regs() {
assert_eq!(ArmMCEncoder::get_reg_field(2040), 0); assert_eq!(ArmMCEncoder::get_reg_field(2070), 30); assert_eq!(ArmMCEncoder::get_reg_field(2072), 31); }
#[test]
fn test_get_reg_field_arm32() {
assert_eq!(ArmMCEncoder::get_reg_field(2100), 0); assert_eq!(ArmMCEncoder::get_reg_field(2115), 15); }
#[test]
fn test_encode_nop() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr(OP_NOP);
let bytes = enc.encode_instruction(&mi);
assert_eq!(bytes.len(), 4);
assert_eq!(bytes, vec![0x1F, 0x20, 0x03, 0xD5]); }
#[test]
fn test_encode_add_imm() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_imm(OP_ADD, 2000, 2001, 42);
let bytes = enc.encode_instruction(&mi);
assert_eq!(bytes.len(), 4);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0x9100A820);
}
#[test]
fn test_encode_sub_imm() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_imm(OP_SUB, 2005, 2003, 16);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xD1004065);
}
#[test]
fn test_encode_add_imm_shifted() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_imm(OP_ADD, 2000, 2001, 4096);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0x91400420);
}
#[test]
fn test_encode_add_reg() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_reg(OP_ADD, 2002, 2003, 2004);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0x8B040062);
}
#[test]
fn test_encode_movz() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_MOVZ);
mi.operands.push(MachineOperand::PhysReg(2000)); mi.operands.push(MachineOperand::Imm(42));
mi.operands.push(MachineOperand::Imm(0)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xD2800540);
}
#[test]
fn test_encode_movk() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_MOVK);
mi.operands.push(MachineOperand::PhysReg(2001)); mi.operands.push(MachineOperand::Imm(0xABCD));
mi.operands.push(MachineOperand::Imm(16)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected =
(1u32 << 31) | (0b11 << 29) | (0b100101 << 23) | (1u32 << 21) | (0xABCD << 5) | 1;
assert_eq!(word, expected);
}
#[test]
fn test_encode_ret() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_one_reg(OP_RET, 2030); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xD65F03C0);
}
#[test]
fn test_encode_ret_default() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr(OP_RET); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xD65F03C0);
}
#[test]
fn test_encode_cmp_imm() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_CMP);
mi.operands.push(MachineOperand::PhysReg(2000)); mi.operands.push(MachineOperand::Imm(0));
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected = (1u32 << 31)
| (1 << 30)
| (1 << 29)
| (0b10001 << 24)
| (0 << 22)
| (0 << 10)
| (0u32 << 5)
| 31;
assert_eq!(word, expected);
}
#[test]
fn test_encode_cmp_reg() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_two_reg(OP_CMP, 2001, 2002);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected = (1u32 << 31)
| (1 << 30)
| (1 << 29)
| (0b01011 << 24)
| (2u32 << 16)
| (1u32 << 5)
| 31;
assert_eq!(word, expected);
}
#[test]
fn test_encode_ldr_imm() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_imm(OP_LDR, 2000, 2001, 8);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected =
(0b11u32 << 30) | (0b1110_0101 << 22) | (1u32 << 12) | (0b01 << 10) | (1u32 << 5) | 0;
assert_eq!(word, expected);
}
#[test]
fn test_encode_str_imm() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_imm(OP_STR, 2005, 2031, 16);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected =
(0b11u32 << 30) | (0b1110_0100 << 22) | (2u32 << 12) | (0b01 << 10) | (31u32 << 5) | 5;
assert_eq!(word, expected);
}
#[test]
fn test_encode_ldp() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_LDP);
mi.operands.push(MachineOperand::PhysReg(2000)); mi.operands.push(MachineOperand::PhysReg(2001)); mi.operands.push(MachineOperand::PhysReg(2002)); mi.operands.push(MachineOperand::Imm(0)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xA9400440);
}
#[test]
fn test_encode_csel() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_CSEL);
mi.operands.push(MachineOperand::PhysReg(2000)); mi.operands.push(MachineOperand::PhysReg(2001)); mi.operands.push(MachineOperand::PhysReg(2002)); mi.operands.push(MachineOperand::Imm(ArmCond::EQ as i64)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0x9A820020);
}
#[test]
fn test_encode_sdiv() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_reg(OP_SDIV, 2003, 2004, 2005);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0x9AC50C83);
}
#[test]
fn test_encode_udiv() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_reg(OP_UDIV, 2000, 2001, 2002);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0x9AC20820);
}
#[test]
fn test_encode_arm32_mov() {
let enc = ArmMCEncoder::new(false); let mut mi = MachineInstr::new(OP_ARM_MOV);
mi.operands.push(MachineOperand::PhysReg(2101)); mi.operands.push(MachineOperand::PhysReg(2102)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xE1A01002);
}
#[test]
fn test_encode_arm32_add() {
let enc = ArmMCEncoder::new(false);
let mut mi = MachineInstr::new(OP_ARM_ADD);
mi.operands.push(MachineOperand::PhysReg(2100)); mi.operands.push(MachineOperand::PhysReg(2101)); mi.operands.push(MachineOperand::PhysReg(2102)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xE0810002);
}
#[test]
fn test_encode_arm32_push_pop() {
let enc = ArmMCEncoder::new(false);
let mut mi = MachineInstr::new(OP_ARM_PUSH);
mi.operands.push(MachineOperand::PhysReg(2104)); mi.operands.push(MachineOperand::PhysReg(2114)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xE92D4010);
}
#[test]
fn test_encode_bfm() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_BFM);
mi.operands.push(MachineOperand::PhysReg(2000)); mi.operands.push(MachineOperand::PhysReg(2001)); mi.operands.push(MachineOperand::Imm(0)); mi.operands.push(MachineOperand::Imm(7)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected =
(1u32 << 31) | (0b01 << 29) | (0b100110 << 23) | (7u32 << 10) | (1u32 << 5) | 0;
assert_eq!(word, expected);
}
#[test]
fn test_encode_adds() {
let enc = ArmMCEncoder::new(true);
let mi = make_instr_reg(OP_ADDS, 2000, 2001, 2002);
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
assert_eq!(word, 0xAB020020);
}
#[test]
fn test_encode_madd() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_MADD);
mi.operands.push(MachineOperand::PhysReg(2000)); mi.operands.push(MachineOperand::PhysReg(2001)); mi.operands.push(MachineOperand::PhysReg(2002)); mi.operands.push(MachineOperand::PhysReg(2003)); let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected = (1u32 << 31)
| (0b11011 << 24)
| (2u32 << 16)
| (0u32 << 15)
| (3u32 << 10)
| (1u32 << 5)
| 0;
assert_eq!(word, expected);
}
#[test]
fn test_encode_msub() {
let enc = ArmMCEncoder::new(true);
let mut mi = MachineInstr::new(OP_MSUB);
mi.operands.push(MachineOperand::PhysReg(2000));
mi.operands.push(MachineOperand::PhysReg(2001));
mi.operands.push(MachineOperand::PhysReg(2002));
mi.operands.push(MachineOperand::PhysReg(2003));
let bytes = enc.encode_instruction(&mi);
let word = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let expected = (1u32 << 31)
| (0b11011 << 24)
| (2u32 << 16)
| (1u32 << 15)
| (3u32 << 10)
| (1u32 << 5)
| 0;
assert_eq!(word, expected);
}
#[test]
fn test_encode_bitmask_32() {
let result = encode_bitmask_imm(0xFFFF0000, 64);
assert!(result.is_some());
let result = encode_bitmask_imm(0x55555555, 32);
assert!(result.is_none());
}
#[test]
fn test_encode_bitmask_all_ones() {
let result = encode_bitmask_imm(0xFFFFFFFFFFFFFFFF, 64);
assert!(result.is_some());
}
#[test]
fn test_encode_bitmask_zero() {
let result = encode_bitmask_imm(0, 64);
assert!(result.is_some());
}
#[test]
fn test_encode_sve_pred_and() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_pred_and(0, 1, 2, 3); let expected = 0b00100101_00_0_0011_0_0001_0010_0_0000u32;
assert_eq!(word, expected);
}
#[test]
fn test_encode_sve_pred_orr() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_pred_orr(1, 2, 3, 4);
assert_eq!((word >> 22) & 0x3, 1);
}
#[test]
fn test_encode_sve_pred_eor() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_pred_eor(0, 0, 0, 0);
assert_eq!((word >> 22) & 0x3, 2);
}
#[test]
fn test_encode_sve_ptrue() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_ptrue(0, 0b00000);
assert_eq!(word & 0xFF000000, 0x25000000);
}
#[test]
fn test_encode_sve_pfirst() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_pfirst(0, 1, 2);
assert!(word != 0);
}
#[test]
fn test_encode_sve_add_z() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_add_z(0, 0, 1, 3);
assert_eq!((word >> 24) & 0xFF, 0x04);
}
#[test]
fn test_encode_sve_sub_z() {
let enc = ArmMCEncoder::new(true);
let add_word = enc.encode_sve_add_z(0, 0, 1, 0);
let sub_word = enc.encode_sve_sub_z(0, 0, 1, 0);
assert_eq!(sub_word & (1 << 13), 1 << 13);
assert_ne!(add_word, sub_word);
}
#[test]
fn test_encode_sve_mul_z() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_mul_z(0, 0, 1, 2, 2);
assert!(word != 0);
assert_eq!(word & (1 << 12), 1 << 12); }
#[test]
fn test_encode_sve_fadd_z() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_fadd_z(0, 0, 1, 2);
assert_eq!((word >> 24) & 0xFF, 0x65);
}
#[test]
fn test_encode_sve_fdiv_z() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_fdiv_z(0, 0, 1, 2, 2);
assert!(word != 0);
assert_eq!(word & (1 << 11), 1 << 11);
}
#[test]
fn test_encode_sve_ld1b_z() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_ld1b_z(0, 0, 0, 1);
assert_eq!((word >> 24) & 0xFF, 0xA5);
}
#[test]
fn test_encode_sve_st1b_z() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_st1b_z(0, 0, 0, 1);
assert_eq!((word >> 24) & 0xFF, 0xE5);
}
#[test]
fn test_encode_sve_gather_load() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_ld1w_gather(0, 0, 1, 2);
assert_eq!((word >> 24) & 0xFF, 0x85);
}
#[test]
fn test_encode_sve_scatter_store() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sve_st1w_scatter(0, 0, 1, 2);
assert_eq!(word & (1 << 26), 1 << 26);
}
#[test]
fn test_encode_sme_addha() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sme_addha(0, 1, 0, 2);
assert_eq!((word >> 24) & 0xFF, 0xC1);
}
#[test]
fn test_encode_sme_zero_za() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sme_zero_za();
assert!(word != 0);
assert_eq!((word >> 24) & 0xFF, 0xC1);
}
#[test]
fn test_encode_sme_mova_za_to_z() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sme_mova_za_to_z(0, 0);
assert_eq!((word >> 24) & 0xFF, 0xC1);
assert_eq!((word >> 22) & 1, 0);
}
#[test]
fn test_encode_sme_mova_z_to_za() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sme_mova_z_to_za(0, 0);
assert_eq!((word >> 22) & 1, 1);
}
#[test]
fn test_encode_mte_stg() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_mte_stg(0, 1, 16);
assert_eq!((word >> 24) & 0xFF, 0xD9);
}
#[test]
fn test_encode_mte_ldg() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_mte_ldg(0, 1, 0);
assert_eq!(word & (1 << 23), 1 << 23);
}
#[test]
fn test_encode_mte_irg() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_mte_irg(0, 1, 2);
assert_eq!((word >> 24) & 0xFF, 0xD9);
}
#[test]
fn test_encode_mte_addg() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_mte_addg(0, 1, 4, 2);
assert_eq!((word >> 24) & 0xFF, 0x91);
}
#[test]
fn test_encode_mte_subg() {
let enc = ArmMCEncoder::new(true);
let addg = enc.encode_mte_addg(0, 1, 0, 0);
let subg = enc.encode_mte_subg(0, 1, 0, 0);
assert_ne!(addg, subg);
}
#[test]
fn test_encode_mte_gmi() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_mte_gmi(0, 1, 2);
assert_eq!((word >> 24) & 0xFF, 0x99);
}
#[test]
fn test_sve_predicate_logical_encodings_unique() {
let enc = ArmMCEncoder::new(true);
let and = enc.encode_sve_pred_and(0, 0, 0, 0);
let orr = enc.encode_sve_pred_orr(0, 0, 0, 0);
let eor = enc.encode_sve_pred_eor(0, 0, 0, 0);
assert_ne!(and, orr);
assert_ne!(orr, eor);
assert_ne!(and, eor);
}
#[test]
fn test_sme2_fmla_multi() {
let enc = ArmMCEncoder::new(true);
let word = enc.encode_sme2_fmla_multi(0, 1, 2, 0);
assert_eq!((word >> 24) & 0xFF, 0xC1);
}
#[test]
fn test_sme2_fmls_multi() {
let enc = ArmMCEncoder::new(true);
let fmla = enc.encode_sme2_fmla_multi(0, 1, 2, 0);
let fmls = enc.encode_sme2_fmls_multi(0, 1, 2, 0);
assert_ne!(fmla, fmls);
}
}