diff --git a/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp b/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp index 3971ba40ea..d0db731de4 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp @@ -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(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(icache))); + MOV(64, R(RSCRATCH), MScaled(RSCRATCH, SCALE_2, static_cast(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(g_jit->GetBlockCache()->GetBlocks()); - IMUL(32, RSCRATCH, R(RSCRATCH), Imm32(sizeof(JitBlock))); - if (blocks <= INT_MAX) - { - ADD(64, R(RSCRATCH), Imm32(static_cast(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(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(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 diff --git a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp index bdb074bb41..20921b2b70 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp @@ -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); } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 93937f9e32..aebff21af8 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -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(&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(block - &blocks[0]); + FastLookupEntryForAddress(addr) = block; LinkBlock(*block); } } -int& JitBaseBlockCache::FastLookupEntryForAddress(u32 address) +JitBlock*& JitBaseBlockCache::FastLookupEntryForAddress(u32 address) { return iCache[(address >> 2) & iCache_Mask]; } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index 3ffe6b8bd8..8c3f141c90 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -127,8 +127,7 @@ public: bool IsFull() const; // Code Cache - JitBlock* GetBlocks(); - int* GetICache(); + JitBlock** GetICache(); void RunOnBlocks(std::function 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 iCache; // start_addr & mask -> number + std::array iCache; // start_addr & mask -> number };