diff --git a/lib/dynasm-backend/src/codegen_x64.rs b/lib/dynasm-backend/src/codegen_x64.rs index 8620781d5..9ad27d2e4 100644 --- a/lib/dynasm-backend/src/codegen_x64.rs +++ b/lib/dynasm-backend/src/codegen_x64.rs @@ -1172,7 +1172,7 @@ impl FunctionCodeGenerator for X64FunctionCode { } fn feed_opcode(&mut self, op: Operator, module_info: &ModuleInfo) -> Result<(), CodegenError> { - println!("{:?} {}", op, self.value_stack.len()); + //println!("{:?} {}", op, self.value_stack.len()); let was_unreachable; if self.unreachable_depth > 0 { @@ -1363,11 +1363,7 @@ impl FunctionCodeGenerator for X64FunctionCode { Operator::I32GeS => Self::emit_cmpop_i32(a, &mut self.machine, &mut self.value_stack, Condition::GreaterEqual), Operator::I64Const { value } => { let value = value as u64; - if value <= ::std::u32::MAX as u64 { - self.value_stack.push((Location::Imm32(value as u32), LocalOrTemp::Temp)) - } else { - self.value_stack.push((Location::Imm64(value), LocalOrTemp::Temp)) - } + self.value_stack.push((Location::Imm64(value), LocalOrTemp::Temp)); }, Operator::I64Add => Self::emit_binop_i64(a, &mut self.machine, &mut self.value_stack, Assembler::emit_add), Operator::I64Sub => Self::emit_binop_i64(a, &mut self.machine, &mut self.value_stack, Assembler::emit_sub), @@ -1770,7 +1766,7 @@ impl FunctionCodeGenerator for X64FunctionCode { self.machine.release_temp_gpr(tmp_in); self.machine.release_temp_xmm(tmp_out); } - Operator::F32ConvertSI64 | Operator::F32ConvertUI64 /* FIXME: INCORRECT */ => { + Operator::F32ConvertSI64 => { let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap()); let ret = self.machine.acquire_locations(a, &[WpType::F32], false)[0]; self.value_stack.push((ret, LocalOrTemp::Temp)); @@ -1784,6 +1780,36 @@ impl FunctionCodeGenerator for X64FunctionCode { self.machine.release_temp_gpr(tmp_in); self.machine.release_temp_xmm(tmp_out); } + Operator::F32ConvertUI64 => { + let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap()); + let ret = self.machine.acquire_locations(a, &[WpType::F32], false)[0]; + self.value_stack.push((ret, LocalOrTemp::Temp)); + let tmp_out = self.machine.acquire_temp_xmm().unwrap(); + let tmp_in = self.machine.acquire_temp_gpr().unwrap(); + let tmp = self.machine.acquire_temp_gpr().unwrap(); + + let do_convert = a.get_label(); + let end_convert = a.get_label(); + + a.emit_mov(Size::S64, loc, Location::GPR(tmp_in)); + a.emit_test_gpr_64(tmp_in); + a.emit_jmp(Condition::Signed, do_convert); + a.emit_vcvtsi2ss_64(tmp_out, GPROrMemory::GPR(tmp_in), tmp_out); + a.emit_jmp(Condition::None, end_convert); + a.emit_label(do_convert); + a.emit_mov(Size::S64, Location::GPR(tmp_in), Location::GPR(tmp)); + a.emit_and(Size::S64, Location::Imm32(1), Location::GPR(tmp)); + a.emit_shr(Size::S64, Location::Imm8(1), Location::GPR(tmp_in)); + a.emit_or(Size::S64, Location::GPR(tmp), Location::GPR(tmp_in)); + a.emit_vcvtsi2ss_64(tmp_out, GPROrMemory::GPR(tmp_in), tmp_out); + a.emit_vaddss(tmp_out, XMMOrMemory::XMM(tmp_out), tmp_out); + a.emit_label(end_convert); + a.emit_mov(Size::S32, Location::XMM(tmp_out), ret); + + self.machine.release_temp_gpr(tmp); + self.machine.release_temp_gpr(tmp_in); + self.machine.release_temp_xmm(tmp_out); + } Operator::F64ConvertSI32 => { let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap()); @@ -1813,7 +1839,7 @@ impl FunctionCodeGenerator for X64FunctionCode { self.machine.release_temp_gpr(tmp_in); self.machine.release_temp_xmm(tmp_out); } - Operator::F64ConvertSI64 | Operator::F64ConvertUI64 /* FIXME: INCORRECT */ => { + Operator::F64ConvertSI64 => { let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap()); let ret = self.machine.acquire_locations(a, &[WpType::F64], false)[0]; self.value_stack.push((ret, LocalOrTemp::Temp)); @@ -1827,6 +1853,36 @@ impl FunctionCodeGenerator for X64FunctionCode { self.machine.release_temp_gpr(tmp_in); self.machine.release_temp_xmm(tmp_out); } + Operator::F64ConvertUI64 => { + let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap()); + let ret = self.machine.acquire_locations(a, &[WpType::F64], false)[0]; + self.value_stack.push((ret, LocalOrTemp::Temp)); + let tmp_out = self.machine.acquire_temp_xmm().unwrap(); + let tmp_in = self.machine.acquire_temp_gpr().unwrap(); + let tmp = self.machine.acquire_temp_gpr().unwrap(); + + let do_convert = a.get_label(); + let end_convert = a.get_label(); + + a.emit_mov(Size::S64, loc, Location::GPR(tmp_in)); + a.emit_test_gpr_64(tmp_in); + a.emit_jmp(Condition::Signed, do_convert); + a.emit_vcvtsi2sd_64(tmp_out, GPROrMemory::GPR(tmp_in), tmp_out); + a.emit_jmp(Condition::None, end_convert); + a.emit_label(do_convert); + a.emit_mov(Size::S64, Location::GPR(tmp_in), Location::GPR(tmp)); + a.emit_and(Size::S64, Location::Imm32(1), Location::GPR(tmp)); + a.emit_shr(Size::S64, Location::Imm8(1), Location::GPR(tmp_in)); + a.emit_or(Size::S64, Location::GPR(tmp), Location::GPR(tmp_in)); + a.emit_vcvtsi2sd_64(tmp_out, GPROrMemory::GPR(tmp_in), tmp_out); + a.emit_vaddsd(tmp_out, XMMOrMemory::XMM(tmp_out), tmp_out); + a.emit_label(end_convert); + a.emit_mov(Size::S64, Location::XMM(tmp_out), ret); + + self.machine.release_temp_gpr(tmp); + self.machine.release_temp_gpr(tmp_in); + self.machine.release_temp_xmm(tmp_out); + } Operator::Call { function_index } => { let function_index = function_index as usize; diff --git a/lib/dynasm-backend/src/emitter_x64.rs b/lib/dynasm-backend/src/emitter_x64.rs index 7cc00c1cd..6f7670ab2 100644 --- a/lib/dynasm-backend/src/emitter_x64.rs +++ b/lib/dynasm-backend/src/emitter_x64.rs @@ -59,6 +59,7 @@ pub enum Condition { LessEqual, Equal, NotEqual, + Signed, } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -181,6 +182,8 @@ pub trait Emitter { fn emit_vcvtsi2sd_32(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM); fn emit_vcvtsi2sd_64(&mut self, src1: XMM, src2: GPROrMemory, dst: XMM); + fn emit_test_gpr_64(&mut self, reg: GPR); + fn emit_ud2(&mut self); fn emit_ret(&mut self); fn emit_call_label(&mut self, label: Self::Label); @@ -449,12 +452,18 @@ impl Emitter for Assembler { (Size::S8, Location::GPR(src), Location::Memory(dst, disp)) => { dynasm!(self ; mov [Rq(dst as u8) + disp], Rb(src as u8)); } + (Size::S8, Location::Memory(src, disp), Location::GPR(dst)) => { + dynasm!(self ; mov Rb(dst as u8), [Rq(src as u8) + disp]); + } (Size::S8, Location::Imm32(src), Location::Memory(dst, disp)) => { dynasm!(self ; mov BYTE [Rq(dst as u8) + disp], src as i8); } (Size::S16, Location::GPR(src), Location::Memory(dst, disp)) => { dynasm!(self ; mov [Rq(dst as u8) + disp], Rw(src as u8)); } + (Size::S16, Location::Memory(src, disp), Location::GPR(dst)) => { + dynasm!(self ; mov Rw(dst as u8), [Rq(src as u8) + disp]); + } (Size::S16, Location::Imm32(src), Location::Memory(dst, disp)) => { dynasm!(self ; mov WORD [Rq(dst as u8) + disp], src as i16); } @@ -534,6 +543,7 @@ impl Emitter for Assembler { Condition::LessEqual => jmp_op!(jle, self, label), Condition::Equal => jmp_op!(je, self, label), Condition::NotEqual => jmp_op!(jne, self, label), + Condition::Signed => jmp_op!(js, self, label), } } fn emit_jmp_location(&mut self, loc: Location) { @@ -556,6 +566,7 @@ impl Emitter for Assembler { Condition::LessEqual => trap_op!(jle, self), Condition::Equal => trap_op!(je, self), Condition::NotEqual => trap_op!(jne, self), + Condition::Signed => trap_op!(js, self), } } fn emit_set(&mut self, condition: Condition, dst: GPR) { @@ -570,6 +581,7 @@ impl Emitter for Assembler { Condition::LessEqual => dynasm!(self ; setle Rb(dst as u8)), Condition::Equal => dynasm!(self ; sete Rb(dst as u8)), Condition::NotEqual => dynasm!(self ; setne Rb(dst as u8)), + Condition::Signed => dynasm!(self ; sets Rb(dst as u8)), _ => unreachable!() } } @@ -806,6 +818,10 @@ impl Emitter for Assembler { } } + fn emit_test_gpr_64(&mut self, reg: GPR) { + dynasm!(self ; test Rq(reg as u8), Rq(reg as u8)); + } + fn emit_ud2(&mut self) { dynasm!(self ; ud2); }