JitCache: Use pointers in the ICache and dispatchers.

This commit is contained in:
degasus 2017-01-11 22:41:30 +01:00
parent 356619642b
commit fe41ed7fa1
4 changed files with 30 additions and 48 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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] = &block;
FastLookupEntryForAddress(block.effectiveAddress) = block_num;
FastLookupEntryForAddress(block.effectiveAddress) = &block;
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];
}

View File

@ -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
};