CPU/Recompiler: Add temporary inhibiting of register allocation

This commit is contained in:
Connor McLaughlin 2020-08-08 22:55:39 +10:00
parent 1d5f810a4b
commit 901ca71fdc
3 changed files with 28 additions and 3 deletions

View File

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

View File

@ -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<u32>(cache_value.constant_value),
Log_DebugPrintf("Copying guest register %s from constant 0x%08X to scratch host register %s",
GetRegName(guest_reg), static_cast<u32>(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

View File

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