diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 828e780ea4..4f9356fd68 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(); @@ -666,8 +669,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) + { + ORR(XA, XA, XB); + } + else + { + EON(WA, WA, WB); + bits_1_to_31_are_set = true; + } break; case 33: // crnor: ~(A || B)