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,6 +465,8 @@ 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 (constant_value >= 0)
{
if (a64::Assembler::IsImmAddSub(constant_value))
{
if (value.size < RegSize_64)
@ -474,6 +476,19 @@ void CodeGenerator::EmitCmp(HostReg to_reg, const Value& value)
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
Value temp_value = m_register_cache.AllocateScratch(value.size);

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: