diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index bd22607f3c..3297daa7c3 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -142,6 +142,10 @@ void Jit::BranchRSRTComp(u32 op, Gen::CCFlags cc, bool likely) } delaySlotIsNice = false; // Until we have time to fully fix this + // Cool, we can do the compare afterward. + if (!likely && delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_NICE); + if (rt == 0) { gpr.KillImmediate(rs, true, true); @@ -157,13 +161,14 @@ void Jit::BranchRSRTComp(u32 op, Gen::CCFlags cc, bool likely) Gen::FixupBranch ptr; if (!likely) { - CompileDelaySlot(!delaySlotIsNice); + if (!delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_SAFE_FLUSH); ptr = J_CC(cc, true); } else { ptr = J_CC(cc, true); - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_FLUSH); } // Take the branch @@ -198,6 +203,10 @@ void Jit::BranchRSZeroComp(u32 op, Gen::CCFlags cc, bool andLink, bool likely) } delaySlotIsNice = false; // Until we have time to fully fix this + // Cool, we can do the compare afterward. + if (!likely && delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_NICE); + gpr.BindToRegister(rs, true, false); CMP(32, gpr.R(rs), Imm32(0)); FlushAll(); @@ -205,13 +214,14 @@ void Jit::BranchRSZeroComp(u32 op, Gen::CCFlags cc, bool andLink, bool likely) Gen::FixupBranch ptr; if (!likely) { - CompileDelaySlot(!delaySlotIsNice); + if (!delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_SAFE_FLUSH); ptr = J_CC(cc, true); } else { ptr = J_CC(cc, true); - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_FLUSH); } // Take the branch @@ -293,19 +303,23 @@ void Jit::BranchFPFlag(u32 op, Gen::CCFlags cc, bool likely) delaySlotIsNice = false; // Until we have time to fully fix this + if (!likely && delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_NICE); + FlushAll(); TEST(32, M((void *)&(mips_->fpcond)), Imm32(1)); Gen::FixupBranch ptr; if (!likely) { - CompileDelaySlot(!delaySlotIsNice); + if (!delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_SAFE_FLUSH); ptr = J_CC(cc, true); } else { ptr = J_CC(cc, true); - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_FLUSH); } // Take the branch @@ -357,6 +371,9 @@ void Jit::BranchVFPUFlag(u32 op, Gen::CCFlags cc, bool likely) delaySlotIsNice = false; // Until we have time to fully fix this + if (!likely && delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_NICE); + FlushAll(); // THE CONDITION @@ -367,13 +384,14 @@ void Jit::BranchVFPUFlag(u32 op, Gen::CCFlags cc, bool likely) Gen::FixupBranch ptr; if (!likely) { - CompileDelaySlot(!delaySlotIsNice); + if (!delaySlotIsNice) + CompileDelaySlot(DELAYSLOT_SAFE_FLUSH); ptr = J_CC(cc, true); } else { ptr = J_CC(cc, true); - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_FLUSH); } // Take the branch @@ -413,7 +431,8 @@ void Jit::Comp_Jump(u32 op) } u32 off = ((op & 0x3FFFFFF) << 2); u32 targetAddr = (js.compilerPC & 0xF0000000) | off; - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_NICE); + FlushAll(); switch (op >> 26) { @@ -456,7 +475,7 @@ void Jit::Comp_JumpReg(u32 op) // If this is a syscall, write the pc (for thread switching and other good reasons.) gpr.BindToRegister(rs, true, false); MOV(32, M(¤tMIPS->pc), gpr.R(rs)); - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_FLUSH); // Syscalls write the exit code for us. _dbg_assert_msg_(JIT, !js.compiling, "Expected syscall to write an exit code."); @@ -464,8 +483,7 @@ void Jit::Comp_JumpReg(u32 op) } else if (delaySlotIsNice) { - // TODO: This flushes which is a waste, could add an extra param to skip. - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_NICE); MOV(32, R(EAX), gpr.R(rs)); FlushAll(); } @@ -474,8 +492,9 @@ void Jit::Comp_JumpReg(u32 op) // Latch destination now - save it in memory. gpr.BindToRegister(rs, true, false); MOV(32, M(&savedPC), gpr.R(rs)); - CompileDelaySlot(false); + CompileDelaySlot(DELAYSLOT_NICE); MOV(32, R(EAX), M(&savedPC)); + FlushAll(); } switch (op & 0x3f) diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index ba5d159faa..963cf8e0f5 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -128,7 +128,7 @@ void Jit::ClearCacheAt(u32 em_address) ClearCache(); } -void Jit::CompileDelaySlot(bool saveFlags) +void Jit::CompileDelaySlot(int flags) { const u32 addr = js.compilerPC + 4; @@ -136,7 +136,7 @@ void Jit::CompileDelaySlot(bool saveFlags) // Need to offset the downcount which was already incremented for the branch + delay slot. CheckJitBreakpoint(addr, -2); - if (saveFlags) + if (flags & DELAYSLOT_SAFE) SAVE_FLAGS; // preserve flag around the delay slot! js.inDelaySlot = true; @@ -144,8 +144,9 @@ void Jit::CompileDelaySlot(bool saveFlags) MIPSCompileOp(op); js.inDelaySlot = false; - FlushAll(); - if (saveFlags) + if (flags & DELAYSLOT_FLUSH) + FlushAll(); + if (flags & DELAYSLOT_SAFE) LOAD_FLAGS; // restore flag! } diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index aeff3fd274..d04aaf23f1 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -56,6 +56,18 @@ struct JitState JitBlock *curBlock; }; +enum CompileDelaySlotFlags +{ + // Easy, nothing extra. + DELAYSLOT_NICE = 0, + // Flush registers after delay slot. + DELAYSLOT_FLUSH = 1, + // Preserve flags. + DELAYSLOT_SAFE = 2, + // Flush registers after and preserve flags. + DELAYSLOT_SAFE_FLUSH = DELAYSLOT_FLUSH | DELAYSLOT_SAFE, +}; + class Jit : public Gen::XCodeBlock { public: @@ -71,7 +83,8 @@ public: void Compile(u32 em_address); // Compiles a block at current MIPS PC const u8 *DoJit(u32 em_address, JitBlock *b); - void CompileDelaySlot(bool saveFlags = false); + // See CompileDelaySlotFlags for flags. + void CompileDelaySlot(int flags); void CompileAt(u32 addr); void Comp_RunBlock(u32 op);