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