summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:16 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:16 -0500
commit05bd3eb4ec3d9fea3dbc46112a47459085d3011c (patch)
tree58d50fab58de1e9165bfc28986913811b26b9568 /src/arch/arm
parentb93ceef5381b7c84b6887b5299ae81ff48ef45c9 (diff)
downloadgem5-05bd3eb4ec3d9fea3dbc46112a47459085d3011c.tar.xz
ARM: Implement support for the IT instruction and the ITSTATE bits of CPSR.
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/isa.cc230
-rw-r--r--src/arch/arm/isa/formats/data.isa148
-rw-r--r--src/arch/arm/isa/insts/macromem.isa4
-rw-r--r--src/arch/arm/isa/insts/misc.isa12
-rw-r--r--src/arch/arm/isa/operands.isa1
-rw-r--r--src/arch/arm/isa/templates/mem.isa44
-rw-r--r--src/arch/arm/isa/templates/pred.isa10
-rw-r--r--src/arch/arm/miscregs.hh11
-rw-r--r--src/arch/arm/predecoder.hh63
-rw-r--r--src/arch/arm/types.hh6
-rw-r--r--src/arch/arm/utility.hh1
11 files changed, 382 insertions, 148 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index 8446962a2..be9e19844 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -159,121 +159,133 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
npc = npc | (ULL(1) << PcTBitShift);
tc->setNextPC(npc);
- }
- if (misc_reg >= MISCREG_CP15_UNIMP_START &&
+ } else if (misc_reg >= MISCREG_CP15_UNIMP_START &&
misc_reg < MISCREG_CP15_END) {
panic("Unimplemented CP15 register %s wrote with %#x.\n",
miscRegName[misc_reg], val);
- }
- switch (misc_reg) {
- case MISCREG_CPACR:
- {
- CPACR newCpacr = 0;
- CPACR valCpacr = val;
- newCpacr.cp10 = valCpacr.cp10;
- newCpacr.cp11 = valCpacr.cp11;
- if (newCpacr.cp10 != 0x3 || newCpacr.cp11 != 3) {
- panic("Disabling coprocessors isn't implemented.\n");
+ } else {
+ switch (misc_reg) {
+ case MISCREG_ITSTATE:
+ {
+ ITSTATE itstate = newVal;
+ CPSR cpsr = miscRegs[MISCREG_CPSR];
+ cpsr.it1 = itstate.bottom2;
+ cpsr.it2 = itstate.top6;
+ miscRegs[MISCREG_CPSR] = cpsr;
+ DPRINTF(MiscRegs,
+ "Updating ITSTATE -> %#x in CPSR -> %#x.\n",
+ (uint8_t)itstate, (uint32_t)cpsr);
}
- newVal = newCpacr;
- }
- break;
- case MISCREG_CSSELR:
- warn("The csselr register isn't implemented.\n");
- break;
- case MISCREG_FPSCR:
- {
- const uint32_t ones = (uint32_t)(-1);
- FPSCR fpscrMask = 0;
- fpscrMask.ioc = ones;
- fpscrMask.dzc = ones;
- fpscrMask.ofc = ones;
- fpscrMask.ufc = ones;
- fpscrMask.ixc = ones;
- fpscrMask.idc = ones;
- fpscrMask.len = ones;
- fpscrMask.stride = ones;
- fpscrMask.rMode = ones;
- fpscrMask.fz = ones;
- fpscrMask.dn = ones;
- fpscrMask.ahp = ones;
- fpscrMask.qc = ones;
- fpscrMask.v = ones;
- fpscrMask.c = ones;
- fpscrMask.z = ones;
- fpscrMask.n = ones;
- newVal = (newVal & (uint32_t)fpscrMask) |
- (miscRegs[MISCREG_FPSCR] & ~(uint32_t)fpscrMask);
- }
- break;
- case MISCREG_FPEXC:
- {
- const uint32_t fpexcMask = 0x60000000;
- newVal = (newVal & fpexcMask) |
- (miscRegs[MISCREG_FPEXC] & ~fpexcMask);
- }
- break;
- case MISCREG_SCTLR:
- {
- DPRINTF(MiscRegs, "Writing SCTLR: %#x\n", newVal);
- SCTLR sctlr = miscRegs[MISCREG_SCTLR];
- SCTLR new_sctlr = newVal;
- new_sctlr.nmfi = (bool)sctlr.nmfi;
- miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr;
+ break;
+ case MISCREG_CPACR:
+ {
+ CPACR newCpacr = 0;
+ CPACR valCpacr = val;
+ newCpacr.cp10 = valCpacr.cp10;
+ newCpacr.cp11 = valCpacr.cp11;
+ if (newCpacr.cp10 != 0x3 || newCpacr.cp11 != 3) {
+ panic("Disabling coprocessors isn't implemented.\n");
+ }
+ newVal = newCpacr;
+ }
+ break;
+ case MISCREG_CSSELR:
+ warn("The csselr register isn't implemented.\n");
+ break;
+ case MISCREG_FPSCR:
+ {
+ const uint32_t ones = (uint32_t)(-1);
+ FPSCR fpscrMask = 0;
+ fpscrMask.ioc = ones;
+ fpscrMask.dzc = ones;
+ fpscrMask.ofc = ones;
+ fpscrMask.ufc = ones;
+ fpscrMask.ixc = ones;
+ fpscrMask.idc = ones;
+ fpscrMask.len = ones;
+ fpscrMask.stride = ones;
+ fpscrMask.rMode = ones;
+ fpscrMask.fz = ones;
+ fpscrMask.dn = ones;
+ fpscrMask.ahp = ones;
+ fpscrMask.qc = ones;
+ fpscrMask.v = ones;
+ fpscrMask.c = ones;
+ fpscrMask.z = ones;
+ fpscrMask.n = ones;
+ newVal = (newVal & (uint32_t)fpscrMask) |
+ (miscRegs[MISCREG_FPSCR] & ~(uint32_t)fpscrMask);
+ }
+ break;
+ case MISCREG_FPEXC:
+ {
+ const uint32_t fpexcMask = 0x60000000;
+ newVal = (newVal & fpexcMask) |
+ (miscRegs[MISCREG_FPEXC] & ~fpexcMask);
+ }
+ break;
+ case MISCREG_SCTLR:
+ {
+ DPRINTF(MiscRegs, "Writing SCTLR: %#x\n", newVal);
+ SCTLR sctlr = miscRegs[MISCREG_SCTLR];
+ SCTLR new_sctlr = newVal;
+ new_sctlr.nmfi = (bool)sctlr.nmfi;
+ miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr;
+ return;
+ }
+ case MISCREG_TLBTR:
+ case MISCREG_MVFR0:
+ case MISCREG_MVFR1:
+ case MISCREG_MPIDR:
+ case MISCREG_FPSID:
+ return;
+ case MISCREG_TLBIALLIS:
+ case MISCREG_TLBIALL:
+ warn("Need to flush all TLBs in MP\n");
+ tc->getITBPtr()->flushAll();
+ tc->getDTBPtr()->flushAll();
+ return;
+ case MISCREG_ITLBIALL:
+ tc->getITBPtr()->flushAll();
+ return;
+ case MISCREG_DTLBIALL:
+ tc->getDTBPtr()->flushAll();
+ return;
+ case MISCREG_TLBIMVAIS:
+ case MISCREG_TLBIMVA:
+ warn("Need to flush all TLBs in MP\n");
+ tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
+ bits(newVal, 7,0));
+ tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
+ bits(newVal, 7,0));
+ return;
+ case MISCREG_TLBIASIDIS:
+ case MISCREG_TLBIASID:
+ warn("Need to flush all TLBs in MP\n");
+ tc->getITBPtr()->flushAsid(bits(newVal, 7,0));
+ tc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
+ return;
+ case MISCREG_TLBIMVAAIS:
+ case MISCREG_TLBIMVAA:
+ warn("Need to flush all TLBs in MP\n");
+ tc->getITBPtr()->flushMva(mbits(newVal, 31,12));
+ tc->getDTBPtr()->flushMva(mbits(newVal, 31,12));
+ return;
+ case MISCREG_ITLBIMVA:
+ tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
+ bits(newVal, 7,0));
+ return;
+ case MISCREG_DTLBIMVA:
+ tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
+ bits(newVal, 7,0));
+ return;
+ case MISCREG_ITLBIASID:
+ tc->getITBPtr()->flushAsid(bits(newVal, 7,0));
+ return;
+ case MISCREG_DTLBIASID:
+ tc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
return;
}
- case MISCREG_TLBTR:
- case MISCREG_MVFR0:
- case MISCREG_MVFR1:
- case MISCREG_MPIDR:
- case MISCREG_FPSID:
- return;
- case MISCREG_TLBIALLIS:
- case MISCREG_TLBIALL:
- warn("Need to flush all TLBs in MP\n");
- tc->getITBPtr()->flushAll();
- tc->getDTBPtr()->flushAll();
- return;
- case MISCREG_ITLBIALL:
- tc->getITBPtr()->flushAll();
- return;
- case MISCREG_DTLBIALL:
- tc->getDTBPtr()->flushAll();
- return;
- case MISCREG_TLBIMVAIS:
- case MISCREG_TLBIMVA:
- warn("Need to flush all TLBs in MP\n");
- tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
- bits(newVal, 7,0));
- tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
- bits(newVal, 7,0));
- return;
- case MISCREG_TLBIASIDIS:
- case MISCREG_TLBIASID:
- warn("Need to flush all TLBs in MP\n");
- tc->getITBPtr()->flushAsid(bits(newVal, 7,0));
- tc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
- return;
- case MISCREG_TLBIMVAAIS:
- case MISCREG_TLBIMVAA:
- warn("Need to flush all TLBs in MP\n");
- tc->getITBPtr()->flushMva(mbits(newVal, 31,12));
- tc->getDTBPtr()->flushMva(mbits(newVal, 31,12));
- return;
- case MISCREG_ITLBIMVA:
- tc->getITBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
- bits(newVal, 7,0));
- return;
- case MISCREG_DTLBIMVA:
- tc->getDTBPtr()->flushMvaAsid(mbits(newVal, 31, 12),
- bits(newVal, 7,0));
- return;
- case MISCREG_ITLBIASID:
- tc->getITBPtr()->flushAsid(bits(newVal, 7,0));
- return;
- case MISCREG_DTLBIASID:
- tc->getDTBPtr()->flushAsid(bits(newVal, 7,0));
- return;
}
setMiscRegNoEffect(misc_reg, newVal);
}
diff --git a/src/arch/arm/isa/formats/data.isa b/src/arch/arm/isa/formats/data.isa
index 3e6265d0b..a1d0c53a2 100644
--- a/src/arch/arm/isa/formats/data.isa
+++ b/src/arch/arm/isa/formats/data.isa
@@ -852,30 +852,70 @@ def format Thumb16ShiftAddSubMoveCmp() {{
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
switch (bits(machInst, 13, 11)) {
case 0x0: // lsl
- return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
+ if (machInst.itstateMask) {
+ return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
+ } else {
+ return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
+ }
case 0x1: // lsr
- return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
+ if (machInst.itstateMask) {
+ return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
+ } else {
+ return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
+ }
case 0x2: // asr
- return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
+ if (machInst.itstateMask) {
+ return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
+ } else {
+ return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
+ }
case 0x3:
switch (bits(machInst, 10, 9)) {
case 0x0:
- return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new AddReg(machInst, rd, rn, rm, 0, LSL);
+ } else {
+ return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
+ }
case 0x1:
- return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new SubReg(machInst, rd, rn, rm, 0, LSL);
+ } else {
+ return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
+ }
case 0x2:
- return new AddImmCc(machInst, rd, rn, imm3, true);
+ if (machInst.itstateMask) {
+ return new AddImm(machInst, rd, rn, imm3, true);
+ } else {
+ return new AddImmCc(machInst, rd, rn, imm3, true);
+ }
case 0x3:
- return new SubImmCc(machInst, rd, rn, imm3, true);
+ if (machInst.itstateMask) {
+ return new SubImm(machInst, rd, rn, imm3, true);
+ } else {
+ return new SubImmCc(machInst, rd, rn, imm3, true);
+ }
}
case 0x4:
- return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
+ if (machInst.itstateMask) {
+ return new MovImm(machInst, rd8, INTREG_ZERO, imm8, false);
+ } else {
+ return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
+ }
case 0x5:
return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
case 0x6:
- return new AddImmCc(machInst, rd8, rd8, imm8, true);
+ if (machInst.itstateMask) {
+ return new AddImm(machInst, rd8, rd8, imm8, true);
+ } else {
+ return new AddImmCc(machInst, rd8, rd8, imm8, true);
+ }
case 0x7:
- return new SubImmCc(machInst, rd8, rd8, imm8, true);
+ if (machInst.itstateMask) {
+ return new SubImm(machInst, rd8, rd8, imm8, true);
+ } else {
+ return new SubImmCc(machInst, rd8, rd8, imm8, true);
+ }
}
}
'''
@@ -888,37 +928,97 @@ def format Thumb16DataProcessing() {{
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
switch (bits(machInst, 9, 6)) {
case 0x0:
- return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new AndReg(machInst, rdn, rdn, rm, 0, LSL);
+ } else {
+ return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ }
case 0x1:
- return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new EorReg(machInst, rdn, rdn, rm, 0, LSL);
+ } else {
+ return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ }
case 0x2: //lsl
- return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSL);
+ if (machInst.itstateMask) {
+ return new MovRegReg(machInst, rdn,
+ INTREG_ZERO, rdn, rm, LSL);
+ } else {
+ return new MovRegRegCc(machInst, rdn,
+ INTREG_ZERO, rdn, rm, LSL);
+ }
case 0x3: //lsr
- return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSR);
+ if (machInst.itstateMask) {
+ return new MovRegReg(machInst, rdn,
+ INTREG_ZERO, rdn, rm, LSR);
+ } else {
+ return new MovRegRegCc(machInst, rdn,
+ INTREG_ZERO, rdn, rm, LSR);
+ }
case 0x4: //asr
- return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ASR);
+ if (machInst.itstateMask) {
+ return new MovRegReg(machInst, rdn,
+ INTREG_ZERO, rdn, rm, ASR);
+ } else {
+ return new MovRegRegCc(machInst, rdn,
+ INTREG_ZERO, rdn, rm, ASR);
+ }
case 0x5:
- return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new AdcReg(machInst, rdn, rdn, rm, 0, LSL);
+ } else {
+ return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ }
case 0x6:
- return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new SbcReg(machInst, rdn, rdn, rm, 0, LSL);
+ } else {
+ return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ }
case 0x7: // ror
- return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ROR);
+ if (machInst.itstateMask) {
+ return new MovRegReg(machInst, rdn,
+ INTREG_ZERO, rdn, rm, ROR);
+ } else {
+ return new MovRegRegCc(machInst, rdn,
+ INTREG_ZERO, rdn, rm, ROR);
+ }
case 0x8:
return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
case 0x9:
- return new RsbImmCc(machInst, rdn, rm, 0, true);
+ if (machInst.itstateMask) {
+ return new RsbImm(machInst, rdn, rm, 0, true);
+ } else {
+ return new RsbImmCc(machInst, rdn, rm, 0, true);
+ }
case 0xa:
return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
case 0xb:
return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
case 0xc:
- return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new OrrReg(machInst, rdn, rdn, rm, 0, LSL);
+ } else {
+ return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ }
case 0xd:
- return new MulCc(machInst, rdn, rm, rdn);
+ if (machInst.itstateMask) {
+ return new Mul(machInst, rdn, rm, rdn);
+ } else {
+ return new MulCc(machInst, rdn, rm, rdn);
+ }
case 0xe:
- return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new BicReg(machInst, rdn, rdn, rm, 0, LSL);
+ } else {
+ return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
+ }
case 0xf:
- return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
+ if (machInst.itstateMask) {
+ return new MvnReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
+ } else {
+ return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
+ }
}
}
'''
@@ -1070,7 +1170,7 @@ def format Thumb16Misc() {{
return new WarnUnimplemented("bkpt", machInst);
case 0xf:
if (bits(machInst, 3, 0) != 0)
- return new WarnUnimplemented("it", machInst);
+ return new ItInst(machInst);
switch (bits(machInst, 7, 4)) {
case 0x0:
return new NopInst(machInst);
diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa
index 82e9d9842..2b42dfac8 100644
--- a/src/arch/arm/isa/insts/macromem.isa
+++ b/src/arch/arm/isa/insts/macromem.isa
@@ -47,10 +47,6 @@
//
let {{
- predicateTest = 'testPredicate(CondCodes, condCode)'
-}};
-
-let {{
microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
'MicroMemOp',
diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa
index 722b05eac..ee6330f48 100644
--- a/src/arch/arm/isa/insts/misc.isa
+++ b/src/arch/arm/isa/insts/misc.isa
@@ -456,10 +456,18 @@ let {{
decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop)
exec_output += PredOpExecute.subst(usada8Iop)
- nopIop = InstObjParams("nop", "NopInst", "ArmStaticInst", "", [])
+ nopIop = InstObjParams("nop", "NopInst", "PredOp", \
+ { "code" : "", "predicate_test" : predicateTest })
header_output += BasicDeclare.subst(nopIop)
decoder_output += BasicConstructor.subst(nopIop)
- exec_output += BasicExecute.subst(nopIop)
+ exec_output += PredOpExecute.subst(nopIop)
+
+ itIop = InstObjParams("it", "ItInst", "PredOp", \
+ { "code" : "Itstate = machInst.newItstate;",
+ "predicate_test" : predicateTest })
+ header_output += BasicDeclare.subst(itIop)
+ decoder_output += BasicConstructor.subst(itIop)
+ exec_output += PredOpExecute.subst(itIop)
ubfxCode = '''
Dest = bits(Op1, imm2, imm1);
diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa
index 4c269276a..b041cef43 100644
--- a/src/arch/arm/isa/operands.isa
+++ b/src/arch/arm/isa/operands.isa
@@ -171,6 +171,7 @@ def operands {{
'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 2),
'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),
diff --git a/src/arch/arm/isa/templates/mem.isa b/src/arch/arm/isa/templates/mem.isa
index 983d99af9..4f1235b03 100644
--- a/src/arch/arm/isa/templates/mem.isa
+++ b/src/arch/arm/isa/templates/mem.isa
@@ -71,6 +71,10 @@ def template SwapExecute {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -101,6 +105,10 @@ def template SwapInitiateAcc {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -127,6 +135,10 @@ def template SwapCompleteAcc {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -154,6 +166,10 @@ def template LoadExecute {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -186,6 +202,10 @@ def template StoreExecute {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -224,6 +244,10 @@ def template StoreExExecute {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -257,6 +281,10 @@ def template StoreExInitiateAcc {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -290,6 +318,10 @@ def template StoreInitiateAcc {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -340,6 +372,10 @@ def template LoadCompleteAcc {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -361,6 +397,10 @@ def template StoreCompleteAcc {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
@@ -385,6 +425,10 @@ def template StoreExCompleteAcc {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
diff --git a/src/arch/arm/isa/templates/pred.isa b/src/arch/arm/isa/templates/pred.isa
index 15d34da19..c8f30ddf0 100644
--- a/src/arch/arm/isa/templates/pred.isa
+++ b/src/arch/arm/isa/templates/pred.isa
@@ -46,7 +46,11 @@
//
let {{
- predicateTest = 'testPredicate(CondCodes, condCode)'
+ predicateTest = '''
+ testPredicate(CondCodes, machInst.itstateMask ?
+ (ConditionCode)(uint8_t)machInst.itstateCond :
+ condCode)
+ '''
}};
def template DataImmDeclare {{
@@ -143,6 +147,10 @@ def template PredOpExecute {{
}
}
+ if (fault == NoFault && machInst.itstateMask != 0) {
+ xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+ }
+
return fault;
}
}};
diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh
index ddb4ea934..ad8f01dd0 100644
--- a/src/arch/arm/miscregs.hh
+++ b/src/arch/arm/miscregs.hh
@@ -67,6 +67,7 @@ namespace ArmISA
enum MiscRegIndex {
MISCREG_CPSR = 0,
+ MISCREG_ITSTATE,
MISCREG_SPSR,
MISCREG_SPSR_FIQ,
MISCREG_SPSR_IRQ,
@@ -189,7 +190,7 @@ namespace ArmISA
unsigned crm, unsigned opc2);
const char * const miscRegName[NUM_MISCREGS] = {
- "cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc",
+ "cpsr", "itstate", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc",
"spsr_mon", "spsr_und", "spsr_abt",
"fpsr", "fpsid", "fpscr", "fpexc", "mvfr0", "mvfr1",
"sctlr_rst", "sev_mailbox",
@@ -241,6 +242,14 @@ namespace ArmISA
Bitfield<4, 0> mode;
EndBitUnion(CPSR)
+ BitUnion8(ITSTATE)
+ Bitfield<7, 4> cond;
+ Bitfield<3, 0> mask;
+ // Bitfields for moving to/from CPSR
+ Bitfield<7, 2> top6;
+ Bitfield<1, 0> bottom2;
+ EndBitUnion(ITSTATE)
+
// This mask selects bits of the CPSR that actually go in the CondCodes
// integer register to allow renaming.
static const uint32_t CondCodesMask = 0xF80F0000;
diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh
index a75199755..f146c30f4 100644
--- a/src/arch/arm/predecoder.hh
+++ b/src/arch/arm/predecoder.hh
@@ -62,11 +62,21 @@ namespace ArmISA
MachInst data;
bool bigThumb;
int offset;
+ ITSTATE itstate;
public:
+ void reset()
+ {
+ bigThumb = false;
+ offset = 0;
+ emi = 0;
+ }
+
Predecoder(ThreadContext * _tc) :
- tc(_tc), data(0), bigThumb(false), offset(0)
- {}
+ tc(_tc), data(0)
+ {
+ reset();
+ }
ThreadContext * getTC()
{
@@ -78,11 +88,24 @@ namespace ArmISA
tc = _tc;
}
- void reset()
+ void advanceThumbCond()
{
- bigThumb = false;
- offset = 0;
- emi = 0;
+ uint8_t condMask = itstate.mask;
+ uint8_t thumbCond = itstate.cond;
+ DPRINTF(Predecoder, "Advancing ITSTATE from %#x, %#x.\n",
+ thumbCond, condMask);
+ condMask = condMask << 1;
+ uint8_t newBit = bits(condMask, 4);
+ condMask &= mask(4);
+ if (condMask == 0) {
+ thumbCond = 0;
+ } else {
+ replaceBits(thumbCond, 0, newBit);
+ }
+ DPRINTF(Predecoder, "Advancing ITSTATE to %#x, %#x.\n",
+ thumbCond, condMask);
+ itstate.mask = condMask;
+ itstate.cond = thumbCond;
}
void process()
@@ -92,7 +115,7 @@ namespace ArmISA
emi.sevenAndFour = bits(data, 7) && bits(data, 4);
emi.isMisc = (bits(data, 24, 23) == 0x2 &&
bits(data, 20) == 0);
- DPRINTF(Predecoder, "Arm inst.\n");
+ DPRINTF(Predecoder, "Arm inst: %#x.\n", (uint64_t)emi);
} else {
uint16_t word = (data >> (offset * 8));
if (bigThumb) {
@@ -102,6 +125,11 @@ namespace ArmISA
offset += 2;
DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n",
emi.instBits);
+ if (itstate.mask) {
+ emi.itstate = itstate;
+ advanceThumbCond();
+ emi.newItstate = itstate;
+ }
} else {
uint16_t highBits = word & 0xF800;
if (highBits == 0xE800 || highBits == 0xF000 ||
@@ -114,6 +142,11 @@ namespace ArmISA
DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n",
emi.instBits);
offset += 4;
+ if (itstate.mask) {
+ emi.itstate = itstate;
+ advanceThumbCond();
+ emi.newItstate = itstate;
+ }
} else {
// We only have the first half word.
DPRINTF(Predecoder,
@@ -130,6 +163,19 @@ namespace ArmISA
emi.condCode = COND_UC;
DPRINTF(Predecoder, "16 bit Thumb: %#x.\n",
emi.instBits);
+ if (bits(word, 15, 8) == 0xbf &&
+ bits(word, 3, 0) != 0x0) {
+ emi.itstate = itstate;
+ itstate = bits(word, 7, 0);
+ emi.newItstate = itstate;
+ DPRINTF(Predecoder,
+ "IT detected, cond = %#x, mask = %#x\n",
+ itstate.cond, itstate.mask);
+ } else if (itstate.mask) {
+ emi.itstate = itstate;
+ advanceThumbCond();
+ emi.newItstate = itstate;
+ }
}
}
}
@@ -145,6 +191,9 @@ namespace ArmISA
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;
process();
}
diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh
index 95e5a18a0..dd6b7e610 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -51,6 +51,12 @@ namespace ArmISA
typedef uint32_t MachInst;
BitUnion64(ExtMachInst)
+ Bitfield<63, 56> newItstate;
+ // ITSTATE bits
+ Bitfield<55, 48> itstate;
+ Bitfield<55, 52> itstateCond;
+ Bitfield<51, 48> itstateMask;
+
// FPSCR fields
Bitfield<41, 40> fpscrStride;
Bitfield<39, 37> fpscrLen;
diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh
index b2c678c46..7d70b3131 100644
--- a/src/arch/arm/utility.hh
+++ b/src/arch/arm/utility.hh
@@ -48,6 +48,7 @@
#include "arch/arm/miscregs.hh"
#include "arch/arm/types.hh"
#include "base/hashmap.hh"
+#include "base/trace.hh"
#include "base/types.hh"
#include "cpu/thread_context.hh"