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".

This commit is contained in:
skidau 2012-05-31 22:09:33 +10:00
parent 372e00632d
commit 99b7c91df5
6 changed files with 34 additions and 2 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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