diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 242ed1eb42..518922343d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -675,11 +675,35 @@ void JitArm64::cmp(UGeckoInstruction inst) } else { + // If we're dealing with immediates, check their most significant bit to + // see if we can skip sign extension. + const auto should_sign_extend = [&](u32 reg) -> bool { + return !gpr.IsImm(reg) || (gpr.GetImm(reg) & (1U << 31)); + }; + bool sign_extend_a = should_sign_extend(a); + bool sign_extend_b = should_sign_extend(b); + ARM64Reg RA = gpr.R(a); ARM64Reg RB = gpr.R(b); - SXTW(CR, RA); - SUB(CR, CR, RB, ArithOption(RB, ExtendSpecifier::SXTW)); + if (sign_extend_a) + { + SXTW(CR, RA); + RA = CR; + } + else + { + RA = EncodeRegTo64(RA); + } + + auto opt = ArithOption(RB, ExtendSpecifier::SXTW); + if (!sign_extend_b) + { + opt = ArithOption(CR, ShiftType::LSL, 0); + RB = EncodeRegTo64(RB); + } + + SUB(CR, RA, RB, opt); } }