sal: allow register sets to overlap
This allows a register to be a member of multiple UniformRegisterSets. Needed to architecture-specifically store, e.g., a list of registers to record in traces. Change-Id: Ia5d20768540efe252a84df967d43e569f107da3a
This commit is contained in:
@ -1,15 +1,19 @@
|
||||
#include <algorithm>
|
||||
#include "CPU.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
void CPUArchitecture::m_addRegister(Register* reg)
|
||||
void CPUArchitecture::m_addRegister(Register* reg, RegisterType type)
|
||||
{
|
||||
assert(!reg->isAssigned() && "FATAL ERROR: The register is already assigned!");
|
||||
m_Registers.push_back(reg);
|
||||
// We may be called multiple times with the same register, if it needs to
|
||||
// reside in multiple subsets.
|
||||
if (std::find(m_Registers.begin(), m_Registers.end(), reg) == m_Registers.end()) {
|
||||
m_Registers.push_back(reg);
|
||||
}
|
||||
|
||||
UniformRegisterSet* urs = getRegisterSetOfType(reg->getType());
|
||||
if (urs == NULL) {
|
||||
urs = new UniformRegisterSet(reg->getType());
|
||||
UniformRegisterSet* urs = getRegisterSetOfType(type);
|
||||
if (!urs) {
|
||||
urs = new UniformRegisterSet(type);
|
||||
m_RegisterSubsets.push_back(urs);
|
||||
}
|
||||
urs->m_add(reg);
|
||||
@ -34,7 +38,7 @@ UniformRegisterSet* CPUArchitecture::getRegisterSetOfType(RegisterType t) const
|
||||
if ((*it)->getType() == t)
|
||||
return *it;
|
||||
}
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
@ -73,7 +73,7 @@ protected:
|
||||
* @param reg a pointer to the register object to be added
|
||||
* @see getType()
|
||||
*/
|
||||
void m_addRegister(Register* reg);
|
||||
void m_addRegister(Register* reg, RegisterType type = RT_NONE);
|
||||
};
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
@ -10,11 +10,8 @@ Register* UniformRegisterSet::getRegister(size_t i) const
|
||||
|
||||
void UniformRegisterSet::m_add(Register* preg)
|
||||
{
|
||||
assert(!preg->m_Assigned &&
|
||||
"FATAL ERROR: The register has already been assigned.");
|
||||
assert(std::find(m_Regs.begin(), m_Regs.end(), preg) == m_Regs.end());
|
||||
m_Regs.push_back(preg);
|
||||
preg->m_Assigned = true;
|
||||
preg->m_Index = m_Regs.size()-1; // the index within the vector (set)
|
||||
}
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
@ -19,10 +19,11 @@ namespace fail {
|
||||
* specific to a simulator/architecture.
|
||||
*/
|
||||
enum RegisterType {
|
||||
RT_GP, //!< general purpose
|
||||
RT_FP, //!< floating point register
|
||||
RT_IP, //!< program counter / instruction pointer
|
||||
RT_ST //!< status register
|
||||
RT_NONE, //!< no classification
|
||||
RT_GP, //!< general purpose
|
||||
RT_FP, //!< floating point register
|
||||
RT_IP, //!< program counter / instruction pointer
|
||||
RT_ST //!< status register
|
||||
};
|
||||
|
||||
/**
|
||||
@ -33,13 +34,8 @@ enum RegisterType {
|
||||
*/
|
||||
class Register {
|
||||
protected:
|
||||
RegisterType m_Type; //!< the type of this register
|
||||
regwidth_t m_Width; //!< the register width
|
||||
unsigned int m_Id; //!< the unique id of this register
|
||||
//! \c true if register has already been assigned, \c false otherwise
|
||||
bool m_Assigned;
|
||||
//! The index in it's register set if assigned (\c -1 otherwise)
|
||||
size_t m_Index;
|
||||
std::string m_Name; //!< The (optional) name, maybe empty
|
||||
friend class UniformRegisterSet;
|
||||
public:
|
||||
@ -49,14 +45,8 @@ public:
|
||||
* @param t the type of the register to be constructed
|
||||
* @param w the width of the register in bits
|
||||
*/
|
||||
Register(unsigned int id, RegisterType t, regwidth_t w)
|
||||
: m_Type(t), m_Width(w), m_Id(id), m_Assigned(false),
|
||||
m_Index(static_cast<size_t>(-1)) { }
|
||||
/**
|
||||
* Returns the (fixed) type of this register.
|
||||
* @return the type of this register
|
||||
*/
|
||||
RegisterType getType() const { return m_Type; }
|
||||
Register(unsigned int id, regwidth_t w)
|
||||
: m_Width(w), m_Id(id) { }
|
||||
/**
|
||||
* Returns the (fixed) width of this register.
|
||||
* @return the width in bits
|
||||
@ -72,20 +62,6 @@ public:
|
||||
* @return the textual register description
|
||||
*/
|
||||
const std::string& getName() const { return m_Name; }
|
||||
/**
|
||||
* Retrieves the unique index within it's assigned register set.
|
||||
* If the register has not been assigned, \c (size_t)-1 will be
|
||||
* returned.
|
||||
* @return the register index or -1 if not assigned
|
||||
* @see isAssigned()
|
||||
*/
|
||||
size_t getIndex() const { return m_Index; }
|
||||
/**
|
||||
* Checks whether this register has already been assigned. On
|
||||
* creation the register isn't initially assigned.
|
||||
* @return \c true if assigned, \c false otherwise
|
||||
*/
|
||||
bool isAssigned() const { return m_Assigned; }
|
||||
/**
|
||||
* Returns the unique id of this register.
|
||||
* @return the unique id
|
||||
|
||||
@ -10,19 +10,19 @@ ArmArchitecture::ArmArchitecture()
|
||||
// 16x 32-Bit GP Registers
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i != RI_IP) { // IP will be added separately (see below)
|
||||
Register *reg = new Register(i, RT_GP, 32);
|
||||
Register *reg = new Register(i, 32);
|
||||
// Build and set the register name:
|
||||
std::stringstream sstr;
|
||||
sstr << "R" << i+1;
|
||||
reg->setName(sstr.str().c_str());
|
||||
m_addRegister(reg);
|
||||
m_addRegister(reg, RT_GP);
|
||||
}
|
||||
}
|
||||
|
||||
// Instruction Pointer:
|
||||
Register *reg = new Register(RI_IP, RT_IP, 32);
|
||||
Register *reg = new Register(RI_IP, 32);
|
||||
reg->setName("IP");
|
||||
m_addRegister(reg);
|
||||
m_addRegister(reg, RT_IP);
|
||||
}
|
||||
|
||||
ArmArchitecture::~ArmArchitecture()
|
||||
|
||||
@ -13,34 +13,34 @@ X86Architecture::X86Architecture()
|
||||
const std::string names[] = { "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8",
|
||||
"R9", "R10", "R11", "R12", "R13", "R14", "R15" };
|
||||
for (unsigned short i = 0; i < 16; i++) {
|
||||
Register* pReg = new Register(i, RT_GP, 64);
|
||||
Register* pReg = new Register(i, 64);
|
||||
pReg->setName(names[i]);
|
||||
m_addRegister(pReg);
|
||||
m_addRegister(pReg, RT_GP);
|
||||
}
|
||||
#else
|
||||
// -- 32 bit register --
|
||||
const std::string names[] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" };
|
||||
for (unsigned short i = 0; i < 8; i++) {
|
||||
Register* pReg = new Register(i, RT_GP, 32);
|
||||
Register* pReg = new Register(i, 32);
|
||||
pReg->setName(names[i]);
|
||||
m_addRegister(pReg);
|
||||
m_addRegister(pReg, RT_GP);
|
||||
}
|
||||
#endif // SIM_SUPPORT_64
|
||||
// -------------------------------------
|
||||
// Add the program counter (PC) register:
|
||||
#ifdef SIM_SUPPORT_64
|
||||
Register* pPCReg = new Register(RID_PC, RT_IP, 64);
|
||||
Register* pPCReg = new Register(RID_PC, 64);
|
||||
pPCReg->setName("RIP");
|
||||
#else
|
||||
Register* pPCReg = new Register(RID_PC, RT_IP, 32);
|
||||
Register* pPCReg = new Register(RID_PC, 32);
|
||||
pPCReg->setName("EIP");
|
||||
#endif // SIM_SUPPORT_64
|
||||
m_addRegister(pPCReg);
|
||||
m_addRegister(pPCReg, RT_IP);
|
||||
// -------------------------------------
|
||||
// Add the status register (EFLAGS):
|
||||
Register* pFlagReg = new Register(RID_FLAGS, RT_ST, 32);
|
||||
Register* pFlagReg = new Register(RID_FLAGS, 32);
|
||||
pFlagReg->setName("EFLAGS");
|
||||
m_addRegister(pFlagReg);
|
||||
m_addRegister(pFlagReg, RT_ST);
|
||||
}
|
||||
|
||||
X86Architecture::~X86Architecture()
|
||||
|
||||
Reference in New Issue
Block a user