Jit: Check the FIFO on EIEIO instructions

The gather pipe optimization postpones checking the FIFO until the end
of the current block (or 32 bytes have been written). This is usually
safe, but is not correct across EIEIO instructions.

This is inferred from a block in NBA2K11 which synchronizes the FIFO
by writing a byte to it, executing eieio, and checking if PI_FIFO_WPTR
has changed. This is not currently an issue, but will become an issue
if the gather pipe optimization is applied to more stores.
This commit is contained in:
hthh 2016-06-13 17:25:24 +10:00
parent 4c9c456846
commit bbc0f0c744
5 changed files with 21 additions and 3 deletions

View File

@ -598,6 +598,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc
js.isLastInstruction = false;
js.blockStart = em_address;
js.fifoBytesThisBlock = 0;
js.mustCheckFifo = false;
js.curBlock = b;
js.numLoadStoreInst = 0;
js.numFloatingPointInst = 0;
@ -723,9 +724,11 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc
js.fifoWriteAddresses.find(ops[i].address) != js.fifoWriteAddresses.end();
// Gather pipe writes using an immediate address are explicitly tracked.
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
if (jo.optimizeGatherPipe && (js.fifoBytesThisBlock >= 32 || js.mustCheckFifo))
{
if (js.fifoBytesThisBlock >= 32)
js.fifoBytesThisBlock -= 32;
js.mustCheckFifo = false;
BitSet32 registersInUse = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
ABI_CallFunction((void*)&GPFifo::FastCheckGatherPipe);

View File

@ -241,4 +241,6 @@ public:
void stmw(UGeckoInstruction inst);
void dcbx(UGeckoInstruction inst);
void eieio(UGeckoInstruction inst);
};

View File

@ -309,7 +309,7 @@ static GekkoOPTemplate table31[] = {
// Unused instructions on GC
{310, &Jit64::FallBackToInterpreter}, // eciwx
{438, &Jit64::FallBackToInterpreter}, // ecowx
{854, &Jit64::DoNothing}, // eieio
{854, &Jit64::eieio}, // eieio
{306, &Jit64::FallBackToInterpreter}, // tlbie
{566, &Jit64::DoNothing}, // tlbsync
};

View File

@ -598,3 +598,15 @@ void Jit64::stmw(UGeckoInstruction inst)
}
gpr.UnlockAllX();
}
void Jit64::eieio(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
// optimizeGatherPipe generally postpones FIFO checks to the end of the JIT block,
// which is generally safe. However postponing FIFO writes across eieio instructions
// is incorrect (would crash NBA2K11 strap screen if we improve our FIFO detection).
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
js.mustCheckFifo = true;
}

View File

@ -103,6 +103,7 @@ protected:
bool generatingTrampoline = false;
u8* trampolineExceptionHandler;
bool mustCheckFifo;
int fifoBytesThisBlock;
PPCAnalyst::BlockStats st;