CondCodes = CondCodesMask & newCpsr;
NextThumb = ((CPSR)newCpsr).t;
NextJazelle = ((CPSR)newCpsr).j;
+ ForcedItState = ((((CPSR)newCpsr).it2 << 2) & 0xFC)
+ | (((CPSR)newCpsr).it1 & 0x3);
'''
buildImmDataInst(mnem + 's', code, flagType,
suffix = "ImmPclr", buildCc = False,
SCTLR sctlr = Sctlr;
// Use the version of NPC that gets set before NextThumb
pNPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
+ uint32_t tempSpsr = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
uint32_t newCpsr =
- cpsrWriteByInstr(cpsr | CondCodes,
- cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
+ cpsrWriteByInstr(cpsr | CondCodes, tempSpsr,
0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
NextThumb = ((CPSR)newCpsr).t;
NextJazelle = ((CPSR)newCpsr).j;
+ ForcedItState = ((((CPSR)tempSpsr).it2 << 2) & 0xFC)
+ | (((CPSR)tempSpsr).it1 & 0x3);
CondCodes = CondCodesMask & newCpsr;
'''
self.codeBlobs["memacc_code"] = accCode
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
+ ForcedItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
+ | (((CPSR)Spsr).it1 & 0x3);
'''
microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
'MicroMemOp',
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",
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",
'Thumb': pcStateReg('thumb', srtPC),
'NextThumb': pcStateReg('nextThumb', srtMode),
'NextJazelle': pcStateReg('nextJazelle', srtMode),
+ 'ForcedItState': pcStateReg('forcedItState', srtMode),
#Register operands depending on a field in the instruction encoding. These
#should be avoided since they may not be portable across different
FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
emi.fpscrLen = fpscr.len;
emi.fpscrStride = fpscr.stride;
- CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
- itstate.top6 = cpsr.it2;
- itstate.bottom2 = cpsr.it1;
+
+ 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 outOfBytes;
int offset;
ITSTATE itstate;
+ Addr predAddr;
+ bool predAddrValid;
public:
void reset()
emi = 0;
emiReady = false;
outOfBytes = true;
+ itstate = 0;
+ predAddr = 0;
+ predAddrValid = false;
}
Predecoder(ThreadContext * _tc) :
assert(emiReady);
ExtMachInst thisEmi = emi;
pc.npc(pc.pc() + getInstSize());
+ predAddrValid = true;
+ predAddr = pc.pc() + getInstSize();
emi = 0;
emiReady = false;
return thisEmi;
};
uint8_t flags;
uint8_t nextFlags;
-
+ uint8_t forcedItStateValue;
+ bool forcedItStateValid;
public:
- PCState() : flags(0), nextFlags(0)
+ PCState() : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
{}
void
npc(val + (thumb() ? 2 : 4));
}
- PCState(Addr val) : flags(0), nextFlags(0)
+ PCState(Addr val) : flags(0), nextFlags(0), forcedItStateValue(0), forcedItStateValid(false)
{ set(val); }
bool
nextFlags &= ~JazelleBit;
}
+ uint8_t
+ forcedItState() const
+ {
+ return forcedItStateValue;
+ }
+
+ void
+ forcedItState(uint8_t value)
+ {
+ forcedItStateValue = value;
+ // Not valid unless the advance is called.
+ forcedItStateValid = false;
+ }
+
+ bool
+ forcedItStateIsValid() const
+ {
+ return forcedItStateValid;
+ }
+
void
advance()
{
Base::advance();
npc(pc() + (thumb() ? 2 : 4));
flags = nextFlags;
+
+ // Validate the itState
+ if (forcedItStateValue != 0 && !forcedItStateValid) {
+ forcedItStateValid = true;
+ } else {
+ forcedItStateValid = false;
+ forcedItStateValue = 0;
+ }
}
void
Base::serialize(os);
SERIALIZE_SCALAR(flags);
SERIALIZE_SCALAR(nextFlags);
+ SERIALIZE_SCALAR(forcedItStateValue);
+ SERIALIZE_SCALAR(forcedItStateValid);
}
void
Base::unserialize(cp, section);
UNSERIALIZE_SCALAR(flags);
UNSERIALIZE_SCALAR(nextFlags);
+ UNSERIALIZE_SCALAR(forcedItStateValue);
+ UNSERIALIZE_SCALAR(forcedItStateValid);
}
};