Add idle loop block tagging.
Some checks are pending
Build Android / build_android (apk) (push) Waiting to run
Build Android / build_android (libretro) (push) Waiting to run
Build iOS / build_ios (push) Waiting to run
Build JavaScript / build_js (push) Waiting to run
Build Linux / build_linux (push) Waiting to run
Build Linux ARM32 / build_linux_arm32 (push) Waiting to run
Build Linux ARM64 / build_linux_arm64 (push) Waiting to run
Build macOS / build_macos (push) Waiting to run
Build Windows / build_windows (x86_32, Visual Studio 16 2019, installer32.nsi, win32_msvc2019, Win32) (push) Waiting to run
Build Windows / build_windows (x86_64, Visual Studio 16 2019, installer64.nsi, win64_msvc2019_64, x64) (push) Waiting to run
Build Windows Psf / build_windows_psf (off, x86_64, Visual Studio 16 2019, installer64.nsi, x64) (push) Waiting to run
Build Windows Psf / build_windows_psf (on, x86_64, Visual Studio 16 2019, installer64.nsi, x64) (push) Waiting to run
Check Format / run_clangformat (push) Waiting to run

This commit is contained in:
Jean-Philip Desjardins 2025-01-14 10:53:33 -05:00
parent 8f73d94401
commit 93c7fdd777
6 changed files with 55 additions and 11 deletions

View file

@ -1,5 +1,11 @@
<GameConfigs>
<GameConfig Executable="SLUS_204.71;1" Title="Rygar - The Legendary Adventure">
<BlockFpRoundingMode Address="0x00147D88" Mode="NEAREST" />
<BlockFpRoundingMode Address="0x00147D88" Mode="NEAREST" Description="Fixes hang when entering first door." />
</GameConfig>
<GameConfig Executable="SLUS_210.48;1" Title="Evil Dead: Regeneration">
<IdleLoopBlock Address="0x00377898" />
</GameConfig>
<GameConfig Executable="SLUS_213.06;1" Title="Ghost Rider">
<IdleLoopBlock Address="0x002F43E8" />
</GameConfig>
</GameConfigs>

View file

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

View file

@ -8,14 +8,17 @@ public:
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;
};

View file

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

View file

@ -15,12 +15,14 @@
class CEeExecutor : public CGenericMipsExecutor<BlockLookupTwoWay>
{
public:
using BlockFpRoundingModes = std::map<uint32, Jitter::CJitter::ROUNDINGMODE>;
using IdleLoopBlockSet = std::set<uint32>;
using BlockFpRoundingModeMap = std::map<uint32, Jitter::CJitter::ROUNDINGMODE>;
CEeExecutor(CMIPS&, uint8*);
virtual ~CEeExecutor() = default;
void SetBlockFpRoundingModes(BlockFpRoundingModes);
void SetBlockFpRoundingModes(BlockFpRoundingModeMap);
void SetIdleLoopBlocks(IdleLoopBlockSet);
void AddExceptionHandler();
void RemoveExceptionHandler();
@ -37,7 +39,8 @@ private:
typedef std::map<CachedBlockKey, BasicBlockPtr> CachedBlockMap;
CachedBlockMap m_cachedBlocks;
BlockFpRoundingModes m_blockFpRoundingModes;
IdleLoopBlockSet m_idleLoopBlocks;
BlockFpRoundingModeMap m_blockFpRoundingModes;
uint8* m_ram = nullptr;
size_t m_pageSize = 0;

View file

@ -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<CEeExecutor*>(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<CEeExecutor*>(m_ee.m_executor.get());
executor->SetBlockFpRoundingModes(std::move(blockFpRoundingModes));
executor->SetIdleLoopBlocks(std::move(idleLoopBlocks));
break;
}
}