O3: Fix some variable length instruction issues with the O3 CPU and ARM ISA.
This commit is contained in:
parent
c98df6f8c2
commit
b13a79ee71
3 changed files with 39 additions and 12 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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 =
|
||||
|
|
Loading…
Reference in a new issue