From bbc0f0c744a8a7d90c3801192446ba1b3bd92584 Mon Sep 17 00:00:00 2001 From: hthh Date: Mon, 13 Jun 2016 17:25:24 +1000 Subject: [PATCH] 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. --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 7 +++++-- Source/Core/Core/PowerPC/Jit64/Jit.h | 2 ++ Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp | 2 +- Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 12 ++++++++++++ Source/Core/Core/PowerPC/JitCommon/JitBase.h | 1 + 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index a1ef3c409c..ba5975ab24 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -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)) { - js.fifoBytesThisBlock -= 32; + if (js.fifoBytesThisBlock >= 32) + js.fifoBytesThisBlock -= 32; + js.mustCheckFifo = false; BitSet32 registersInUse = CallerSavedRegistersInUse(); ABI_PushRegistersAndAdjustStack(registersInUse, 0); ABI_CallFunction((void*)&GPFifo::FastCheckGatherPipe); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index b00b63845b..4fce2e91bf 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -241,4 +241,6 @@ public: void stmw(UGeckoInstruction inst); void dcbx(UGeckoInstruction inst); + + void eieio(UGeckoInstruction inst); }; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp index 75df5bf07e..700e87c3ae 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp @@ -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 }; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index a67dad0274..2059587dd6 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -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; +} diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h index 7b96a6b739..489bb5ba38 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h @@ -103,6 +103,7 @@ protected: bool generatingTrampoline = false; u8* trampolineExceptionHandler; + bool mustCheckFifo; int fifoBytesThisBlock; PPCAnalyst::BlockStats st;