diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/isa/insts/data.isa --- a/src/arch/arm/isa/insts/data.isa Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/isa/insts/data.isa Wed Jan 12 11:12:01 2011 -0600 @@ -241,6 +241,8 @@ 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, diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/isa/insts/ldr.isa --- a/src/arch/arm/isa/insts/ldr.isa Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/isa/insts/ldr.isa Wed Jan 12 11:12:01 2011 -0600 @@ -107,13 +107,15 @@ SCTLR sctlr = Sctlr; // Use the version of NPC that gets set before NextThumb pNPC = cSwap(Mem.ud, cpsr.e); + uint32_t tempSpsr = cSwap(Mem.ud >> 32, cpsr.e); uint32_t newCpsr = - cpsrWriteByInstr(cpsr | CondCodes, - cSwap(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 diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/isa/insts/macromem.isa --- a/src/arch/arm/isa/insts/macromem.isa Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/isa/insts/macromem.isa Wed Jan 12 11:12:01 2011 -0600 @@ -94,6 +94,8 @@ 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', diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/isa/insts/misc.isa --- a/src/arch/arm/isa/insts/misc.isa Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/isa/insts/misc.isa Wed Jan 12 11:12:01 2011 -0600 @@ -85,6 +85,8 @@ 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", @@ -111,6 +113,8 @@ 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", diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/isa/operands.isa --- a/src/arch/arm/isa/operands.isa Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/isa/operands.isa Wed Jan 12 11:12:01 2011 -0600 @@ -245,6 +245,7 @@ '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 diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/predecoder.hh --- a/src/arch/arm/predecoder.hh Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/predecoder.hh Wed Jan 12 11:12:01 2011 -0600 @@ -67,6 +67,8 @@ bool outOfBytes; int offset; ITSTATE itstate; + Addr predAddr; + bool predAddrValid; public: void reset() @@ -76,6 +78,9 @@ emi = 0; emiReady = false; outOfBytes = true; + itstate = 0; + predAddr = 0; + predAddrValid = false; } Predecoder(ThreadContext * _tc) : @@ -138,6 +143,8 @@ assert(emiReady); ExtMachInst thisEmi = emi; pc.npc(pc.pc() + getInstSize()); + predAddrValid = true; + predAddr = pc.pc() + getInstSize(); emi = 0; emiReady = false; return thisEmi; diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/predecoder.cc --- a/src/arch/arm/predecoder.cc Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/predecoder.cc Wed Jan 12 11:12:01 2011 -0600 @@ -162,9 +162,17 @@ 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(); } diff -r cc274e4275fe -r 87cc0f60ea63 src/arch/arm/types.hh --- a/src/arch/arm/types.hh Wed Jan 12 11:12:01 2011 -0600 +++ b/src/arch/arm/types.hh Wed Jan 12 11:12:01 2011 -0600 @@ -202,9 +202,10 @@ }; 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 @@ -214,7 +215,7 @@ 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 @@ -277,12 +278,40 @@ 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 @@ -366,6 +395,8 @@ Base::serialize(os); SERIALIZE_SCALAR(flags); SERIALIZE_SCALAR(nextFlags); + SERIALIZE_SCALAR(forcedItStateValue); + SERIALIZE_SCALAR(forcedItStateValid); } void @@ -374,6 +405,8 @@ Base::unserialize(cp, section); UNSERIALIZE_SCALAR(flags); UNSERIALIZE_SCALAR(nextFlags); + UNSERIALIZE_SCALAR(forcedItStateValue); + UNSERIALIZE_SCALAR(forcedItStateValid); } };