From 901ca71fdc4351d8ddeb07c20c3946cd562081b8 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 8 Aug 2020 22:55:39 +1000 Subject: [PATCH] CPU/Recompiler: Add temporary inhibiting of register allocation --- src/core/cpu_recompiler_code_generator.cpp | 4 ++++ src/core/cpu_recompiler_register_cache.cpp | 22 +++++++++++++++++++--- src/core/cpu_recompiler_register_cache.h | 5 +++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index f2ee702f3..04359a8ac 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -1433,6 +1433,7 @@ bool CodeGenerator::Compile_Divide(const CodeBlockInstruction& cbi) Value lo = m_register_cache.AllocateScratch(RegSize_32); Value hi = m_register_cache.AllocateScratch(RegSize_32); + m_register_cache.InhibitAllocation(); LabelType do_divide, done; @@ -1458,6 +1459,7 @@ bool CodeGenerator::Compile_Divide(const CodeBlockInstruction& cbi) EmitBindLabel(&done); + m_register_cache.UnunhibitAllocation(); m_register_cache.WriteGuestRegister(Reg::lo, std::move(lo)); m_register_cache.WriteGuestRegister(Reg::hi, std::move(hi)); } @@ -1488,6 +1490,7 @@ bool CodeGenerator::Compile_SignedDivide(const CodeBlockInstruction& cbi) Value lo = m_register_cache.AllocateScratch(RegSize_32); Value hi = m_register_cache.AllocateScratch(RegSize_32); + m_register_cache.InhibitAllocation(); // we need this in a register on ARM because it won't fit in an immediate EmitCopyValue(lo.GetHostRegister(), Value::FromConstantU32(0x80000000u)); @@ -1538,6 +1541,7 @@ bool CodeGenerator::Compile_SignedDivide(const CodeBlockInstruction& cbi) EmitBindLabel(&done); + m_register_cache.UnunhibitAllocation(); m_register_cache.WriteGuestRegister(Reg::lo, std::move(lo)); m_register_cache.WriteGuestRegister(Reg::hi, std::move(hi)); } diff --git a/src/core/cpu_recompiler_register_cache.cpp b/src/core/cpu_recompiler_register_cache.cpp index d108dd993..816e2e89e 100644 --- a/src/core/cpu_recompiler_register_cache.cpp +++ b/src/core/cpu_recompiler_register_cache.cpp @@ -184,6 +184,9 @@ u32 RegisterCache::GetFreeHostRegisters() const HostReg RegisterCache::AllocateHostReg(HostRegState state /* = HostRegState::InUse */) { + if (m_state.allocator_inhibit_count > 0) + Panic("Allocating when inhibited"); + // try for a free register in allocation order for (u32 i = 0; i < m_state.available_count; i++) { @@ -359,6 +362,7 @@ void RegisterCache::PushState() save_state.available_count = m_state.available_count; save_state.callee_saved_order_count = m_state.callee_saved_order_count; save_state.guest_reg_order_count = m_state.guest_reg_order_count; + save_state.allocator_inhibit_count = m_state.allocator_inhibit_count; save_state.load_delay_register = m_state.load_delay_register; save_state.load_delay_value.regcache = m_state.load_delay_value.regcache; save_state.load_delay_value.host_reg = m_state.load_delay_value.host_reg; @@ -496,14 +500,15 @@ Value RegisterCache::ReadGuestRegisterToScratch(Reg guest_reg) if (cache_value.IsConstant()) { - Log_DebugPrintf("Copying guest register %s from constant 0x%08X to scratch host register %s", GetRegName(guest_reg), - static_cast(cache_value.constant_value), + Log_DebugPrintf("Copying guest register %s from constant 0x%08X to scratch host register %s", + GetRegName(guest_reg), static_cast(cache_value.constant_value), m_code_generator.GetHostRegName(host_reg, RegSize_32)); } else { Log_DebugPrintf("Copying guest register %s from %s to scratch host register %s", GetRegName(guest_reg), - m_code_generator.GetHostRegName(cache_value.host_reg, RegSize_32), m_code_generator.GetHostRegName(host_reg, RegSize_32)); + m_code_generator.GetHostRegName(cache_value.host_reg, RegSize_32), + m_code_generator.GetHostRegName(host_reg, RegSize_32)); } } else @@ -796,4 +801,15 @@ void RegisterCache::AppendRegisterToOrder(Reg reg) m_state.guest_reg_order_count++; } +void RegisterCache::InhibitAllocation() +{ + m_state.allocator_inhibit_count++; +} + +void RegisterCache::UnunhibitAllocation() +{ + Assert(m_state.allocator_inhibit_count > 0); + m_state.allocator_inhibit_count--; +} + } // namespace CPU::Recompiler diff --git a/src/core/cpu_recompiler_register_cache.h b/src/core/cpu_recompiler_register_cache.h index cbb24c962..f5cef6f5c 100644 --- a/src/core/cpu_recompiler_register_cache.h +++ b/src/core/cpu_recompiler_register_cache.h @@ -317,6 +317,10 @@ public: void FlushAllGuestRegisters(bool invalidate, bool clear_dirty); bool EvictOneGuestRegister(); + /// Temporarily prevents register allocation. + void InhibitAllocation(); + void UnunhibitAllocation(); + private: void ClearRegisterFromOrder(Reg reg); void PushRegisterToOrder(Reg reg); @@ -338,6 +342,7 @@ private: u32 available_count = 0; u32 callee_saved_order_count = 0; u32 guest_reg_order_count = 0; + u32 allocator_inhibit_count = 0; Reg load_delay_register = Reg::count; Value load_delay_value{};