diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 17ee8f6db0..2f87e092bb 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -425,6 +425,8 @@ u32 sceKernelIcacheInvalidateAll() #ifdef LOG_CACHE NOTICE_LOG(CPU, "Icache invalidated - should clear JIT someday"); #endif + // Note that this doesn't actually fully invalidate all with such a large range. + currentMIPS->InvalidateICache(0, 0x3FFFFFFF); return 0; } @@ -435,6 +437,8 @@ u32 sceKernelIcacheClearAll() NOTICE_LOG(CPU, "Icache cleared - should clear JIT someday"); #endif DEBUG_LOG(CPU, "Icache cleared - should clear JIT someday"); + // Note that this doesn't actually fully invalidate all with such a large range. + currentMIPS->InvalidateICache(0, 0x3FFFFFFF); return 0; } diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index bb03c0a58b..30503d6e01 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -626,6 +626,11 @@ void JitBlockCache::InvalidateICache(u32 address, const u32 length) { return; } + if (pAddr == 0 && pEnd >= 0x1FFFFFFF) { + InvalidateChangedBlocks(); + return; + } + // Blocks may start and end in overlapping ways, and destroying one invalidates iterators. // So after destroying one, we start over. do { @@ -647,6 +652,21 @@ void JitBlockCache::InvalidateICache(u32 address, const u32 length) { } while (false); } +void JitBlockCache::InvalidateChangedBlocks() { + // The primary goal of this is to make sure block linking is cleared up. + for (int block_num = 0; block_num < num_blocks_; ++block_num) { + JitBlock &b = blocks_[block_num]; + if (b.invalid || b.IsPureProxy()) + continue; + + const u32 emuhack = GetEmuHackOpForBlock(block_num).encoding; + if (Memory::ReadUnchecked_U32(b.originalAddress) != emuhack) { + DEBUG_LOG(JIT, "Invalidating changed block at %08x", b.originalAddress); + DestroyBlock(block_num, true); + } + } +} + int JitBlockCache::GetBlockExitSize() { #if defined(ARM) // Will depend on the sequence found to encode the destination address. diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index 168e101018..ccd448337b 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -147,6 +147,7 @@ public: // DOES NOT WORK CORRECTLY WITH JIT INLINING void InvalidateICache(u32 address, const u32 length); + void InvalidateChangedBlocks(); void DestroyBlock(int block_num, bool invalidate); // No jit operations may be run between these calls.