diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:58:16 -0500 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:58:16 -0500 |
commit | 05bd3eb4ec3d9fea3dbc46112a47459085d3011c (patch) | |
tree | 58d50fab58de1e9165bfc28986913811b26b9568 /src/arch/arm | |
parent | b93ceef5381b7c84b6887b5299ae81ff48ef45c9 (diff) | |
download | gem5-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.cc | 230 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/data.isa | 148 | ||||
-rw-r--r-- | src/arch/arm/isa/insts/macromem.isa | 4 | ||||
-rw-r--r-- | src/arch/arm/isa/insts/misc.isa | 12 | ||||
-rw-r--r-- | src/arch/arm/isa/operands.isa | 1 | ||||
-rw-r--r-- | src/arch/arm/isa/templates/mem.isa | 44 | ||||
-rw-r--r-- | src/arch/arm/isa/templates/pred.isa | 10 | ||||
-rw-r--r-- | src/arch/arm/miscregs.hh | 11 | ||||
-rw-r--r-- | src/arch/arm/predecoder.hh | 63 | ||||
-rw-r--r-- | src/arch/arm/types.hh | 6 | ||||
-rw-r--r-- | src/arch/arm/utility.hh | 1 |
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" |