From ed5cea2635ed2169ace9170079cf2f34e6c1e355 Mon Sep 17 00:00:00 2001 From: Sintendo <3380580+Sintendo@users.noreply.github.com> Date: Wed, 30 Jul 2025 22:08:38 +0200 Subject: [PATCH] JitArm64_Integer: subfex - Explicitly handle a == b Number of instructions stays the same, but we remove the false dependency on the input registers. Before: 0x7a1b037a sbcs w26, w27, w27 After: 0x5a9f23fa csetm w26, lo --- .../PowerPC/JitArm64/JitArm64_Integer.cpp | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 78a8d579da..d66ebe488d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -1306,13 +1306,10 @@ void JitArm64::subfex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); - bool mex = inst.SUBOP10 & 32; - int a = inst.RA, b = inst.RB, d = inst.RD; + const bool mex = inst.SUBOP10 & 32; + const int a = inst.RA, b = inst.RB, d = inst.RD; - if (gpr.IsImm(a) && (mex || gpr.IsImm(b))) - { - const u32 i = gpr.GetImm(a); - const u32 j = mex ? -1 : gpr.GetImm(b); + const auto handle_imm = [&](const u32 i, const u32 j) { const u32 imm = ~i + j; const bool is_zero = imm == 0; const bool is_all_ones = imm == 0xFFFFFFFF; @@ -1385,6 +1382,21 @@ void JitArm64::subfex(UGeckoInstruction inst) { ComputeCarry(false); } + }; + + if (!mex && a == b) + { + // Special case: subfe A, B, B is a common compiler idiom to copy the carry + // flag to a register. + // We handle this as-if we're dealing with two identical immediate values. + // The exact values used here don't matter. We use zeroes. + handle_imm(0, 0); + } + else if (gpr.IsImm(a) && (mex || gpr.IsImm(b))) + { + const u32 i = gpr.GetImm(a); + const u32 j = mex ? -1 : gpr.GetImm(b); + handle_imm(i, j); } else {