Don't use utility functions in F32Min implementation.

This commit is contained in:
Nick Lewycky
2019-10-14 13:45:42 -07:00
parent 765e1d3b9e
commit 336dab7fd9

View File

@ -2818,67 +2818,112 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
&mut self.value_stack, &mut self.value_stack,
Assembler::emit_vmaxss, Assembler::emit_vmaxss,
), ),
Operator::F32Min => Self::emit_fp_binop_avx( Operator::F32Min => {
a, let src2 =
&mut self.machine, get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
&mut self.value_stack, let src1 =
|a, src1, src2, dst| { get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
// TODO: pick values safely. let ret = self.machine.acquire_locations(
let tmp_xmm1 = XMM::XMM7; a,
let tmp_xmm2 = XMM::XMM6; &[(WpType::F64, MachineValue::WasmStack(self.value_stack.len()))],
let tmp_xmm3 = XMM::XMM5; false,
)[0];
self.value_stack.push(ret);
static NEG_ZERO: u128 = 0x8000_0000; let tmp1 = self.machine.acquire_temp_xmm().unwrap();
static CANONICAL_NAN: u128 = 0x7FC0_0000; let tmp2 = self.machine.acquire_temp_xmm().unwrap();
let loc2 = match src2 { let tmpg = self.machine.acquire_temp_gpr().unwrap();
XMMOrMemory::XMM(x) => Location::XMM(x),
XMMOrMemory::Memory(base, disp) => Location::Memory(base, disp), let src1 = match src1 {
}; Location::XMM(x) => x,
let spare_base = GPR::RDX; Location::GPR(_) | Location::Memory(_, _) => {
a.emit_mov(Size::S32, Location::XMM(src1), Location::GPR(GPR::RAX)); a.emit_mov(Size::S64, src1, Location::XMM(tmp1));
a.emit_mov(Size::S32, loc2, Location::GPR(GPR::RDX)); tmp1
a.emit_cmp(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RAX)); }
let src2 = match src2 { Location::Imm32(_) => {
XMMOrMemory::XMM(x) => x, a.emit_mov(Size::S32, src1, Location::GPR(tmpg));
XMMOrMemory::Memory(_, _) => panic!(), a.emit_mov(Size::S32, Location::GPR(tmpg), Location::XMM(tmp1));
}; tmp1
a.emit_vminss(src1, XMMOrMemory::XMM(src2), tmp_xmm1); }
let label1 = a.get_label(); Location::Imm64(_) => {
let label2 = a.get_label(); a.emit_mov(Size::S64, src1, Location::GPR(tmpg));
a.emit_jmp(Condition::NotEqual, label1); a.emit_mov(Size::S64, Location::GPR(tmpg), Location::XMM(tmp1));
a.emit_vmovaps(XMMOrMemory::XMM(tmp_xmm1), XMMOrMemory::XMM(tmp_xmm2)); tmp1
a.emit_jmp(Condition::None, label2); }
a.emit_label(label1); _ => unreachable!(),
// load float -0.0 };
a.emit_mov( let src2 = match src2 {
Size::S64, Location::XMM(x) => x,
Location::Imm64((&NEG_ZERO as *const u128) as u64), Location::GPR(_) | Location::Memory(_, _) => {
Location::GPR(spare_base), a.emit_mov(Size::S64, src2, Location::XMM(tmp2));
); tmp2
a.emit_mov( }
Size::S64, Location::Imm32(_) => {
Location::Memory(spare_base, 0), a.emit_mov(Size::S32, src2, Location::GPR(tmpg));
Location::XMM(tmp_xmm2), a.emit_mov(Size::S32, Location::GPR(tmpg), Location::XMM(tmp2));
); tmp2
a.emit_label(label2); }
a.emit_vcmpeqss(src1, XMMOrMemory::XMM(src2), tmp_xmm3); Location::Imm64(_) => {
a.emit_vblendvps(tmp_xmm3, XMMOrMemory::XMM(tmp_xmm2), tmp_xmm1, tmp_xmm1); a.emit_mov(Size::S64, src2, Location::GPR(tmpg));
a.emit_vcmpunordss(src1, XMMOrMemory::XMM(src2), src1); a.emit_mov(Size::S64, Location::GPR(tmpg), Location::XMM(tmp2));
// load float canonical nan tmp2
a.emit_mov( }
Size::S64, _ => unreachable!(),
Location::Imm64((&CANONICAL_NAN as *const u128) as u64), };
Location::GPR(spare_base),
); let tmp_xmm1 = XMM::XMM8;
a.emit_mov( let tmp_xmm2 = XMM::XMM9;
Size::S64, let tmp_xmm3 = XMM::XMM10;
Location::Memory(spare_base, 0),
Location::XMM(src2), static NEG_ZERO: u128 = 0x8000_0000;
); static CANONICAL_NAN: u128 = 0x7FC0_0000;
a.emit_vblendvps(src1, XMMOrMemory::XMM(src2), tmp_xmm1, src1); a.emit_mov(Size::S32, Location::XMM(src1), Location::GPR(GPR::RAX));
a.emit_vmovaps(XMMOrMemory::XMM(src1), XMMOrMemory::XMM(dst)); a.emit_mov(Size::S32, Location::XMM(src2), Location::GPR(GPR::RDX));
}, a.emit_cmp(Size::S32, Location::GPR(GPR::RDX), Location::GPR(GPR::RAX));
), a.emit_vminss(src1, XMMOrMemory::XMM(src2), tmp_xmm1);
let label1 = a.get_label();
let label2 = a.get_label();
a.emit_jmp(Condition::NotEqual, label1);
a.emit_vmovaps(XMMOrMemory::XMM(tmp_xmm1), XMMOrMemory::XMM(tmp_xmm2));
a.emit_jmp(Condition::None, label2);
a.emit_label(label1);
// load float -0.0
a.emit_mov(
Size::S64,
Location::Imm64((&NEG_ZERO as *const u128) as u64),
Location::GPR(tmpg),
);
a.emit_mov(
Size::S64,
Location::Memory(tmpg, 0),
Location::XMM(tmp_xmm2),
);
a.emit_label(label2);
a.emit_vcmpeqss(src1, XMMOrMemory::XMM(src2), tmp_xmm3);
a.emit_vblendvps(tmp_xmm3, XMMOrMemory::XMM(tmp_xmm2), tmp_xmm1, tmp_xmm1);
a.emit_vcmpunordss(src1, XMMOrMemory::XMM(src2), src1);
// load float canonical nan
a.emit_mov(
Size::S64,
Location::Imm64((&CANONICAL_NAN as *const u128) as u64),
Location::GPR(tmpg),
);
a.emit_mov(
Size::S64,
Location::Memory(tmpg, 0),
Location::XMM(src2),
);
a.emit_vblendvps(src1, XMMOrMemory::XMM(src2), tmp_xmm1, src1);
match ret {
Location::XMM(x) => {
a.emit_vmovaps(XMMOrMemory::XMM(src1), XMMOrMemory::XMM(x));
}
Location::Memory(_, _) | Location::GPR(_) => {
a.emit_mov(Size::S64, Location::XMM(src1), ret);
}
_ => unreachable!(),
}
}
Operator::F32Eq => Self::emit_fp_cmpop_avx( Operator::F32Eq => Self::emit_fp_cmpop_avx(
a, a,
&mut self.machine, &mut self.machine,