Merge pull request #5254 from lioncash/arm-rc
JitArm64_RegCache: Use std::array where applicable
This commit is contained in:
commit
722aca0830
|
@ -2,12 +2,18 @@
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Core/PowerPC/JitArm64/Jit.h"
|
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/BitSet.h"
|
#include "Common/BitSet.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
|
#include "Core/PowerPC/JitArm64/Jit.h"
|
||||||
|
|
||||||
using namespace Arm64Gen;
|
using namespace Arm64Gen;
|
||||||
|
|
||||||
|
@ -66,18 +72,22 @@ void Arm64RegCache::UnlockRegister(ARM64Reg host_reg)
|
||||||
|
|
||||||
void Arm64RegCache::FlushMostStaleRegister()
|
void Arm64RegCache::FlushMostStaleRegister()
|
||||||
{
|
{
|
||||||
u32 most_stale_preg = 0;
|
size_t most_stale_preg = 0;
|
||||||
u32 most_stale_amount = 0;
|
u32 most_stale_amount = 0;
|
||||||
for (u32 i = 0; i < 32; ++i)
|
|
||||||
|
for (size_t i = 0; i < m_guest_registers.size(); ++i)
|
||||||
{
|
{
|
||||||
u32 last_used = m_guest_registers[i].GetLastUsed();
|
const auto& reg = m_guest_registers[i];
|
||||||
if (last_used > most_stale_amount && (m_guest_registers[i].GetType() != REG_NOTLOADED &&
|
const u32 last_used = reg.GetLastUsed();
|
||||||
m_guest_registers[i].GetType() != REG_IMM))
|
|
||||||
|
if (last_used > most_stale_amount &&
|
||||||
|
(reg.GetType() != REG_NOTLOADED && reg.GetType() != REG_IMM))
|
||||||
{
|
{
|
||||||
most_stale_preg = i;
|
most_stale_preg = i;
|
||||||
most_stale_amount = last_used;
|
most_stale_amount = last_used;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlushRegister(most_stale_preg, false);
|
FlushRegister(most_stale_preg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,13 +98,14 @@ void Arm64GPRCache::Start(PPCAnalyst::BlockRegStats& stats)
|
||||||
|
|
||||||
bool Arm64GPRCache::IsCalleeSaved(ARM64Reg reg)
|
bool Arm64GPRCache::IsCalleeSaved(ARM64Reg reg)
|
||||||
{
|
{
|
||||||
static std::vector<ARM64Reg> callee_regs = {
|
static constexpr std::array<ARM64Reg, 11> callee_regs{{
|
||||||
X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, INVALID_REG,
|
X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, INVALID_REG,
|
||||||
};
|
}};
|
||||||
|
|
||||||
return std::find(callee_regs.begin(), callee_regs.end(), EncodeRegTo64(reg)) != callee_regs.end();
|
return std::find(callee_regs.begin(), callee_regs.end(), EncodeRegTo64(reg)) != callee_regs.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arm64GPRCache::FlushRegister(u32 preg, bool maintain_state)
|
void Arm64GPRCache::FlushRegister(size_t preg, bool maintain_state)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
if (reg.GetType() == REG_REG)
|
if (reg.GetType() == REG_REG)
|
||||||
|
@ -132,7 +143,7 @@ void Arm64GPRCache::FlushRegister(u32 preg, bool maintain_state)
|
||||||
|
|
||||||
void Arm64GPRCache::FlushRegisters(BitSet32 regs, bool maintain_state)
|
void Arm64GPRCache::FlushRegisters(BitSet32 regs, bool maintain_state)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 32; ++i)
|
for (size_t i = 0; i < m_guest_registers.size(); ++i)
|
||||||
{
|
{
|
||||||
if (regs[i])
|
if (regs[i])
|
||||||
{
|
{
|
||||||
|
@ -168,7 +179,7 @@ void Arm64GPRCache::FlushRegisters(BitSet32 regs, bool maintain_state)
|
||||||
void Arm64GPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
|
void Arm64GPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
|
||||||
{
|
{
|
||||||
BitSet32 to_flush;
|
BitSet32 to_flush;
|
||||||
for (int i = 0; i < 32; ++i)
|
for (size_t i = 0; i < m_guest_registers.size(); ++i)
|
||||||
{
|
{
|
||||||
bool flush = true;
|
bool flush = true;
|
||||||
if (m_guest_registers[i].GetType() == REG_REG)
|
if (m_guest_registers[i].GetType() == REG_REG)
|
||||||
|
@ -183,7 +194,7 @@ void Arm64GPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
|
||||||
FlushRegisters(to_flush, mode == FLUSH_MAINTAIN_STATE);
|
FlushRegisters(to_flush, mode == FLUSH_MAINTAIN_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARM64Reg Arm64GPRCache::R(u32 preg)
|
ARM64Reg Arm64GPRCache::R(size_t preg)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
IncrementAllUsed();
|
IncrementAllUsed();
|
||||||
|
@ -223,7 +234,7 @@ ARM64Reg Arm64GPRCache::R(u32 preg)
|
||||||
return INVALID_REG;
|
return INVALID_REG;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arm64GPRCache::SetImmediate(u32 preg, u32 imm)
|
void Arm64GPRCache::SetImmediate(size_t preg, u32 imm)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
if (reg.GetType() == REG_REG)
|
if (reg.GetType() == REG_REG)
|
||||||
|
@ -231,7 +242,7 @@ void Arm64GPRCache::SetImmediate(u32 preg, u32 imm)
|
||||||
reg.LoadToImm(imm);
|
reg.LoadToImm(imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arm64GPRCache::BindToRegister(u32 preg, bool do_load)
|
void Arm64GPRCache::BindToRegister(size_t preg, bool do_load)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
|
|
||||||
|
@ -250,13 +261,13 @@ void Arm64GPRCache::BindToRegister(u32 preg, bool do_load)
|
||||||
void Arm64GPRCache::GetAllocationOrder()
|
void Arm64GPRCache::GetAllocationOrder()
|
||||||
{
|
{
|
||||||
// Callee saved registers first in hopes that we will keep everything stored there first
|
// Callee saved registers first in hopes that we will keep everything stored there first
|
||||||
const std::vector<ARM64Reg> allocation_order = {
|
static constexpr std::array<ARM64Reg, 29> allocation_order{{
|
||||||
// Callee saved
|
// Callee saved
|
||||||
W27, W26, W25, W24, W23, W22, W21, W20, W19,
|
W27, W26, W25, W24, W23, W22, W21, W20, W19,
|
||||||
|
|
||||||
// Caller saved
|
// Caller saved
|
||||||
W18, W17, W16, W15, W14, W13, W12, W11, W10, W9, W8, W7, W6, W5, W4, W3, W2, W1, W0, W30,
|
W18, W17, W16, W15, W14, W13, W12, W11, W10, W9, W8, W7, W6, W5, W4, W3, W2, W1, W0, W30,
|
||||||
};
|
}};
|
||||||
|
|
||||||
for (ARM64Reg reg : allocation_order)
|
for (ARM64Reg reg : allocation_order)
|
||||||
m_host_registers.push_back(HostReg(reg));
|
m_host_registers.push_back(HostReg(reg));
|
||||||
|
@ -273,9 +284,9 @@ BitSet32 Arm64GPRCache::GetCallerSavedUsed()
|
||||||
|
|
||||||
void Arm64GPRCache::FlushByHost(ARM64Reg host_reg)
|
void Arm64GPRCache::FlushByHost(ARM64Reg host_reg)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 32; ++i)
|
for (size_t i = 0; i < m_guest_registers.size(); ++i)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[i];
|
const OpArg& reg = m_guest_registers[i];
|
||||||
if (reg.GetType() == REG_REG && reg.GetReg() == host_reg)
|
if (reg.GetType() == REG_REG && reg.GetReg() == host_reg)
|
||||||
{
|
{
|
||||||
FlushRegister(i, false);
|
FlushRegister(i, false);
|
||||||
|
@ -287,10 +298,11 @@ void Arm64GPRCache::FlushByHost(ARM64Reg host_reg)
|
||||||
// FPR Cache
|
// FPR Cache
|
||||||
void Arm64FPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
|
void Arm64FPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 32; ++i)
|
for (size_t i = 0; i < m_guest_registers.size(); ++i)
|
||||||
{
|
{
|
||||||
if (m_guest_registers[i].GetType() != REG_NOTLOADED &&
|
const RegType reg_type = m_guest_registers[i].GetType();
|
||||||
m_guest_registers[i].GetType() != REG_IMM)
|
|
||||||
|
if (reg_type != REG_NOTLOADED && reg_type != REG_IMM)
|
||||||
{
|
{
|
||||||
// XXX: Determine if we can keep a register in the lower 64bits
|
// XXX: Determine if we can keep a register in the lower 64bits
|
||||||
// Which will allow it to be callee saved.
|
// Which will allow it to be callee saved.
|
||||||
|
@ -299,7 +311,7 @@ void Arm64FPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ARM64Reg Arm64FPRCache::R(u32 preg, RegType type)
|
ARM64Reg Arm64FPRCache::R(size_t preg, RegType type)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
IncrementAllUsed();
|
IncrementAllUsed();
|
||||||
|
@ -408,7 +420,7 @@ ARM64Reg Arm64FPRCache::R(u32 preg, RegType type)
|
||||||
return INVALID_REG;
|
return INVALID_REG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARM64Reg Arm64FPRCache::RW(u32 preg, RegType type)
|
ARM64Reg Arm64FPRCache::RW(size_t preg, RegType type)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
|
|
||||||
|
@ -470,13 +482,14 @@ ARM64Reg Arm64FPRCache::RW(u32 preg, RegType type)
|
||||||
|
|
||||||
void Arm64FPRCache::GetAllocationOrder()
|
void Arm64FPRCache::GetAllocationOrder()
|
||||||
{
|
{
|
||||||
const std::vector<ARM64Reg> allocation_order = {// Callee saved
|
static constexpr std::array<ARM64Reg, 32> allocation_order{{
|
||||||
Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15,
|
// Callee saved
|
||||||
|
Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15,
|
||||||
|
|
||||||
// Caller saved
|
// Caller saved
|
||||||
Q16, Q17, Q18, Q19, Q20, Q21, Q22, Q23, Q24, Q25,
|
Q16, Q17, Q18, Q19, Q20, Q21, Q22, Q23, Q24, Q25, Q26, Q27, Q28, Q29, Q30, Q31, Q7, Q6, Q5,
|
||||||
Q26, Q27, Q28, Q29, Q30, Q31, Q7, Q6, Q5, Q4, Q3,
|
Q4, Q3, Q2, Q1, Q0,
|
||||||
Q2, Q1, Q0};
|
}};
|
||||||
|
|
||||||
for (ARM64Reg reg : allocation_order)
|
for (ARM64Reg reg : allocation_order)
|
||||||
m_host_registers.push_back(HostReg(reg));
|
m_host_registers.push_back(HostReg(reg));
|
||||||
|
@ -484,10 +497,12 @@ void Arm64FPRCache::GetAllocationOrder()
|
||||||
|
|
||||||
void Arm64FPRCache::FlushByHost(ARM64Reg host_reg)
|
void Arm64FPRCache::FlushByHost(ARM64Reg host_reg)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 32; ++i)
|
for (size_t i = 0; i < m_guest_registers.size(); ++i)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[i];
|
const OpArg& reg = m_guest_registers[i];
|
||||||
if ((reg.GetType() != REG_NOTLOADED && reg.GetType() != REG_IMM) && reg.GetReg() == host_reg)
|
const RegType reg_type = reg.GetType();
|
||||||
|
|
||||||
|
if ((reg_type != REG_NOTLOADED && reg_type != REG_IMM) && reg.GetReg() == host_reg)
|
||||||
{
|
{
|
||||||
FlushRegister(i, false);
|
FlushRegister(i, false);
|
||||||
return;
|
return;
|
||||||
|
@ -497,13 +512,14 @@ void Arm64FPRCache::FlushByHost(ARM64Reg host_reg)
|
||||||
|
|
||||||
bool Arm64FPRCache::IsCalleeSaved(ARM64Reg reg)
|
bool Arm64FPRCache::IsCalleeSaved(ARM64Reg reg)
|
||||||
{
|
{
|
||||||
static std::vector<ARM64Reg> callee_regs = {
|
static constexpr std::array<ARM64Reg, 9> callee_regs{{
|
||||||
Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, INVALID_REG,
|
Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, INVALID_REG,
|
||||||
};
|
}};
|
||||||
|
|
||||||
return std::find(callee_regs.begin(), callee_regs.end(), reg) != callee_regs.end();
|
return std::find(callee_regs.begin(), callee_regs.end(), reg) != callee_regs.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arm64FPRCache::FlushRegister(u32 preg, bool maintain_state)
|
void Arm64FPRCache::FlushRegister(size_t preg, bool maintain_state)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
ARM64Reg host_reg = reg.GetReg();
|
ARM64Reg host_reg = reg.GetReg();
|
||||||
|
@ -580,14 +596,14 @@ BitSet32 Arm64FPRCache::GetCallerSavedUsed()
|
||||||
return registers;
|
return registers;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arm64FPRCache::IsSingle(u32 preg, bool lower_only)
|
bool Arm64FPRCache::IsSingle(size_t preg, bool lower_only)
|
||||||
{
|
{
|
||||||
RegType type = m_guest_registers[preg].GetType();
|
RegType type = m_guest_registers[preg].GetType();
|
||||||
return type == REG_REG_SINGLE || type == REG_DUP_SINGLE ||
|
return type == REG_REG_SINGLE || type == REG_DUP_SINGLE ||
|
||||||
(lower_only && type == REG_LOWER_PAIR_SINGLE);
|
(lower_only && type == REG_LOWER_PAIR_SINGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arm64FPRCache::FixSinglePrecision(u32 preg)
|
void Arm64FPRCache::FixSinglePrecision(size_t preg)
|
||||||
{
|
{
|
||||||
OpArg& reg = m_guest_registers[preg];
|
OpArg& reg = m_guest_registers[preg];
|
||||||
ARM64Reg host_reg = reg.GetReg();
|
ARM64Reg host_reg = reg.GetReg();
|
||||||
|
|
|
@ -4,10 +4,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/Arm64Emitter.h"
|
#include "Common/Arm64Emitter.h"
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
@ -171,7 +174,7 @@ protected:
|
||||||
// Flushes a guest register by host provided
|
// Flushes a guest register by host provided
|
||||||
virtual void FlushByHost(ARM64Reg host_reg) = 0;
|
virtual void FlushByHost(ARM64Reg host_reg) = 0;
|
||||||
|
|
||||||
virtual void FlushRegister(u32 preg, bool maintain_state) = 0;
|
virtual void FlushRegister(size_t preg, bool maintain_state) = 0;
|
||||||
|
|
||||||
virtual void FlushRegisters(BitSet32 regs, bool maintain_state) = 0;
|
virtual void FlushRegisters(BitSet32 regs, bool maintain_state) = 0;
|
||||||
|
|
||||||
|
@ -196,7 +199,7 @@ protected:
|
||||||
// Our guest GPRs
|
// Our guest GPRs
|
||||||
// PowerPC has 32 GPRs
|
// PowerPC has 32 GPRs
|
||||||
// PowerPC also has 32 paired FPRs
|
// PowerPC also has 32 paired FPRs
|
||||||
OpArg m_guest_registers[32];
|
std::array<OpArg, 32> m_guest_registers;
|
||||||
|
|
||||||
// Register stats for the current block
|
// Register stats for the current block
|
||||||
PPCAnalyst::BlockRegStats* m_reg_stats;
|
PPCAnalyst::BlockRegStats* m_reg_stats;
|
||||||
|
@ -213,16 +216,16 @@ public:
|
||||||
|
|
||||||
// Returns a guest register inside of a host register
|
// Returns a guest register inside of a host register
|
||||||
// Will dump an immediate to the host register as well
|
// Will dump an immediate to the host register as well
|
||||||
ARM64Reg R(u32 preg);
|
ARM64Reg R(size_t preg);
|
||||||
|
|
||||||
// Set a register to an immediate
|
// Set a register to an immediate
|
||||||
void SetImmediate(u32 preg, u32 imm);
|
void SetImmediate(size_t preg, u32 imm);
|
||||||
|
|
||||||
// Returns if a register is set as an immediate
|
// Returns if a register is set as an immediate
|
||||||
bool IsImm(u32 reg) const { return m_guest_registers[reg].GetType() == REG_IMM; }
|
bool IsImm(size_t reg) const { return m_guest_registers[reg].GetType() == REG_IMM; }
|
||||||
// Gets the immediate that a register is set to
|
// Gets the immediate that a register is set to
|
||||||
u32 GetImm(u32 reg) const { return m_guest_registers[reg].GetImm(); }
|
u32 GetImm(size_t reg) const { return m_guest_registers[reg].GetImm(); }
|
||||||
void BindToRegister(u32 preg, bool do_load);
|
void BindToRegister(size_t preg, bool do_load);
|
||||||
|
|
||||||
BitSet32 GetCallerSavedUsed() override;
|
BitSet32 GetCallerSavedUsed() override;
|
||||||
|
|
||||||
|
@ -233,7 +236,7 @@ protected:
|
||||||
// Flushes a guest register by host provided
|
// Flushes a guest register by host provided
|
||||||
void FlushByHost(ARM64Reg host_reg) override;
|
void FlushByHost(ARM64Reg host_reg) override;
|
||||||
|
|
||||||
void FlushRegister(u32 preg, bool maintain_state) override;
|
void FlushRegister(size_t preg, bool maintain_state) override;
|
||||||
|
|
||||||
void FlushRegisters(BitSet32 regs, bool maintain_state) override;
|
void FlushRegisters(BitSet32 regs, bool maintain_state) override;
|
||||||
|
|
||||||
|
@ -250,15 +253,15 @@ public:
|
||||||
|
|
||||||
// Returns a guest register inside of a host register
|
// Returns a guest register inside of a host register
|
||||||
// Will dump an immediate to the host register as well
|
// Will dump an immediate to the host register as well
|
||||||
ARM64Reg R(u32 preg, RegType type = REG_LOWER_PAIR);
|
ARM64Reg R(size_t preg, RegType type = REG_LOWER_PAIR);
|
||||||
|
|
||||||
ARM64Reg RW(u32 preg, RegType type = REG_LOWER_PAIR);
|
ARM64Reg RW(size_t preg, RegType type = REG_LOWER_PAIR);
|
||||||
|
|
||||||
BitSet32 GetCallerSavedUsed() override;
|
BitSet32 GetCallerSavedUsed() override;
|
||||||
|
|
||||||
bool IsSingle(u32 preg, bool lower_only = false);
|
bool IsSingle(size_t preg, bool lower_only = false);
|
||||||
|
|
||||||
void FixSinglePrecision(u32 preg);
|
void FixSinglePrecision(size_t preg);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Get the order of the host registers
|
// Get the order of the host registers
|
||||||
|
@ -267,7 +270,7 @@ protected:
|
||||||
// Flushes a guest register by host provided
|
// Flushes a guest register by host provided
|
||||||
void FlushByHost(ARM64Reg host_reg) override;
|
void FlushByHost(ARM64Reg host_reg) override;
|
||||||
|
|
||||||
void FlushRegister(u32 preg, bool maintain_state) override;
|
void FlushRegister(size_t preg, bool maintain_state) override;
|
||||||
|
|
||||||
void FlushRegisters(BitSet32 regs, bool maintain_state) override;
|
void FlushRegisters(BitSet32 regs, bool maintain_state) override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue