From 93c7fdd7779b44a12b53ea506233047b59b01c5b Mon Sep 17 00:00:00 2001 From: Jean-Philip Desjardins Date: Tue, 14 Jan 2025 10:53:33 -0500 Subject: [PATCH] Add idle loop block tagging. --- GameConfig.xml | 8 +++++++- Source/ee/EeBasicBlock.cpp | 9 +++++++-- Source/ee/EeBasicBlock.h | 5 ++++- Source/ee/EeExecutor.cpp | 13 +++++++++++-- Source/ee/EeExecutor.h | 9 ++++++--- Source/ee/PS2OS.cpp | 22 ++++++++++++++++++++-- 6 files changed, 55 insertions(+), 11 deletions(-) diff --git a/GameConfig.xml b/GameConfig.xml index 4ead88de91..6945cd797f 100644 --- a/GameConfig.xml +++ b/GameConfig.xml @@ -1,5 +1,11 @@ - + + + + + + + diff --git a/Source/ee/EeBasicBlock.cpp b/Source/ee/EeBasicBlock.cpp index 1e7aa352f8..23c5319938 100644 --- a/Source/ee/EeBasicBlock.cpp +++ b/Source/ee/EeBasicBlock.cpp @@ -6,6 +6,11 @@ void CEeBasicBlock::SetFpRoundingMode(Jitter::CJitter::ROUNDINGMODE fpRoundingMo m_fpRoundingMode = fpRoundingMode; } +void CEeBasicBlock::SetIsIdleLoopBlock() +{ + m_isIdleLoopBlock = true; +} + void CEeBasicBlock::CompileProlog(CMipsJitter* jitter) { if(m_fpRoundingMode != DEFAULT_FP_ROUNDING_MODE) @@ -22,7 +27,7 @@ void CEeBasicBlock::CompileEpilog(CMipsJitter* jitter, bool loopsOnItself) jitter->FP_SetRoundingMode(DEFAULT_FP_ROUNDING_MODE); } - if(IsIdleLoopBlock()) + if(m_isIdleLoopBlock || IsCodeIdleLoopBlock()) { jitter->PushCst(MIPS_EXCEPTION_IDLE); jitter->PullRel(offsetof(CMIPS, m_State.nHasException)); @@ -31,7 +36,7 @@ void CEeBasicBlock::CompileEpilog(CMipsJitter* jitter, bool loopsOnItself) CBasicBlock::CompileEpilog(jitter, loopsOnItself); } -bool CEeBasicBlock::IsIdleLoopBlock() const +bool CEeBasicBlock::IsCodeIdleLoopBlock() const { enum OP { diff --git a/Source/ee/EeBasicBlock.h b/Source/ee/EeBasicBlock.h index 3cbb2e0e27..a2900e9148 100644 --- a/Source/ee/EeBasicBlock.h +++ b/Source/ee/EeBasicBlock.h @@ -8,14 +8,17 @@ class CEeBasicBlock : public CBasicBlock using CBasicBlock::CBasicBlock; void SetFpRoundingMode(Jitter::CJitter::ROUNDINGMODE); + void SetIsIdleLoopBlock(); protected: void CompileProlog(CMipsJitter*) override; void CompileEpilog(CMipsJitter*, bool) override; private: - bool IsIdleLoopBlock() const; + bool IsCodeIdleLoopBlock() const; static constexpr auto DEFAULT_FP_ROUNDING_MODE = Jitter::CJitter::ROUND_TRUNCATE; Jitter::CJitter::ROUNDINGMODE m_fpRoundingMode = DEFAULT_FP_ROUNDING_MODE; + + bool m_isIdleLoopBlock = false; }; diff --git a/Source/ee/EeExecutor.cpp b/Source/ee/EeExecutor.cpp index e50c4fac48..4328fbc0b4 100644 --- a/Source/ee/EeExecutor.cpp +++ b/Source/ee/EeExecutor.cpp @@ -40,9 +40,14 @@ CEeExecutor::CEeExecutor(CMIPS& context, uint8* ram) m_pageSize = framework_getpagesize(); } -void CEeExecutor::SetBlockFpRoundingModes(BlockFpRoundingModes blockFpRoundingMode) +void CEeExecutor::SetBlockFpRoundingModes(BlockFpRoundingModeMap blockFpRoundingModes) { - m_blockFpRoundingModes = std::move(blockFpRoundingMode); + m_blockFpRoundingModes = std::move(blockFpRoundingModes); +} + +void CEeExecutor::SetIdleLoopBlocks(IdleLoopBlockSet idleLoopBlocks) +{ + m_idleLoopBlocks = std::move(idleLoopBlocks); } void CEeExecutor::AddExceptionHandler() @@ -182,6 +187,10 @@ BasicBlockPtr CEeExecutor::BlockFactory(CMIPS& context, uint32 start, uint32 end { result->SetFpRoundingMode(blockFpRoundingModeIterator->second); } + if(m_idleLoopBlocks.count(start)) + { + result->SetIsIdleLoopBlock(); + } result->Compile(); if(!hasBreakpoint) diff --git a/Source/ee/EeExecutor.h b/Source/ee/EeExecutor.h index 117a5e0f85..0b43cda5dd 100644 --- a/Source/ee/EeExecutor.h +++ b/Source/ee/EeExecutor.h @@ -15,12 +15,14 @@ class CEeExecutor : public CGenericMipsExecutor { public: - using BlockFpRoundingModes = std::map; + using IdleLoopBlockSet = std::set; + using BlockFpRoundingModeMap = std::map; CEeExecutor(CMIPS&, uint8*); virtual ~CEeExecutor() = default; - void SetBlockFpRoundingModes(BlockFpRoundingModes); + void SetBlockFpRoundingModes(BlockFpRoundingModeMap); + void SetIdleLoopBlocks(IdleLoopBlockSet); void AddExceptionHandler(); void RemoveExceptionHandler(); @@ -37,7 +39,8 @@ class CEeExecutor : public CGenericMipsExecutor typedef std::map CachedBlockMap; CachedBlockMap m_cachedBlocks; - BlockFpRoundingModes m_blockFpRoundingModes; + IdleLoopBlockSet m_idleLoopBlocks; + BlockFpRoundingModeMap m_blockFpRoundingModes; uint8* m_ram = nullptr; size_t m_pageSize = 0; diff --git a/Source/ee/PS2OS.cpp b/Source/ee/PS2OS.cpp index 2623ac3bf1..f3651d2d08 100644 --- a/Source/ee/PS2OS.cpp +++ b/Source/ee/PS2OS.cpp @@ -661,7 +661,8 @@ void CPS2OS::ApplyGameConfig() return; } - CEeExecutor::BlockFpRoundingModes blockFpRoundingModes; + CEeExecutor::BlockFpRoundingModeMap blockFpRoundingModes; + CEeExecutor::IdleLoopBlockSet idleLoopBlocks; for(Framework::Xml::CFilteringNodeIterator itNode(gameConfigsNode, "GameConfig"); !itNode.IsEnd(); itNode++) @@ -702,7 +703,24 @@ void CPS2OS::ApplyGameConfig() blockFpRoundingModes.insert(std::make_pair(address, roundingMode)); } - static_cast(m_ee.m_executor.get())->SetBlockFpRoundingModes(std::move(blockFpRoundingModes)); + for(Framework::Xml::CFilteringNodeIterator itNode(gameConfigNode, "IdleLoopBlock"); + !itNode.IsEnd(); itNode++) + { + auto node = (*itNode); + + const char* addressString = node->GetAttribute("Address"); + if(!addressString) continue; + + uint32 address = 0; + if(sscanf(addressString, "%x", &address) == 0) continue; + + idleLoopBlocks.insert(address); + } + + auto executor = static_cast(m_ee.m_executor.get()); + executor->SetBlockFpRoundingModes(std::move(blockFpRoundingModes)); + executor->SetIdleLoopBlocks(std::move(idleLoopBlocks)); + break; } }