summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/faults.cc34
-rw-r--r--src/arch/arm/insts/macromem.hh12
-rw-r--r--src/arch/arm/insts/mem.hh38
-rw-r--r--src/arch/arm/insts/pred_inst.hh11
-rw-r--r--src/arch/arm/insts/static_inst.hh62
-rw-r--r--src/arch/arm/insts/vfp.hh12
-rw-r--r--src/arch/arm/isa.cc25
-rw-r--r--src/arch/arm/isa/formats/breakpoint.isa2
-rw-r--r--src/arch/arm/isa/insts/branch.isa56
-rw-r--r--src/arch/arm/isa/insts/data.isa7
-rw-r--r--src/arch/arm/isa/insts/ldr.isa6
-rw-r--r--src/arch/arm/isa/insts/macromem.isa4
-rw-r--r--src/arch/arm/isa/insts/misc.isa24
-rw-r--r--src/arch/arm/isa/operands.isa204
-rw-r--r--src/arch/arm/isa_traits.hh9
-rw-r--r--src/arch/arm/linux/system.cc3
-rw-r--r--src/arch/arm/nativetrace.cc4
-rw-r--r--src/arch/arm/predecoder.cc6
-rw-r--r--src/arch/arm/predecoder.hh5
-rw-r--r--src/arch/arm/process.cc10
-rw-r--r--src/arch/arm/system.hh2
-rw-r--r--src/arch/arm/table_walker.cc2
-rw-r--r--src/arch/arm/tlb.cc4
-rw-r--r--src/arch/arm/types.hh185
-rw-r--r--src/arch/arm/utility.cc10
-rw-r--r--src/arch/arm/utility.hh21
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 &section)
+ {
+ 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);
+}
+
};