Merge pull request #5254 from lioncash/arm-rc

JitArm64_RegCache: Use std::array where applicable
This commit is contained in:
Markus Wick 2017-04-13 10:37:27 +02:00 committed by GitHub
commit 722aca0830
2 changed files with 70 additions and 51 deletions

View File

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

View File

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