machinst x64: implement Fabs/Fneg in terms of other instructions;

This commit is contained in:
Benjamin Bouvier
2020-07-21 14:58:14 +02:00
parent 03b9e1e86a
commit 48ec806a9d
3 changed files with 43 additions and 2 deletions

View File

@@ -377,6 +377,8 @@ pub enum SseOpcode {
Subsd, Subsd,
Ucomiss, Ucomiss,
Ucomisd, Ucomisd,
Xorps,
Xorpd,
} }
impl SseOpcode { impl SseOpcode {
@@ -403,7 +405,8 @@ impl SseOpcode {
| SseOpcode::Ucomiss | SseOpcode::Ucomiss
| SseOpcode::Sqrtss | SseOpcode::Sqrtss
| SseOpcode::Comiss | SseOpcode::Comiss
| SseOpcode::Cmpss => SSE, | SseOpcode::Cmpss
| SseOpcode::Xorps => SSE,
SseOpcode::Addsd SseOpcode::Addsd
| SseOpcode::Andpd | SseOpcode::Andpd
@@ -424,7 +427,8 @@ impl SseOpcode {
| SseOpcode::Subsd | SseOpcode::Subsd
| SseOpcode::Ucomisd | SseOpcode::Ucomisd
| SseOpcode::Comisd | SseOpcode::Comisd
| SseOpcode::Cmpsd => SSE2, | SseOpcode::Cmpsd
| SseOpcode::Xorpd => SSE2,
SseOpcode::Insertps | SseOpcode::Roundss | SseOpcode::Roundsd => SSE41, SseOpcode::Insertps | SseOpcode::Roundss | SseOpcode::Roundsd => SSE41,
} }
@@ -485,6 +489,8 @@ impl fmt::Debug for SseOpcode {
SseOpcode::Cmpss => "cmpss", SseOpcode::Cmpss => "cmpss",
SseOpcode::Cmpsd => "cmpsd", SseOpcode::Cmpsd => "cmpsd",
SseOpcode::Insertps => "insertps", SseOpcode::Insertps => "insertps",
SseOpcode::Xorps => "xorps",
SseOpcode::Xorpd => "xorpd",
}; };
write!(fmt, "{}", name) write!(fmt, "{}", name)
} }

View File

@@ -1545,6 +1545,8 @@ pub(crate) fn emit(
SseOpcode::Divsd => (LegacyPrefix::_F2, 0x0F5E), SseOpcode::Divsd => (LegacyPrefix::_F2, 0x0F5E),
SseOpcode::Maxss => (LegacyPrefix::_F3, 0x0F5F), SseOpcode::Maxss => (LegacyPrefix::_F3, 0x0F5F),
SseOpcode::Maxsd => (LegacyPrefix::_F2, 0x0F5F), SseOpcode::Maxsd => (LegacyPrefix::_F2, 0x0F5F),
SseOpcode::Xorps => (LegacyPrefix::None, 0x0F57),
SseOpcode::Xorpd => (LegacyPrefix::_66, 0x0F57),
_ => unimplemented!("Opcode {:?} not implemented", op), _ => unimplemented!("Opcode {:?} not implemented", op),
}; };

View File

@@ -1120,6 +1120,39 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
} }
Opcode::Fabs | Opcode::Fneg => {
let src = input_to_reg_mem(ctx, inputs[0]);
let dst = output_to_reg(ctx, outputs[0]);
// In both cases, generate a constant and apply a single binary instruction:
// - to compute the absolute value, set all bits to 1 but the MSB to 0, and bit-AND the
// src with it.
// - to compute the negated value, set all bits to 0 but the MSB to 1, and bit-XOR the
// src with it.
let output_ty = ty.unwrap();
let (val, opcode) = match output_ty {
F32 => match op {
Opcode::Fabs => (0x7fffffff, SseOpcode::Andps),
Opcode::Fneg => (0x80000000, SseOpcode::Xorps),
_ => unreachable!(),
},
F64 => match op {
Opcode::Fabs => (0x7fffffffffffffff, SseOpcode::Andpd),
Opcode::Fneg => (0x8000000000000000, SseOpcode::Xorpd),
_ => unreachable!(),
},
_ => panic!("unexpected type {:?} for Fabs", output_ty),
};
for inst in Inst::gen_constant(dst, val, output_ty, |reg_class, ty| {
ctx.alloc_tmp(reg_class, ty)
}) {
ctx.emit(inst);
}
ctx.emit(Inst::xmm_rm_r(opcode, src, dst));
}
Opcode::Fcopysign => { Opcode::Fcopysign => {
let dst = output_to_reg(ctx, outputs[0]); let dst = output_to_reg(ctx, outputs[0]);
let lhs = input_to_reg(ctx, inputs[0]); let lhs = input_to_reg(ctx, inputs[0]);