diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index a2d6c3026f..2352d90c03 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -241,7 +241,7 @@ public: void negx(UGeckoInstruction inst); void slwx(UGeckoInstruction inst); void srwx(UGeckoInstruction inst); - void dcbst(UGeckoInstruction inst); + void dcbt(UGeckoInstruction inst); void dcbz(UGeckoInstruction inst); void subfic(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp index 636a9b2396..c33f22e8d5 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp @@ -197,10 +197,10 @@ static GekkoOPTemplate table31[] = {824, &Jit64::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_SET_CA | FL_RC_BIT}}, {24, &Jit64::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, - {54, &Jit64::dcbst}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, + {54, &Jit64::FallBackToInterpreter}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, {86, &Jit64::FallBackToInterpreter}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, - {246, &Jit64::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, - {278, &Jit64::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, + {246, &Jit64::dcbt }, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, + {278, &Jit64::dcbt }, //"dcbt", OPTYPE_DCACHE, 0, 1}}, {470, &Jit64::FallBackToInterpreter}, //"dcbi", OPTYPE_DCACHE, 0, 4}}, {758, &Jit64::DoNothing}, //"dcba", OPTYPE_DCACHE, 0, 4}}, {1014, &Jit64::dcbz}, //"dcbz", OPTYPE_DCACHE, 0, 4}}, diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index 0c0a23acfc..29e83e034d 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -111,10 +111,11 @@ void Jit64::lXXx(UGeckoInstruction inst) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle && PowerPC::GetState() != PowerPC::CPU_STEPPING && inst.OPCD == 32 && + MergeAllowedNextInstructions(2) && (inst.hex & 0xFFFF0000) == 0x800D0000 && - (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 || - (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) && - Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8) + (js.op[1].inst.hex == 0x28000000 || + (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && js.op[1].inst.hex == 0x2C000000)) && + js.op[2].inst.hex == 0x4182fff8) { // TODO(LinesPrower): // - Rewrite this! @@ -284,16 +285,24 @@ void Jit64::lXXx(UGeckoInstruction inst) gpr.UnlockAllX(); } -void Jit64::dcbst(UGeckoInstruction inst) +void Jit64::dcbt(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITLoadStoreOff); - // 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 - FALLBACK_IF((Memory::ReadUnchecked_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c); + // Prefetch. Since we don't emulate the data cache, we don't need to do anything. + + // If a dcbst follows a dcbt, it probably isn't a case of dynamic code + // modification, so don't bother invalidating the jit block cache. + // This is important because invalidating the block cache when we don't + // need to is terrible for performance. + // (Invalidating the jit block cache on dcbst is a heuristic.) + if (MergeAllowedNextInstructions(1) && + js.op[1].inst.OPCD == 31 && js.op[1].inst.SUBOP10 == 54 && + js.op[1].inst.RA == inst.RA && js.op[1].inst.RB == inst.RB) + { + js.skipInstructions = 1; + } } // Zero cache line.