CPU/Recompiler/AArch64: Use cmn for negative constant comparisons

This commit is contained in:
Connor McLaughlin 2020-08-08 22:56:15 +10:00
parent 901ca71fdc
commit 70767dc6bf
3 changed files with 24 additions and 8 deletions

View file

@ -1522,8 +1522,8 @@ bool CodeGenerator::Compile_SignedDivide(const CodeBlockInstruction& cbi)
// else if (static_cast<u32>(num) == UINT32_C(0x80000000) && denom == -1)
{
EmitBindLabel(&not_zero);
EmitConditionalBranch(Condition::NotEqual, false, denom_reg.GetHostRegister(),
Value::FromConstantU32(0xFFFFFFFFu), &do_divide);
EmitConditionalBranch(Condition::NotEqual, false, denom_reg.GetHostRegister(), Value::FromConstantS32(-1),
&do_divide);
EmitConditionalBranch(Condition::NotEqual, false, num_reg.GetHostRegister(), lo, &do_divide);
// unrepresentable

View file

@ -465,14 +465,29 @@ void CodeGenerator::EmitCmp(HostReg to_reg, const Value& value)
// do we need temporary storage for the constant, if it won't fit in an immediate?
const s64 constant_value = value.GetS64ConstantValue();
if (a64::Assembler::IsImmAddSub(constant_value))
if (constant_value >= 0)
{
if (value.size < RegSize_64)
m_emit->cmp(GetHostReg32(to_reg), constant_value);
else
m_emit->cmp(GetHostReg64(to_reg), constant_value);
if (a64::Assembler::IsImmAddSub(constant_value))
{
if (value.size < RegSize_64)
m_emit->cmp(GetHostReg32(to_reg), constant_value);
else
m_emit->cmp(GetHostReg64(to_reg), constant_value);
return;
return;
}
}
else
{
if (a64::Assembler::IsImmAddSub(-constant_value))
{
if (value.size < RegSize_64)
m_emit->cmn(GetHostReg32(to_reg), -constant_value);
else
m_emit->cmn(GetHostReg64(to_reg), -constant_value);
return;
}
}
// need a temporary

View file

@ -191,6 +191,7 @@ struct Value
static Value FromConstantU8(u8 value) { return FromConstant(ZeroExtend64(value), RegSize_8); }
static Value FromConstantU16(u16 value) { return FromConstant(ZeroExtend64(value), RegSize_16); }
static Value FromConstantU32(u32 value) { return FromConstant(ZeroExtend64(value), RegSize_32); }
static Value FromConstantS32(s32 value) { return FromConstant(ZeroExtend64(static_cast<u32>(value)), RegSize_32); }
static Value FromConstantU64(u64 value) { return FromConstant(value, RegSize_64); }
private: