machinst x64: implement Fabs/Fneg in terms of other instructions;
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|||||||
Reference in New Issue
Block a user