JitCache: Get physical addresses from PPCAnalyst.

So we support all kind of degenerated blocks now, not just range+length based ones.
This commit is contained in:
degasus
2017-01-22 16:23:56 +01:00
parent 3529af61c4
commit 70caf447b9
10 changed files with 34 additions and 28 deletions

View File

@ -211,7 +211,7 @@ void CachedInterpreter::Jit(u32 address)
b->codeSize = (u32)(GetCodePtr() - b->checkedEntry); b->codeSize = (u32)(GetCodePtr() - b->checkedEntry);
b->originalSize = code_block.m_num_instructions; b->originalSize = code_block.m_num_instructions;
m_block_cache.FinalizeBlock(*b, jo.enableBlocklink, b->checkedEntry); m_block_cache.FinalizeBlock(*b, jo.enableBlocklink, code_block.m_physical_addresses);
} }
void CachedInterpreter::ClearCache() void CachedInterpreter::ClearCache()

View File

@ -590,7 +590,8 @@ void Jit64::Jit(u32 em_address)
} }
JitBlock* b = blocks.AllocateBlock(em_address); JitBlock* b = blocks.AllocateBlock(em_address);
blocks.FinalizeBlock(*b, jo.enableBlocklink, DoJit(em_address, &code_buffer, b, nextPC)); DoJit(em_address, &code_buffer, b, nextPC);
blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block.m_physical_addresses);
} }
const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC)

View File

@ -508,7 +508,8 @@ void JitIL::Jit(u32 em_address)
} }
JitBlock* b = blocks.AllocateBlock(em_address); JitBlock* b = blocks.AllocateBlock(em_address);
blocks.FinalizeBlock(*b, jo.enableBlocklink, DoJit(em_address, &code_buffer, b, nextPC)); DoJit(em_address, &code_buffer, b, nextPC);
blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block.m_physical_addresses);
} }
const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC)

View File

@ -399,7 +399,7 @@ void JitArm64::Jit(u32)
JitBlock* b = blocks.AllocateBlock(em_address); JitBlock* b = blocks.AllocateBlock(em_address);
const u8* BlockPtr = DoJit(em_address, &code_buffer, b, nextPC); const u8* BlockPtr = DoJit(em_address, &code_buffer, b, nextPC);
blocks.FinalizeBlock(*b, jo.enableBlocklink, BlockPtr); blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block.m_physical_addresses);
} }
const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC)

View File

@ -38,11 +38,7 @@ static void ClearCacheThreadSafe(u64 userdata, s64 cyclesdata)
bool JitBlock::Overlap(u32 addr, u32 length) bool JitBlock::Overlap(u32 addr, u32 length)
{ {
if (addr >= physicalAddress + originalSize) return physical_addresses.lower_bound(addr) != physical_addresses.lower_bound(addr + length);
return false;
if (physicalAddress >= addr + length)
return false;
return true;
} }
JitBaseBlockCache::JitBaseBlockCache(JitBase& jit) : m_jit{jit} JitBaseBlockCache::JitBaseBlockCache(JitBase& jit) : m_jit{jit}
@ -120,21 +116,21 @@ JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
return &b; return &b;
} }
void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr) void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link,
const std::set<u32>& physical_addresses)
{ {
size_t index = FastLookupIndexForAddress(block.effectiveAddress); size_t index = FastLookupIndexForAddress(block.effectiveAddress);
fast_block_map[index] = &block; fast_block_map[index] = &block;
block.fast_block_map_index = index; block.fast_block_map_index = index;
u32 block_start = block.physicalAddress; block.physical_addresses = physical_addresses;
u32 block_end = block_start + (block.originalSize - 1) * 4;
for (u32 addr = block_start / 32; addr <= block_end / 32; ++addr) u32 range_mask = ~(BLOCK_RANGE_MAP_ELEMENTS - 1);
valid_block.Set(addr); for (u32 addr : physical_addresses)
{
u32 mask = ~(BLOCK_RANGE_MAP_ELEMENTS - 1); valid_block.Set(addr / 32);
for (u32 addr = block_start & mask; addr <= (block_end & mask); addr += BLOCK_RANGE_MAP_ELEMENTS) block_range_map[addr & range_mask].insert(&block);
block_range_map[addr].insert(&block); }
if (block_link) if (block_link)
{ {
@ -207,8 +203,8 @@ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool for
if (destroy_block) if (destroy_block)
{ {
// Iterate over all macro blocks which overlap the given range. // Iterate over all macro blocks which overlap the given range.
u32 mask = ~(BLOCK_RANGE_MAP_ELEMENTS - 1); u32 range_mask = ~(BLOCK_RANGE_MAP_ELEMENTS - 1);
auto start = block_range_map.lower_bound(pAddr & mask); auto start = block_range_map.lower_bound(pAddr & range_mask);
auto end = block_range_map.lower_bound(pAddr + length); auto end = block_range_map.lower_bound(pAddr + length);
while (start != end) while (start != end)
{ {
@ -221,11 +217,9 @@ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool for
{ {
// If the block overlaps, also remove all other occupied slots in the other macro blocks. // If the block overlaps, also remove all other occupied slots in the other macro blocks.
// This will leak empty macro blocks, but they may be reused or cleared later on. // This will leak empty macro blocks, but they may be reused or cleared later on.
u32 block_start = block->physicalAddress; for (u32 addr : block->physical_addresses)
u32 block_end = block_start + (block->originalSize - 1) * 4; if ((addr & range_mask) != start->first)
for (u32 addr = block_start & mask; addr <= (block_end & mask); addr += BLOCK_RANGE_MAP_ELEMENTS) block_range_map[addr & range_mask].erase(block);
if (addr != start->first)
block_range_map[addr].erase(block);
// And remove the block. // And remove the block.
DestroyBlock(*block); DestroyBlock(*block);

View File

@ -60,6 +60,9 @@ struct JitBlock
}; };
std::vector<LinkData> linkData; std::vector<LinkData> linkData;
// This set stores all physical addresses of all occupied instructions.
std::set<u32> physical_addresses;
// we don't really need to save start and stop // we don't really need to save start and stop
// TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;) // TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;)
u64 ticStart; // for profiling - time. u64 ticStart; // for profiling - time.
@ -127,7 +130,7 @@ public:
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);
void FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr); void FinalizeBlock(JitBlock& block, bool block_link, const std::set<u32>& physical_addresses);
// Look for the block in the slow but accurate way. // Look for the block in the slow but accurate way.
// This function shall be used if FastLookupIndexForAddress() failed. // This function shall be used if FastLookupIndexForAddress() failed.

View File

@ -384,7 +384,7 @@ TryReadInstResult TryReadInstruction(u32 address)
auto tlb_addr = TranslateAddress<FLAG_OPCODE>(address); auto tlb_addr = TranslateAddress<FLAG_OPCODE>(address);
if (!tlb_addr.Success()) if (!tlb_addr.Success())
{ {
return TryReadInstResult{false, false, 0}; return TryReadInstResult{false, false, 0, 0};
} }
else else
{ {
@ -403,7 +403,7 @@ TryReadInstResult TryReadInstruction(u32 address)
{ {
hex = PowerPC::ppcState.iCache.ReadInstruction(address); hex = PowerPC::ppcState.iCache.ReadInstruction(address);
} }
return TryReadInstResult{true, from_bat, hex}; return TryReadInstResult{true, from_bat, hex, address};
} }
u32 HostRead_Instruction(const u32 address) u32 HostRead_Instruction(const u32 address)

View File

@ -646,6 +646,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32
block->m_memory_exception = false; block->m_memory_exception = false;
block->m_num_instructions = 0; block->m_num_instructions = 0;
block->m_gqr_used = BitSet8(0); block->m_gqr_used = BitSet8(0);
block->m_physical_addresses.clear();
CodeOp* code = buffer->codebuffer; CodeOp* code = buffer->codebuffer;
@ -676,6 +677,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32
code[i].branchToIndex = -1; code[i].branchToIndex = -1;
code[i].skip = false; code[i].skip = false;
block->m_stats->numCycles += opinfo->numCycles; block->m_stats->numCycles += opinfo->numCycles;
block->m_physical_addresses.insert(result.physical_address);
SetInstructionStats(block, &code[i], opinfo, i); SetInstructionStats(block, &code[i], opinfo, i);

View File

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
@ -157,6 +158,9 @@ struct CodeBlock
// Which GPRs this block reads from before defining, if any. // Which GPRs this block reads from before defining, if any.
BitSet32 m_gpr_inputs; BitSet32 m_gpr_inputs;
// Which memory locations are occupied by this block.
std::set<u32> m_physical_addresses;
}; };
class PPCAnalyzer class PPCAnalyzer

View File

@ -232,6 +232,7 @@ struct TryReadInstResult
bool valid; bool valid;
bool from_bat; bool from_bat;
u32 hex; u32 hex;
u32 physical_address;
}; };
TryReadInstResult TryReadInstruction(const u32 address); TryReadInstResult TryReadInstruction(const u32 address);