mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 07:21:14 +01:00
JitCache: Implement block unlinking.
This commit is contained in:
parent
ba39a0b3b4
commit
814f29b25b
@ -212,11 +212,3 @@ void CachedInterpreter::ClearCache()
|
||||
JitBaseBlockCache::Clear();
|
||||
UpdateMemoryOptions();
|
||||
}
|
||||
|
||||
void CachedInterpreter::WriteDestroyBlock(const u8* location, u32 address)
|
||||
{
|
||||
}
|
||||
|
||||
void CachedInterpreter::WriteLinkBlock(u8* location, const JitBlock& block)
|
||||
{
|
||||
}
|
||||
|
@ -28,11 +28,8 @@ public:
|
||||
|
||||
JitBaseBlockCache* GetBlockCache() override { return this; }
|
||||
const char* GetName() override { return "Cached Interpreter"; }
|
||||
void WriteLinkBlock(u8* location, const JitBlock& block) override;
|
||||
|
||||
void WriteDestroyBlock(const u8* location, u32 address) override;
|
||||
|
||||
const CommonAsmRoutinesBase* GetAsmRoutines() override { return nullptr; };
|
||||
void WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest) override {}
|
||||
const CommonAsmRoutinesBase* GetAsmRoutines() override { return nullptr; }
|
||||
private:
|
||||
struct Instruction
|
||||
{
|
||||
|
@ -196,7 +196,6 @@ void JitArm64::WriteExit(u32 destination)
|
||||
linkData.linkStatus = false;
|
||||
b->linkData.push_back(linkData);
|
||||
|
||||
// the code generated in JitArm64BlockCache::WriteDestroyBlock must fit in this block
|
||||
MOVI2R(DISPATCHER_PC, destination);
|
||||
B(dispatcher);
|
||||
}
|
||||
|
@ -7,32 +7,39 @@
|
||||
#include "Core/PowerPC/JitArm64/JitArm64Cache.h"
|
||||
#include "Core/PowerPC/JitInterface.h"
|
||||
|
||||
void JitArm64BlockCache::WriteLinkBlock(u8* location, const JitBlock& block)
|
||||
void JitArm64BlockCache::WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest)
|
||||
{
|
||||
u8* location = source.exitPtrs;
|
||||
ARM64XEmitter emit(location);
|
||||
|
||||
// Are we able to jump directly to the normal entry?
|
||||
s64 distance = ((s64)block.normalEntry - (s64)location) >> 2;
|
||||
if (distance >= -0x40000 && distance <= 0x3FFFF)
|
||||
if (dest)
|
||||
{
|
||||
emit.B(CC_LE, block.normalEntry);
|
||||
// Are we able to jump directly to the normal entry?
|
||||
s64 distance = ((s64)dest->normalEntry - (s64)location) >> 2;
|
||||
if (distance >= -0x40000 && distance <= 0x3FFFF)
|
||||
{
|
||||
emit.B(CC_LE, dest->normalEntry);
|
||||
}
|
||||
|
||||
// We can't write DISPATCHER_PC here, as block linking may only use 8 bytes.
|
||||
// So we'll hit two jumps when calling Advance.
|
||||
emit.B(block.checkedEntry);
|
||||
// Use the checked entry if either downcount is smaller zero,
|
||||
// or if we're not able to inline the downcount check here.
|
||||
emit.B(dest->checkedEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit.B(block.checkedEntry);
|
||||
emit.MOVI2R(DISPATCHER_PC, source.exitAddress);
|
||||
emit.B(jit->GetAsmRoutines()->dispatcher);
|
||||
}
|
||||
emit.FlushIcache();
|
||||
}
|
||||
|
||||
void JitArm64BlockCache::WriteDestroyBlock(const u8* location, u32 address)
|
||||
void JitArm64BlockCache::WriteDestroyBlock(const JitBlock& block)
|
||||
{
|
||||
// must fit within the code generated in JitArm64::WriteExit
|
||||
ARM64XEmitter emit((u8*)location);
|
||||
emit.MOVI2R(DISPATCHER_PC, address);
|
||||
emit.B(jit->GetAsmRoutines()->dispatcher);
|
||||
// Only clear the entry points as we might still be within this block.
|
||||
ARM64XEmitter emit((u8*)block.checkedEntry);
|
||||
|
||||
while (emit.GetWritableCodePtr() <= block.normalEntry)
|
||||
emit.BRK(0x123);
|
||||
|
||||
emit.FlushIcache();
|
||||
}
|
||||
|
@ -11,6 +11,6 @@ typedef void (*CompiledCode)();
|
||||
class JitArm64BlockCache : public JitBaseBlockCache
|
||||
{
|
||||
private:
|
||||
void WriteLinkBlock(u8* location, const JitBlock& block);
|
||||
void WriteDestroyBlock(const u8* location, u32 address);
|
||||
void WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest) override;
|
||||
void WriteDestroyBlock(const JitBlock& block) override;
|
||||
};
|
||||
|
@ -134,7 +134,6 @@ void JitBaseBlockCache::FinalizeBlock(int block_num, bool block_link, const u8*
|
||||
}
|
||||
|
||||
LinkBlock(block_num);
|
||||
LinkBlockExits(block_num);
|
||||
}
|
||||
|
||||
JitRegister::Register(b.checkedEntry, b.codeSize, "JIT_PPC_%08x", b.physicalAddress);
|
||||
@ -216,8 +215,11 @@ void JitBaseBlockCache::LinkBlockExits(int i)
|
||||
int destinationBlock = GetBlockNumberFromStartAddress(e.exitAddress, b.msrBits);
|
||||
if (destinationBlock != -1)
|
||||
{
|
||||
WriteLinkBlock(e.exitPtrs, blocks[destinationBlock]);
|
||||
e.linkStatus = true;
|
||||
if (!blocks[destinationBlock].invalid)
|
||||
{
|
||||
WriteLinkBlock(e, &blocks[destinationBlock]);
|
||||
e.linkStatus = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -251,10 +253,12 @@ void JitBaseBlockCache::UnlinkBlock(int i)
|
||||
for (auto& e : sourceBlock.linkData)
|
||||
{
|
||||
if (e.exitAddress == b.effectiveAddress)
|
||||
{
|
||||
WriteLinkBlock(e, nullptr);
|
||||
e.linkStatus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
links_to.erase(b.effectiveAddress);
|
||||
}
|
||||
|
||||
void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate)
|
||||
@ -277,10 +281,18 @@ void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate)
|
||||
|
||||
UnlinkBlock(block_num);
|
||||
|
||||
// Send anyone who tries to run this block back to the dispatcher.
|
||||
// Not entirely ideal, but .. pretty good.
|
||||
// Spurious entrances from previously linked blocks can only come through checkedEntry
|
||||
WriteDestroyBlock(b.checkedEntry, b.effectiveAddress);
|
||||
// Delete linking adresses
|
||||
auto it = links_to.equal_range(b.effectiveAddress);
|
||||
while (it.first != it.second)
|
||||
{
|
||||
if (it.first->second == block_num)
|
||||
it.first = links_to.erase(it.first);
|
||||
else
|
||||
it.first++;
|
||||
}
|
||||
|
||||
// Raise an signal if we are going to call this block again
|
||||
WriteDestroyBlock(b);
|
||||
}
|
||||
|
||||
void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool forced)
|
||||
@ -327,9 +339,10 @@ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool for
|
||||
}
|
||||
}
|
||||
|
||||
void JitBlockCache::WriteLinkBlock(u8* location, const JitBlock& block)
|
||||
void JitBlockCache::WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest)
|
||||
{
|
||||
const u8* address = block.checkedEntry;
|
||||
u8* location = source.exitPtrs;
|
||||
const u8* address = dest ? dest->checkedEntry : jit->GetAsmRoutines()->dispatcher;
|
||||
XEmitter emit(location);
|
||||
if (*location == 0xE8)
|
||||
{
|
||||
@ -348,9 +361,11 @@ void JitBlockCache::WriteLinkBlock(u8* location, const JitBlock& block)
|
||||
}
|
||||
}
|
||||
|
||||
void JitBlockCache::WriteDestroyBlock(const u8* location, u32 address)
|
||||
void JitBlockCache::WriteDestroyBlock(const JitBlock& block)
|
||||
{
|
||||
XEmitter emit((u8*)location);
|
||||
emit.MOV(32, PPCSTATE(pc), Imm32(address));
|
||||
emit.JMP(jit->GetAsmRoutines()->dispatcher, true);
|
||||
// Only clear the entry points as we might still be within this block.
|
||||
XEmitter emit((u8*)block.checkedEntry);
|
||||
emit.INT3();
|
||||
XEmitter emit2((u8*)block.normalEntry);
|
||||
emit2.INT3();
|
||||
}
|
||||
|
@ -149,9 +149,8 @@ private:
|
||||
// Fast but risky block lookup based on iCache.
|
||||
int& FastLookupEntryForAddress(u32 address) { return iCache[(address >> 2) & iCache_Mask]; }
|
||||
// Virtual for overloaded
|
||||
virtual void WriteLinkBlock(u8* location, const JitBlock& block) = 0;
|
||||
virtual void WriteDestroyBlock(const u8* location, u32 address) = 0;
|
||||
|
||||
virtual void WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest) = 0;
|
||||
virtual void WriteDestroyBlock(const JitBlock& block) {}
|
||||
public:
|
||||
JitBaseBlockCache() : num_blocks(0) {}
|
||||
virtual ~JitBaseBlockCache() {}
|
||||
@ -190,6 +189,6 @@ public:
|
||||
class JitBlockCache : public JitBaseBlockCache
|
||||
{
|
||||
private:
|
||||
void WriteLinkBlock(u8* location, const JitBlock& block) override;
|
||||
void WriteDestroyBlock(const u8* location, u32 address) override;
|
||||
void WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest) override;
|
||||
void WriteDestroyBlock(const JitBlock& block) override;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user