diff options
author | Matt Horsnell <Matt.Horsnell@arm.com> | 2011-01-18 16:30:05 -0600 |
---|---|---|
committer | Matt Horsnell <Matt.Horsnell@arm.com> | 2011-01-18 16:30:05 -0600 |
commit | b13a79ee717b876e4bc837ba95985abd4d18162f (patch) | |
tree | cc11aa8c68e1a22854f2201bf6073e69db88e84e /src/arch/arm | |
parent | c98df6f8c2f3a3685fd9210ccaee2fac07e4f604 (diff) | |
download | gem5-b13a79ee717b876e4bc837ba95985abd4d18162f.tar.xz |
O3: Fix some variable length instruction issues with the O3 CPU and ARM ISA.
Diffstat (limited to 'src/arch/arm')
-rw-r--r-- | src/arch/arm/predecoder.cc | 15 | ||||
-rw-r--r-- | src/arch/arm/predecoder.hh | 22 |
2 files changed, 29 insertions, 8 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 <cassert> + #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; } }; |