O3: Fix some variable length instruction issues with the O3 CPU and ARM ISA.

This commit is contained in:
Matt Horsnell 2011-01-18 16:30:05 -06:00
parent c98df6f8c2
commit b13a79ee71
3 changed files with 39 additions and 12 deletions

View file

@ -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();
}

View file

@ -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;
}
};

View file

@ -384,7 +384,7 @@ DefaultFetch<Impl>::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<Impl>::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<Impl>::fetch(bool &status_change)
ExtMachInst extMachInst;
extMachInst = predecoder.getExtMachInst(thisPC);
pcOffset = 0;
staticInst = StaticInstPtr(extMachInst,
thisPC.instAddr());
@ -1188,7 +1187,12 @@ DefaultFetch<Impl>::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<Impl>::fetch(bool &status_change)
}
if (curMacroop) {
staticInst = curMacroop->fetchMicroop(thisPC.microPC());
if (staticInst->isLastMicroop())
if (staticInst->isLastMicroop()) {
curMacroop = NULL;
pcOffset = 0;
}
}
DynInstPtr instruction =