Merge pull request #3894 from hthh/optimize-fifo-bug

Jit: Check the FIFO on EIEIO instructions
This commit is contained in:
Markus Wick
2016-08-12 13:25:25 +02:00
committed by GitHub
9 changed files with 40 additions and 6 deletions

View File

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

View File

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

View File

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

View File

@ -598,3 +598,15 @@ void Jit64::stmw(UGeckoInstruction inst)
} }
gpr.UnlockAllX(); 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

@ -405,6 +405,7 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitB
js.assumeNoPairedQuantize = false; js.assumeNoPairedQuantize = false;
js.blockStart = em_address; js.blockStart = em_address;
js.fifoBytesThisBlock = 0; js.fifoBytesThisBlock = 0;
js.mustCheckFifo = false;
js.downcountAmount = 0; js.downcountAmount = 0;
js.skipInstructions = 0; js.skipInstructions = 0;
js.curBlock = b; js.curBlock = b;
@ -491,9 +492,11 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitB
bool gatherPipeIntCheck = bool gatherPipeIntCheck =
jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end(); jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end();
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32) if (jo.optimizeGatherPipe && (js.fifoBytesThisBlock >= 32 || js.mustCheckFifo))
{ {
js.fifoBytesThisBlock -= 32; if (js.fifoBytesThisBlock >= 32)
js.fifoBytesThisBlock -= 32;
js.mustCheckFifo = false;
gpr.Lock(W30); gpr.Lock(W30);
BitSet32 regs_in_use = gpr.GetCallerSavedUsed(); BitSet32 regs_in_use = gpr.GetCallerSavedUsed();

View File

@ -116,6 +116,7 @@ public:
void dcbx(UGeckoInstruction inst); void dcbx(UGeckoInstruction inst);
void dcbt(UGeckoInstruction inst); void dcbt(UGeckoInstruction inst);
void dcbz(UGeckoInstruction inst); void dcbz(UGeckoInstruction inst);
void eieio(UGeckoInstruction inst);
// LoadStore floating point // LoadStore floating point
void lfXX(UGeckoInstruction inst); void lfXX(UGeckoInstruction inst);

View File

@ -853,3 +853,15 @@ void JitArm64::dcbz(UGeckoInstruction inst)
gpr.Unlock(W0); gpr.Unlock(W0);
} }
void JitArm64::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

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

View File

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