diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 165231c0fe..8ad68e148e 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -284,9 +284,7 @@ std::vector CWCheatEngine::GetCodesList() { //Reads the entire chea } void CWCheatEngine::InvalidateICache(u32 addr, int size) { - if (MIPSComp::jit) { - MIPSComp::jit->GetBlockCache()->InvalidateICache(addr & ~3, size); - } + currentMIPS->InvalidateICache(addr & ~3, size); } void CWCheatEngine::Run() { 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/ARM/ArmCompALU.cpp b/Core/MIPS/ARM/ArmCompALU.cpp index 0fe3d7c87b..6232044290 100644 --- a/Core/MIPS/ARM/ArmCompALU.cpp +++ b/Core/MIPS/ARM/ArmCompALU.cpp @@ -533,7 +533,7 @@ namespace MIPSComp int pos = _POS; int size = _SIZE + 1; - u32 mask = (1 << size) - 1; + u32 mask = 0xFFFFFFFFUL >> (32 - size); // Don't change $zr. if (rt == 0) diff --git a/Core/MIPS/ARM64/Arm64CompALU.cpp b/Core/MIPS/ARM64/Arm64CompALU.cpp index 0e891e164d..bcbfca5bda 100644 --- a/Core/MIPS/ARM64/Arm64CompALU.cpp +++ b/Core/MIPS/ARM64/Arm64CompALU.cpp @@ -431,8 +431,7 @@ void Arm64Jit::Comp_Special3(MIPSOpcode op) { int pos = _POS; int size = _SIZE + 1; - // Workaround for a compiler bug. - u32 mask = size == 32 ? 0xFFFFFFFF : (1 << size) - 1; + u32 mask = 0xFFFFFFFFUL >> (32 - size); // Don't change $zr. if (rt == 0) diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index 04db18d33d..30503d6e01 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -566,14 +566,21 @@ void JitBlockCache::DestroyBlock(int block_num, bool invalidate) { } b->invalid = true; - if (Memory::ReadUnchecked_U32(b->originalAddress) == GetEmuHackOpForBlock(block_num).encoding) - Memory::Write_Opcode_JIT(b->originalAddress, b->originalFirstOpcode); + if (!b->IsPureProxy()) { + if (Memory::ReadUnchecked_U32(b->originalAddress) == GetEmuHackOpForBlock(block_num).encoding) + Memory::Write_Opcode_JIT(b->originalAddress, b->originalFirstOpcode); + } // It's not safe to set normalEntry to 0 here, since we use a binary search // that looks at that later to find blocks. Marking it invalid is enough. UnlinkBlock(block_num); + // Don't change the jit code when invalidating a pure proxy block. + if (b->IsPureProxy()) { + return; + } + #if defined(ARM) // Send anyone who tries to run this block back to the dispatcher. @@ -619,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 { @@ -640,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. diff --git a/Core/MIPS/MIPSInt.cpp b/Core/MIPS/MIPSInt.cpp index e246901752..60ce72b299 100644 --- a/Core/MIPS/MIPSInt.cpp +++ b/Core/MIPS/MIPSInt.cpp @@ -866,14 +866,15 @@ namespace MIPSInt case 0x0: //ext { int size = _SIZE + 1; - R(rt) = (R(rs) >> pos) & ((1<> (32 - size); + R(rt) = (R(rs) >> pos) & sourcemask; } break; case 0x4: //ins { int size = (_SIZE + 1) - pos; - int sourcemask = (1 << size) - 1; - int destmask = sourcemask << pos; + u32 sourcemask = 0xFFFFFFFFUL >> (32 - size); + u32 destmask = sourcemask << pos; R(rt) = (R(rt) & ~destmask) | ((R(rs)&sourcemask) << pos); } break;