diff options
Diffstat (limited to 'src/arch/arm')
26 files changed, 495 insertions, 263 deletions
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 6e138119c..54cf5cfe5 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -104,6 +104,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) | tc->readIntReg(INTREG_CONDCODES); + Addr curPc M5_VAR_USED = tc->pcState().pc(); cpsr.mode = nextMode(); @@ -116,7 +117,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) cpsr.i = 1; cpsr.e = sctlr.ee; tc->setMiscReg(MISCREG_CPSR, cpsr); - tc->setIntReg(INTREG_LR, tc->readPC() + + tc->setIntReg(INTREG_LR, curPc + (saved_cpsr.t ? thumbPcOffset() : armPcOffset())); switch (nextMode()) { @@ -139,14 +140,15 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) panic("unknown Mode\n"); } - Addr pc M5_VAR_USED = tc->readPC(); - Addr newPc = getVector(tc) | (sctlr.te ? PcTBit : 0); + Addr newPc = getVector(tc); DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n", - name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc); - tc->setPC(newPc); - tc->setNextPC(newPc + cpsr.t ? 2 : 4 ); - tc->setMicroPC(0); - tc->setNextMicroPC(1); + name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc); + PCState pc(newPc); + pc.thumb(cpsr.t); + pc.nextThumb(pc.thumb()); + pc.jazelle(cpsr.j); + pc.nextJazelle(pc.jazelle()); + tc->pcState(pc); } void @@ -193,10 +195,10 @@ SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst) tc->syscall(callNum); // Advance the PC since that won't happen automatically. - tc->setPC(tc->readNextPC()); - tc->setNextPC(tc->readNextNPC()); - tc->setMicroPC(0); - tc->setNextMicroPC(1); + PCState pc = tc->pcState(); + assert(inst); + inst->advancePC(pc); + tc->pcState(pc); } #endif // FULL_SYSTEM @@ -223,10 +225,10 @@ FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) { // Set the PC to the next instruction of the faulting instruction. // Net effect is simply squashing all instructions behind and // start refetching from the next instruction. - tc->setPC(tc->readNextPC()); - tc->setNextPC(tc->readNextNPC()); - tc->setMicroPC(0); - tc->setNextMicroPC(1); + PCState pc = tc->pcState(); + assert(inst); + inst->advancePC(pc); + tc->pcState(pc); } template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc, diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh index c1c8383da..018cb1de5 100644 --- a/src/arch/arm/insts/macromem.hh +++ b/src/arch/arm/insts/macromem.hh @@ -77,6 +77,18 @@ class MicroOp : public PredOp { flags[IsDelayedCommit] = true; } + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) { + pcState.uEnd(); + } else if (flags[IsMicroop]) { + pcState.uAdvance(); + } else { + pcState.advance(); + } + } }; /** diff --git a/src/arch/arm/insts/mem.hh b/src/arch/arm/insts/mem.hh index 1baba5112..2aa4de1d7 100644 --- a/src/arch/arm/insts/mem.hh +++ b/src/arch/arm/insts/mem.hh @@ -63,8 +63,28 @@ class Swap : public PredOp std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; +class MightBeMicro : public PredOp +{ + protected: + MightBeMicro(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : PredOp(mnem, _machInst, __opClass) + {} + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) { + pcState.uEnd(); + } else if (flags[IsMicroop]) { + pcState.uAdvance(); + } else { + pcState.advance(); + } + } +}; + // The address is a base register plus an immediate. -class RfeOp : public PredOp +class RfeOp : public MightBeMicro { public: enum AddrMode { @@ -83,7 +103,7 @@ class RfeOp : public PredOp RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _base, AddrMode _mode, bool _wb) - : PredOp(mnem, _machInst, __opClass), + : MightBeMicro(mnem, _machInst, __opClass), base(_base), mode(_mode), wb(_wb), uops(NULL) {} @@ -94,7 +114,7 @@ class RfeOp : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; @@ -104,7 +124,7 @@ class RfeOp : public PredOp }; // The address is a base register plus an immediate. -class SrsOp : public PredOp +class SrsOp : public MightBeMicro { public: enum AddrMode { @@ -123,7 +143,7 @@ class SrsOp : public PredOp SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _regMode, AddrMode _mode, bool _wb) - : PredOp(mnem, _machInst, __opClass), + : MightBeMicro(mnem, _machInst, __opClass), regMode(_regMode), mode(_mode), wb(_wb), uops(NULL) {} @@ -134,7 +154,7 @@ class SrsOp : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; @@ -143,7 +163,7 @@ class SrsOp : public PredOp std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; -class Memory : public PredOp +class Memory : public MightBeMicro { public: enum AddrMode { @@ -163,7 +183,7 @@ class Memory : public PredOp Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, bool _add) - : PredOp(mnem, _machInst, __opClass), + : MightBeMicro(mnem, _machInst, __opClass), dest(_dest), base(_base), add(_add), uops(NULL) {} @@ -174,7 +194,7 @@ class Memory : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; diff --git a/src/arch/arm/insts/pred_inst.hh b/src/arch/arm/insts/pred_inst.hh index b7d4c4709..f779b46f5 100644 --- a/src/arch/arm/insts/pred_inst.hh +++ b/src/arch/arm/insts/pred_inst.hh @@ -312,7 +312,7 @@ class PredMacroOp : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(microPC < numMicroops); return microOps[microPC]; @@ -332,6 +332,15 @@ class PredMicroop : public PredOp { flags[IsMicroop] = true; } + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) + pcState.uEnd(); + else + pcState.uAdvance(); + } }; } diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index ad89a1a79..fa850190f 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -155,6 +155,12 @@ class ArmStaticInst : public StaticInst IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type, uint32_t imm) const; + void + advancePC(PCState &pcState) const + { + pcState.advance(); + } + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; static inline uint32_t @@ -219,26 +225,16 @@ class ArmStaticInst : public StaticInst static inline Addr readPC(XC *xc) { - Addr pc = xc->readPC(); - if (isThumb(pc)) - return pc + 4; - else - return pc + 8; + return xc->pcState().instPC(); } - // Perform an regular branch. template<class XC> static inline void setNextPC(XC *xc, Addr val) { - Addr npc = xc->readNextPC(); - if (isThumb(npc)) { - val &= ~mask(1); - } else { - val &= ~mask(2); - } - xc->setNextPC((npc & PcModeMask) | - (val & ~PcModeMask)); + PCState pc = xc->pcState(); + pc.instNPC(val); + xc->pcState(pc); } template<class T> @@ -279,30 +275,9 @@ class ArmStaticInst : public StaticInst static inline void setIWNextPC(XC *xc, Addr val) { - Addr stateBits = xc->readPC() & PcModeMask; - Addr jBit = PcJBit; - Addr tBit = PcTBit; - bool thumbEE = (stateBits == (tBit | jBit)); - - Addr newPc = (val & ~PcModeMask); - if (thumbEE) { - if (bits(newPc, 0)) { - newPc = newPc & ~mask(1); - } else { - panic("Bad thumbEE interworking branch address %#x.\n", newPc); - } - } else { - if (bits(newPc, 0)) { - stateBits = tBit; - newPc = newPc & ~mask(1); - } else if (!bits(newPc, 1)) { - stateBits = 0; - } else { - warn("Bad interworking branch address %#x.\n", newPc); - } - } - newPc = newPc | stateBits; - xc->setNextPC(newPc); + PCState pc = xc->pcState(); + pc.instIWNPC(val); + xc->pcState(pc); } // Perform an interworking branch in ARM mode, a regular branch @@ -311,14 +286,9 @@ class ArmStaticInst : public StaticInst static inline void setAIWNextPC(XC *xc, Addr val) { - Addr stateBits = xc->readPC() & PcModeMask; - Addr jBit = PcJBit; - Addr tBit = PcTBit; - if (!jBit && !tBit) { - setIWNextPC(xc, val); - } else { - setNextPC(xc, val); - } + PCState pc = xc->pcState(); + pc.instAIWNPC(val); + xc->pcState(pc); } inline Fault diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh index 964b62673..e962704e0 100644 --- a/src/arch/arm/insts/vfp.hh +++ b/src/arch/arm/insts/vfp.hh @@ -459,6 +459,18 @@ class FpOp : public PredOp unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), bool flush, uint32_t rMode) const; + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) { + pcState.uEnd(); + } else if (flags[IsMicroop]) { + pcState.uAdvance(); + } else { + pcState.advance(); + } + } }; class FpRegRegOp : public FpOp diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index d557cecbb..0ba62f08d 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -168,15 +168,9 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc) { if (misc_reg == MISCREG_CPSR) { CPSR cpsr = miscRegs[misc_reg]; - Addr pc = tc->readPC(); - if (pc & (ULL(1) << PcJBitShift)) - cpsr.j = 1; - else - cpsr.j = 0; - if (isThumb(pc)) - cpsr.t = 1; - else - cpsr.t = 0; + PCState pc = tc->pcState(); + cpsr.j = pc.jazelle() ? 1 : 0; + cpsr.t = pc.thumb() ? 1 : 0; return cpsr; } if (misc_reg >= MISCREG_CP15_UNIMP_START && @@ -239,13 +233,10 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) CPSR cpsr = val; DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n", miscRegs[misc_reg], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode); - Addr npc = tc->readNextPC() & ~PcModeMask; - if (cpsr.j) - npc = npc | PcJBit; - if (cpsr.t) - npc = npc | PcTBit; - - tc->setNextPC(npc); + PCState pc = tc->pcState(); + pc.nextThumb(cpsr.t); + pc.nextJazelle(cpsr.j); + tc->pcState(pc); } else if (misc_reg >= MISCREG_CP15_UNIMP_START && misc_reg < MISCREG_CP15_END) { panic("Unimplemented CP15 register %s wrote with %#x.\n", @@ -414,7 +405,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) default: panic("Security Extensions not implemented!"); } - req->setVirt(0, val, 1, flags, tc->readPC()); + req->setVirt(0, val, 1, flags, tc->pcState().pc()); fault = tc->getDTBPtr()->translateAtomic(req, tc, mode); if (fault == NoFault) { miscRegs[MISCREG_PAR] = diff --git a/src/arch/arm/isa/formats/breakpoint.isa b/src/arch/arm/isa/formats/breakpoint.isa index d59f6a712..1825d0878 100644 --- a/src/arch/arm/isa/formats/breakpoint.isa +++ b/src/arch/arm/isa/formats/breakpoint.isa @@ -83,7 +83,7 @@ output exec {{ Breakpoint::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - return new PrefetchAbort(xc->readPC(), ArmFault::DebugEvent); + return new PrefetchAbort(xc->pcState().pc(), ArmFault::DebugEvent); } }}; diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa index e9ddd77b7..3ff9042e6 100644 --- a/src/arch/arm/isa/insts/branch.isa +++ b/src/arch/arm/isa/insts/branch.isa @@ -46,15 +46,17 @@ let {{ # B, BL for (mnem, link) in (("b", False), ("bl", True)): bCode = ''' - Addr curPc = readPC(xc); - NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32)); + ArmISA::PCState pc = PCS; + Addr curPc = pc.instPC(); + pc.instNPC((uint32_t)(curPc + imm)); + PCS = pc; ''' if (link): bCode += ''' - if (!isThumb(curPc)) - LR = curPc - 4; - else + if (pc.thumb()) LR = curPc | 1; + else + LR = curPc - 4; ''' bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond", @@ -66,10 +68,12 @@ let {{ # BX, BLX blxCode = ''' - Addr curPc M5_VAR_USED = readPC(xc); + ArmISA::PCState pc = PCS; + Addr curPc M5_VAR_USED = pc.instPC(); %(link)s // Switch modes %(branch)s + PCS = pc; ''' blxList = (("blx", True, True), @@ -81,8 +85,8 @@ let {{ if imm: Name += "Imm" # Since we're switching ISAs, the target ISA will be the opposite - # of the current ISA. !arm is whether the target is ARM. - newPC = '(isThumb(curPc) ? (roundDown(curPc, 4) + imm) : (curPc + imm))' + # of the current ISA. pc.thumb() is whether the target is ARM. + newPC = '(pc.thumb() ? (roundDown(curPc, 4) + imm) : (curPc + imm))' base = "BranchImmCond" declare = BranchImmCondDeclare constructor = BranchImmCondConstructor @@ -97,28 +101,28 @@ let {{ // The immediate version of the blx thumb instruction // is 32 bits wide, but "next pc" doesn't reflect that // so we don't want to substract 2 from it at this point - if (!isThumb(curPc)) - LR = curPc - 4; - else + if (pc.thumb()) LR = curPc | 1; + else + LR = curPc - 4; ''' elif link: linkStr = ''' - if (!isThumb(curPc)) - LR = curPc - 4; - else + if (pc.thumb()) LR = (curPc - 2) | 1; + else + LR = curPc - 4; ''' else: linkStr = "" if imm and link: #blx with imm branchStr = ''' - Addr tempPc = ((%(newPC)s) & mask(32)) | (curPc & ~mask(32)); - FNPC = tempPc ^ PcTBit; + pc.nextThumb(!pc.thumb()); + pc.instNPC(%(newPC)s); ''' else: - branchStr = "IWNPC = %(newPC)s;" + branchStr = "pc.instIWNPC(%(newPC)s);" branchStr = branchStr % { "newPC" : newPC } code = blxCode % {"link": linkStr, @@ -136,8 +140,10 @@ let {{ #CBNZ, CBZ. These are always unconditional as far as predicates for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")): code = ''' - Addr curPc = readPC(xc); - NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32)); + ArmISA::PCState pc = PCS; + Addr curPc = pc.instPC(); + pc.instNPC((uint32_t)(curPc + imm)); + PCS = pc; ''' predTest = "Op1 %(test)s 0" % {"test": test} iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg", @@ -155,7 +161,11 @@ let {{ ArmISA::TLB::MustBeOne; EA = Op1 + Op2 * 2 ''' - accCode = "NPC = readPC(xc) + 2 * (Mem.uh);" + accCode = ''' + ArmISA::PCState pc = PCS; + pc.instNPC(pc.instPC() + 2 * (Mem.uh)); + PCS = pc; + ''' mnem = "tbh" else: eaCode = ''' @@ -164,7 +174,11 @@ let {{ ArmISA::TLB::MustBeOne; EA = Op1 + Op2 ''' - accCode = "NPC = readPC(xc) + 2 * (Mem.ub);" + accCode = ''' + ArmISA::PCState pc = PCS; + pc.instNPC(pc.instPC() + 2 * (Mem.ub)); + PCS = pc; + ''' mnem = "tbb" iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg", {'ea_code': eaCode, diff --git a/src/arch/arm/isa/insts/data.isa b/src/arch/arm/isa/insts/data.isa index 74eeee3b2..4d368e181 100644 --- a/src/arch/arm/isa/insts/data.isa +++ b/src/arch/arm/isa/insts/data.isa @@ -239,6 +239,10 @@ let {{ cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; CondCodes = CondCodesMask & newCpsr; + ArmISA::PCState pc = PCS; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; ''' buildImmDataInst(mnem + 's', code, flagType, suffix = "ImmPclr", buildCc = False, @@ -253,7 +257,8 @@ let {{ buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb") buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add") buildImmDataInst("adr", ''' - Dest = resTemp = (readPC(xc) & ~0x3) + + ArmISA::PCState pc = PCS; + Dest = resTemp = (pc.instPC() & ~0x3) + (op1 ? secondOp : -secondOp); ''') buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add") diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa index dc043ed8e..92ad52a6d 100644 --- a/src/arch/arm/isa/insts/ldr.isa +++ b/src/arch/arm/isa/insts/ldr.isa @@ -105,12 +105,16 @@ let {{ accCode = ''' CPSR cpsr = Cpsr; SCTLR sctlr = Sctlr; - NPC = cSwap<uint32_t>(Mem.ud, cpsr.e); + ArmISA::PCState pc = PCS; + pc.instNPC(cSwap<uint32_t>(Mem.ud, cpsr.e)); uint32_t newCpsr = cpsrWriteByInstr(cpsr | CondCodes, cSwap<uint32_t>(Mem.ud >> 32, cpsr.e), 0xF, true, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; CondCodes = CondCodesMask & newCpsr; ''' self.codeBlobs["memacc_code"] = accCode diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa index 6bf789efd..a81050b1e 100644 --- a/src/arch/arm/isa/insts/macromem.isa +++ b/src/arch/arm/isa/insts/macromem.isa @@ -93,7 +93,9 @@ let {{ cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; CondCodes = CondCodesMask & newCpsr; - IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); + ArmISA::PCState pc = PCS; + pc.instIWNPC(cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0)); + PCS = pc; ''' microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 'MicroMemOp', diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index 5742f84ab..1abbc3de1 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -83,6 +83,10 @@ let {{ uint32_t newCpsr = cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; + ArmISA::PCState pc = PCS; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; CondCodes = CondCodesMask & newCpsr; ''' msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp", @@ -107,6 +111,10 @@ let {{ uint32_t newCpsr = cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; + ArmISA::PCState pc = PCS; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; CondCodes = CondCodesMask & newCpsr; ''' msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp", @@ -462,8 +470,12 @@ let {{ decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop) exec_output += PredOpExecute.subst(usada8Iop) + bkptCode = ''' + ArmISA::PCState pc = PCS; + return new PrefetchAbort(pc.pc(), ArmFault::DebugEvent); + ''' bkptIop = InstObjParams("bkpt", "BkptInst", "ArmStaticInst", - "return new PrefetchAbort(PC, ArmFault::DebugEvent);") + bkptCode) header_output += BasicDeclare.subst(bkptIop) decoder_output += BasicConstructor.subst(bkptIop) exec_output += BasicExecute.subst(bkptIop) @@ -638,7 +650,10 @@ let {{ exec_output += PredOpExecute.subst(mcr15UserIop) enterxCode = ''' - FNPC = NPC | PcJBit | PcTBit; + ArmISA::PCState pc = PCS; + pc.nextThumb(true); + pc.nextJazelle(true); + PCS = pc; ''' enterxIop = InstObjParams("enterx", "Enterx", "PredOp", { "code": enterxCode, @@ -648,7 +663,10 @@ let {{ exec_output += PredOpExecute.subst(enterxIop) leavexCode = ''' - FNPC = (NPC & ~PcJBit) | PcTBit; + ArmISA::PCState pc = PCS; + pc.nextThumb(true); + pc.nextJazelle(false); + PCS = pc; ''' leavexIop = InstObjParams("leavex", "Leavex", "PredOp", { "code": leavexCode, diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa index 4f1b7f610..8e856e74d 100644 --- a/src/arch/arm/isa/operands.isa +++ b/src/arch/arm/isa/operands.isa @@ -54,11 +54,10 @@ def operand_types {{ let {{ maybePCRead = ''' - ((%(reg_idx)s == PCReg) ? (readPC(xc) & ~PcModeMask) : - xc->%(func)s(this, %(op_idx)s)) + ((%(reg_idx)s == PCReg) ? readPC(xc) : xc->%(func)s(this, %(op_idx)s)) ''' maybeAlignedPCRead = ''' - ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc) & ~PcModeMask, 4)) : + ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc), 4)) : xc->%(func)s(this, %(op_idx)s)) ''' maybePCWrite = ''' @@ -81,140 +80,133 @@ let {{ xc->%(func)s(this, %(op_idx)s, %(final_val)s); } ''' - - readNPC = 'xc->readNextPC() & ~PcModeMask' - writeNPC = 'setNextPC(xc, %(final_val)s)' - writeIWNPC = 'setIWNextPC(xc, %(final_val)s)' - forceNPC = 'xc->setNextPC(%(final_val)s)' }}; def operands {{ #Abstracted integer reg operands - 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), - 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), - 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 2), - 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 2), - 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 2), - 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 2), - 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 2), - 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 2), - 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 2), - 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 2), - 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 2), - 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 2), - 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 2), - 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 2), - 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 2), - 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 2), - 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 2), - 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 2, + 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3), + 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3), + 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 3), + 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 3), + 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 3), + 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 3), + 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 3), + 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 3), + 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 3), + 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 3), + 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 3), + 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 3), + 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 3), + 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 3), + 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 3), + 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 3), + 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 3), + 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 2, + 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), - 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), - 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 2), - 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 2), - 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 2), - 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3), + 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3), + 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 3), + 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 3), + 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 3), + 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3, maybePCRead, maybeIWPCWrite), - 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3, maybePCRead, maybeAIWPCWrite), 'SpMode': ('IntReg', 'uw', 'intRegInMode((OperatingMode)regMode, INTREG_SP)', - 'IsInteger', 2), - 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 2), - 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 0, + 'IsInteger', 3), + 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 3), + 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 1, maybeAlignedPCRead, maybePCWrite), - 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 2, + 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 2, + 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), - 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), - 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 2), - 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 2), - 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 2), - 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 2), - 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 2), - 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 2), - 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 2), - 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 2), - 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 2), - 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 2), - 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 2), - 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 2), - 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 2), - 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 2), - 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 2), - 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 2), - 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 2, + 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3), + 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3), + 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 3), + 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 3), + 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 3), + 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 3), + 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 3), + 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 3), + 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 3), + 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 3), + 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 3), + 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 3), + 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 3), + 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 3), + 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 3), + 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 3), + 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 3), + 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 3), + 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), - 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), - 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 2), - 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 2), - 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 2), - 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 2, + 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3), + 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3), + 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 3), + 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 3), + 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 3), + 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 2, + 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 2, + 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 2, + 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 2, + 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 2, + 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 3, maybePCRead, maybePCWrite), #General Purpose Integer Reg Operands - 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'R7': ('IntReg', 'uw', '7', 'IsInteger', 2), - 'R0': ('IntReg', 'uw', '0', 'IsInteger', 2), + 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'R7': ('IntReg', 'uw', '7', 'IsInteger', 3), + 'R0': ('IntReg', 'uw', '0', 'IsInteger', 3), - 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 2), - 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 2), + 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 3), + 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 3), 'OptCondCodes': ('IntReg', 'uw', '''(condCode == COND_AL || condCode == COND_UC) ? - INTREG_ZERO : INTREG_CONDCODES''', None, 2), - 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 2), + INTREG_ZERO : INTREG_CONDCODES''', None, 3), + 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 3), #Register fields for microops - 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, + 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 3, maybePCRead, maybeIWPCWrite), - 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 2), - 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 3), + 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 3, maybePCRead, maybePCWrite), #General Purpose Floating Point Reg Operands - 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 2), - 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2), - 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 2), + 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 3), + 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 3), + 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 3), #Memory Operand - 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 2), + 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 3), - 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 1), - 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 2), - 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 2), - 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 2), - 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 2), - 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 2), - 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 2), - 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 2), - 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 2), - 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 2), - 'PC': ('PC', 'ud', None, None, 2), - 'NPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, - readNPC, writeNPC), - 'FNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, - readNPC, forceNPC), - 'IWNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, - readNPC, writeIWNPC), + 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 2), + 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 3), + 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 3), + 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 3), + 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 3), + 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 3), + 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 3), + 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 3), + 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 3), + 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 3), + #PCS needs to have a sorting index (the number at the end) less than all + #the integer registers which might update the PC. That way if the flag + #bits of the pc state are updated and a branch happens through R15, the + #updates are layered properly and the R15 update isn't lost. + 'PCS': ('PCState', 'uw', None, (None, None, 'IsControl'), 0) }}; diff --git a/src/arch/arm/isa_traits.hh b/src/arch/arm/isa_traits.hh index 8d3f0ffe3..f6aa7fcf0 100644 --- a/src/arch/arm/isa_traits.hh +++ b/src/arch/arm/isa_traits.hh @@ -123,15 +123,6 @@ namespace ArmISA INT_FIQ, NumInterruptTypes }; - - // These otherwise unused bits of the PC are used to select a mode - // like the J and T bits of the CPSR. - static const Addr PcJBitShift = 33; - static const Addr PcJBit = ULL(1) << PcJBitShift; - static const Addr PcTBitShift = 34; - static const Addr PcTBit = ULL(1) << PcTBitShift; - static const Addr PcModeMask = (ULL(1) << PcJBitShift) | - (ULL(1) << PcTBitShift); }; using namespace ArmISA; diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc index 7c4e00921..40658976b 100644 --- a/src/arch/arm/linux/system.cc +++ b/src/arch/arm/linux/system.cc @@ -103,8 +103,7 @@ LinuxArmSystem::startup() ThreadContext *tc = threadContexts[0]; // Set the initial PC to be at start of the kernel code - tc->setPC(tc->getSystemPtr()->kernelEntry & loadAddrMask); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); + tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask); // Setup the machine type tc->setIntReg(0, 0); diff --git a/src/arch/arm/nativetrace.cc b/src/arch/arm/nativetrace.cc index d97be88a2..75546f8de 100644 --- a/src/arch/arm/nativetrace.cc +++ b/src/arch/arm/nativetrace.cc @@ -106,7 +106,7 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc) } //R15, aliased with the PC - newState[STATE_PC] = tc->readNextPC(); + newState[STATE_PC] = tc->pcState().npc(); changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]); //CPSR @@ -121,7 +121,7 @@ Trace::ArmNativeTrace::check(NativeTraceRecord *record) ThreadContext *tc = record->getThread(); // This area is read only on the target. It can't stop there to tell us // what's going on, so we should skip over anything there also. - if (tc->readNextPC() > 0xffff0000) + if (tc->nextInstAddr() > 0xffff0000) return; nState.update(this); mState.update(tc); diff --git a/src/arch/arm/predecoder.cc b/src/arch/arm/predecoder.cc index 04cec59b9..456b9e4c4 100644 --- a/src/arch/arm/predecoder.cc +++ b/src/arch/arm/predecoder.cc @@ -148,11 +148,11 @@ Predecoder::process() //Use this to give data to the predecoder. This should be used //when there is control flow. void -Predecoder::moreBytes(Addr pc, Addr fetchPC, MachInst inst) +Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) { data = inst; - offset = (fetchPC >= pc) ? 0 : pc - fetchPC; - emi.thumb = isThumb(pc); + offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; + emi.thumb = pc.thumb(); FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR); emi.fpscrLen = fpscr.len; emi.fpscrStride = fpscr.stride; diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh index 2db550024..47242b8ff 100644 --- a/src/arch/arm/predecoder.hh +++ b/src/arch/arm/predecoder.hh @@ -94,7 +94,7 @@ namespace ArmISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, MachInst inst); + void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst); //Use this to give data to the predecoder. This should be used //when instructions are executed in order. @@ -121,9 +121,10 @@ namespace ArmISA } //This returns a constant reference to the ExtMachInst to avoid a copy - ExtMachInst getExtMachInst() + ExtMachInst getExtMachInst(PCState &pc) { ExtMachInst thisEmi = emi; + pc.npc(pc.pc() + getInstSize()); emi = 0; return thisEmi; } diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index bc2aee4c8..a5460ac19 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -360,11 +360,11 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) tc->setIntReg(ArgumentReg2, 0); } - Addr prog_entry = objFile->entryPoint(); - if (arch == ObjectFile::Thumb) - prog_entry = (prog_entry & ~mask(1)) | PcTBit; - tc->setPC(prog_entry); - tc->setNextPC(prog_entry + sizeof(MachInst)); + PCState pc; + pc.thumb(arch == ObjectFile::Thumb); + pc.nextThumb(pc.thumb()); + pc.set(objFile->entryPoint() & ~mask(1)); + tc->pcState(pc); //Align the "stack_min" to a page boundary. stack_min = roundDown(stack_min, pageSize); diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh index fe5ba6447..c64673df5 100644 --- a/src/arch/arm/system.hh +++ b/src/arch/arm/system.hh @@ -70,7 +70,7 @@ class ArmSystem : public System // Remove the low bit that thumb symbols have set // but that aren't actually odd aligned if (addr & 0x1) - return (addr & ~1) | PcTBit; + return addr & ~1; return addr; } }; diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 73dd24e1c..06bb10219 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -107,7 +107,7 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _ /** @todo These should be cached or grabbed from cached copies in the TLB, all these miscreg reads are expensive */ - currState->vaddr = currState->req->getVaddr() & ~PcModeMask; + currState->vaddr = currState->req->getVaddr(); currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR); sctlr = currState->sctlr; currState->N = currState->tc->readMiscReg(MISCREG_TTBCR); diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index c0ebb52b2..239d5d8a2 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -316,7 +316,7 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing) { // XXX Cache misc registers and have miscreg write function inv cache - Addr vaddr = req->getVaddr() & ~PcModeMask; + Addr vaddr = req->getVaddr(); SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); uint32_t flags = req->getFlags(); @@ -362,7 +362,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing) { // XXX Cache misc registers and have miscreg write function inv cache - Addr vaddr = req->getVaddr() & ~PcModeMask; + Addr vaddr = req->getVaddr(); SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); uint32_t flags = req->getFlags(); diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 3c3b29494..57f34e3c2 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -43,8 +43,10 @@ #ifndef __ARCH_ARM_TYPES_HH__ #define __ARCH_ARM_TYPES_HH__ +#include "arch/generic/types.hh" #include "base/bitunion.hh" #include "base/hashmap.hh" +#include "base/misc.hh" #include "base/types.hh" namespace ArmISA @@ -188,6 +190,189 @@ namespace ArmISA Bitfield<11, 8> ltcoproc; EndBitUnion(ExtMachInst) + class PCState : public GenericISA::UPCState<MachInst> + { + protected: + + typedef GenericISA::UPCState<MachInst> Base; + + enum FlagBits { + ThumbBit = (1 << 0), + JazelleBit = (1 << 1) + }; + uint8_t flags; + uint8_t nextFlags; + + public: + PCState() : flags(0), nextFlags(0) + {} + + void + set(Addr val) + { + Base::set(val); + npc(val + (thumb() ? 2 : 4)); + } + + PCState(Addr val) : flags(0), nextFlags(0) + { set(val); } + + bool + thumb() const + { + return flags & ThumbBit; + } + + void + thumb(bool val) + { + if (val) + flags |= ThumbBit; + else + flags &= ~ThumbBit; + } + + bool + nextThumb() const + { + return nextFlags & ThumbBit; + } + + void + nextThumb(bool val) + { + if (val) + nextFlags |= ThumbBit; + else + nextFlags &= ~ThumbBit; + } + + bool + jazelle() const + { + return flags & JazelleBit; + } + + void + jazelle(bool val) + { + if (val) + flags |= JazelleBit; + else + flags &= ~JazelleBit; + } + + bool + nextJazelle() const + { + return nextFlags & JazelleBit; + } + + void + nextJazelle(bool val) + { + if (val) + nextFlags |= JazelleBit; + else + nextFlags &= ~JazelleBit; + } + + void + advance() + { + Base::advance(); + npc(pc() + (thumb() ? 2 : 4)); + flags = nextFlags; + } + + void + uEnd() + { + advance(); + upc(0); + nupc(1); + } + + Addr + instPC() const + { + return pc() + (thumb() ? 4 : 8); + } + + void + instNPC(uint32_t val) + { + npc(val &~ mask(nextThumb() ? 1 : 2)); + } + + Addr + instNPC() const + { + return npc(); + } + + // Perform an interworking branch. + void + instIWNPC(uint32_t val) + { + bool thumbEE = (thumb() && jazelle()); + + Addr newPC = val; + if (thumbEE) { + if (bits(newPC, 0)) { + newPC = newPC & ~mask(1); + } else { + panic("Bad thumbEE interworking branch address %#x.\n", + newPC); + } + } else { + if (bits(newPC, 0)) { + nextThumb(true); + newPC = newPC & ~mask(1); + } else if (!bits(newPC, 1)) { + nextThumb(false); + } else { + warn("Bad interworking branch address %#x.\n", newPC); + } + } + npc(newPC); + } + + // Perform an interworking branch in ARM mode, a regular branch + // otherwise. + void + instAIWNPC(uint32_t val) + { + if (!thumb() && !jazelle()) + instIWNPC(val); + else + instNPC(val); + } + + bool + operator == (const PCState &opc) const + { + return Base::operator == (opc) && + flags == opc.flags && nextFlags == opc.nextFlags; + } + + void + serialize(std::ostream &os) + { + Base::serialize(os); + SERIALIZE_SCALAR(flags); + SERIALIZE_SCALAR(nextFlags); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + Base::unserialize(cp, section); + UNSERIALIZE_SCALAR(flags); + UNSERIALIZE_SCALAR(nextFlags); + } + }; + // Shift types for ARM instructions enum ArmShiftType { LSL = 0, diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 7609b3991..a114ec5e0 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -128,13 +128,9 @@ readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2) void skipFunction(ThreadContext *tc) { - Addr newpc = tc->readIntReg(ReturnAddressReg); - newpc &= ~ULL(1); - if (isThumb(tc->readPC())) - tc->setPC(newpc | PcTBit); - else - tc->setPC(newpc); - tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst)); + TheISA::PCState newPC = tc->pcState(); + newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1)); + tc->pcState(newPC); } diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 571a74ef8..a92ab072c 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -51,10 +51,19 @@ #include "base/misc.hh" #include "base/trace.hh" #include "base/types.hh" +#include "cpu/static_inst.hh" #include "cpu/thread_context.hh" namespace ArmISA { + inline PCState + buildRetPC(const PCState &curPC, const PCState &callPC) + { + PCState retPC = callPC; + retPC.uEnd(); + return retPC; + } + inline bool testPredicate(CPSR cpsr, ConditionCode code) { @@ -93,12 +102,6 @@ namespace ArmISA { tc->activate(0); } - static inline bool - isThumb(Addr pc) - { - return (pc & PcTBit); - } - static inline void copyRegs(ThreadContext *src, ThreadContext *dest) { @@ -163,6 +166,12 @@ Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2); void skipFunction(ThreadContext *tc); +inline void +advancePC(PCState &pc, const StaticInstPtr inst) +{ + inst->advancePC(pc); +} + }; |