F32ConvertUI64, F64ConvertUI64

This commit is contained in:
losfair 2019-04-10 01:38:16 +08:00
parent 69d6093955
commit e78a5ba602
2 changed files with 80 additions and 8 deletions

View File

@ -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;

View File

@ -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);
}