diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp index 4e926b4faa..72f278434c 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -276,6 +276,18 @@ void Jit64::FloatCompare(UGeckoInstruction inst, bool upper) int a = inst.FA; int b = inst.FB; int crf = inst.CRFD; + int output[4] = { CR_SO, CR_EQ, CR_GT, CR_LT }; + + // Merge neighboring fcmp and cror (the primary use of cror). + UGeckoInstruction next = js.next_inst; + if (next.OPCD == 19 && next.SUBOP10 == 449 && (next.CRBA >> 2) == crf && (next.CRBB >> 2) == crf && (next.CRBD >> 2) == crf) + { + js.skipnext = true; + js.downcountAmount++; + int dst = 3 - (next.CRBD & 3); + output[3 - (next.CRBA & 3)] |= 1 << dst; + output[3 - (next.CRBB & 3)] |= 1 << dst; + } fpr.Lock(a, b); fpr.BindToRegister(b, true, false); @@ -315,14 +327,14 @@ void Jit64::FloatCompare(UGeckoInstruction inst, bool upper) pGreater = J_CC(CC_B); } - MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(CR_EQ))); + MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(output[CR_EQ_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(CR_EQ << FPRF_SHIFT)); continue1 = J(); SetJumpTarget(pNaN); - MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(CR_SO))); + MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(output[CR_SO_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(CR_SO << FPRF_SHIFT)); @@ -331,13 +343,13 @@ void Jit64::FloatCompare(UGeckoInstruction inst, bool upper) continue2 = J(); SetJumpTarget(pGreater); - MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(CR_GT))); + MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(output[CR_GT_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(CR_GT << FPRF_SHIFT)); continue3 = J(); SetJumpTarget(pLesser); - MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(CR_LT))); + MOV(64, R(RSCRATCH), Imm64(PPCCRToInternal(output[CR_LT_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(CR_LT << FPRF_SHIFT)); } diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index acc5d372ed..cefba76d93 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -406,6 +406,11 @@ static bool isCarryOp(const CodeOp& a) return (a.opinfo->flags & FL_SET_CA) && !(a.opinfo->flags & FL_SET_OE) && a.opinfo->type == OPTYPE_INTEGER; } +static bool isCror(const CodeOp& a) +{ + return a.inst.OPCD == 19 && a.inst.SUBOP10 == 449; +} + void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool reverse, ReorderType type) { // Bubbling an instruction sometimes reveals another opportunity to bubble an instruction, so do @@ -426,7 +431,7 @@ void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool r CodeOp &b = code[i + increment]; // Reorder integer compares, rlwinm., and carry-affecting ops // (if we add more merged branch instructions, add them here!) - if ((type == REORDER_CARRY && isCarryOp(a)) || (type == REORDER_CMP && (isCmp(a) || a.outputCR0))) + if ((type == REORDER_CROR && isCror(a)) || (type == REORDER_CARRY && isCarryOp(a)) || (type == REORDER_CMP && (isCmp(a) || a.outputCR0))) { // once we're next to a carry instruction, don't move away! if (type == REORDER_CARRY && i != start) @@ -454,6 +459,10 @@ void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool r void PPCAnalyzer::ReorderInstructions(u32 instructions, CodeOp *code) { + // Reorder cror instructions upwards (e.g. towards an fcmp). Technically we should be more + // picky about this, but cror seems to almost solely be used for this purpose in real code. + // Additionally, the other boolean ops seem to almost never be used. + ReorderInstructionsCore(instructions, code, true, REORDER_CROR); // For carry, bubble instructions *towards* each other; one direction often isn't enough // to get pairs like addc/adde next to each other. if (HasOption(OPTION_CARRY_MERGE)) diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.h b/Source/Core/Core/PowerPC/PPCAnalyst.h index 8b3f4bc85a..8abf4bbdfe 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.h +++ b/Source/Core/Core/PowerPC/PPCAnalyst.h @@ -156,7 +156,8 @@ private: enum ReorderType { REORDER_CARRY, - REORDER_CMP + REORDER_CMP, + REORDER_CROR }; void ReorderInstructionsCore(u32 instructions, CodeOp* code, bool reverse, ReorderType type);