summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2025-01-06 09:56:07 +0100
committerJosJuice <josjuice@gmail.com>2025-01-15 21:22:31 +0100
commit85cd0ca51b304c385b73534c8cbcd50e30f0bd87 (patch)
treea3b891d0569231365369b57792bd724b30d85ad4 /Source
parentaa9696e1c18550fa58f80a9fcf12da9a83fa667b (diff)
JitArm64: Optimize creqv setting eq/gt bit
For the eq and gt bits specifically, setting negate_result is one instruction shorter than not setting it.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp20
1 files changed, 16 insertions, 4 deletions
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp
index da68b1876d..fe6af4c958 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp
@@ -635,8 +635,11 @@ void JitArm64::crXXX(UGeckoInstruction inst)
}
}
- // crnor or crnand
- const bool negate_result = inst.SUBOP10 == 33 || inst.SUBOP10 == 225;
+ const u32 crbd_bit = 3 - (inst.CRBD & 3);
+ // crnor, crnand and sometimes creqv
+ const bool negate_result =
+ inst.SUBOP10 == 33 || inst.SUBOP10 == 225 ||
+ (inst.SUBOP10 == 289 && (crbd_bit == PowerPC::CR_EQ_BIT || crbd_bit == PowerPC::CR_GT_BIT));
bool bits_1_to_31_are_set = false;
auto WA = gpr.GetScopedReg();
@@ -665,8 +668,17 @@ void JitArm64::crXXX(UGeckoInstruction inst)
break;
case 289: // creqv: ~(A ^ B) = A ^ ~B
- EON(WA, WA, WB);
- bits_1_to_31_are_set = true;
+ // Both of these two implementations are equally correct, but which one is more efficient
+ // depends on which bit we're going to set in CRBD
+ if (negate_result)
+ {
+ EOR(XA, XA, XB);
+ }
+ else
+ {
+ EON(WA, WA, WB);
+ bits_1_to_31_are_set = true;
+ }
break;
case 33: // crnor: ~(A || B)