ARM: Implement support for the IT instruction and the ITSTATE bits of CPSR.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:16 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:16 +0000 (12:58 -0500)
12 files changed:
src/arch/arm/isa.cc
src/arch/arm/isa/formats/data.isa
src/arch/arm/isa/insts/macromem.isa
src/arch/arm/isa/insts/misc.isa
src/arch/arm/isa/operands.isa
src/arch/arm/isa/templates/mem.isa
src/arch/arm/isa/templates/pred.isa
src/arch/arm/miscregs.hh
src/arch/arm/predecoder.hh
src/arch/arm/types.hh
src/arch/arm/utility.hh
src/cpu/simple/base.cc

index 8446962a26f4129977db1832b4f862a7e1e3e0ff..be9e19844102e97e33e478208a3a80b9d97c423d 100644 (file)
@@ -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);
 }
index 3e6265d0bf5e896a7f6f6a9bef2f140d35524679..a1d0c53a29a093730de527628b0a7de41e6e6a46 100644 (file)
@@ -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);
index 82e9d98424174148639705c2177a9bd41d0b70a5..2b42dfac828eab672c8613fcf9a71bde161631f6 100644 (file)
 // Load/store microops
 //
 
-let {{
-    predicateTest = 'testPredicate(CondCodes, condCode)'
-}};
-
 let {{
     microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
     microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
index 722b05eac25edf46afc346959e66b13a465b7bcd..ee6330f48f8da39aff49f49328adc0376c4fe6c7 100644 (file)
@@ -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);
index 4c269276a522d789f524dff9bfd3fbd0646919ba..b041cef43b19c811900c2f9697147b5f90a56afe 100644 (file)
@@ -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),
index 983d99af99f09eac74308265621af938610cfc08..4f1235b03440a13669c14c03374400d2c00c8eb1 100644 (file)
@@ -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;
     }
 }};
index 15d34da19cf2a2d94c5943c59655173889f5475d..c8f30ddf041ecf2cf551f0d96cf17d6fb1364039 100644 (file)
 //
 
 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;
     }
 }};
index ddb4ea9343004f1e6cde0a4419bef10002079700..ad8f01dd02216586fbe496e89039be95f45c47e5 100644 (file)
@@ -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;
index a7519975568ce537f971396d00ca62a43965d47d..f146c30f49df640ceb0159e1b3278e7ee6db6783 100644 (file)
@@ -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();
         }
 
index 95e5a18a0ef1c239b156445b5e03d24631ce999a..dd6b7e610034850e606f46e5fbdf17245253454e 100644 (file)
@@ -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;
index b2c678c46a63cd7db9c6a63ab2d3cec720a6c788..7d70b31311f234dbf07538d18ad191cfa3aa1dcc 100644 (file)
@@ -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"
 
index 7a063d9d7907f6f170eaa87bfd41b3de9028c6b8..713ffd0818f4374e2cc4fc13bde58e9ffc95efe4 100644 (file)
@@ -357,10 +357,10 @@ BaseSimpleCPU::checkForInterrupts()
         Fault interrupt = interrupts->getInterrupt(tc);
 
         if (interrupt != NoFault) {
-            predecoder.reset();
             fetchOffset = 0;
             interrupts->updateIntrInfo(tc);
             interrupt->invoke(tc);
+            predecoder.reset();
         }
     }
 #endif
@@ -508,8 +508,8 @@ BaseSimpleCPU::advancePC(Fault fault)
     fetchOffset = 0;
     if (fault != NoFault) {
         curMacroStaticInst = StaticInst::nullStaticInstPtr;
-        predecoder.reset();
         fault->invoke(tc);
+        predecoder.reset();
     } else {
         //If we're at the last micro op for this instruction
         if (curStaticInst && curStaticInst->isLastMicroop()) {