diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 53b36a0025..1e0e512bd4 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -183,13 +183,46 @@ const u8* JitBaseBlockCache::Dispatch() return block->normalEntry; } -void JitBaseBlockCache::InvalidateICache(u32 address, u32 length, bool forced) +void JitBaseBlockCache::InvalidateICacheLine(u32 address) { - const auto translated = PowerPC::JitCache_TranslateAddress(address); - if (!translated.valid) - return; - const u32 physical_address = translated.address; + const u32 cache_line_address = address & ~0x1f; + const auto translated = PowerPC::JitCache_TranslateAddress(cache_line_address); + if (translated.valid) + InvalidateICacheInternal(translated.address, cache_line_address, 32, false); +} +void JitBaseBlockCache::InvalidateICache(u32 initial_address, u32 initial_length, bool forced) +{ + u32 address = initial_address; + u32 length = initial_length; + while (length > 0) + { + const auto translated = PowerPC::JitCache_TranslateAddress(address); + + const bool address_from_bat = translated.valid && translated.translated && translated.from_bat; + const int shift = address_from_bat ? PowerPC::BAT_INDEX_SHIFT : PowerPC::HW_PAGE_INDEX_SHIFT; + const u32 mask = ~((1u << shift) - 1u); + const u32 first_address = address; + const u32 last_address = address + (length - 1u); + if ((first_address & mask) == (last_address & mask)) + { + if (translated.valid) + InvalidateICacheInternal(translated.address, address, length, forced); + return; + } + + const u32 end_of_page = (first_address + (1u << shift)) & mask; + const u32 length_this_page = end_of_page - first_address; + if (translated.valid) + InvalidateICacheInternal(translated.address, address, length_this_page, forced); + address = address + length_this_page; + length = length - length_this_page; + } +} + +void JitBaseBlockCache::InvalidateICacheInternal(u32 physical_address, u32 address, u32 length, + bool forced) +{ // Optimization for the case of invalidating a single cache line, which is used by the dcb* // instructions. If the valid_block bit for that cacheline is not set, we can safely skip // the remaining invalidation logic. diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index ec8e9951df..c9e3f02d91 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -161,6 +161,7 @@ public: const u8* Dispatch(); void InvalidateICache(u32 address, u32 length, bool forced); + void InvalidateICacheLine(u32 address); void ErasePhysicalRange(u32 address, u32 length); u32* GetBlockBitSet() const; @@ -177,6 +178,7 @@ private: void LinkBlockExits(JitBlock& block); void LinkBlock(JitBlock& block); void UnlinkBlock(const JitBlock& block); + void InvalidateICacheInternal(u32 physical_address, u32 address, u32 length, bool forced); JitBlock* MoveBlockIntoFastCache(u32 em_address, u32 msr); diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index 127fb7419d..0e45a6f3f6 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -226,7 +226,8 @@ void InvalidateICache(u32 address, u32 size, bool forced) void InvalidateICacheLine(u32 address) { - InvalidateICache(address & ~0x1f, 32, false); + if (g_jit) + g_jit->GetBlockCache()->InvalidateICacheLine(address); } void CompileExceptionCheck(ExceptionType type) diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index ab9edf71a7..87cd6102d7 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -30,10 +30,6 @@ namespace PowerPC { -constexpr size_t HW_PAGE_SIZE = 4096; -constexpr u32 HW_PAGE_INDEX_SHIFT = 12; -constexpr u32 HW_PAGE_INDEX_MASK = 0x3f; - // EFB RE /* GXPeekZ diff --git a/Source/Core/Core/PowerPC/MMU.h b/Source/Core/Core/PowerPC/MMU.h index ab02ad01d8..47786078cb 100644 --- a/Source/Core/Core/PowerPC/MMU.h +++ b/Source/Core/Core/PowerPC/MMU.h @@ -222,5 +222,9 @@ inline bool TranslateBatAddess(const BatTable& bat_table, u32* address, bool* wi return true; } +constexpr size_t HW_PAGE_SIZE = 4096; +constexpr u32 HW_PAGE_INDEX_SHIFT = 12; +constexpr u32 HW_PAGE_INDEX_MASK = 0x3f; + std::optional GetTranslatedAddress(u32 address); } // namespace PowerPC