diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index e4635bcd74..d4c921c9ee 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -524,42 +524,39 @@ void Jit64::cmpXX(UGeckoInstruction inst) u32 crf = inst.CRFD; bool merge_branch = CheckMergedBranch(crf); - OpArg comparand; bool signedCompare; - if (inst.OPCD == 31) + RCOpArg comparand; + switch (inst.OPCD) { - // cmp / cmpl - gpr.Lock(a, b); - comparand = gpr.R(b); + // cmp / cmpl + case 31: signedCompare = (inst.SUBOP10 == 0); - } - else - { - gpr.Lock(a); - if (inst.OPCD == 10) - { - // cmpli - comparand = Imm32((u32)inst.UIMM); - signedCompare = false; - } - else if (inst.OPCD == 11) - { - // cmpi - comparand = Imm32((u32)(s32)(s16)inst.UIMM); - signedCompare = true; - } - else - { - signedCompare = false; // silence compiler warning - PanicAlert("cmpXX"); - } + comparand = signedCompare ? gpr.Use(b, RCMode::Read) : gpr.Bind(b, RCMode::Read); + RegCache::Realize(comparand); + break; + + // cmpli + case 10: + signedCompare = false; + comparand = RCOpArg::Imm32((u32)inst.UIMM); + break; + + // cmpi + case 11: + signedCompare = true; + comparand = RCOpArg::Imm32((u32)(s32)(s16)inst.UIMM); + break; + + default: + signedCompare = false; // silence compiler warning + PanicAlert("cmpXX"); } - if (gpr.R(a).IsImm() && comparand.IsImm()) + if (gpr.IsImm(a) && comparand.IsImm()) { // Both registers contain immediate values, so we can pre-compile the compare result - s64 compareResult = signedCompare ? (s64)gpr.R(a).SImm32() - (s64)comparand.SImm32() : - (u64)gpr.R(a).Imm32() - (u64)comparand.Imm32(); + s64 compareResult = signedCompare ? (s64)gpr.SImm32(a) - (s64)comparand.SImm32() : + (u64)gpr.Imm32(a) - (u64)comparand.Imm32(); if (compareResult == (s32)compareResult) { MOV(64, PPCSTATE(cr_val[crf]), Imm32((u32)compareResult)); @@ -571,73 +568,83 @@ void Jit64::cmpXX(UGeckoInstruction inst) } if (merge_branch) + { + RegCache::Unlock(comparand); DoMergedBranchImmediate(compareResult); + } + + return; + } + + if (!gpr.IsImm(a) && !signedCompare && comparand.IsImm() && comparand.Imm32() == 0) + { + RCX64Reg Ra = gpr.Bind(a, RCMode::Read); + RegCache::Realize(Ra); + + MOV(64, PPCSTATE(cr_val[crf]), Ra); + if (merge_branch) + { + TEST(64, Ra, Ra); + RegCache::Unlock(comparand, Ra); + DoMergedBranchCondition(); + } + return; + } + + const X64Reg input = RSCRATCH; + if (gpr.IsImm(a)) + { + if (signedCompare) + MOV(64, R(input), Imm32(gpr.SImm32(a))); + else + MOV(32, R(input), Imm32(gpr.Imm32(a))); } else { - X64Reg input = RSCRATCH; + RCOpArg Ra = gpr.Use(a, RCMode::Read); + RegCache::Realize(Ra); if (signedCompare) - { - if (gpr.R(a).IsImm()) - MOV(64, R(input), Imm32(gpr.R(a).SImm32())); - else - MOVSX(64, 32, input, gpr.R(a)); - - if (!comparand.IsImm()) - { - MOVSX(64, 32, RSCRATCH2, comparand); - comparand = R(RSCRATCH2); - } - } + MOVSX(64, 32, input, Ra); else - { - if (gpr.R(a).IsImm()) - { - MOV(32, R(input), Imm32(gpr.R(a).Imm32())); - } - else if (comparand.IsImm() && !comparand.Imm32()) - { - gpr.BindToRegister(a, true, false); - input = gpr.RX(a); - } - else - { - MOVZX(64, 32, input, gpr.R(a)); - } - - if (comparand.IsImm()) - { - // sign extension will ruin this, so store it in a register - if (comparand.Imm32() & 0x80000000U) - { - MOV(32, R(RSCRATCH2), comparand); - comparand = R(RSCRATCH2); - } - } - else - { - gpr.BindToRegister(b, true, false); - comparand = gpr.R(b); - } - } - if (comparand.IsImm() && !comparand.Imm32()) - { - MOV(64, PPCSTATE(cr_val[crf]), R(input)); - // Place the comparison next to the branch for macro-op fusion - if (merge_branch) - TEST(64, R(input), R(input)); - } - else - { - SUB(64, R(input), comparand); - MOV(64, PPCSTATE(cr_val[crf]), R(input)); - } - - if (merge_branch) - DoMergedBranchCondition(); + MOVZX(64, 32, input, Ra); } - gpr.UnlockAll(); + if (comparand.IsImm()) + { + // sign extension will ruin this, so store it in a register + if (!signedCompare && (comparand.Imm32() & 0x80000000U) != 0) + { + MOV(32, R(RSCRATCH2), comparand); + comparand = RCOpArg::R(RSCRATCH2); + } + } + else + { + if (signedCompare) + { + MOVSX(64, 32, RSCRATCH2, comparand); + comparand = RCOpArg::R(RSCRATCH2); + } + } + + if (comparand.IsImm() && comparand.Imm32() == 0) + { + MOV(64, PPCSTATE(cr_val[crf]), R(input)); + // Place the comparison next to the branch for macro-op fusion + if (merge_branch) + TEST(64, R(input), R(input)); + } + else + { + SUB(64, R(input), comparand); + MOV(64, PPCSTATE(cr_val[crf]), R(input)); + } + + if (merge_branch) + { + RegCache::Unlock(comparand); + DoMergedBranchCondition(); + } } void Jit64::boolX(UGeckoInstruction inst)