emiIsReady = false;
}
- void
- reset(const ExtMachInst &old_emi)
- {
- reset();
- }
-
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) |
tc->readIntReg(INTREG_CONDCODES);
Addr curPc M5_VAR_USED = tc->pcState().pc();
-
+ ITSTATE it = tc->pcState().itstate();
+ saved_cpsr.it2 = it.top6;
+ saved_cpsr.it1 = it.bottom2;
cpsr.mode = nextMode();
cpsr.it1 = cpsr.it2 = 0;
{
tc->getCpuPtr()->clearInterrupts();
tc->clearArchRegs();
- ArmFault::invoke(tc);
+ ArmFault::invoke(tc, inst);
}
#else
void
AbortFault<T>::invoke(ThreadContext *tc, StaticInstPtr inst)
{
- ArmFaultVals<T>::invoke(tc);
+ ArmFaultVals<T>::invoke(tc, inst);
FSR fsr = 0;
fsr.fsLow = bits(status, 3, 0);
fsr.fsHigh = bits(status, 4);
// start refetching from the next instruction.
PCState pc = tc->pcState();
assert(inst);
- pc.forcedItState(inst->machInst.newItstate);
inst->advancePC(pc);
tc->pcState(pc);
}
miscRegName[misc_reg], val);
} else {
switch (misc_reg) {
- case MISCREG_ITSTATE:
- {
- ITSTATE itstate = newVal;
- CPSR cpsr = miscRegs[MISCREG_CPSR];
- cpsr.it1 = itstate.bottom2;
- cpsr.it2 = itstate.top6;
- miscRegs[MISCREG_CPSR] = cpsr;
- DPRINTF(MiscRegs,
- "Updating ITSTATE -> %#x in CPSR -> %#x.\n",
- (uint8_t)itstate, (uint32_t)cpsr);
- }
- break;
case MISCREG_CPACR:
{
CPACR newCpacr = 0;
CondCodes = CondCodesMask & newCpsr;
NextThumb = ((CPSR)newCpsr).t;
NextJazelle = ((CPSR)newCpsr).j;
- ForcedItState = ((((CPSR)newCpsr).it2 << 2) & 0xFC)
+ NextItState = ((((CPSR)newCpsr).it2 << 2) & 0xFC)
| (((CPSR)newCpsr).it1 & 0x3);
'''
buildImmDataInst(mnem + 's', code, flagType,
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
IWNPC = cSwap(%s, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
- ForcedItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
+ NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
| (((CPSR)Spsr).it1 & 0x3);
'''
Cpsr = ~CondCodesMask & newCpsr;
NextThumb = ((CPSR)newCpsr).t;
NextJazelle = ((CPSR)newCpsr).j;
- ForcedItState = ((((CPSR)URb).it2 << 2) & 0xFC)
+ NextItState = ((((CPSR)URb).it2 << 2) & 0xFC)
| (((CPSR)URb).it1 & 0x3);
CondCodes = CondCodesMask & newCpsr;
'''
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
- NextThumb = ((CPSR)newCpsr).t;
- NextJazelle = ((CPSR)newCpsr).j;
- ForcedItState = ((((CPSR)Op1).it2 << 2) & 0xFC)
- | (((CPSR)Op1).it1 & 0x3);
CondCodes = CondCodesMask & newCpsr;
'''
msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp",
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
- NextThumb = ((CPSR)newCpsr).t;
- NextJazelle = ((CPSR)newCpsr).j;
- ForcedItState = ((((CPSR)imm).it2 << 2) & 0xFC)
- | (((CPSR)imm).it1 & 0x3);
CondCodes = CondCodesMask & newCpsr;
'''
msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp",
exec_output += PredOpExecute.subst(sevIop)
itIop = InstObjParams("it", "ItInst", "PredOp", \
- { "code" : "Itstate = machInst.newItstate;",
+ { "code" : ";",
"predicate_test" : predicateTest },
["IsNonSpeculative", "IsSerializeAfter"])
header_output += BasicDeclare.subst(itIop)
#Fixed index control regs
'Cpsr': cntrlReg('MISCREG_CPSR', srtCpsr),
- 'Itstate': cntrlRegNC('MISCREG_ITSTATE', type = 'ub'),
'Spsr': cntrlRegNC('MISCREG_SPSR'),
'Fpsr': cntrlRegNC('MISCREG_FPSR'),
'Fpsid': cntrlRegNC('MISCREG_FPSID'),
'Thumb': pcStateReg('thumb', srtPC),
'NextThumb': pcStateReg('nextThumb', srtMode),
'NextJazelle': pcStateReg('nextJazelle', srtMode),
- 'ForcedItState': pcStateReg('forcedItState', srtMode),
+ 'NextItState': pcStateReg('nextItstate', srtMode),
+ 'Itstate': pcStateReg('itstate', srtMode),
#Register operands depending on a field in the instruction encoding. These
#should be avoided since they may not be portable across different
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
}
}
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
} else {
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
return fault;
}
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
}
} else {
xc->setPredicate(false);
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
}
return fault;
}
} else {
xc->setPredicate(false);
- if (fault == NoFault && machInst.itstateMask != 0 &&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
}
return fault;
}
}
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
}
}
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
- if (machInst.itstateMask != 0) {
- warn_once("Complete acc isn't called on normal stores in O3.");
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
return NoFault;
}
}};
PacketPtr pkt, %(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
- if (machInst.itstateMask != 0) {
- warn_once("Complete acc isn't called on normal stores in O3.");
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
return NoFault;
}
}};
}
}
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
}
} else {
xc->setPredicate(false);
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
}
return fault;
%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
- if (machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return NoFault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
xc->setPredicate(false);
}
- if (fault == NoFault && machInst.itstateMask != 0&&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
#endif
}
- if (fault == NoFault && machInst.itstateMask != 0&&
- (!isMicroop() || isLastMicroop())) {
- xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
- }
-
return fault;
}
}};
enum MiscRegIndex {
MISCREG_CPSR = 0,
- MISCREG_ITSTATE,
MISCREG_SPSR,
MISCREG_SPSR_FIQ,
MISCREG_SPSR_IRQ,
unsigned crm, unsigned opc2);
const char * const miscRegName[NUM_MISCREGS] = {
- "cpsr", "itstate", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc",
+ "cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc",
"spsr_mon", "spsr_und", "spsr_abt",
"fpsr", "fpsid", "fpscr", "fpscr_qc", "fpscr_exc", "fpexc",
"mvfr0", "mvfr1",
Bitfield<4, 0> mode;
EndBitUnion(CPSR)
- BitUnion8(ITSTATE)
- /* Note that the split (cond, mask) below is not as in ARM ARM.
- * But it is more convenient for simulation. The condition
- * is always the concatenation of the top 3 bits and the next bit,
- * which applies when one of the bottom 4 bits is set.
- * Refer to predecoder.cc for the use case.
- */
- Bitfield<7, 4> cond;
- Bitfield<3, 0> mask;
- // Bitfields for moving to/from CPSR
- Bitfield<7, 2> top6;
- Bitfield<1, 0> bottom2;
- EndBitUnion(ITSTATE)
-
// This mask selects bits of the CPSR that actually go in the CondCodes
// integer register to allow renaming.
static const uint32_t CondCodesMask = 0xF80F0000;
namespace ArmISA
{
-void
-Predecoder::advanceThumbCond()
-{
- uint8_t condMask = itstate.mask;
- uint8_t thumbCond = itstate.cond;
- DPRINTF(Predecoder, "Advancing ITSTATE from %#x, %#x.\n",
- thumbCond, condMask);
- condMask = condMask << 1;
- uint8_t newBit = bits(condMask, 4);
- condMask &= mask(4);
- if (condMask == 0) {
- thumbCond = 0;
- } else {
- replaceBits(thumbCond, 0, newBit);
- }
- DPRINTF(Predecoder, "Advancing ITSTATE to %#x, %#x.\n",
- thumbCond, condMask);
- itstate.mask = condMask;
- itstate.cond = thumbCond;
-}
-
void
Predecoder::process()
{
consumeBytes(2);
DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n",
emi.instBits);
- if (itstate.mask) {
- emi.itstate = itstate;
- advanceThumbCond();
- emi.newItstate = itstate;
- }
} else {
uint16_t highBits = word & 0xF800;
if (highBits == 0xE800 || highBits == 0xF000 ||
DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n",
emi.instBits);
consumeBytes(4);
- if (itstate.mask) {
- emi.itstate = itstate;
- advanceThumbCond();
- emi.newItstate = itstate;
- }
} else {
// We only have the first half word.
DPRINTF(Predecoder,
emi.instBits);
if (bits(word, 15, 8) == 0xbf &&
bits(word, 3, 0) != 0x0) {
- emi.itstate = itstate;
- itstate = bits(word, 7, 0);
- emi.newItstate = itstate;
+ foundIt = true;
+ itBits = bits(word, 7, 0);
DPRINTF(Predecoder,
"IT detected, cond = %#x, mask = %#x\n",
- itstate.cond, itstate.mask);
- } else if (itstate.mask) {
- emi.itstate = itstate;
- advanceThumbCond();
- emi.newItstate = itstate;
+ itBits.cond, itBits.mask);
}
}
}
emi.fpscrLen = fpscr.len;
emi.fpscrStride = fpscr.stride;
- if (pc.forcedItStateIsValid()) {
- // returns from exceptions/interrupts force the it state.
- itstate = pc.forcedItState();
- DPRINTF(Predecoder, "Predecoder, itstate forced = %08x.\n", pc.forcedItState());
- } else if (predAddrValid && (pc.instAddr() != predAddr)) {
- // Control flow changes necessitate a 0 itstate.
- itstate.top6 = 0;
- itstate.bottom2 = 0;
- }
-
outOfBytes = false;
process();
}
bool emiReady;
bool outOfBytes;
int offset;
- ITSTATE itstate;
- Addr predAddr;
- bool predAddrValid;
+ bool foundIt;
+ ITSTATE itBits;
public:
void reset()
emi = 0;
emiReady = false;
outOfBytes = true;
- itstate = 0;
- predAddr = 0;
- predAddrValid = false;
- }
-
- void reset(const ExtMachInst &old_emi)
- {
- reset();
- itstate = old_emi.newItstate;
+ foundIt = false;
}
Predecoder(ThreadContext * _tc) :
tc = _tc;
}
- void advanceThumbCond();
void process();
//Use this to give data to the predecoder. This should be used
assert(emiReady);
ExtMachInst thisEmi = emi;
pc.npc(pc.pc() + getInstSize());
- predAddrValid = true;
- predAddr = pc.pc() + getInstSize();
+ if (foundIt)
+ pc.nextItstate(itBits);
+ thisEmi.itstate = pc.itstate();
pc.size(getInstSize());
emi = 0;
emiReady = false;
+ foundIt = false;
return thisEmi;
}
};
{
typedef uint32_t MachInst;
+ BitUnion8(ITSTATE)
+ /* Note that the split (cond, mask) below is not as in ARM ARM.
+ * But it is more convenient for simulation. The condition
+ * is always the concatenation of the top 3 bits and the next bit,
+ * which applies when one of the bottom 4 bits is set.
+ * Refer to predecoder.cc for the use case.
+ */
+ Bitfield<7, 4> cond;
+ Bitfield<3, 0> mask;
+ // Bitfields for moving to/from CPSR
+ Bitfield<7, 2> top6;
+ Bitfield<1, 0> bottom2;
+ EndBitUnion(ITSTATE)
+
+
BitUnion64(ExtMachInst)
- Bitfield<63, 56> newItstate;
// ITSTATE bits
Bitfield<55, 48> itstate;
Bitfield<55, 52> itstateCond;
};
uint8_t flags;
uint8_t nextFlags;
- uint8_t forcedItStateValue;
+ uint8_t _itstate;
+ uint8_t _nextItstate;
uint8_t _size;
- bool forcedItStateValid;
public:
- PCState() : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
+ PCState() : flags(0), nextFlags(0), _itstate(0), _nextItstate(0)
{}
void
npc(val + (thumb() ? 2 : 4));
}
- PCState(Addr val) : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
+ PCState(Addr val) : flags(0), nextFlags(0), _itstate(0), _nextItstate(0)
{ set(val); }
bool
}
uint8_t
- forcedItState() const
+ itstate() const
{
- return forcedItStateValue;
+ return _itstate;
}
void
- forcedItState(uint8_t value)
+ itstate(uint8_t value)
{
- forcedItStateValue = value;
- // Not valid unless the advance is called.
- forcedItStateValid = false;
+ _itstate = value;
}
- bool
- forcedItStateIsValid() const
+ uint8_t
+ nextItstate() const
{
- return forcedItStateValid;
+ return _nextItstate;
+ }
+
+ void
+ nextItstate(uint8_t value)
+ {
+ _nextItstate = value;
}
void
npc(pc() + (thumb() ? 2 : 4));
flags = nextFlags;
- // Validate the itState
- if (forcedItStateValue != 0 && !forcedItStateValid) {
- forcedItStateValid = true;
- } else {
- forcedItStateValid = false;
- forcedItStateValue = 0;
+ if (_nextItstate) {
+ _itstate = _nextItstate;
+ _nextItstate = 0;
+ } else if (_itstate) {
+ ITSTATE it = _itstate;
+ uint8_t cond_mask = it.mask;
+ uint8_t thumb_cond = it.cond;
+ DPRINTF(Predecoder, "Advancing ITSTATE from %#x,%#x.\n",
+ thumb_cond, cond_mask);
+ cond_mask <<= 1;
+ uint8_t new_bit = bits(cond_mask, 4);
+ cond_mask &= mask(4);
+ if (cond_mask == 0)
+ thumb_cond = 0;
+ else
+ replaceBits(thumb_cond, 0, new_bit);
+ DPRINTF(Predecoder, "Advancing ITSTATE to %#x,%#x.\n",
+ thumb_cond, cond_mask);
+ it.mask = cond_mask;
+ it.cond = thumb_cond;
+ _itstate = it;
}
}
operator == (const PCState &opc) const
{
return Base::operator == (opc) &&
- flags == opc.flags && nextFlags == opc.nextFlags;
+ flags == opc.flags && nextFlags == opc.nextFlags &&
+ _itstate == opc._itstate && _nextItstate == opc._nextItstate;
}
void
SERIALIZE_SCALAR(flags);
SERIALIZE_SCALAR(_size);
SERIALIZE_SCALAR(nextFlags);
- SERIALIZE_SCALAR(forcedItStateValue);
- SERIALIZE_SCALAR(forcedItStateValid);
+ SERIALIZE_SCALAR(_itstate);
+ SERIALIZE_SCALAR(_nextItstate);
}
void
UNSERIALIZE_SCALAR(flags);
UNSERIALIZE_SCALAR(_size);
UNSERIALIZE_SCALAR(nextFlags);
- UNSERIALIZE_SCALAR(forcedItStateValue);
- UNSERIALIZE_SCALAR(forcedItStateValid);
+ UNSERIALIZE_SCALAR(_itstate);
+ UNSERIALIZE_SCALAR(_nextItstate);
}
};
emiIsReady = false;
}
- void
- reset(const ExtMachInst &old_emi)
- {
- reset();
- }
-
//Use this to give data to the predecoder. This should be used
//when there is control flow.
void
emiIsReady = false;
}
- void
- reset(const ExtMachInst &old_emi)
- {
- reset();
- }
-
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
emiIsReady = false;
}
- void
- reset(const ExtMachInst &old_emi)
- {
- reset();
- }
-
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
state = ResetState;
}
- void
- reset(const ExtMachInst &old_emi)
- {
- reset();
- }
-
ThreadContext * getTC()
{
return tc;
DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid);
doSquash(newPC, tid);
- if (squashInst)
- predecoder.reset(squashInst->staticInst->machInst);
// Tell the CPU to remove any instructions that are not in the ROB.
cpu->removeInstsNotInROB(tid);