Move around the jit nice delay slot logic.

Nice delay slots don't not save flags, they run before the CMP.
This commit is contained in:
Unknown W. Brackets 2013-01-24 01:56:47 -08:00
parent 6ca6fdd02a
commit 2eba209f64
3 changed files with 51 additions and 18 deletions

View file

@ -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(&currentMIPS->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)

View file

@ -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!
}

View file

@ -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);