diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 7ec62e04c8..7d5a91240c 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -170,6 +170,9 @@ public: JitBlockCache *GetBlockCache() override { return &blocks; } + std::vector SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); } + void RestoreSavedEmuHackOps(std::vector saved) override { blocks.RestoreSavedEmuHackOps(saved); } + void ClearCache() override; void InvalidateCache() override; void InvalidateCacheAt(u32 em_address, int length = 4) override; diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index 4aec5fecca..d7b6956ffe 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -171,6 +171,9 @@ public: JitBlockCache *GetBlockCache() { return &blocks; } + std::vector SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); } + void RestoreSavedEmuHackOps(std::vector saved) override { blocks.RestoreSavedEmuHackOps(saved); } + void ClearCache(); void InvalidateCache(); void InvalidateCacheAt(u32 em_address, int length = 4); diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 24a5df88dc..c89feb9fd9 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -159,6 +159,50 @@ void IRBlockCache::InvalidateICache(u32 addess, u32 length) { // TODO } +std::vector IRBlockCache::SaveAndClearEmuHackOps() { + std::vector result; + result.resize(size_); + + for (int number = 0; number < size_; ++number) { + IRBlock &b = blocks_[number]; + if (b.IsValid() && b.RestoreOriginalFirstOp(number)) { + result[number] = number; + } else { + result[number] = 0; + } + } + + return result; +} + +void IRBlockCache::RestoreSavedEmuHackOps(std::vector saved) { + if (size_ != (int)saved.size()) { + ERROR_LOG(JIT, "RestoreSavedEmuHackOps: Wrong saved block size."); + return; + } + + for (int number = 0; number < size_; ++number) { + IRBlock &b = blocks_[number]; + // Only if we restored it, write it back. + if (b.IsValid() && saved[number] != 0 && b.HasOriginalFirstOp()) { + b.Finalize(number); + } + } +} + +bool IRBlock::HasOriginalFirstOp() { + return Memory::ReadUnchecked_U32(origAddr_) == origFirstOpcode_.encoding; +} + +bool IRBlock::RestoreOriginalFirstOp(int number) { + const u32 emuhack = MIPS_EMUHACK_OPCODE | number; + if (Memory::ReadUnchecked_U32(origAddr_) == emuhack) { + Memory::Write_Opcode_JIT(origAddr_, origFirstOpcode_); + return true; + } + return false; +} + void IRBlock::Finalize(int number) { origFirstOpcode_ = Memory::Read_Opcode_JIT(origAddr_); MIPSOpcode opcode = MIPSOpcode(MIPS_EMUHACK_OPCODE | number); diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index 998622285f..ee95199935 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -97,6 +97,9 @@ public: const u32 *GetConstants() const { return const_; } int GetNumInstructions() const { return numInstructions_; } MIPSOpcode GetOriginalFirstOp() const { return origFirstOpcode_; } + bool HasOriginalFirstOp(); + bool RestoreOriginalFirstOp(int number); + bool IsValid() const { return origAddr_ != 0; } void Finalize(int number); void Destroy(int number); @@ -127,6 +130,10 @@ public: return nullptr; } } + + std::vector SaveAndClearEmuHackOps(); + void RestoreSavedEmuHackOps(std::vector saved); + private: int size_; std::vector blocks_; @@ -151,6 +158,9 @@ public: JitBlockCache *GetBlockCache() override { return nullptr; } MIPSOpcode GetOriginalOp(MIPSOpcode op) override; + std::vector SaveAndClearEmuHackOps() override { return blocks_.SaveAndClearEmuHackOps(); } + void RestoreSavedEmuHackOps(std::vector saved) override { blocks_.RestoreSavedEmuHackOps(saved); } + void ClearCache(); void InvalidateCache(); void InvalidateCacheAt(u32 em_address, int length = 4); diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h index 62a91a30c2..004c7990f0 100644 --- a/Core/MIPS/JitCommon/JitCommon.h +++ b/Core/MIPS/JitCommon/JitCommon.h @@ -132,6 +132,11 @@ namespace MIPSComp { virtual void ClearCache() = 0; virtual MIPSOpcode GetOriginalOp(MIPSOpcode op) = 0; + // No jit operations may be run between these calls. + // Meant to be used to make memory safe for savestates, memcpy, etc. + virtual std::vector SaveAndClearEmuHackOps() = 0; + virtual void RestoreSavedEmuHackOps(std::vector saved) = 0; + // Block linking. This may need to work differently for whole-function JITs and stuff // like that. virtual void LinkBlock(u8 *exitPoint, const u8 *entryPoint) = 0; diff --git a/Core/MIPS/MIPS/MipsJit.h b/Core/MIPS/MIPS/MipsJit.h index 8c5dbf9bd3..c9a11e2835 100644 --- a/Core/MIPS/MIPS/MipsJit.h +++ b/Core/MIPS/MIPS/MipsJit.h @@ -131,6 +131,9 @@ public: JitBlockCache *GetBlockCache() { return &blocks; } + std::vector SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); } + void RestoreSavedEmuHackOps(std::vector saved) override { blocks.RestoreSavedEmuHackOps(saved); } + void ClearCache(); void InvalidateCache(); void InvalidateCacheAt(u32 em_address, int length = 4); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 4206f4d307..1326555c7c 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -163,6 +163,9 @@ public: JitBlockCache *GetBlockCache() { return &blocks; } MIPSOpcode GetOriginalOp(MIPSOpcode op) override; + std::vector SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); } + void RestoreSavedEmuHackOps(std::vector saved) override { blocks.RestoreSavedEmuHackOps(saved); } + void ClearCache(); void InvalidateCache() override; void InvalidateCacheAt(u32 em_address, int length = 4) { diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index 0d3b3817cc..e13d7275c0 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -425,8 +425,6 @@ __forceinline static Opcode Read_Instruction(u32 address, bool resolveReplacemen } if (MIPS_IS_RUNBLOCK(inst.encoding) && MIPSComp::jit) { - JitBlockCache *bc = MIPSComp::jit->GetBlockCache(); - inst = MIPSComp::jit->GetOriginalOp(inst); if (resolveReplacements && MIPS_IS_REPLACEMENT(inst)) { u32 op; diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 0b4465144c..7b3391d903 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -233,15 +233,10 @@ namespace SaveState auto savedReplacements = SaveAndClearReplacements(); if (MIPSComp::jit && p.mode == p.MODE_WRITE) { - auto blockCache = MIPSComp::jit->GetBlockCache(); std::vector savedBlocks; - if (blockCache) { - savedBlocks = blockCache->SaveAndClearEmuHackOps(); - } + savedBlocks = MIPSComp::jit->SaveAndClearEmuHackOps(); Memory::DoState(p); - if (blockCache) { - blockCache->RestoreSavedEmuHackOps(savedBlocks); - } + MIPSComp::jit->RestoreSavedEmuHackOps(savedBlocks); } else Memory::DoState(p);