SPARC: Make PSTATE and HPSTATE a BitUnion.

This gets rid of cryptic bits of code with lots of bit manipulation, and makes
some comments redundant.
This commit is contained in:
Gabe Black 2012-02-11 14:16:38 -08:00
parent aa513a4a99
commit 5b557a314f
14 changed files with 182 additions and 156 deletions

View file

@ -276,17 +276,15 @@ enterREDState(ThreadContext *tc)
{ {
//@todo Disable the mmu? //@todo Disable the mmu?
//@todo Disable watchpoints? //@todo Disable watchpoints?
MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); HPSTATE hpstate= tc->readMiscRegNoEffect(MISCREG_HPSTATE);
// HPSTATE.red = 1 hpstate.red = 1;
HPSTATE |= (1 << 5); hpstate.hpriv = 1;
// HPSTATE.hpriv = 1 tc->setMiscReg(MISCREG_HPSTATE, hpstate);
HPSTATE |= (1 << 2);
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
// PSTATE.priv is set to 1 here. The manual says it should be 0, but // PSTATE.priv is set to 1 here. The manual says it should be 0, but
// Legion sets it to 1. // Legion sets it to 1.
MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
PSTATE |= (1 << 2); pstate.priv = 1;
tc->setMiscReg(MISCREG_PSTATE, PSTATE); tc->setMiscReg(MISCREG_PSTATE, pstate);
} }
/** /**
@ -299,8 +297,8 @@ doREDFault(ThreadContext *tc, TrapType tt)
{ {
MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL);
MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE);
MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI);
MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP);
@ -310,7 +308,7 @@ doREDFault(ThreadContext *tc, TrapType tt)
TL++; TL++;
Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64); Addr pcMask = pstate.am ? mask(32) : mask(64);
// set TSTATE.gl to gl // set TSTATE.gl to gl
replaceBits(TSTATE, 42, 40, GL); replaceBits(TSTATE, 42, 40, GL);
@ -319,7 +317,7 @@ doREDFault(ThreadContext *tc, TrapType tt)
// set TSTATE.asi to asi // set TSTATE.asi to asi
replaceBits(TSTATE, 31, 24, ASI); replaceBits(TSTATE, 31, 24, ASI);
// set TSTATE.pstate to pstate // set TSTATE.pstate to pstate
replaceBits(TSTATE, 20, 8, PSTATE); replaceBits(TSTATE, 20, 8, pstate);
// set TSTATE.cwp to cwp // set TSTATE.cwp to cwp
replaceBits(TSTATE, 4, 0, CWP); replaceBits(TSTATE, 4, 0, CWP);
@ -332,7 +330,7 @@ doREDFault(ThreadContext *tc, TrapType tt)
tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
// set HTSTATE.hpstate to hpstate // set HTSTATE.hpstate to hpstate
tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate);
// TT = trap type; // TT = trap type;
tc->setMiscRegNoEffect(MISCREG_TT, tt); tc->setMiscRegNoEffect(MISCREG_TT, tt);
@ -340,19 +338,17 @@ doREDFault(ThreadContext *tc, TrapType tt)
// Update GL // Update GL
tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL));
PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit bool priv = pstate.priv; // just save the priv bit
PSTATE |= (1 << 4); // set PSTATE.pef to 1 pstate = 0;
tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); pstate.priv = priv;
pstate.pef = 1;
tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
// set HPSTATE.red to 1 hpstate.red = 1;
HPSTATE |= (1 << 5); hpstate.hpriv = 1;
// set HPSTATE.hpriv to 1 hpstate.ibe = 0;
HPSTATE |= (1 << 2); hpstate.tlz = 0;
// set HPSTATE.ibe to 0 tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
HPSTATE &= ~(1 << 10);
// set HPSTATE.tlz to 0
HPSTATE &= ~(1 << 0);
tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE);
bool changedCWP = true; bool changedCWP = true;
if (tt == 0x24) if (tt == 0x24)
@ -380,8 +376,8 @@ doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
{ {
MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL);
MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE);
MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI);
MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP);
@ -393,7 +389,7 @@ doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
TL++; TL++;
tc->setMiscRegNoEffect(MISCREG_TL, TL); tc->setMiscRegNoEffect(MISCREG_TL, TL);
Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64); Addr pcMask = pstate.am ? mask(32) : mask(64);
// Save off state // Save off state
@ -404,7 +400,7 @@ doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
// set TSTATE.asi to asi // set TSTATE.asi to asi
replaceBits(TSTATE, 31, 24, ASI); replaceBits(TSTATE, 31, 24, ASI);
// set TSTATE.pstate to pstate // set TSTATE.pstate to pstate
replaceBits(TSTATE, 20, 8, PSTATE); replaceBits(TSTATE, 20, 8, pstate);
// set TSTATE.cwp to cwp // set TSTATE.cwp to cwp
replaceBits(TSTATE, 4, 0, CWP); replaceBits(TSTATE, 4, 0, CWP);
@ -417,7 +413,7 @@ doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
// set HTSTATE.hpstate to hpstate // set HTSTATE.hpstate to hpstate
tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate);
// TT = trap type; // TT = trap type;
tc->setMiscRegNoEffect(MISCREG_TT, tt); tc->setMiscRegNoEffect(MISCREG_TT, tt);
@ -428,26 +424,26 @@ doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
else else
tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxGL)); tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxGL));
// PSTATE.mm is unchanged // pstate.mm is unchanged
PSTATE |= (1 << 4); // PSTATE.pef = whether or not an fpu is present pstate.pef = 1; // PSTATE.pef = whether or not an fpu is present
PSTATE &= ~(1 << 3); // PSTATE.am = 0 pstate.am = 0;
PSTATE &= ~(1 << 1); // PSTATE.ie = 0 pstate.ie = 0;
// PSTATE.tle is unchanged // pstate.tle is unchanged
// PSTATE.tct = 0 // pstate.tct = 0
if (gotoHpriv) { if (gotoHpriv) {
PSTATE &= ~(1 << 9); // PSTATE.cle = 0 pstate.cle = 0;
// The manual says PSTATE.priv should be 0, but Legion leaves it alone // The manual says PSTATE.priv should be 0, but Legion leaves it alone
HPSTATE &= ~(1 << 5); // HPSTATE.red = 0 hpstate.red = 0;
HPSTATE |= (1 << 2); // HPSTATE.hpriv = 1 hpstate.hpriv = 1;
HPSTATE &= ~(1 << 10); // HPSTATE.ibe = 0 hpstate.ibe = 0;
// HPSTATE.tlz is unchanged // hpstate.tlz is unchanged
tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
} else { // we are going to priv } else { // we are going to priv
PSTATE |= (1 << 2); // PSTATE.priv = 1 pstate.priv = 1;
replaceBits(PSTATE, 9, 9, PSTATE >> 8); // PSTATE.cle = PSTATE.tle pstate.cle = pstate.tle;
} }
tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
bool changedCWP = true; bool changedCWP = true;
@ -506,22 +502,22 @@ SparcFaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
// in the middle could change it in the regfile out from under us. // in the middle could change it in the regfile out from under us.
MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL); MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL);
MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT); MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT);
MiscReg pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
MiscReg hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
Addr PC, NPC; Addr PC, NPC;
PrivilegeLevel current; PrivilegeLevel current;
if (hpstate & HPSTATE::hpriv) if (hpstate.hpriv)
current = Hyperprivileged; current = Hyperprivileged;
else if (pstate & PSTATE::priv) else if (pstate.priv)
current = Privileged; current = Privileged;
else else
current = User; current = User;
PrivilegeLevel level = getNextLevel(current); PrivilegeLevel level = getNextLevel(current);
if ((hpstate & HPSTATE::red) || (tl == MaxTL - 1)) { if (hpstate.red || (tl == MaxTL - 1)) {
getREDVector(5, PC, NPC); getREDVector(5, PC, NPC);
doREDFault(tc, tt); doREDFault(tc, tt);
// This changes the hpstate and pstate, so we need to make sure we // This changes the hpstate and pstate, so we need to make sure we
@ -565,20 +561,18 @@ PowerOnReset::invoke(ThreadContext *tc, StaticInstPtr inst)
tc->setMiscRegNoEffect(MISCREG_TT, trapType()); tc->setMiscRegNoEffect(MISCREG_TT, trapType());
tc->setMiscReg(MISCREG_GL, MaxGL); tc->setMiscReg(MISCREG_GL, MaxGL);
// Turn on pef and priv, set everything else to 0 PSTATE pstate = 0;
tc->setMiscRegNoEffect(MISCREG_PSTATE, (1 << 4) | (1 << 2)); pstate.pef = 1;
pstate.priv = 1;
tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
// Turn on red and hpriv, set everything else to 0 // Turn on red and hpriv, set everything else to 0
MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
// HPSTATE.red = 1 hpstate.red = 1;
HPSTATE |= (1 << 5); hpstate.hpriv = 1;
// HPSTATE.hpriv = 1 hpstate.ibe = 0;
HPSTATE |= (1 << 2); hpstate.tlz = 0;
// HPSTATE.ibe = 0 tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
HPSTATE &= ~(1 << 10);
// HPSTATE.tlz = 0
HPSTATE &= ~(1 << 0);
tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE);
// The tick register is unreadable by nonprivileged software // The tick register is unreadable by nonprivileged software
tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63); tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63);

View file

@ -127,17 +127,16 @@ class Interrupts : public SimObject
Fault Fault
getInterrupt(ThreadContext *tc) getInterrupt(ThreadContext *tc)
{ {
int hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
int pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
bool ie = pstate & PSTATE::ie;
// THESE ARE IN ORDER OF PRIORITY // THESE ARE IN ORDER OF PRIORITY
// since there are early returns, and the highest // since there are early returns, and the highest
// priority interrupts should get serviced, // priority interrupts should get serviced,
// it is v. important that new interrupts are inserted // it is v. important that new interrupts are inserted
// in the right order of processing // in the right order of processing
if (hpstate & HPSTATE::hpriv) { if (hpstate.hpriv) {
if (ie) { if (pstate.ie) {
if (interrupts[IT_HINTP]) { if (interrupts[IT_HINTP]) {
// This will be cleaned by a HINTP write // This will be cleaned by a HINTP write
return new HstickMatch; return new HstickMatch;
@ -160,7 +159,7 @@ class Interrupts : public SimObject
// this will be cleared by an ASI read (or write) // this will be cleared by an ASI read (or write)
return new InterruptVector; return new InterruptVector;
} }
if (ie) { if (pstate.ie) {
if (interrupts[IT_CPU_MONDO]) { if (interrupts[IT_CPU_MONDO]) {
return new CpuMondo; return new CpuMondo;
} }
@ -175,7 +174,7 @@ class Interrupts : public SimObject
if (interrupts[IT_RES_ERROR]) { if (interrupts[IT_RES_ERROR]) {
return new ResumableError; return new ResumableError;
} }
} // !hpriv && ie } // !hpriv && pstate.ie
} // !hpriv } // !hpriv
return NoFault; return NoFault;
} }

View file

@ -40,10 +40,22 @@
namespace SparcISA namespace SparcISA
{ {
enum RegMask static PSTATE
buildPstateMask()
{ {
PSTATE_MASK = (((1 << 4) - 1) << 1) | (((1 << 4) - 1) << 6) | (1 << 12) PSTATE mask = 0;
}; mask.ie = 1;
mask.priv = 1;
mask.am = 1;
mask.pef = 1;
mask.mm = 3;
mask.tle = 1;
mask.cle = 1;
mask.pid1 = 1;
return mask;
}
static const PSTATE PstateMask = buildPstateMask();
void void
ISA::reloadRegMap() ISA::reloadRegMap()
@ -110,7 +122,8 @@ ISA::clear()
// otherwin = 0; // otherwin = 0;
// wstate = 0; // wstate = 0;
// In a T1, bit 11 is apparently always 1 // In a T1, bit 11 is apparently always 1
hpstate = (1 << 11); hpstate = 0;
hpstate.id = 1;
memset(htstate, 0, sizeof(htstate)); memset(htstate, 0, sizeof(htstate));
hintp = 0; hintp = 0;
htba = 0; htba = 0;
@ -163,9 +176,10 @@ ISA::readMiscRegNoEffect(int miscReg)
* |^lsuim * |^lsuim
* ^lsudm * ^lsudm
*/ */
return bits((uint64_t)hpstate,2,2) | return (uint64_t)hpstate.hpriv |
bits((uint64_t)hpstate,5,5) << 1 | (uint64_t)hpstate.red << 1 |
bits((uint64_t)pstate,3,2) << 2 | (uint64_t)pstate.priv << 2 |
(uint64_t)pstate.am << 3 |
bits((uint64_t)lsuCtrlReg,3,2) << 4 | bits((uint64_t)lsuCtrlReg,3,2) << 4 |
bits((uint64_t)partId,7,0) << 8 | bits((uint64_t)partId,7,0) << 8 |
bits((uint64_t)tl,2,0) << 16 | bits((uint64_t)tl,2,0) << 16 |
@ -215,7 +229,7 @@ ISA::readMiscRegNoEffect(int miscReg)
case MISCREG_TBA: case MISCREG_TBA:
return tba; return tba;
case MISCREG_PSTATE: case MISCREG_PSTATE:
return pstate; return (MiscReg)pstate;
case MISCREG_TL: case MISCREG_TL:
return tl; return tl;
case MISCREG_PIL: case MISCREG_PIL:
@ -238,7 +252,7 @@ ISA::readMiscRegNoEffect(int miscReg)
/** Hyper privileged registers */ /** Hyper privileged registers */
case MISCREG_HPSTATE: case MISCREG_HPSTATE:
return hpstate; return (MiscReg)hpstate;
case MISCREG_HTSTATE: case MISCREG_HTSTATE:
return htstate[tl-1]; return htstate[tl-1];
case MISCREG_HINTP: case MISCREG_HINTP:
@ -408,7 +422,7 @@ ISA::setMiscRegNoEffect(int miscReg, MiscReg val)
tba = val & ULL(~0x7FFF); tba = val & ULL(~0x7FFF);
break; break;
case MISCREG_PSTATE: case MISCREG_PSTATE:
pstate = (val & PSTATE_MASK); pstate = (val & PstateMask);
break; break;
case MISCREG_TL: case MISCREG_TL:
tl = val; tl = val;
@ -550,15 +564,17 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
// Set up performance counting based on pcr value // Set up performance counting based on pcr value
break; break;
case MISCREG_PSTATE: case MISCREG_PSTATE:
pstate = val & PSTATE_MASK; pstate = val & PstateMask;
return; return;
case MISCREG_TL: case MISCREG_TL:
{
tl = val; tl = val;
if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) if (hpstate.tlz && tl == 0 && !hpstate.hpriv)
tc->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO, 0); tc->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO, 0);
else else
tc->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0); tc->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0);
return; return;
}
case MISCREG_CWP: case MISCREG_CWP:
new_val = val >= NWindows ? NWindows - 1 : val; new_val = val >= NWindows ? NWindows - 1 : val;
if (val >= NWindows) if (val >= NWindows)
@ -616,12 +632,12 @@ ISA::serialize(EventManager *em, std::ostream &os)
SERIALIZE_ARRAY(tstate,MaxTL); SERIALIZE_ARRAY(tstate,MaxTL);
SERIALIZE_ARRAY(tt,MaxTL); SERIALIZE_ARRAY(tt,MaxTL);
SERIALIZE_SCALAR(tba); SERIALIZE_SCALAR(tba);
SERIALIZE_SCALAR(pstate); SERIALIZE_SCALAR((uint16_t)pstate);
SERIALIZE_SCALAR(tl); SERIALIZE_SCALAR(tl);
SERIALIZE_SCALAR(pil); SERIALIZE_SCALAR(pil);
SERIALIZE_SCALAR(cwp); SERIALIZE_SCALAR(cwp);
SERIALIZE_SCALAR(gl); SERIALIZE_SCALAR(gl);
SERIALIZE_SCALAR(hpstate); SERIALIZE_SCALAR((uint64_t)hpstate);
SERIALIZE_ARRAY(htstate,MaxTL); SERIALIZE_ARRAY(htstate,MaxTL);
SERIALIZE_SCALAR(hintp); SERIALIZE_SCALAR(hintp);
SERIALIZE_SCALAR(htba); SERIALIZE_SCALAR(htba);
@ -692,13 +708,21 @@ ISA::unserialize(EventManager *em, Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(tstate,MaxTL); UNSERIALIZE_ARRAY(tstate,MaxTL);
UNSERIALIZE_ARRAY(tt,MaxTL); UNSERIALIZE_ARRAY(tt,MaxTL);
UNSERIALIZE_SCALAR(tba); UNSERIALIZE_SCALAR(tba);
{
uint16_t pstate;
UNSERIALIZE_SCALAR(pstate); UNSERIALIZE_SCALAR(pstate);
this->pstate = pstate;
}
UNSERIALIZE_SCALAR(tl); UNSERIALIZE_SCALAR(tl);
UNSERIALIZE_SCALAR(pil); UNSERIALIZE_SCALAR(pil);
UNSERIALIZE_SCALAR(cwp); UNSERIALIZE_SCALAR(cwp);
UNSERIALIZE_SCALAR(gl); UNSERIALIZE_SCALAR(gl);
reloadRegMap(); reloadRegMap();
{
uint64_t hpstate;
UNSERIALIZE_SCALAR(hpstate); UNSERIALIZE_SCALAR(hpstate);
this->hpstate = hpstate;
}
UNSERIALIZE_ARRAY(htstate,MaxTL); UNSERIALIZE_ARRAY(htstate,MaxTL);
UNSERIALIZE_SCALAR(hintp); UNSERIALIZE_SCALAR(hintp);
UNSERIALIZE_SCALAR(htba); UNSERIALIZE_SCALAR(htba);

View file

@ -71,7 +71,7 @@ class ISA
// on the previous level) // on the previous level)
uint64_t tba; // Trap Base Address uint64_t tba; // Trap Base Address
uint16_t pstate; // Process State Register PSTATE pstate; // Process State Register
uint8_t tl; // Trap Level uint8_t tl; // Trap Level
uint8_t pil; // Process Interrupt Register uint8_t pil; // Process Interrupt Register
uint8_t cwp; // Current Window Pointer uint8_t cwp; // Current Window Pointer
@ -83,7 +83,7 @@ class ISA
uint8_t gl; // Global level register uint8_t gl; // Global level register
/** Hyperprivileged Registers */ /** Hyperprivileged Registers */
uint64_t hpstate; // Hyperprivileged State Register HPSTATE hpstate; // Hyperprivileged State Register
uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register
uint64_t hintp; uint64_t hintp;
uint64_t htba; // Hyperprivileged Trap Base Address register uint64_t htba; // Hyperprivileged Trap Base Address register
@ -172,8 +172,8 @@ class ISA
protected: protected:
bool isHyperPriv() { return (hpstate & (1 << 2)); } bool isHyperPriv() { return hpstate.hpriv; }
bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); } bool isPriv() { return hpstate.hpriv || pstate.priv; }
bool isNonPriv() { return !isPriv(); } bool isNonPriv() { return !isPriv(); }
public: public:

View file

@ -567,8 +567,8 @@ output exec {{
checkFpEnableFault(%(CPU_exec_context)s *xc) checkFpEnableFault(%(CPU_exec_context)s *xc)
{ {
if (FullSystem) { if (FullSystem) {
if (xc->readMiscReg(MISCREG_PSTATE) & PSTATE::pef && PSTATE pstate = xc->readMiscReg(MISCREG_PSTATE);
xc->readMiscReg(MISCREG_FPRS) & 0x4) { if (pstate.pef && xc->readMiscReg(MISCREG_FPRS) & 0x4) {
return NoFault; return NoFault;
} else { } else {
return new FpDisabled; return new FpDisabled;

View file

@ -139,7 +139,7 @@ decode OP default Unknown::unknown()
} }
0x1: BranchN::call(30, {{ 0x1: BranchN::call(30, {{
IntReg midVal; IntReg midVal;
R15 = midVal = (Pstate<3:> ? (PC)<31:0> : PC); R15 = midVal = (Pstate.am ? (PC)<31:0> : PC);
NNPC = midVal + disp; NNPC = midVal + disp;
}},None, None, IsIndirectControl, IsCall); }},None, None, IsIndirectControl, IsCall);
0x2: decode OP3 { 0x2: decode OP3 {
@ -327,7 +327,7 @@ decode OP default Unknown::unknown()
0x03: NoPriv::rdasi({{Rd = Asi;}}); 0x03: NoPriv::rdasi({{Rd = Asi;}});
0x04: Priv::rdtick({{Rd = Tick;}}, {{Tick<63:>}}); 0x04: Priv::rdtick({{Rd = Tick;}}, {{Tick<63:>}});
0x05: NoPriv::rdpc({{ 0x05: NoPriv::rdpc({{
if (Pstate<3:>) if (Pstate.am)
Rd = (PC)<31:0>; Rd = (PC)<31:0>;
else else
Rd = PC; Rd = PC;
@ -356,7 +356,7 @@ decode OP default Unknown::unknown()
0x18: Priv::rdstick({{Rd = Stick}}, {{Stick<63:>}}); 0x18: Priv::rdstick({{Rd = Stick}}, {{Stick<63:>}});
0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}}); 0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}});
0x1A: Priv::rdstrand_sts_reg({{ 0x1A: Priv::rdstrand_sts_reg({{
if (Pstate<2:> && !Hpstate<2:>) if (Pstate.am && !Hpstate.hpriv)
Rd = StrandStsReg<0:>; Rd = StrandStsReg<0:>;
else else
Rd = StrandStsReg; Rd = StrandStsReg;
@ -479,7 +479,7 @@ decode OP default Unknown::unknown()
0x11: Priv::wrpic({{Pic = Rs1 ^ Rs2_or_imm13;}}, {{Pcr<0:>}}); 0x11: Priv::wrpic({{Pic = Rs1 ^ Rs2_or_imm13;}}, {{Pcr<0:>}});
// 0x12 should cause an illegal instruction exception // 0x12 should cause an illegal instruction exception
0x13: NoPriv::wrgsr({{ 0x13: NoPriv::wrgsr({{
if (Fprs<2:> == 0 || Pstate<4:> == 0) if (Fprs<2:> == 0 || Pstate.pef == 0)
return new FpDisabled; return new FpDisabled;
Gsr = Rs1 ^ Rs2_or_imm13; Gsr = Rs1 ^ Rs2_or_imm13;
}}); }});
@ -488,7 +488,7 @@ decode OP default Unknown::unknown()
0x16: Priv::wrsoftint({{Softint = Rs1 ^ Rs2_or_imm13;}}); 0x16: Priv::wrsoftint({{Softint = Rs1 ^ Rs2_or_imm13;}});
0x17: Priv::wrtick_cmpr({{TickCmpr = Rs1 ^ Rs2_or_imm13;}}); 0x17: Priv::wrtick_cmpr({{TickCmpr = Rs1 ^ Rs2_or_imm13;}});
0x18: NoPriv::wrstick({{ 0x18: NoPriv::wrstick({{
if (!Hpstate<2:>) if (!Hpstate.hpriv)
return new IllegalInstruction; return new IllegalInstruction;
Stick = Rs1 ^ Rs2_or_imm13; Stick = Rs1 ^ Rs2_or_imm13;
}}); }});
@ -536,7 +536,7 @@ decode OP default Unknown::unknown()
0x05: Priv::wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}}); 0x05: Priv::wrprtba({{Tba = Rs1 ^ Rs2_or_imm13;}});
0x06: Priv::wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}}); 0x06: Priv::wrprpstate({{Pstate = Rs1 ^ Rs2_or_imm13;}});
0x07: Priv::wrprtl({{ 0x07: Priv::wrprtl({{
if (Pstate<2:> && !Hpstate<2:>) if (Pstate.priv && !Hpstate.hpriv)
Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPTL); Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPTL);
else else
Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxTL); Tl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxTL);
@ -550,7 +550,7 @@ decode OP default Unknown::unknown()
0x0E: Priv::wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}}); 0x0E: Priv::wrprwstate({{Wstate = Rs1 ^ Rs2_or_imm13;}});
// 0x0F should cause an illegal instruction exception // 0x0F should cause an illegal instruction exception
0x10: Priv::wrprgl({{ 0x10: Priv::wrprgl({{
if (Pstate<2:> && !Hpstate<2:>) if (Pstate.priv && !Hpstate.hpriv)
Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPGL); Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxPGL);
else else
Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxGL); Gl = std::min<uint64_t>(Rs1 ^ Rs2_or_imm13, MaxGL);
@ -997,7 +997,7 @@ decode OP default Unknown::unknown()
if (target & 0x3) { if (target & 0x3) {
fault = new MemAddressNotAligned; fault = new MemAddressNotAligned;
} else { } else {
if (Pstate<3:>) if (Pstate.am)
Rd = (PC)<31:0>; Rd = (PC)<31:0>;
else else
Rd = PC; Rd = PC;

View file

@ -317,17 +317,17 @@ let {{
# are split into ones that are available in priv and hpriv, and # are split into ones that are available in priv and hpriv, and
# those that are only available in hpriv # those that are only available in hpriv
AlternateASIPrivFaultCheck = ''' AlternateASIPrivFaultCheck = '''
if ((!bits(Pstate,2,2) && !bits(Hpstate,2,2) && if ((!Pstate.priv && !Hpstate.hpriv &&
!asiIsUnPriv((ASI)EXT_ASI)) || !asiIsUnPriv((ASI)EXT_ASI)) ||
(!bits(Hpstate,2,2) && asiIsHPriv((ASI)EXT_ASI))) (!Hpstate.hpriv && asiIsHPriv((ASI)EXT_ASI)))
fault = new PrivilegedAction; fault = new PrivilegedAction;
else if (asiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2)) else if (asiIsAsIfUser((ASI)EXT_ASI) && !Pstate.priv)
fault = new PrivilegedAction; fault = new PrivilegedAction;
''' '''
TruncateEA = ''' TruncateEA = '''
if (!FullSystem) if (!FullSystem)
EA = Pstate<3:> ? EA<31:0> : EA; EA = Pstate.am ? EA<31:0> : EA;
''' '''
}}; }};

View file

@ -264,7 +264,7 @@ let {{
}}; }};
def format Priv(code, extraCond=true, checkTl=false, *opt_flags) {{ def format Priv(code, extraCond=true, checkTl=false, *opt_flags) {{
checkCode = "(%s) && !(Pstate<2:> || Hpstate<2:>)" % extraCond checkCode = "(%s) && !(Pstate.priv || Hpstate.hpriv)" % extraCond
if checkTl != "false": if checkTl != "false":
tlCheck = "Tl == 0" tlCheck = "Tl == 0"
else: else:
@ -289,7 +289,7 @@ def format NoPriv(code, checkTl=false, *opt_flags) {{
}}; }};
def format HPriv(code, checkTl=false, *opt_flags) {{ def format HPriv(code, checkTl=false, *opt_flags) {{
checkCode = "!Hpstate<2:2>" checkCode = "!Hpstate.hpriv"
if checkTl != "false": if checkTl != "false":
tlCheck = "Tl == 0" tlCheck = "Tl == 0"
else: else:

View file

@ -40,7 +40,10 @@ def operand_types {{
'tudw' : 'Twin64_t', 'tudw' : 'Twin64_t',
'tuw' : 'Twin32_t', 'tuw' : 'Twin32_t',
'sf' : 'float', 'sf' : 'float',
'df' : 'double' 'df' : 'double',
'pstate' : 'PSTATE',
'hpstate' : 'HPSTATE'
}}; }};
output header {{ output header {{
@ -167,7 +170,7 @@ def operands {{
'Tt': ('ControlReg', 'udw', 'MISCREG_TT', None, 56), 'Tt': ('ControlReg', 'udw', 'MISCREG_TT', None, 56),
'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 57), 'Tick': ('ControlReg', 'udw', 'MISCREG_TICK', None, 57),
'Tba': ('ControlReg', 'udw', 'MISCREG_TBA', None, 58), 'Tba': ('ControlReg', 'udw', 'MISCREG_TBA', None, 58),
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 59), 'Pstate': ('ControlReg', 'pstate', 'MISCREG_PSTATE', None, 59),
'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60), 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 60),
'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61), 'Pil': ('ControlReg', 'udw', 'MISCREG_PIL', None, 61),
'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 62), 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 62),
@ -183,7 +186,7 @@ def operands {{
'Wstate': ('IntReg', 'udw', 'NumIntArchRegs + 7', None, 67), 'Wstate': ('IntReg', 'udw', 'NumIntArchRegs + 7', None, 67),
'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 68), 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 68),
'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 69), 'Hpstate': ('ControlReg', 'hpstate', 'MISCREG_HPSTATE', None, 69),
'Htstate': ('ControlReg', 'udw', 'MISCREG_HTSTATE', None, 70), 'Htstate': ('ControlReg', 'udw', 'MISCREG_HTSTATE', None, 70),
'Hintp': ('ControlReg', 'udw', 'MISCREG_HINTP', None, 71), 'Hintp': ('ControlReg', 'udw', 'MISCREG_HINTP', None, 71),
'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72), 'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72),

View file

@ -32,6 +32,7 @@
#ifndef __ARCH_SPARC_MISCREGS_HH__ #ifndef __ARCH_SPARC_MISCREGS_HH__
#define __ARCH_SPARC_MISCREGS_HH__ #define __ARCH_SPARC_MISCREGS_HH__
#include "base/bitunion.hh"
#include "base/types.hh" #include "base/types.hh"
namespace SparcISA namespace SparcISA
@ -115,26 +116,25 @@ enum MiscRegIndex
MISCREG_NUMMISCREGS MISCREG_NUMMISCREGS
}; };
struct HPSTATE BitUnion64(HPSTATE)
{ Bitfield<0> tlz;
const static uint64_t id = 0x800; // this impl. dependent (id) field m Bitfield<2> hpriv;
const static uint64_t ibe = 0x400; Bitfield<5> red;
const static uint64_t red = 0x20; Bitfield<10> ibe;
const static uint64_t hpriv = 0x4; Bitfield<11> id; // this impl. dependent (id) field m
const static uint64_t tlz = 0x1; EndBitUnion(HPSTATE)
};
BitUnion16(PSTATE)
struct PSTATE Bitfield<1> ie;
{ Bitfield<2> priv;
const static int cle = 0x200; Bitfield<3> am;
const static int tle = 0x100; Bitfield<4> pef;
const static int mm = 0xC0; Bitfield<6, 7> mm;
const static int pef = 0x10; Bitfield<8> tle;
const static int am = 0x8; Bitfield<9> cle;
const static int priv = 0x4; Bitfield<10> pid0;
const static int ie = 0x2; Bitfield<11> pid1;
}; EndBitUnion(PSTATE)
struct STS struct STS
{ {

View file

@ -161,7 +161,10 @@ Sparc32LiveProcess::initState()
ThreadContext *tc = system->getThreadContext(contextIds[0]); ThreadContext *tc = system->getThreadContext(contextIds[0]);
// The process runs in user mode with 32 bit addresses // The process runs in user mode with 32 bit addresses
tc->setMiscReg(MISCREG_PSTATE, 0x0a); PSTATE pstate = 0;
pstate.ie = 1;
pstate.am = 1;
tc->setMiscReg(MISCREG_PSTATE, pstate);
argsInit(32 / 8, VMPageSize); argsInit(32 / 8, VMPageSize);
} }
@ -173,7 +176,9 @@ Sparc64LiveProcess::initState()
ThreadContext *tc = system->getThreadContext(contextIds[0]); ThreadContext *tc = system->getThreadContext(contextIds[0]);
// The process runs in user mode // The process runs in user mode
tc->setMiscReg(MISCREG_PSTATE, 0x02); PSTATE pstate = 0;
pstate.ie = 1;
tc->setMiscReg(MISCREG_PSTATE, pstate);
argsInit(sizeof(IntReg), VMPageSize); argsInit(sizeof(IntReg), VMPageSize);
} }
@ -533,27 +538,22 @@ SparcLiveProcess::setSyscallReturn(ThreadContext *tc,
// check for error condition. SPARC syscall convention is to // check for error condition. SPARC syscall convention is to
// indicate success/failure in reg the carry bit of the ccr // indicate success/failure in reg the carry bit of the ccr
// and put the return value itself in the standard return value reg (). // and put the return value itself in the standard return value reg ().
PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
if (return_value.successful()) { if (return_value.successful()) {
// no error, clear XCC.C // no error, clear XCC.C
tc->setIntReg(NumIntArchRegs + 2, tc->setIntReg(NumIntArchRegs + 2,
tc->readIntReg(NumIntArchRegs + 2) & 0xEE); tc->readIntReg(NumIntArchRegs + 2) & 0xEE);
// tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE);
IntReg val = return_value.value(); IntReg val = return_value.value();
if (bits(tc->readMiscRegNoEffect( if (pstate.am)
SparcISA::MISCREG_PSTATE), 3, 3)) {
val = bits(val, 31, 0); val = bits(val, 31, 0);
}
tc->setIntReg(ReturnValueReg, val); tc->setIntReg(ReturnValueReg, val);
} else { } else {
// got an error, set XCC.C // got an error, set XCC.C
tc->setIntReg(NumIntArchRegs + 2, tc->setIntReg(NumIntArchRegs + 2,
tc->readIntReg(NumIntArchRegs + 2) | 0x11); tc->readIntReg(NumIntArchRegs + 2) | 0x11);
// tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11);
IntReg val = -return_value.value(); IntReg val = -return_value.value();
if (bits(tc->readMiscRegNoEffect( if (pstate.am)
SparcISA::MISCREG_PSTATE), 3, 3)) {
val = bits(val, 31, 0); val = bits(val, 31, 0);
}
tc->setIntReg(ReturnValueReg, val); tc->setIntReg(ReturnValueReg, val);
} }
} }

View file

@ -181,9 +181,9 @@ RemoteGDB::getregs()
memset(gdbregs.regs, 0, gdbregs.size); memset(gdbregs.regs, 0, gdbregs.size);
PCState pc = context->pcState(); PCState pc = context->pcState();
PSTATE pstate = context->readMiscReg(MISCREG_PSTATE);
if (context->readMiscReg(MISCREG_PSTATE) & if (pstate.am) {
PSTATE::am) {
uint32_t *regs; uint32_t *regs;
regs = (uint32_t*)gdbregs.regs; regs = (uint32_t*)gdbregs.regs;
regs[Reg32Pc] = htobe((uint32_t)pc.pc()); regs[Reg32Pc] = htobe((uint32_t)pc.pc());
@ -192,7 +192,7 @@ RemoteGDB::getregs()
regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0)); regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0));
regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1)); regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1));
regs[Reg32Psr] = htobe((uint32_t)context->readMiscReg(MISCREG_PSTATE)); regs[Reg32Psr] = htobe((uint32_t)pstate);
regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR)); regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR));
regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2)); regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2));
} else { } else {
@ -206,7 +206,7 @@ RemoteGDB::getregs()
gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1)); gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1));
gdbregs.regs[RegState] = htobe( gdbregs.regs[RegState] = htobe(
context->readMiscReg(MISCREG_CWP) | context->readMiscReg(MISCREG_CWP) |
context->readMiscReg(MISCREG_PSTATE) << 8 | pstate << 8 |
context->readMiscReg(MISCREG_ASI) << 24 | context->readMiscReg(MISCREG_ASI) << 24 |
context->readIntReg(NumIntArchRegs + 2) << 32); context->readIntReg(NumIntArchRegs + 2) << 32);
} }

View file

@ -206,13 +206,18 @@ ISA::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
break; break;
case MISCREG_HPSTATE: case MISCREG_HPSTATE:
{
HPSTATE newVal = val;
newVal.id = 1;
// T1000 spec says impl. dependent val must always be 1 // T1000 spec says impl. dependent val must always be 1
setMiscRegNoEffect(miscReg, val | HPSTATE::id); setMiscRegNoEffect(miscReg, newVal);
if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) newVal = hpstate;
if (newVal.tlz && tl == 0 && !newVal.hpriv)
cpu->postInterrupt(IT_TRAP_LEVEL_ZERO, 0); cpu->postInterrupt(IT_TRAP_LEVEL_ZERO, 0);
else else
cpu->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0); cpu->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0);
break; break;
}
case MISCREG_HTSTATE: case MISCREG_HTSTATE:
setMiscRegNoEffect(miscReg, val); setMiscRegNoEffect(miscReg, val);
break; break;

View file

@ -58,8 +58,9 @@ uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
static inline bool static inline bool
inUserMode(ThreadContext *tc) inUserMode(ThreadContext *tc)
{ {
return !((tc->readMiscRegNoEffect(MISCREG_PSTATE) & (1 << 2)) || PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
(tc->readMiscRegNoEffect(MISCREG_HPSTATE) & (1 << 2))); HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
return !(pstate.priv || hpstate.hpriv);
} }
/** /**