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.
|
// The following is a translation of JitBaseBlockCache::Dispatch into assembly.
|
||||||
|
|
||||||
// Fast block number lookup.
|
// Fast block number lookup.
|
||||||
|
// ((PC >> 2) & mask) * sizeof(JitBlock*) = (PC & (mask << 2)) * 2
|
||||||
MOV(32, R(RSCRATCH), PPCSTATE(pc));
|
MOV(32, R(RSCRATCH), PPCSTATE(pc));
|
||||||
u64 icache = reinterpret_cast<u64>(g_jit->GetBlockCache()->GetICache());
|
u64 icache = reinterpret_cast<u64>(g_jit->GetBlockCache()->GetICache());
|
||||||
AND(32, R(RSCRATCH), Imm32(JitBaseBlockCache::iCache_Mask << 2));
|
AND(32, R(RSCRATCH), Imm32(JitBaseBlockCache::iCache_Mask << 2));
|
||||||
if (icache <= INT_MAX)
|
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
|
else
|
||||||
{
|
{
|
||||||
MOV(64, R(RSCRATCH2), Imm64(icache));
|
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.
|
// Check if we found a block.
|
||||||
u64 blocks = reinterpret_cast<u64>(g_jit->GetBlockCache()->GetBlocks());
|
TEST(64, R(RSCRATCH), R(RSCRATCH));
|
||||||
IMUL(32, RSCRATCH, R(RSCRATCH), Imm32(sizeof(JitBlock)));
|
FixupBranch not_found = J_CC(CC_Z);
|
||||||
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 both block.effectiveAddress and block.msrBits.
|
// Check both block.effectiveAddress and block.msrBits.
|
||||||
MOV(32, R(RSCRATCH2), PPCSTATE(msr));
|
MOV(32, R(RSCRATCH2), PPCSTATE(msr));
|
||||||
AND(32, R(RSCRATCH2), Imm32(JitBlock::JIT_CACHE_MSR_MASK));
|
AND(32, R(RSCRATCH2), Imm32(JitBlock::JIT_CACHE_MSR_MASK));
|
||||||
|
@ -138,10 +131,11 @@ void Jit64AsmRoutineManager::Generate()
|
||||||
MOV(32, R(RSCRATCH_EXTRA), PPCSTATE(pc));
|
MOV(32, R(RSCRATCH_EXTRA), PPCSTATE(pc));
|
||||||
OR(64, R(RSCRATCH2), R(RSCRATCH_EXTRA));
|
OR(64, R(RSCRATCH2), R(RSCRATCH_EXTRA));
|
||||||
CMP(64, R(RSCRATCH2), MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlock, effectiveAddress))));
|
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.
|
// Success; branch to the block we found.
|
||||||
JMPptr(MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlock, normalEntry))));
|
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.
|
// 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
|
// (We need to loop because Jit() might not actually generate a block
|
||||||
|
|
|
@ -73,18 +73,12 @@ void JitArm64::GenerateAsm()
|
||||||
// iCache[(address >> 2) & iCache_Mask];
|
// iCache[(address >> 2) & iCache_Mask];
|
||||||
ARM64Reg pc_masked = W25;
|
ARM64Reg pc_masked = W25;
|
||||||
ARM64Reg cache_base = X27;
|
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 block = X30;
|
||||||
ARM64Reg jit_block_size = W24;
|
ORRI2R(pc_masked, WZR, JitBaseBlockCache::iCache_Mask << 3);
|
||||||
MOVI2R(jit_block_size, sizeof(JitBlock));
|
AND(pc_masked, pc_masked, DISPATCHER_PC, ArithOption(DISPATCHER_PC, ST_LSL, 1));
|
||||||
MUL(block_num, block_num, jit_block_size);
|
MOVP2R(cache_base, g_jit->GetBlockCache()->GetICache());
|
||||||
MOVP2R(block, g_jit->GetBlockCache()->GetBlocks());
|
LDR(block, cache_base, EncodeRegTo64(pc_masked));
|
||||||
ADD(block, block, EncodeRegTo64(block_num));
|
FixupBranch not_found = CBZ(block);
|
||||||
|
|
||||||
// b.effectiveAddress != addr || b.msrBits != msr
|
// b.effectiveAddress != addr || b.msrBits != msr
|
||||||
ARM64Reg pc_and_msr = W25;
|
ARM64Reg pc_and_msr = W25;
|
||||||
|
@ -102,6 +96,7 @@ void JitArm64::GenerateAsm()
|
||||||
// return blocks[block_num].normalEntry;
|
// return blocks[block_num].normalEntry;
|
||||||
LDR(INDEX_UNSIGNED, block, block, offsetof(JitBlock, normalEntry));
|
LDR(INDEX_UNSIGNED, block, block, offsetof(JitBlock, normalEntry));
|
||||||
BR(block);
|
BR(block);
|
||||||
|
SetJumpTarget(not_found);
|
||||||
SetJumpTarget(pc_missmatch);
|
SetJumpTarget(pc_missmatch);
|
||||||
SetJumpTarget(msr_missmatch);
|
SetJumpTarget(msr_missmatch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ void JitBaseBlockCache::Init()
|
||||||
s_clear_jit_cache_thread_safe = CoreTiming::RegisterEvent("clearJitCache", ClearCacheThreadSafe);
|
s_clear_jit_cache_thread_safe = CoreTiming::RegisterEvent("clearJitCache", ClearCacheThreadSafe);
|
||||||
JitRegister::Init(SConfig::GetInstance().m_perfDir);
|
JitRegister::Init(SConfig::GetInstance().m_perfDir);
|
||||||
|
|
||||||
iCache.fill(0);
|
iCache.fill(nullptr);
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,12 +99,7 @@ bool JitBaseBlockCache::IsFull() const
|
||||||
return num_blocks >= MAX_NUM_BLOCKS - 1;
|
return num_blocks >= MAX_NUM_BLOCKS - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
JitBlock* JitBaseBlockCache::GetBlocks()
|
JitBlock** JitBaseBlockCache::GetICache()
|
||||||
{
|
|
||||||
return blocks.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
int* JitBaseBlockCache::GetICache()
|
|
||||||
{
|
{
|
||||||
return iCache.data();
|
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));
|
std::make_pair(old_b.physicalAddress + 4 * old_b.originalSize - 1, old_b.physicalAddress));
|
||||||
DestroyBlock(old_b, true);
|
DestroyBlock(old_b, true);
|
||||||
}
|
}
|
||||||
const int block_num = static_cast<int>(&block - &blocks[0]);
|
|
||||||
start_block_map[block.physicalAddress] = █
|
start_block_map[block.physicalAddress] = █
|
||||||
FastLookupEntryForAddress(block.effectiveAddress) = block_num;
|
FastLookupEntryForAddress(block.effectiveAddress) = █
|
||||||
|
|
||||||
u32 pAddr = block.physicalAddress;
|
u32 pAddr = block.physicalAddress;
|
||||||
|
|
||||||
|
@ -190,16 +184,16 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr)
|
||||||
|
|
||||||
const u8* JitBaseBlockCache::Dispatch()
|
const u8* JitBaseBlockCache::Dispatch()
|
||||||
{
|
{
|
||||||
int block_num = FastLookupEntryForAddress(PC);
|
JitBlock* block = FastLookupEntryForAddress(PC);
|
||||||
|
|
||||||
while (blocks[block_num].effectiveAddress != PC ||
|
while (!block || block->effectiveAddress != PC ||
|
||||||
blocks[block_num].msrBits != (MSR & JitBlock::JIT_CACHE_MSR_MASK))
|
block->msrBits != (MSR & JitBlock::JIT_CACHE_MSR_MASK))
|
||||||
{
|
{
|
||||||
MoveBlockIntoFastCache(PC, 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)
|
void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool forced)
|
||||||
|
@ -326,7 +320,7 @@ void JitBaseBlockCache::DestroyBlock(JitBlock& block, bool invalidate)
|
||||||
}
|
}
|
||||||
block.invalid = true;
|
block.invalid = true;
|
||||||
start_block_map.erase(block.physicalAddress);
|
start_block_map.erase(block.physicalAddress);
|
||||||
FastLookupEntryForAddress(block.effectiveAddress) = 0;
|
FastLookupEntryForAddress(block.effectiveAddress) = nullptr;
|
||||||
|
|
||||||
UnlinkBlock(block);
|
UnlinkBlock(block);
|
||||||
|
|
||||||
|
@ -353,12 +347,12 @@ void JitBaseBlockCache::MoveBlockIntoFastCache(u32 addr, u32 msr)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FastLookupEntryForAddress(addr) = static_cast<int>(block - &blocks[0]);
|
FastLookupEntryForAddress(addr) = block;
|
||||||
LinkBlock(*block);
|
LinkBlock(*block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int& JitBaseBlockCache::FastLookupEntryForAddress(u32 address)
|
JitBlock*& JitBaseBlockCache::FastLookupEntryForAddress(u32 address)
|
||||||
{
|
{
|
||||||
return iCache[(address >> 2) & iCache_Mask];
|
return iCache[(address >> 2) & iCache_Mask];
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,7 @@ public:
|
||||||
bool IsFull() const;
|
bool IsFull() const;
|
||||||
|
|
||||||
// Code Cache
|
// Code Cache
|
||||||
JitBlock* GetBlocks();
|
JitBlock** GetICache();
|
||||||
int* GetICache();
|
|
||||||
void RunOnBlocks(std::function<void(const JitBlock&)> f);
|
void RunOnBlocks(std::function<void(const JitBlock&)> f);
|
||||||
|
|
||||||
JitBlock* AllocateBlock(u32 em_address);
|
JitBlock* AllocateBlock(u32 em_address);
|
||||||
|
@ -164,7 +163,7 @@ private:
|
||||||
void MoveBlockIntoFastCache(u32 em_address, u32 msr);
|
void MoveBlockIntoFastCache(u32 em_address, u32 msr);
|
||||||
|
|
||||||
// Fast but risky block lookup based on iCache.
|
// 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.
|
// 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.
|
// 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 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.
|
// 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