Merge pull request #4650 from degasus/jitcache
JitCache: Use pointers in the ICache and dispatchers.
This commit is contained in:
commit
5297309dfa
|
@ -106,31 +106,24 @@ void Jit64AsmRoutineManager::Generate()
|
|||
// The following is a translation of JitBaseBlockCache::Dispatch into assembly.
|
||||
|
||||
// Fast block number lookup.
|
||||
// ((PC >> 2) & mask) * sizeof(JitBlock*) = (PC & (mask << 2)) * 2
|
||||
MOV(32, R(RSCRATCH), PPCSTATE(pc));
|
||||
u64 icache = reinterpret_cast<u64>(g_jit->GetBlockCache()->GetICache());
|
||||
AND(32, R(RSCRATCH), Imm32(JitBaseBlockCache::iCache_Mask << 2));
|
||||
if (icache <= INT_MAX)
|
||||
{
|
||||
MOV(32, R(RSCRATCH), MDisp(RSCRATCH, static_cast<s32>(icache)));
|
||||
MOV(64, R(RSCRATCH), MScaled(RSCRATCH, SCALE_2, static_cast<s32>(icache)));
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(64, R(RSCRATCH2), Imm64(icache));
|
||||
MOV(32, R(RSCRATCH), MRegSum(RSCRATCH2, RSCRATCH));
|
||||
MOV(64, R(RSCRATCH), MComplex(RSCRATCH2, RSCRATCH, SCALE_2, 0));
|
||||
}
|
||||
|
||||
// Check whether the block we found matches the current state.
|
||||
u64 blocks = reinterpret_cast<u64>(g_jit->GetBlockCache()->GetBlocks());
|
||||
IMUL(32, RSCRATCH, R(RSCRATCH), Imm32(sizeof(JitBlock)));
|
||||
if (blocks <= INT_MAX)
|
||||
{
|
||||
ADD(64, R(RSCRATCH), Imm32(static_cast<s32>(blocks)));
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(64, R(RSCRATCH2), Imm64(blocks));
|
||||
ADD(64, R(RSCRATCH), R(RSCRATCH2));
|
||||
}
|
||||
// Check if we found a block.
|
||||
TEST(64, R(RSCRATCH), R(RSCRATCH));
|
||||
FixupBranch not_found = J_CC(CC_Z);
|
||||
|
||||
// Check both block.effectiveAddress and block.msrBits.
|
||||
MOV(32, R(RSCRATCH2), PPCSTATE(msr));
|
||||
AND(32, R(RSCRATCH2), Imm32(JitBlock::JIT_CACHE_MSR_MASK));
|
||||
|
@ -138,10 +131,11 @@ void Jit64AsmRoutineManager::Generate()
|
|||
MOV(32, R(RSCRATCH_EXTRA), PPCSTATE(pc));
|
||||
OR(64, R(RSCRATCH2), R(RSCRATCH_EXTRA));
|
||||
CMP(64, R(RSCRATCH2), MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlock, effectiveAddress))));
|
||||
FixupBranch notfound = J_CC(CC_NE);
|
||||
FixupBranch state_mismatch = J_CC(CC_NE);
|
||||
// Success; branch to the block we found.
|
||||
JMPptr(MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlock, normalEntry))));
|
||||
SetJumpTarget(notfound);
|
||||
SetJumpTarget(not_found);
|
||||
SetJumpTarget(state_mismatch);
|
||||
|
||||
// Failure; call into the block cache to update the state, then try again.
|
||||
// (We need to loop because Jit() might not actually generate a block
|
||||
|
|
|
@ -73,18 +73,12 @@ void JitArm64::GenerateAsm()
|
|||
// iCache[(address >> 2) & iCache_Mask];
|
||||
ARM64Reg pc_masked = W25;
|
||||
ARM64Reg cache_base = X27;
|
||||
ARM64Reg block_num = W27;
|
||||
ANDI2R(pc_masked, DISPATCHER_PC, JitBaseBlockCache::iCache_Mask << 2);
|
||||
MOVP2R(cache_base, g_jit->GetBlockCache()->GetICache());
|
||||
LDR(block_num, cache_base, EncodeRegTo64(pc_masked));
|
||||
|
||||
// blocks[block_num]
|
||||
ARM64Reg block = X30;
|
||||
ARM64Reg jit_block_size = W24;
|
||||
MOVI2R(jit_block_size, sizeof(JitBlock));
|
||||
MUL(block_num, block_num, jit_block_size);
|
||||
MOVP2R(block, g_jit->GetBlockCache()->GetBlocks());
|
||||
ADD(block, block, EncodeRegTo64(block_num));
|
||||
ORRI2R(pc_masked, WZR, JitBaseBlockCache::iCache_Mask << 3);
|
||||
AND(pc_masked, pc_masked, DISPATCHER_PC, ArithOption(DISPATCHER_PC, ST_LSL, 1));
|
||||
MOVP2R(cache_base, g_jit->GetBlockCache()->GetICache());
|
||||
LDR(block, cache_base, EncodeRegTo64(pc_masked));
|
||||
FixupBranch not_found = CBZ(block);
|
||||
|
||||
// b.effectiveAddress != addr || b.msrBits != msr
|
||||
ARM64Reg pc_and_msr = W25;
|
||||
|
@ -102,6 +96,7 @@ void JitArm64::GenerateAsm()
|
|||
// return blocks[block_num].normalEntry;
|
||||
LDR(INDEX_UNSIGNED, block, block, offsetof(JitBlock, normalEntry));
|
||||
BR(block);
|
||||
SetJumpTarget(not_found);
|
||||
SetJumpTarget(pc_missmatch);
|
||||
SetJumpTarget(msr_missmatch);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ void JitBaseBlockCache::Init()
|
|||
s_clear_jit_cache_thread_safe = CoreTiming::RegisterEvent("clearJitCache", ClearCacheThreadSafe);
|
||||
JitRegister::Init(SConfig::GetInstance().m_perfDir);
|
||||
|
||||
iCache.fill(0);
|
||||
iCache.fill(nullptr);
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
@ -99,12 +99,7 @@ bool JitBaseBlockCache::IsFull() const
|
|||
return num_blocks >= MAX_NUM_BLOCKS - 1;
|
||||
}
|
||||
|
||||
JitBlock* JitBaseBlockCache::GetBlocks()
|
||||
{
|
||||
return blocks.data();
|
||||
}
|
||||
|
||||
int* JitBaseBlockCache::GetICache()
|
||||
JitBlock** JitBaseBlockCache::GetICache()
|
||||
{
|
||||
return iCache.data();
|
||||
}
|
||||
|
@ -140,9 +135,8 @@ void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8
|
|||
std::make_pair(old_b.physicalAddress + 4 * old_b.originalSize - 1, old_b.physicalAddress));
|
||||
DestroyBlock(old_b, true);
|
||||
}
|
||||
const int block_num = static_cast<int>(&block - &blocks[0]);
|
||||
start_block_map[block.physicalAddress] = █
|
||||
FastLookupEntryForAddress(block.effectiveAddress) = block_num;
|
||||
FastLookupEntryForAddress(block.effectiveAddress) = █
|
||||
|
||||
u32 pAddr = block.physicalAddress;
|
||||
|
||||
|
@ -190,16 +184,16 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr)
|
|||
|
||||
const u8* JitBaseBlockCache::Dispatch()
|
||||
{
|
||||
int block_num = FastLookupEntryForAddress(PC);
|
||||
JitBlock* block = FastLookupEntryForAddress(PC);
|
||||
|
||||
while (blocks[block_num].effectiveAddress != PC ||
|
||||
blocks[block_num].msrBits != (MSR & JitBlock::JIT_CACHE_MSR_MASK))
|
||||
while (!block || block->effectiveAddress != PC ||
|
||||
block->msrBits != (MSR & JitBlock::JIT_CACHE_MSR_MASK))
|
||||
{
|
||||
MoveBlockIntoFastCache(PC, MSR & JitBlock::JIT_CACHE_MSR_MASK);
|
||||
block_num = FastLookupEntryForAddress(PC);
|
||||
block = FastLookupEntryForAddress(PC);
|
||||
}
|
||||
|
||||
return blocks[block_num].normalEntry;
|
||||
return block->normalEntry;
|
||||
}
|
||||
|
||||
void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool forced)
|
||||
|
@ -326,7 +320,7 @@ void JitBaseBlockCache::DestroyBlock(JitBlock& block, bool invalidate)
|
|||
}
|
||||
block.invalid = true;
|
||||
start_block_map.erase(block.physicalAddress);
|
||||
FastLookupEntryForAddress(block.effectiveAddress) = 0;
|
||||
FastLookupEntryForAddress(block.effectiveAddress) = nullptr;
|
||||
|
||||
UnlinkBlock(block);
|
||||
|
||||
|
@ -353,12 +347,12 @@ void JitBaseBlockCache::MoveBlockIntoFastCache(u32 addr, u32 msr)
|
|||
}
|
||||
else
|
||||
{
|
||||
FastLookupEntryForAddress(addr) = static_cast<int>(block - &blocks[0]);
|
||||
FastLookupEntryForAddress(addr) = block;
|
||||
LinkBlock(*block);
|
||||
}
|
||||
}
|
||||
|
||||
int& JitBaseBlockCache::FastLookupEntryForAddress(u32 address)
|
||||
JitBlock*& JitBaseBlockCache::FastLookupEntryForAddress(u32 address)
|
||||
{
|
||||
return iCache[(address >> 2) & iCache_Mask];
|
||||
}
|
||||
|
|
|
@ -127,8 +127,7 @@ public:
|
|||
bool IsFull() const;
|
||||
|
||||
// Code Cache
|
||||
JitBlock* GetBlocks();
|
||||
int* GetICache();
|
||||
JitBlock** GetICache();
|
||||
void RunOnBlocks(std::function<void(const JitBlock&)> f);
|
||||
|
||||
JitBlock* AllocateBlock(u32 em_address);
|
||||
|
@ -164,7 +163,7 @@ private:
|
|||
void MoveBlockIntoFastCache(u32 em_address, u32 msr);
|
||||
|
||||
// Fast but risky block lookup based on iCache.
|
||||
int& FastLookupEntryForAddress(u32 address);
|
||||
JitBlock*& FastLookupEntryForAddress(u32 address);
|
||||
|
||||
// We store the metadata of all blocks in a linear way within this array.
|
||||
// Note: blocks[0] must not be used as it is referenced as invalid block in iCache.
|
||||
|
@ -190,5 +189,5 @@ private:
|
|||
|
||||
// This array is indexed with the masked PC and likely holds the correct block id.
|
||||
// This is used as a fast cache of start_block_map used in the assembly dispatcher.
|
||||
std::array<int, iCache_Num_Elements> iCache; // start_addr & mask -> number
|
||||
std::array<JitBlock*, iCache_Num_Elements> iCache; // start_addr & mask -> number
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue