From 70767dc6bf34c5998451c3d35cff02fbfc5b2899 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 8 Aug 2020 22:56:15 +1000 Subject: [PATCH] CPU/Recompiler/AArch64: Use cmn for negative constant comparisons --- src/core/cpu_recompiler_code_generator.cpp | 4 +-- .../cpu_recompiler_code_generator_aarch64.cpp | 27 ++++++++++++++----- src/core/cpu_recompiler_register_cache.h | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index 04359a8ac..48e257bfd 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -1522,8 +1522,8 @@ bool CodeGenerator::Compile_SignedDivide(const CodeBlockInstruction& cbi) // else if (static_cast(num) == UINT32_C(0x80000000) && denom == -1) { EmitBindLabel(¬_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 diff --git a/src/core/cpu_recompiler_code_generator_aarch64.cpp b/src/core/cpu_recompiler_code_generator_aarch64.cpp index 693d17e81..9d3a6ec14 100644 --- a/src/core/cpu_recompiler_code_generator_aarch64.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch64.cpp @@ -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 diff --git a/src/core/cpu_recompiler_register_cache.h b/src/core/cpu_recompiler_register_cache.h index f5cef6f5c..4bc8dee19 100644 --- a/src/core/cpu_recompiler_register_cache.h +++ b/src/core/cpu_recompiler_register_cache.h @@ -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(value)), RegSize_32); } static Value FromConstantU64(u64 value) { return FromConstant(value, RegSize_64); } private: