From b13a79ee717b876e4bc837ba95985abd4d18162f Mon Sep 17 00:00:00 2001 From: Matt Horsnell Date: Tue, 18 Jan 2011 16:30:05 -0600 Subject: O3: Fix some variable length instruction issues with the O3 CPU and ARM ISA. --- src/arch/arm/predecoder.cc | 15 +++++++++++---- src/arch/arm/predecoder.hh | 22 ++++++++++++++++++---- src/cpu/o3/fetch_impl.hh | 14 ++++++++++---- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/arch/arm/predecoder.cc b/src/arch/arm/predecoder.cc index 456b9e4c4..71d399e35 100644 --- a/src/arch/arm/predecoder.cc +++ b/src/arch/arm/predecoder.cc @@ -74,11 +74,15 @@ Predecoder::advanceThumbCond() void Predecoder::process() { + // emi is typically ready, with some caveats below... + emiReady = true; + if (!emi.thumb) { emi.instBits = data; emi.sevenAndFour = bits(data, 7) && bits(data, 4); emi.isMisc = (bits(data, 24, 23) == 0x2 && bits(data, 20) == 0); + consumeBytes(4); DPRINTF(Predecoder, "Arm inst: %#x.\n", (uint64_t)emi); } else { uint16_t word = (data >> (offset * 8)); @@ -86,7 +90,7 @@ Predecoder::process() // A 32 bit thumb inst is half collected. emi.instBits = emi.instBits | word; bigThumb = false; - offset += 2; + consumeBytes(2); DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n", emi.instBits); if (itstate.mask) { @@ -105,7 +109,7 @@ Predecoder::process() emi.instBits = (data >> 16) | (data << 16); DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n", emi.instBits); - offset += 4; + consumeBytes(4); if (itstate.mask) { emi.itstate = itstate; advanceThumbCond(); @@ -117,11 +121,13 @@ Predecoder::process() "First half of 32 bit Thumb.\n"); emi.instBits = (uint32_t)word << 16; bigThumb = true; - offset += 2; + consumeBytes(2); + // emi not ready yet. + emiReady = false; } } else { // A 16 bit thumb inst. - offset += 2; + consumeBytes(2); emi.instBits = word; // Set the condition code field artificially. emi.condCode = COND_UC; @@ -159,6 +165,7 @@ Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); itstate.top6 = cpsr.it2; itstate.bottom2 = cpsr.it1; + outOfBytes = false; process(); } diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh index 47242b8ff..92aab6e30 100644 --- a/src/arch/arm/predecoder.hh +++ b/src/arch/arm/predecoder.hh @@ -45,6 +45,8 @@ #ifndef __ARCH_ARM_PREDECODER_HH__ #define __ARCH_ARM_PREDECODER_HH__ +#include + #include "arch/arm/types.hh" #include "arch/arm/miscregs.hh" #include "base/types.hh" @@ -61,6 +63,8 @@ namespace ArmISA ExtMachInst emi; MachInst data; bool bigThumb; + bool emiReady; + bool outOfBytes; int offset; ITSTATE itstate; @@ -70,6 +74,8 @@ namespace ArmISA bigThumb = false; offset = 0; emi = 0; + emiReady = false; + outOfBytes = true; } Predecoder(ThreadContext * _tc) : @@ -103,16 +109,22 @@ namespace ArmISA moreBytes(0, 0, machInst); } + inline void consumeBytes(int numBytes) + { + offset += numBytes; + assert(offset <= sizeof(MachInst)); + if (offset == sizeof(MachInst)) + outOfBytes = true; + } + bool needMoreBytes() { - return sizeof(MachInst) > offset; + return outOfBytes; } bool extMachInstReady() { - // The only way an instruction wouldn't be ready is if this is a - // 32 bit ARM instruction that's not 32 bit aligned. - return !bigThumb; + return emiReady; } int getInstSize() @@ -123,9 +135,11 @@ namespace ArmISA //This returns a constant reference to the ExtMachInst to avoid a copy ExtMachInst getExtMachInst(PCState &pc) { + assert(emiReady); ExtMachInst thisEmi = emi; pc.npc(pc.pc() + getInstSize()); emi = 0; + emiReady = false; return thisEmi; } }; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 736a66c64..927af42c3 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -384,7 +384,7 @@ DefaultFetch::processCacheCompletion(PacketPtr pkt) { ThreadID tid = pkt->req->threadId(); - DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n",tid); + DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n", tid); assert(!pkt->wasNacked()); @@ -1011,7 +1011,7 @@ DefaultFetch::buildInst(ThreadID tid, StaticInstPtr staticInst, instruction->setThreadState(cpu->thread[tid]); DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created " - "[sn:%lli]\n", tid, thisPC.instAddr(), + "[sn:%lli].\n", tid, thisPC.instAddr(), thisPC.microPC(), seq); DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid, @@ -1180,7 +1180,6 @@ DefaultFetch::fetch(bool &status_change) ExtMachInst extMachInst; extMachInst = predecoder.getExtMachInst(thisPC); - pcOffset = 0; staticInst = StaticInstPtr(extMachInst, thisPC.instAddr()); @@ -1188,7 +1187,12 @@ DefaultFetch::fetch(bool &status_change) ++fetchedInsts; if (staticInst->isMacroop()) + { curMacroop = staticInst; + } + else { + pcOffset = 0; + } } else { // We need more bytes for this instruction. break; @@ -1196,8 +1200,10 @@ DefaultFetch::fetch(bool &status_change) } if (curMacroop) { staticInst = curMacroop->fetchMicroop(thisPC.microPC()); - if (staticInst->isLastMicroop()) + if (staticInst->isLastMicroop()) { curMacroop = NULL; + pcOffset = 0; + } } DynInstPtr instruction = -- cgit v1.2.3