diff --git a/Core/MIPS/IR/IRFrontend.cpp b/Core/MIPS/IR/IRFrontend.cpp index e2e5a207ed40..15f01480f3f3 100644 --- a/Core/MIPS/IR/IRFrontend.cpp +++ b/Core/MIPS/IR/IRFrontend.cpp @@ -221,7 +221,7 @@ MIPSOpcode IRFrontend::GetOffsetInstruction(int offset) { return Memory::Read_Instruction(GetCompilerPC() + 4 * offset); } -void IRFrontend::DoJit(u32 em_address, std::vector &instructions, std::vector &constants) { +void IRFrontend::DoJit(u32 em_address, std::vector &instructions, std::vector &constants, u32 &mipsBytes) { js.cancel = false; js.blockStart = em_address; js.compilerPC = em_address; @@ -254,6 +254,8 @@ void IRFrontend::DoJit(u32 em_address, std::vector &instructions, std::v } } + mipsBytes = js.compilerPC - em_address; + IRWriter simplified; IRWriter *code = &ir; if (!js.hadBreakpoints) { diff --git a/Core/MIPS/IR/IRFrontend.h b/Core/MIPS/IR/IRFrontend.h index 0baa04605736..e91c8ec9131b 100644 --- a/Core/MIPS/IR/IRFrontend.h +++ b/Core/MIPS/IR/IRFrontend.h @@ -88,7 +88,7 @@ class IRFrontend : public MIPSFrontendInterface { void DoState(PointerWrap &p); bool CheckRounding(); // returns true if we need a do-over - void DoJit(u32 em_address, std::vector &instructions, std::vector &constants); + void DoJit(u32 em_address, std::vector &instructions, std::vector &constants, u32 &mipsBytes); void EatPrefix() override { js.EatPrefix(); diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 0ed6b92b8b8e..d02d65d1e7e3 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -85,8 +85,10 @@ void IRJit::Compile(u32 em_address) { std::vector instructions; std::vector constants; - frontend_.DoJit(em_address, instructions, constants); + u32 mipsBytes; + frontend_.DoJit(em_address, instructions, constants, mipsBytes); b->SetInstructions(instructions, constants); + b->SetOriginalSize(mipsBytes); b->Finalize(block_num); // Overwrites the first instruction if (frontend_.CheckRounding()) { @@ -152,8 +154,13 @@ void IRBlockCache::Clear() { blocks_.clear(); } -void IRBlockCache::InvalidateICache(u32 addess, u32 length) { - // TODO +void IRBlockCache::InvalidateICache(u32 address, u32 length) { + // TODO: Could be more efficient. + for (int i = 0; i < size_; ++i) { + if (blocks_[i].OverlapsRange(address, length)) { + blocks_[i].Destroy(i); + } + } } std::vector IRBlockCache::SaveAndClearEmuHackOps() { @@ -217,6 +224,10 @@ void IRBlock::Destroy(int number) { } } +bool IRBlock::OverlapsRange(u32 addr, u32 size) { + return addr + size > origAddr_ && addr < origAddr_ + origSize_; +} + MIPSOpcode IRJit::GetOriginalOp(MIPSOpcode op) { IRBlock *b = blocks_.GetBlock(op.encoding & 0xFFFFFF); return b->GetOriginalFirstOp(); diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index 3b1a840e718a..97cd4341f6c8 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -100,6 +100,10 @@ class IRBlock { bool HasOriginalFirstOp(); bool RestoreOriginalFirstOp(int number); bool IsValid() const { return origAddr_ != 0; } + void SetOriginalSize(u32 size) { + origSize_ = size; + } + bool OverlapsRange(u32 addr, u32 size); void Finalize(int number); void Destroy(int number); @@ -110,13 +114,14 @@ class IRBlock { u16 numInstructions_; u16 numConstants_; u32 origAddr_; + u32 origSize_; MIPSOpcode origFirstOpcode_; }; class IRBlockCache { public: void Clear(); - void InvalidateICache(u32 addess, u32 length); + void InvalidateICache(u32 address, u32 length); int GetNumBlocks() const { return (int)blocks_.size(); } int AllocateBlock(int emAddr) { blocks_.push_back(IRBlock(emAddr));