///|
pub fn Instruction::emit(self : Instruction, mc : MachineCode) -> Unit {
match self {
LoadImm64(rd, imm) => {
// Load a 64-bit immediate using MOVZ/MOVK or MOVN/MOVK sequence.
// Prefer the shorter sequence; on ties prefer MOVZ to keep output stable.
let hw0 = (imm & 0xFFFFL).to_int()
let hw1 = ((imm >> 16) & 0xFFFFL).to_int()
let hw2 = ((imm >> 32) & 0xFFFFL).to_int()
let hw3 = ((imm >> 48) & 0xFFFFL).to_int()
let halfwords = FixedArray::make(4, 0)
halfwords[0] = hw0
halfwords[1] = hw1
halfwords[2] = hw2
halfwords[3] = hw3
let mut non_zero = 0
let mut non_ffff = 0
for i in 0..<4 {
if halfwords[i] != 0 {
non_zero = non_zero + 1
}
if halfwords[i] != 0xFFFF {
non_ffff = non_ffff + 1
}
}
let movz_count = if non_zero == 0 { 1 } else { non_zero }
let movn_count = if non_ffff == 0 { 1 } else { non_ffff }
// Cranelift-aligned fast path: if neither MOVZ nor MOVN is single-instruction,
// try logical-immediate materialization via:
// orr xD, xzr, #imm
// This can materialize many mask/pattern constants in one instruction.
if movz_count > 1 && movn_count > 1 {
match @instr.aarch64_logic_imm_enc_bits(imm, true) {
Some(imm_bits) => {
OrrImm(rd, 31, imm_bits).emit(mc)
return
}
None => ()
}
}
if movn_count < movz_count {
// MOVN strategy: start from all-ones, patch non-0xFFFF halfwords.
if non_ffff == 0 {
Movn(rd, 0, 0).emit(mc)
} else {
let mut init_i = 0
while init_i < 4 && halfwords[init_i] == 0xFFFF {
init_i = init_i + 1
}
let init_hw = halfwords[init_i]
let init_imm = init_hw ^ 0xFFFF
Movn(rd, init_imm, init_i * 16).emit(mc)
for i in 0..<4 {
if i != init_i && halfwords[i] != 0xFFFF {
Movk(rd, halfwords[i], i * 16).emit(mc)
}
}
}
// MOVZ strategy: start from 0, patch non-zero halfwords.
} else if non_zero == 0 {
Movz(rd, 0, 0).emit(mc)
} else {
let mut init_i = 0
while init_i < 4 && halfwords[init_i] == 0 {
init_i = init_i + 1
}
Movz(rd, halfwords[init_i], init_i * 16).emit(mc)
for i in 0..<4 {
if i != init_i && halfwords[i] != 0 {
Movk(rd, halfwords[i], i * 16).emit(mc)
}
}
}
}
AlignTo(alignment) =>
// Emit NOPs until aligned to the specified byte boundary
while mc.current_pos() % alignment != 0 {
Nop.emit(mc)
}
B(target_block) => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
mc.add_fixup(target_block, Branch26)
}
BCond(_, target_block) => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
mc.add_fixup(target_block, Branch19)
}
Cbz(_, target_block) => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
mc.add_fixup(target_block, Branch19)
}
Cbnz(_, target_block) => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
mc.add_fixup(target_block, Branch19)
}
Cbz32(_, target_block) => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
mc.add_fixup(target_block, Branch19)
}
Cbnz32(_, target_block) => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
mc.add_fixup(target_block, Branch19)
}
Bl(target_block) => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
mc.add_fixup(target_block, Branch26)
}
_ => {
mc.annotate(self.annotate())
let (b0, b1, b2, b3) = self.instr_bytes()
mc.emit_inst(b0, b1, b2, b3)
}
}
}
// ============ Low-level AArch64 encoder helpers ============
///|
pub fn MachineCode::emit_add_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
AddReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_add_shifted(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
AddShifted(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_add_shifted32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
AddShifted32(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_add_uxtw(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
AddExtUxtw(rd, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_add_sxtw(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
AddExtSxtw(rd, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_sub_uxtw(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
SubExtUxtw(rd, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_sub_sxtw(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
SubExtSxtw(rd, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_sub_shifted(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
SubShifted(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_sub_shifted32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
SubShifted32(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_and_shifted(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
AndShifted(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_and_shifted32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
AndShifted32(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_orr_shifted(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
OrrShifted(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_orr_shifted32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
OrrShifted32(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_eor_shifted(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
EorShifted(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_eor_shifted32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : @instr.ShiftType,
amount : Int,
) -> Unit {
EorShifted32(rd, rn, rm, shift, amount).emit(self)
}
///|
pub fn MachineCode::emit_madd(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
ra : Int,
) -> Unit {
Madd(rd, rn, rm, ra).emit(self)
}
///|
pub fn MachineCode::emit_msub(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
ra : Int,
) -> Unit {
Msub(rd, rn, rm, ra).emit(self)
}
///|
pub fn MachineCode::emit_mneg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Mneg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_madd32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
ra : Int,
) -> Unit {
Madd32(rd, rn, rm, ra).emit(self)
}
///|
pub fn MachineCode::emit_msub32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
ra : Int,
) -> Unit {
Msub32(rd, rn, rm, ra).emit(self)
}
///|
pub fn MachineCode::emit_mneg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Mneg32(rd, rn, rm).emit(self)
}
///|
/// UMULH Xd, Xn, Xm - Unsigned multiply high (64-bit)
pub fn MachineCode::emit_umulh(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Umulh(rd, rn, rm).emit(self)
}
///|
/// SMULH Xd, Xn, Xm - Signed multiply high (64-bit)
pub fn MachineCode::emit_smulh(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Smulh(rd, rn, rm).emit(self)
}
///|
/// UMULL Xd, Wn, Wm - Unsigned 32x32->64 multiply
pub fn MachineCode::emit_umull(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Umull(rd, rn, rm).emit(self)
}
///|
/// SMULL Xd, Wn, Wm - Signed 32x32->64 multiply
pub fn MachineCode::emit_smull(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Smull(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_add_imm(
self : MachineCode,
rd : Int,
rn : Int,
imm12 : Int,
) -> Unit {
AddImm(rd, rn, imm12).emit(self)
}
///|
/// Emit ADD with immediate shifted left by 12 bits
pub fn MachineCode::emit_add_imm_shifted12(
self : MachineCode,
rd : Int,
rn : Int,
imm12 : Int,
) -> Unit {
AddImmShifted12(rd, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_sub_imm_shifted12(
self : MachineCode,
rd : Int,
rn : Int,
imm12 : Int,
) -> Unit {
SubImmShifted12(rd, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_sub_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
SubReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_sub_imm(
self : MachineCode,
rd : Int,
rn : Int,
imm12 : Int,
) -> Unit {
SubImm(rd, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_mul(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Mul(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_sdiv(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Sdiv(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_udiv(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Udiv(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_and_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
AndReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_and_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
AndReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_bic_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
BicReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_bic_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
BicReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_and_imm(
self : MachineCode,
rd : Int,
rn : Int,
imm_bits : Int,
) -> Unit {
AndImm(rd, rn, imm_bits).emit(self)
}
///|
pub fn MachineCode::emit_and_imm32(
self : MachineCode,
rd : Int,
rn : Int,
imm_bits : Int,
) -> Unit {
AndImm32(rd, rn, imm_bits).emit(self)
}
///|
pub fn MachineCode::emit_orr_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
OrrReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_orr_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
OrrReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_orn_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
OrnReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_orn_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
OrnReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_orr_imm(
self : MachineCode,
rd : Int,
rn : Int,
imm_bits : Int,
) -> Unit {
OrrImm(rd, rn, imm_bits).emit(self)
}
///|
pub fn MachineCode::emit_orr_imm32(
self : MachineCode,
rd : Int,
rn : Int,
imm_bits : Int,
) -> Unit {
OrrImm32(rd, rn, imm_bits).emit(self)
}
///|
pub fn MachineCode::emit_eor_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
EorReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_eor_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
EorReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_eon_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
EonReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_eon_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
EonReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_eor_imm(
self : MachineCode,
rd : Int,
rn : Int,
imm_bits : Int,
) -> Unit {
EorImm(rd, rn, imm_bits).emit(self)
}
///|
pub fn MachineCode::emit_eor_imm32(
self : MachineCode,
rd : Int,
rn : Int,
imm_bits : Int,
) -> Unit {
EorImm32(rd, rn, imm_bits).emit(self)
}
///|
pub fn MachineCode::emit_lsl_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
LslReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_asr_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
AsrReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_lsr_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
LsrReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_ror_reg(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
RorReg(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_mvn(self : MachineCode, rd : Int, rm : Int) -> Unit {
Mvn(rd, rm).emit(self)
}
///|
pub fn MachineCode::emit_mvn32(self : MachineCode, rd : Int, rm : Int) -> Unit {
Mvn32(rd, rm).emit(self)
}
///|
pub fn MachineCode::emit_clz(self : MachineCode, rd : Int, rn : Int) -> Unit {
Clz(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_rbit(self : MachineCode, rd : Int, rn : Int) -> Unit {
Rbit(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_sdiv32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Sdiv32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_udiv32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Udiv32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_sub_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
SubReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_add_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
AddReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_add_imm32(
self : MachineCode,
rd : Int,
rn : Int,
imm : Int,
) -> Unit {
AddImm32(rd, rn, imm).emit(self)
}
///|
pub fn MachineCode::emit_add_imm32_shifted12(
self : MachineCode,
rd : Int,
rn : Int,
imm12 : Int,
) -> Unit {
AddImm32Shifted12(rd, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_sub_imm32(
self : MachineCode,
rd : Int,
rn : Int,
imm : Int,
) -> Unit {
SubImm32(rd, rn, imm).emit(self)
}
///|
pub fn MachineCode::emit_sub_imm32_shifted12(
self : MachineCode,
rd : Int,
rn : Int,
imm12 : Int,
) -> Unit {
SubImm32Shifted12(rd, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_mul32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
Mul32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_lsl_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
LslReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_lsr_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
LsrReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_asr_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
AsrReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_ror_reg32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
RorReg32(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_lsr_imm(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
LsrImm(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_lsr_imm32(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
LsrImm32(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_lsl_imm(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
LslImm(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_lsl_imm32(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
LslImm32(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_asr_imm(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
AsrImm(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_asr_imm32(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
AsrImm32(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_ror_imm(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
RorImm(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_extr_imm(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
ExtrImm(rd, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_ror_imm32(
self : MachineCode,
rd : Int,
rn : Int,
shift : Int,
) -> Unit {
RorImm32(rd, rn, shift).emit(self)
}
///|
pub fn MachineCode::emit_extr_imm32(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
ExtrImm32(rd, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_clz32(self : MachineCode, rd : Int, rn : Int) -> Unit {
Clz32(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_rbit32(self : MachineCode, rd : Int, rn : Int) -> Unit {
Rbit32(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_cmp_reg32(
self : MachineCode,
rn : Int,
rm : Int,
) -> Unit {
CmpReg32(rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_cmp_imm32(
self : MachineCode,
rn : Int,
imm : Int,
) -> Unit {
// AArch64 CMP immediate supports a 12-bit unsigned immediate, optionally shifted left by 12.
//
// For larger/negative immediates, materialize the value in a reserved scratch register and
// use CMP (register) instead. This avoids silent truncation of imm12.
if imm >= 0 && imm <= 4095 {
CmpImm32(rn, imm).emit(self)
} else if imm >= 0 && (imm & 0xFFF) == 0 && imm >> 12 <= 4095 {
CmpImm32Shifted12(rn, imm >> 12).emit(self)
} else {
let scratch = self.isa.scratch_reg_1_index()
self.emit_load_imm64(scratch, imm.to_int64())
self.emit_cmp_reg32(rn, scratch)
}
}
///|
fn MachineCode::emit_adds_imm_zr(
self : MachineCode,
rn : Int,
imm12 : Int,
is_64 : Bool,
) -> Unit {
AddsImmZr(rn, imm12, is_64).emit(self)
}
///|
fn MachineCode::emit_ccmp_imm(
self : MachineCode,
rn : Int,
imm5 : Int,
nzcv : Int,
cond : Int,
is_64 : Bool,
) -> Unit {
CCmpImm(rn, imm5, nzcv, cond, is_64).emit(self)
}
///|
pub fn MachineCode::emit_fcvtzs(
self : MachineCode,
rd : Int,
rn : Int,
int64~ : Bool,
double~ : Bool,
) -> Unit {
Fcvtzs(rd, rn, int64, double).emit(self)
}
///|
pub fn MachineCode::emit_fcvtzu(
self : MachineCode,
rd : Int,
rn : Int,
int64~ : Bool,
double~ : Bool,
) -> Unit {
Fcvtzu(rd, rn, int64, double).emit(self)
}
///|
pub fn MachineCode::emit_scvtf(
self : MachineCode,
rd : Int,
rn : Int,
int64~ : Bool,
double~ : Bool,
) -> Unit {
Scvtf(rd, rn, int64, double).emit(self)
}
///|
pub fn MachineCode::emit_ucvtf(
self : MachineCode,
rd : Int,
rn : Int,
int64~ : Bool,
double~ : Bool,
) -> Unit {
Ucvtf(rd, rn, int64, double).emit(self)
}
///|
pub fn MachineCode::emit_mov_reg(
self : MachineCode,
rd : Int,
rm : Int,
) -> Unit {
MovReg(rd, rm).emit(self)
}
///|
pub fn MachineCode::emit_mov_reg32(
self : MachineCode,
rd : Int,
rm : Int,
) -> Unit {
MovReg32(rd, rm).emit(self)
}
///|
pub fn MachineCode::emit_movz(
self : MachineCode,
rd : Int,
imm16 : Int,
shift : Int,
) -> Unit {
Movz(rd, imm16, shift).emit(self)
}
///|
pub fn MachineCode::emit_movk(
self : MachineCode,
rd : Int,
imm16 : Int,
shift : Int,
) -> Unit {
Movk(rd, imm16, shift).emit(self)
}
///|
pub fn MachineCode::emit_load_imm64(
self : MachineCode,
rd : Int,
imm : Int64,
) -> Unit {
LoadImm64(rd, imm).emit(self)
}
///|
/// Load 64-bit immediate with fixed 4 instructions (MOVZ + 3 MOVKs or NOPs).
/// Use this when you need a predictable instruction count for branch offset calculations.
pub fn MachineCode::emit_load_imm64_fixed(
self : MachineCode,
rd : Int,
imm : Int64,
) -> Unit {
let v0 = (imm & 0xFFFFL).to_int()
let v1 = ((imm >> 16) & 0xFFFFL).to_int()
let v2 = ((imm >> 32) & 0xFFFFL).to_int()
let v3 = ((imm >> 48) & 0xFFFFL).to_int()
// Always emit exactly 4 instructions
Movz(rd, v0, 0).emit(self)
Movk(rd, v1, 16).emit(self)
Movk(rd, v2, 32).emit(self)
Movk(rd, v3, 48).emit(self)
}
///|
pub fn MachineCode::emit_ldr_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldr_imm_signed(
self : MachineCode,
rt : Int,
rn : Int,
simm9 : Int,
) -> Unit {
LdrImmSigned(rt, rn, simm9).emit(self)
}
///|
pub fn MachineCode::emit_str_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
StrImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldr_reg_scaled(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
LdrRegScaled(rt, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_ldr_reg_offset(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
option : Int,
size_bits : Int,
shift : Int,
) -> Unit {
LdrRegOffset(rt, rn, rm, option, size_bits, shift).emit(self)
}
///|
pub fn MachineCode::emit_str_reg_scaled(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
StrRegScaled(rt, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_str_reg_offset(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
option : Int,
size_bits : Int,
shift : Int,
) -> Unit {
StrRegOffset(rt, rn, rm, option, size_bits, shift).emit(self)
}
///|
pub fn MachineCode::emit_ldr_w_reg_scaled(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
LdrWRegScaled(rt, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_str_w_reg_scaled(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
shift : Int,
) -> Unit {
StrWRegScaled(rt, rn, rm, shift).emit(self)
}
///|
pub fn MachineCode::emit_ldrb_reg(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
) -> Unit {
LdrbReg(rt, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_strb_reg(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
) -> Unit {
StrbReg(rt, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_ldrh_reg(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
) -> Unit {
LdrhReg(rt, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_strh_reg(
self : MachineCode,
rt : Int,
rn : Int,
rm : Int,
) -> Unit {
StrhReg(rt, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_ldrb_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrbImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldrh_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrhImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldr_w_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrWImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_strb_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
StrbImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_strh_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
StrhImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_str_w_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
StrWImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_stp_pre(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
imm : Int,
) -> Unit {
StpPre(rt1, rt2, rn, imm).emit(self)
}
///|
pub fn MachineCode::emit_ldp_post(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
imm : Int,
) -> Unit {
LdpPost(rt1, rt2, rn, imm).emit(self)
}
///|
pub fn MachineCode::emit_ldrsb_x_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrsbXImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldrsb_w_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrsbWImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldrsh_x_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrshXImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldrsh_w_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrshWImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldrsw_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrswImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_sxtb_x(self : MachineCode, rd : Int, rn : Int) -> Unit {
SxtbX(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_sxth_x(self : MachineCode, rd : Int, rn : Int) -> Unit {
SxthX(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_sxtw(self : MachineCode, rd : Int, rn : Int) -> Unit {
Sxtw(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_sxtb_w(self : MachineCode, rd : Int, rn : Int) -> Unit {
SxtbW(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_sxth_w(self : MachineCode, rd : Int, rn : Int) -> Unit {
SxthW(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_uxtb_x(self : MachineCode, rd : Int, rn : Int) -> Unit {
UxtbX(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_uxth_x(self : MachineCode, rd : Int, rn : Int) -> Unit {
UxthX(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_uxtb_w(self : MachineCode, rd : Int, rn : Int) -> Unit {
UxtbW(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_uxth_w(self : MachineCode, rd : Int, rn : Int) -> Unit {
UxthW(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_b(self : MachineCode, target_block : Int) -> Unit {
B(target_block).emit(self)
}
///|
pub fn MachineCode::emit_b_cond(
self : MachineCode,
cond : Int,
target_block : Int,
) -> Unit {
BCond(cond, target_block).emit(self)
}
///|
pub fn MachineCode::emit_cbz(
self : MachineCode,
rt : Int,
target_block : Int,
) -> Unit {
Cbz(rt, target_block).emit(self)
}
///|
pub fn MachineCode::emit_cbnz(
self : MachineCode,
rt : Int,
target_block : Int,
) -> Unit {
Cbnz(rt, target_block).emit(self)
}
///|
pub fn MachineCode::emit_cbz32(
self : MachineCode,
rt : Int,
target_block : Int,
) -> Unit {
Cbz32(rt, target_block).emit(self)
}
///|
pub fn MachineCode::emit_cbnz32(
self : MachineCode,
rt : Int,
target_block : Int,
) -> Unit {
Cbnz32(rt, target_block).emit(self)
}
///|
fn MachineCode::emit_b_cond_offset(
self : MachineCode,
cond : Int,
offset_bytes : Int,
) -> Unit {
BCondOffset(cond, offset_bytes).emit(self)
}
///|
fn MachineCode::emit_brk(self : MachineCode, imm16 : Int) -> Unit {
Brk(imm16).emit(self)
}
///|
fn MachineCode::emit_cbnz_offset(
self : MachineCode,
rt : Int,
is_64 : Bool,
offset_bytes : Int,
) -> Unit {
CbnzOffset(rt, is_64, offset_bytes).emit(self)
}
///|
pub fn MachineCode::emit_ret(self : MachineCode, rn : Int) -> Unit {
Ret(rn).emit(self)
}
///|
pub fn MachineCode::emit_br(self : MachineCode, rn : Int) -> Unit {
Br(rn).emit(self)
}
///|
pub fn MachineCode::emit_adr(
self : MachineCode,
rd : Int,
offset : Int,
) -> Unit {
Adr(rd, offset).emit(self)
}
///|
pub fn MachineCode::emit_bl(self : MachineCode, target_block : Int) -> Unit {
Bl(target_block).emit(self)
}
///|
pub fn MachineCode::emit_blr(self : MachineCode, rn : Int) -> Unit {
Blr(rn).emit(self)
}
///|
pub fn MachineCode::emit_dmb_ish(self : MachineCode) -> Unit {
DmbIsh.emit(self)
}
///|
pub fn MachineCode::emit_cmp_reg(
self : MachineCode,
rn : Int,
rm : Int,
) -> Unit {
CmpReg(rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_cmp_imm(
self : MachineCode,
rn : Int,
imm : Int,
) -> Unit {
// AArch64 CMP immediate supports a 12-bit unsigned immediate, optionally shifted left by 12.
//
// For larger/negative immediates, materialize the value in a reserved scratch register and
// use CMP (register) instead. This avoids silent truncation of imm12.
if imm >= 0 && imm <= 4095 {
CmpImm(rn, imm).emit(self)
} else if imm >= 0 && (imm & 0xFFF) == 0 && imm >> 12 <= 4095 {
CmpImmShifted12(rn, imm >> 12).emit(self)
} else {
let scratch = self.isa.scratch_reg_1_index()
self.emit_load_imm64(scratch, imm.to_int64())
self.emit_cmp_reg(rn, scratch)
}
}
///|
pub fn MachineCode::emit_cset(self : MachineCode, rd : Int, cond : Int) -> Unit {
Cset(rd, cond).emit(self)
}
///|
pub fn MachineCode::emit_csel(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
cond : Int,
) -> Unit {
Csel(rd, rn, rm, cond).emit(self)
}
///|
pub fn MachineCode::emit_fcsel_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
cond : Int,
) -> Unit {
FcselD(rd, rn, rm, cond).emit(self)
}
///|
pub fn MachineCode::emit_fcsel_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
cond : Int,
) -> Unit {
FcselS(rd, rn, rm, cond).emit(self)
}
///|
pub fn MachineCode::emit_fadd_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FaddD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fadd_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FaddS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fsub_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FsubD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fsub_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FsubS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmul_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FmulD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmul_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FmulS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fdiv_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FdivD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fdiv_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FdivS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmax_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FmaxD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmax_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FmaxS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmin_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FminD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmin_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FminS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmaxnm_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FmaxnmD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmaxnm_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FmaxnmS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fminnm_d(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FminnmD(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fminnm_s(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
) -> Unit {
FminnmS(rd, rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fsqrt_d(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FsqrtD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fsqrt_s(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FsqrtS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fabs_d(self : MachineCode, rd : Int, rn : Int) -> Unit {
FabsD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fabs_s(self : MachineCode, rd : Int, rn : Int) -> Unit {
FabsS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fneg_d(self : MachineCode, rd : Int, rn : Int) -> Unit {
FnegD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fneg_s(self : MachineCode, rd : Int, rn : Int) -> Unit {
FnegS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintp_d(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintpD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintp_s(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintpS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintm_d(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintmD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintm_s(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintmS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintz_d(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintzD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintz_s(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintzS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintn_d(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintnD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_frintn_s(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FrintnS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fmov_d(self : MachineCode, rd : Int, rm : Int) -> Unit {
FmovD(rd, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmov_s(self : MachineCode, rd : Int, rm : Int) -> Unit {
FmovS(rd, rm).emit(self)
}
///|
pub fn MachineCode::emit_fmov_d_to_x(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FmovDToX(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fmov_s_to_w(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FmovSToW(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fmov_x_to_d(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FmovXToD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fmov_w_to_s(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FmovWToS(rd, rn).emit(self)
}
///|
/// EXT Vd.16B, Vn.16B, Vm.16B, #imm
/// Extract and concatenate bytes from two vectors
/// imm is the byte offset (0-15)
pub fn MachineCode::emit_ext_16b(
self : MachineCode,
rd : Int,
rn : Int,
rm : Int,
imm : Int,
) -> Unit {
// EXT Vd.16B, Vn.16B, Vm.16B, #imm: 0x6E000000 | (Rm << 16) | (imm4 << 11) | (Rn << 5) | Rd
let enc = 0x6E000000 |
((rm & 31) << 16) |
((imm & 15) << 11) |
((rn & 31) << 5) |
(rd & 31)
let b0 = enc & 0xFF
let b1 = (enc >> 8) & 0xFF
let b2 = (enc >> 16) & 0xFF
let b3 = (enc >> 24) & 0xFF
self.emit_inst(b0, b1, b2, b3)
}
///|
pub fn MachineCode::emit_fcvt_d_s(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FcvtDS(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_fcvt_s_d(
self : MachineCode,
rd : Int,
rn : Int,
) -> Unit {
FcvtSD(rd, rn).emit(self)
}
///|
pub fn MachineCode::emit_ldr_s_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrSImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_str_s_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
StrSImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_ldr_d_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
LdrDImm(rt, rn, imm12).emit(self)
}
///|
pub fn MachineCode::emit_str_d_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm12 : Int,
) -> Unit {
StrDImm(rt, rn, imm12).emit(self)
}
///|
/// LDR Qt, [Xn, #imm] (128-bit Q-register load)
pub fn MachineCode::emit_ldr_q_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm : Int,
) -> Unit {
LdrQ(rt, rn, imm).emit(self)
}
///|
/// STR Qt, [Xn, #imm] (128-bit Q-register store)
pub fn MachineCode::emit_str_q_imm(
self : MachineCode,
rt : Int,
rn : Int,
imm : Int,
) -> Unit {
StrQ(rt, rn, imm).emit(self)
}
///|
fn MachineCode::emit_str_offset(
self : MachineCode,
rt : Int,
rn : Int,
offset : Int,
) -> Unit {
StrImm(rt, rn, offset).emit(self)
}
///|
fn MachineCode::emit_str_d_offset(
self : MachineCode,
rt : Int,
rn : Int,
offset : Int,
) -> Unit {
StrDImm(rt, rn, offset).emit(self)
}
///|
/// Emit STP with signed offset (not pre/post indexed)
pub fn MachineCode::emit_stp_offset(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
offset : Int,
) -> Unit {
StpOffset(rt1, rt2, rn, offset).emit(self)
}
///|
/// Emit LDP with signed offset (not pre/post indexed)
pub fn MachineCode::emit_ldp_offset(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
offset : Int,
) -> Unit {
LdpOffset(rt1, rt2, rn, offset).emit(self)
}
///|
/// Emit STP for FPR pairs (64-bit D registers) with signed offset
pub fn MachineCode::emit_stp_d_offset(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
offset : Int,
) -> Unit {
StpDOffset(rt1, rt2, rn, offset).emit(self)
}
///|
/// Emit LDP for FPR pairs (64-bit D registers) with signed offset
pub fn MachineCode::emit_ldp_d_offset(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
offset : Int,
) -> Unit {
LdpDOffset(rt1, rt2, rn, offset).emit(self)
}
///|
/// Emit STR with pre-indexed addressing: STR Xt, [Xn, #simm9]!
pub fn MachineCode::emit_str_pre(
self : MachineCode,
rt : Int,
rn : Int,
simm9 : Int,
) -> Unit {
StrPre(rt, rn, simm9).emit(self)
}
///|
/// Emit STP for FPR pairs with pre-indexed addressing: STP Dt1, Dt2, [Xn, #imm]!
pub fn MachineCode::emit_stp_d_pre(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
imm : Int,
) -> Unit {
StpDPre(rt1, rt2, rn, imm).emit(self)
}
///|
/// Emit STR for FPR with pre-indexed addressing: STR Dt, [Xn, #simm9]!
pub fn MachineCode::emit_str_d_pre(
self : MachineCode,
rt : Int,
rn : Int,
simm9 : Int,
) -> Unit {
StrDPre(rt, rn, simm9).emit(self)
}
///|
/// Emit LDR with post-indexed addressing: LDR Xt, [Xn], #simm9
pub fn MachineCode::emit_ldr_post(
self : MachineCode,
rt : Int,
rn : Int,
simm9 : Int,
) -> Unit {
LdrPost(rt, rn, simm9).emit(self)
}
///|
/// Emit LDP for FPR pairs with post-indexed addressing: LDP Dt1, Dt2, [Xn], #imm
pub fn MachineCode::emit_ldp_d_post(
self : MachineCode,
rt1 : Int,
rt2 : Int,
rn : Int,
imm : Int,
) -> Unit {
LdpDPost(rt1, rt2, rn, imm).emit(self)
}
///|
/// Emit LDR for FPR with post-indexed addressing: LDR Dt, [Xn], #simm9
pub fn MachineCode::emit_ldr_d_post(
self : MachineCode,
rt : Int,
rn : Int,
simm9 : Int,
) -> Unit {
LdrDPost(rt, rn, simm9).emit(self)
}
///|
pub fn MachineCode::emit_fcmp_d(self : MachineCode, rn : Int, rm : Int) -> Unit {
FcmpD(rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_fcmp_s(self : MachineCode, rn : Int, rm : Int) -> Unit {
FcmpS(rn, rm).emit(self)
}
///|
pub fn MachineCode::emit_nop(self : MachineCode) -> Unit {
Nop.emit(self)
}
///|
/// CNT Vd.8B, Vn.8B - count bits in each byte
pub fn MachineCode::emit_cnt_8b(self : MachineCode, rd : Int, rn : Int) -> Unit {
Cnt8B(rd, rn).emit(self)
}
///|
/// ADDV Bd, Vn.8B - sum all bytes into Bd
pub fn MachineCode::emit_addv_b(self : MachineCode, rd : Int, rn : Int) -> Unit {
AddvB(rd, rn).emit(self)
}