From 99b7c91df5dbfe2d3b0d8fd273e416420eabf514 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 31 May 2012 22:09:33 +1000 Subject: [PATCH] Checked if dcbst instructions are preceded by dcbt. If it is, the game is prefetching memory into the data cache, and not loading new code. In these cases, the JIT cache will no longer be flushed. Fixes the frequent "Clearing code cache" issue in games like "The Last Story". --- Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 1 + .../Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp | 2 +- .../Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp | 15 +++++++++++++++ Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h | 1 + .../Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp | 15 +++++++++++++++ .../Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp | 2 +- 6 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 791934bd18..1ebd476134 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -222,6 +222,7 @@ public: void negx(UGeckoInstruction inst); void slwx(UGeckoInstruction inst); void srwx(UGeckoInstruction inst); + void dcbst(UGeckoInstruction inst); void dcbz(UGeckoInstruction inst); void lfsx(UGeckoInstruction inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp index 1c654a4a9a..8d593a6742 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp @@ -210,7 +210,7 @@ static GekkoOPTemplate table31[] = {824, &Jit64::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, {24, &Jit64::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, - {54, &Jit64::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, + {54, &Jit64::dcbst}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, {86, &Jit64::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, {246, &Jit64::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, {278, &Jit64::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index e9de594465..1dae2ec17e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -235,6 +235,21 @@ void Jit64::lXXx(UGeckoInstruction inst) gpr.UnlockAllX(); } +void Jit64::dcbst(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + // If the dcbst instruction is preceded by dcbt, it is flushing a prefetched + // memory location. Do not invalidate the JIT cache in this case as the memory + // will be the same. + // dcbt = 0x7c00022c + if ((Memory::ReadUnchecked_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c) + { + Default(inst); return; + } +} + // Zero cache line. void Jit64::dcbz(UGeckoInstruction inst) { diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h index bb4c2d8ee1..fdda098e44 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h @@ -212,6 +212,7 @@ public: void negx(UGeckoInstruction inst); void slwx(UGeckoInstruction inst); void srwx(UGeckoInstruction inst); + void dcbst(UGeckoInstruction inst); void dcbz(UGeckoInstruction inst); void lfsx(UGeckoInstruction inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp index 65e2c4097f..45ceda694a 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp @@ -114,6 +114,21 @@ void JitIL::lXzx(UGeckoInstruction inst) ibuild.EmitStoreGReg(val, inst.RD); } +void JitIL::dcbst(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + // If the dcbst instruction is preceded by dcbt, it is flushing a prefetched + // memory location. Do not invalidate the JIT cache in this case as the memory + // will be the same. + // dcbt = 0x7c00022c + if ((Memory::ReadUnchecked_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c) + { + Default(inst); return; + } +} + // Zero cache line. void JitIL::dcbz(UGeckoInstruction inst) { diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp index 9b2e3ff466..9e8e36f9c3 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp @@ -212,7 +212,7 @@ static GekkoOPTemplate table31[] = {824, &JitIL::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, {24, &JitIL::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, - {54, &JitIL::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, + {54, &JitIL::dcbst}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, {86, &JitIL::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, {246, &JitIL::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, {278, &JitIL::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}},