improv(compiler) Added some machine_arm64 methods

This commit is contained in:
ptitSeb
2021-12-13 16:34:44 +01:00
parent 26d334f4ac
commit 900220826e
2 changed files with 412 additions and 164 deletions

View File

@@ -70,17 +70,20 @@ pub trait EmitterARM64 {
fn emit_str(&mut self, sz: Size, src: Location, dst: Location);
fn emit_ldr(&mut self, sz: Size, src: Location, dst: Location);
fn emit_stur(&mut self, sz: Size, reg: Location, addr: GPR, offset: i32);
fn emit_ldur(&mut self, sz: Size, reg: Location, addr: GPR, offset: i32);
fn emit_strbd(&mut self, sz: Size, reg: Location, addr: GPR, offset: u32);
fn emit_ldrai(&mut self, sz: Size, reg: Location, addr: GPR, offset: u32);
fn emit_stpbd(&mut self, sz: Size, reg1: Location, reg2: Location, addr: GPR, offset: u32);
fn emit_ldpai(&mut self, sz: Size, reg1: Location, reg2: Location, addr: GPR, offset: u32);
fn emit_mov(&mut self, sz: Size, src: Location, dst: Location);
fn emit_mov_imm(&mut self, dst: Location, val: u64);
fn emit_add(&mut self, sz: Size, src1: Location, src2: Location, dst: Location);
fn emit_sub(&mut self, sz: Size, src1: Location, src2: Location, dst: Location);
fn emit_push(&mut self, sz: Size, src: Location);
fn emit_double_push(&mut self, sz: Size, src1: Location, src2: Location);
fn emit_pop(&mut self, sz: Size, dst: Location);
fn emit_double_pop(&mut self, sz: Size, dst1: Location, dst2: Location);
fn emit_label(&mut self, label: Label);
fn emit_b_label(&mut self, label: Label);
fn emit_bcond_label(&mut self, condition: Condition, label: Label);
@@ -198,6 +201,146 @@ impl EmitterARM64 for Assembler {
_ => unreachable!(),
}
}
fn emit_stur(&mut self, sz: Size, reg: Location, addr: GPR, offset: i32) {
match (sz, reg) {
(Size::S64, Location::GPR(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; stur X(reg), [X(addr), offset]);
}
(Size::S32, Location::GPR(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; stur W(reg), [X(addr), offset]);
}
(Size::S64, Location::SIMD(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; stur D(reg), [X(addr), offset]);
}
_ => unreachable!(),
}
}
fn emit_ldur(&mut self, sz: Size, reg: Location, addr: GPR, offset: i32) {
match (sz, reg) {
(Size::S64, Location::GPR(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; ldur X(reg), [X(addr), offset]);
}
(Size::S32, Location::GPR(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; ldur W(reg), [X(addr), offset]);
}
(Size::S64, Location::SIMD(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; ldur D(reg), [X(addr), offset]);
}
_ => unreachable!(),
}
}
fn emit_strbd(&mut self, sz: Size, reg: Location, addr: GPR, offset: u32) {
match (sz, reg) {
(Size::S64, Location::GPR(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; str X(reg), [X(addr), -(offset as i32)]!);
}
(Size::S64, Location::SIMD(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; str D(reg), [X(addr), -(offset as i32)]!);
}
_ => unreachable!(),
}
}
fn emit_ldrai(&mut self, sz: Size, reg: Location, addr: GPR, offset: u32) {
match (sz, reg) {
(Size::S64, Location::GPR(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; ldr X(reg), [X(addr)], offset);
}
(Size::S64, Location::SIMD(reg)) => {
let reg = reg.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; ldr D(reg), [X(addr)], offset);
}
_ => unreachable!(),
}
}
fn emit_stpbd(&mut self, sz: Size, reg1: Location, reg2: Location, addr: GPR, offset: u32) {
match (sz, reg1, reg2) {
(Size::S64, Location::GPR(reg1), Location::GPR(reg2)) => {
let reg1 = reg1.into_index() as u32;
let reg2 = reg2.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; stp X(reg1), X(reg2), [X(addr), -(offset as i32)]!);
}
_ => unreachable!(),
}
}
fn emit_ldpai(&mut self, sz: Size, reg1: Location, reg2: Location, addr: GPR, offset: u32) {
match (sz, reg1, reg2) {
(Size::S64, Location::GPR(reg1), Location::GPR(reg2)) => {
let reg1 = reg1.into_index() as u32;
let reg2 = reg2.into_index() as u32;
let addr = addr.into_index() as u32;
dynasm!(self ; ldp X(reg1), X(reg2), [X(addr)], offset);
}
_ => unreachable!(),
}
}
fn emit_mov(&mut self, sz: Size, src: Location, dst: Location) {
match(sz, src, dst) {
(Size::S64, Location::GPR(src), Location::GPR(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov X(dst), X(src));
}
(Size::S32, Location::GPR(src), Location::GPR(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov W(dst), W(src));
}
(Size::S64, Location::SIMD(src), Location::SIMD(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov V(dst).D[0], V(src).D[0]);
}
(Size::S32, Location::SIMD(src), Location::SIMD(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov V(dst).S[0], V(src).S[0]);
}
(Size::S64, Location::GPR(src), Location::SIMD(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov V(dst).D[0], X(src));
}
(Size::S32, Location::GPR(src), Location::SIMD(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov V(dst).S[0], W(src));
}
(Size::S64, Location::SIMD(src), Location::GPR(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov X(dst), V(src).D[0]);
}
(Size::S32, Location::SIMD(src), Location::GPR(dst)) => {
let src = src.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; mov W(dst), V(src).S[0]);
}
_ => unreachable!(),
}
}
fn emit_mov_imm(&mut self, dst: Location, val: u64) {
match dst {
@@ -229,6 +372,16 @@ impl EmitterARM64 for Assembler {
let dst = dst.into_index() as u32;
dynasm!(self ; add W(dst), W(src1), W(src2));
}
(Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
let src1 = src1.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; add X(dst), X(src1), imm as u32);
}
(Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
let src1 = src1.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; add W(dst), W(src1), imm as u32);
}
_ => panic!(
"singlepass can't emit ADD {:?} {:?} {:?} {:?}",
sz, src1, src2, dst
@@ -249,6 +402,16 @@ impl EmitterARM64 for Assembler {
let dst = dst.into_index() as u32;
dynasm!(self ; sub W(dst), W(src1), W(src2));
}
(Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
let src1 = src1.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; sub X(dst), X(src1), imm as u32);
}
(Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => {
let src1 = src1.into_index() as u32;
let dst = dst.into_index() as u32;
dynasm!(self ; sub W(dst), W(src1), imm as u32);
}
_ => panic!(
"singlepass can't emit ADD {:?} {:?} {:?} {:?}",
sz, src1, src2, dst
@@ -256,59 +419,6 @@ impl EmitterARM64 for Assembler {
}
}
fn emit_push(&mut self, sz: Size, src: Location) {
match (sz, src) {
(Size::S64, Location::GPR(src)) => {
let src = src.into_index() as u32;
dynasm!(self ; str X(src), [sp, -16]!);
}
(Size::S64, Location::SIMD(src)) => {
let src = src.into_index() as u32;
dynasm!(self ; str Q(src), [sp, -16]!);
}
_ => panic!("singlepass can't emit PUSH {:?} {:?}", sz, src),
}
}
fn emit_double_push(&mut self, sz: Size, src1: Location, src2: Location) {
match (sz, src1, src2) {
(Size::S64, Location::GPR(src1), Location::GPR(src2)) => {
let src1 = src1.into_index() as u32;
let src2 = src2.into_index() as u32;
dynasm!(self ; stp X(src1), X(src2), [sp, -16]!);
}
_ => panic!(
"singlepass can't emit DOUBLE PUSH {:?} {:?} {:?}",
sz, src1, src2
),
}
}
fn emit_pop(&mut self, sz: Size, dst: Location) {
match (sz, dst) {
(Size::S64, Location::GPR(dst)) => {
let dst = dst.into_index() as u32;
dynasm!(self ; ldr X(dst), [sp], 16);
}
(Size::S64, Location::SIMD(dst)) => {
let dst = dst.into_index() as u32;
dynasm!(self ; ldr Q(dst), [sp], 16);
}
_ => panic!("singlepass can't emit PUSH {:?} {:?}", sz, dst),
}
}
fn emit_double_pop(&mut self, sz: Size, dst1: Location, dst2: Location) {
match (sz, dst1, dst2) {
(Size::S64, Location::GPR(dst1), Location::GPR(dst2)) => {
let dst1 = dst1.into_index() as u32;
let dst2 = dst2.into_index() as u32;
dynasm!(self ; ldp X(dst1), X(dst2), [sp], 16);
}
_ => panic!(
"singlepass can't emit DOUBLE PUSH {:?} {:?} {:?}",
sz, dst1, dst2
),
}
}
fn emit_label(&mut self, label: Label) {
self.emit_label(label);
}

View File

@@ -28,6 +28,8 @@ pub struct MachineARM64 {
instructions_address_map: Vec<InstructionAddressMap>,
/// The source location for the current operator.
src_loc: u32,
/// is last push on a 8byte multiple or 16bytes?
pushed: bool,
}
impl MachineARM64 {
@@ -39,24 +41,25 @@ impl MachineARM64 {
trap_table: TrapTable::default(),
instructions_address_map: vec![],
src_loc: 0,
pushed: false,
}
}
pub fn emit_relaxed_binop(
fn emit_relaxed_binop(
&mut self,
op: fn(&mut Assembler, Size, Location, Location),
sz: Size,
src: Location,
dst: Location,
_op: fn(&mut Assembler, Size, Location, Location),
_sz: Size,
_src: Location,
_dst: Location,
) {
unimplemented!();
}
/// I32 binary operation with both operands popped from the virtual stack.
fn emit_binop_i32(
&mut self,
f: fn(&mut Assembler, Size, Location, Location),
loc_a: Location,
loc_b: Location,
ret: Location,
_f: fn(&mut Assembler, Size, Location, Location),
_loc_a: Location,
_loc_b: Location,
_ret: Location,
) {
unimplemented!();
}
@@ -81,73 +84,73 @@ impl MachineARM64 {
/// I64 comparison with.
fn emit_cmpop_i64_dynamic_b(
&mut self,
c: Condition,
loc_a: Location,
loc_b: Location,
ret: Location,
_c: Condition,
_loc_a: Location,
_loc_b: Location,
_ret: Location,
) {
unimplemented!();
}
/// I64 shift with both operands popped from the virtual stack.
fn emit_shift_i64(
&mut self,
f: fn(&mut Assembler, Size, Location, Location),
loc_a: Location,
loc_b: Location,
ret: Location,
_f: fn(&mut Assembler, Size, Location, Location),
_loc_a: Location,
_loc_b: Location,
_ret: Location,
) {
unimplemented!();
}
/// I32 comparison with.
fn emit_cmpop_i32_dynamic_b(
&mut self,
c: Condition,
loc_a: Location,
loc_b: Location,
ret: Location,
_c: Condition,
_loc_a: Location,
_loc_b: Location,
_ret: Location,
) {
unimplemented!();
}
/// I32 shift with both operands popped from the virtual stack.
fn emit_shift_i32(
&mut self,
f: fn(&mut Assembler, Size, Location, Location),
loc_a: Location,
loc_b: Location,
ret: Location,
_f: fn(&mut Assembler, Size, Location, Location),
_loc_a: Location,
_loc_b: Location,
_ret: Location,
) {
unimplemented!();
}
fn memory_op<F: FnOnce(&mut Self, GPR)>(
&mut self,
addr: Location,
memarg: &MemoryImmediate,
check_alignment: bool,
value_size: usize,
need_check: bool,
imported_memories: bool,
offset: i32,
heap_access_oob: Label,
cb: F,
_addr: Location,
_memarg: &MemoryImmediate,
_check_alignment: bool,
_value_size: usize,
_need_check: bool,
_imported_memories: bool,
_offset: i32,
_heap_access_oob: Label,
_cb: F,
) {
unimplemented!();
}
fn emit_compare_and_swap<F: FnOnce(&mut Self, GPR, GPR)>(
&mut self,
loc: Location,
target: Location,
ret: Location,
memarg: &MemoryImmediate,
value_size: usize,
memory_sz: Size,
stack_sz: Size,
need_check: bool,
imported_memories: bool,
offset: i32,
heap_access_oob: Label,
cb: F,
_loc: Location,
_target: Location,
_ret: Location,
_memarg: &MemoryImmediate,
_value_size: usize,
_memory_sz: Size,
_stack_sz: Size,
_need_check: bool,
_imported_memories: bool,
_offset: i32,
_heap_access_oob: Label,
_cb: F,
) {
unimplemented!();
}
@@ -155,13 +158,13 @@ impl MachineARM64 {
// Checks for underflow/overflow/nan.
fn emit_f32_int_conv_check(
&mut self,
reg: NEON,
lower_bound: f32,
upper_bound: f32,
underflow_label: Label,
overflow_label: Label,
nan_label: Label,
succeed_label: Label,
_reg: NEON,
_lower_bound: f32,
_upper_bound: f32,
_underflow_label: Label,
_overflow_label: Label,
_nan_label: Label,
_succeed_label: Label,
) {
unimplemented!();
}
@@ -177,26 +180,26 @@ impl MachineARM64 {
F4: FnOnce(&mut Self),
>(
&mut self,
reg: NEON,
lower_bound: f32,
upper_bound: f32,
underflow_cb: F1,
overflow_cb: F2,
nan_cb: Option<F3>,
convert_cb: F4,
_reg: NEON,
_lower_bound: f32,
_upper_bound: f32,
_underflow_cb: F1,
_overflow_cb: F2,
_nan_cb: Option<F3>,
_convert_cb: F4,
) {
unimplemented!();
}
// Checks for underflow/overflow/nan.
fn emit_f64_int_conv_check(
&mut self,
reg: NEON,
lower_bound: f64,
upper_bound: f64,
underflow_label: Label,
overflow_label: Label,
nan_label: Label,
succeed_label: Label,
_reg: NEON,
_lower_bound: f64,
_upper_bound: f64,
_underflow_label: Label,
_overflow_label: Label,
_nan_label: Label,
_succeed_label: Label,
) {
unimplemented!();
}
@@ -211,65 +214,143 @@ impl MachineARM64 {
F4: FnOnce(&mut Self),
>(
&mut self,
reg: NEON,
lower_bound: f64,
upper_bound: f64,
underflow_cb: F1,
overflow_cb: F2,
nan_cb: Option<F3>,
convert_cb: F4,
_reg: NEON,
_lower_bound: f64,
_upper_bound: f64,
_underflow_cb: F1,
_overflow_cb: F2,
_nan_cb: Option<F3>,
_convert_cb: F4,
) {
unimplemented!();
}
fn convert_i64_f64_u_s(&mut self, loc: Location, ret: Location) {
fn convert_i64_f64_u_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i64_f64_u_u(&mut self, loc: Location, ret: Location) {
fn convert_i64_f64_u_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i64_f64_s_s(&mut self, loc: Location, ret: Location) {
fn convert_i64_f64_s_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i64_f64_s_u(&mut self, loc: Location, ret: Location) {
fn convert_i64_f64_s_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f64_s_s(&mut self, loc: Location, ret: Location) {
fn convert_i32_f64_s_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f64_s_u(&mut self, loc: Location, ret: Location) {
fn convert_i32_f64_s_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f64_u_s(&mut self, loc: Location, ret: Location) {
fn convert_i32_f64_u_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f64_u_u(&mut self, loc: Location, ret: Location) {
fn convert_i32_f64_u_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i64_f32_u_s(&mut self, loc: Location, ret: Location) {
fn convert_i64_f32_u_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i64_f32_u_u(&mut self, loc: Location, ret: Location) {
fn convert_i64_f32_u_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i64_f32_s_s(&mut self, loc: Location, ret: Location) {
fn convert_i64_f32_s_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i64_f32_s_u(&mut self, loc: Location, ret: Location) {
fn convert_i64_f32_s_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f32_s_s(&mut self, loc: Location, ret: Location) {
fn convert_i32_f32_s_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f32_s_u(&mut self, loc: Location, ret: Location) {
fn convert_i32_f32_s_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f32_u_s(&mut self, loc: Location, ret: Location) {
fn convert_i32_f32_u_s(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn convert_i32_f32_u_u(&mut self, loc: Location, ret: Location) {
fn convert_i32_f32_u_u(&mut self, _loc: Location, _ret: Location) {
unimplemented!();
}
fn offset_is_ok(&self, size: Size, offset: i32) -> bool {
if offset<0 { return false;}
let shift = match size {
Size::S8 => 0,
Size::S16 => 1,
Size::S32 => 2,
Size::S64 => 3,
};
if offset >= 0x1000<<shift { return false; }
if (offset>>shift)<<shift != offset { return false; }
return true;
}
fn emit_push(&mut self, sz: Size, src: Location) {
match (sz, src) {
(Size::S64, Location::GPR(_)) | (Size::S64, Location::SIMD(_)) => {
let offset = if self.pushed {
8
} else {
self.assembler.emit_sub(Size::S64, Location::GPR(GPR::XzrSp), Location::GPR(GPR::XzrSp), Location::Imm8(16));
0
};
self.assembler.emit_str(Size::S64, src, Location::Memory(GPR::XzrSp, offset));
self.pushed = !self.pushed;
}
_ => panic!("singlepass can't emit PUSH {:?} {:?}", sz, src),
}
}
fn emit_double_push(&mut self, sz: Size, src1: Location, src2: Location) {
if !self.pushed {
match (sz, src1, src2) {
(Size::S64, Location::GPR(_), Location::GPR(_)) => {
self.assembler.emit_stpbd(Size::S64, src1, src2, GPR::XzrSp, 16);
}
_ => {
self.emit_push(sz, src1);
self.emit_push(sz, src2);
}
}
} else {
self.emit_push(sz, src1);
self.emit_push(sz, src2);
}
}
fn emit_pop(&mut self, sz: Size, dst: Location) {
match (sz, dst) {
(Size::S64, Location::GPR(_)) | (Size::S64, Location::SIMD(_)) => {
let offset = if self.pushed {
0
} else {
8
};
self.assembler.emit_ldr(Size::S64, dst, Location::Memory(GPR::XzrSp, offset));
if self.pushed {
self.assembler.emit_add(Size::S64, Location::GPR(GPR::XzrSp), Location::GPR(GPR::XzrSp), Location::Imm8(16));
}
self.pushed = !self.pushed;
}
_ => panic!("singlepass can't emit PUSH {:?} {:?}", sz, dst),
}
}
fn emit_double_pop(&mut self, sz: Size, dst1: Location, dst2: Location) {
if !self.pushed {
match (sz, dst1, dst2) {
(Size::S64, Location::GPR(_), Location::GPR(_)) => {
self.assembler.emit_ldpai(Size::S64, dst1, dst2, GPR::XzrSp, 16);
}
_ => {
self.emit_pop(sz, dst2);
self.emit_pop(sz, dst1);
}
}
} else {
self.emit_pop(sz, dst2);
self.emit_pop(sz, dst1);
}
}
}
impl Machine for MachineARM64 {
@@ -347,13 +428,13 @@ impl Machine for MachineARM64 {
fn push_used_gpr(&mut self) {
let used_gprs = self.get_used_gprs();
for r in used_gprs.iter() {
self.assembler.emit_push(Size::S64, Location::GPR(*r));
self.emit_push(Size::S64, Location::GPR(*r));
}
}
fn pop_used_gpr(&mut self) {
let used_gprs = self.get_used_gprs();
for r in used_gprs.iter().rev() {
self.assembler.emit_pop(Size::S64, Location::GPR(*r));
self.emit_pop(Size::S64, Location::GPR(*r));
}
}
@@ -420,10 +501,17 @@ impl Machine for MachineARM64 {
Location::Memory(GPR::XzrSp, (i * 8) as i32),
);
}
let delta = if (used_neons.len() * 8) < 256 {
Location::Imm8((used_neons.len() * 8) as u8)
} else {
let tmp = self.pick_temp_gpr().unwrap();
self.assembler.emit_mov_imm(Location::GPR(tmp), (used_neons.len() * 8) as u64);
Location::GPR(tmp)
};
self.assembler.emit_add(
Size::S64,
Location::GPR(GPR::XzrSp),
Location::Imm32((used_neons.len() * 8) as u32),
delta,
Location::GPR(GPR::XzrSp),
);
}
@@ -495,29 +583,50 @@ impl Machine for MachineARM64 {
// Adjust stack for locals
fn adjust_stack(&mut self, delta_stack_offset: u32) {
let delta = if delta_stack_offset < 256 {
Location::Imm8(delta_stack_offset as u8)
} else {
let tmp = self.pick_temp_gpr().unwrap();
self.assembler.emit_mov_imm(Location::GPR(tmp), delta_stack_offset as u64);
Location::GPR(tmp)
};
self.assembler.emit_sub(
Size::S64,
Location::GPR(GPR::XzrSp),
Location::Imm32(delta_stack_offset),
delta,
Location::GPR(GPR::XzrSp),
);
}
// restore stack
fn restore_stack(&mut self, delta_stack_offset: u32) {
let delta = if delta_stack_offset < 256 {
Location::Imm8(delta_stack_offset as u8)
} else {
let tmp = self.pick_temp_gpr().unwrap();
self.assembler.emit_mov_imm(Location::GPR(tmp), delta_stack_offset as u64);
Location::GPR(tmp)
};
self.assembler.emit_add(
Size::S64,
Location::GPR(GPR::XzrSp),
Location::Imm32(delta_stack_offset),
delta,
Location::GPR(GPR::XzrSp),
);
}
fn push_callee_saved(&mut self) {}
fn pop_callee_saved(&mut self) {}
fn pop_stack_locals(&mut self, delta_stack_offset: u32) {
let delta = if delta_stack_offset < 256 {
Location::Imm8(delta_stack_offset as u8)
} else {
let tmp = self.pick_temp_gpr().unwrap();
self.assembler.emit_mov_imm(Location::GPR(tmp), delta_stack_offset as u64);
Location::GPR(tmp)
};
self.assembler.emit_add(
Size::S64,
Location::GPR(GPR::XzrSp),
Location::Imm32(delta_stack_offset),
delta,
Location::GPR(GPR::XzrSp),
);
}
@@ -527,10 +636,10 @@ impl Machine for MachineARM64 {
Location::Imm64(_) => {
self.reserve_unused_temp_gpr(GPR::X4);
self.move_location(Size::S64, loc, Location::GPR(GPR::X4));
self.assembler.emit_push(Size::S64, Location::GPR(GPR::X4));
self.emit_push(Size::S64, Location::GPR(GPR::X4));
self.release_gpr(GPR::X4);
}
_ => self.assembler.emit_push(Size::S64, loc),
_ => self.emit_push(Size::S64, loc),
}
}
@@ -569,7 +678,14 @@ impl Machine for MachineARM64 {
}
// Move a local to the stack
fn move_local(&mut self, stack_offset: i32, location: Location) {
unimplemented!();
if stack_offset<256 {
self.assembler.emit_stur(Size::S64, location, GPR::X27, -stack_offset);
} else {
let tmp = self.pick_temp_gpr().unwrap();
self.assembler.emit_mov_imm(Location::GPR(tmp), stack_offset as u64);
self.assembler.emit_sub(Size::S64, Location::GPR(GPR::X27), Location::GPR(tmp), Location::GPR(tmp));
self.assembler.emit_str(Size::S64, location, Location::GPR(tmp));
}
}
// List of register to save, depending on the CallingConvention
@@ -595,7 +711,30 @@ impl Machine for MachineARM64 {
}
// move a location to another
fn move_location(&mut self, size: Size, source: Location, dest: Location) {
unimplemented!();
match source {
Location::GPR(_) | Location::SIMD(_) => {
match dest {
Location::GPR(_) | Location::SIMD(_) => self.assembler.emit_mov(size, source, dest),
Location::Memory(addr, offs) => {
if self.offset_is_ok(size, offs) {
self.assembler.emit_str(size, source, dest);
} else {
let tmp = self.pick_temp_gpr().unwrap();
if offs < 0 {
self.assembler.emit_mov_imm(Location::GPR(tmp), (-offs) as u64);
self.assembler.emit_sub(Size::S64, Location::GPR(addr), Location::GPR(tmp), Location::GPR(tmp));
} else {
self.assembler.emit_mov_imm(Location::GPR(tmp), offs as u64);
self.assembler.emit_add(Size::S64, Location::GPR(addr), Location::GPR(tmp), Location::GPR(tmp));
}
self.assembler.emit_str(size, source,Location::GPR(tmp));
}
}
_ => unimplemented!(),
}
}
_ => unimplemented!(),
}
}
// move a location to another
fn move_location_extend(
@@ -621,7 +760,7 @@ impl Machine for MachineARM64 {
}
// Pop a location
fn pop_location(&mut self, location: Location) {
self.assembler.emit_pop(Size::S64, location);
self.emit_pop(Size::S64, location);
}
// Create a new `MachineState` with default values.
fn new_machine_state(&self) -> MachineState {
@@ -642,7 +781,7 @@ impl Machine for MachineARM64 {
}
fn emit_function_prolog(&mut self) {
self.assembler.emit_double_push(
self.emit_double_push(
Size::S64,
Location::GPR(GPR::X27),
Location::GPR(GPR::X30),
@@ -660,8 +799,7 @@ impl Machine for MachineARM64 {
Location::GPR(GPR::X27),
Location::GPR(GPR::XzrSp),
);
self.assembler
.emit_double_pop(Size::S64, Location::GPR(GPR::X27), Location::GPR(GPR::X30));
self.emit_double_pop(Size::S64, Location::GPR(GPR::X27), Location::GPR(GPR::X30));
}
fn emit_function_return_value(&mut self, ty: WpType, canonicalize: bool, loc: Location) {
@@ -793,10 +931,10 @@ impl Machine for MachineARM64 {
}
fn emit_push(&mut self, size: Size, loc: Location) {
self.assembler.emit_push(size, loc);
self.emit_push(size, loc);
}
fn emit_pop(&mut self, size: Size, loc: Location) {
self.assembler.emit_pop(size, loc);
self.emit_pop(size, loc);
}
fn emit_memory_fence(&mut self) {