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));
// 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) {
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();
"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;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
itstate.top6 = cpsr.it2;
itstate.bottom2 = cpsr.it1;
+ outOfBytes = false;
process();
}
#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"
ExtMachInst emi;
MachInst data;
bool bigThumb;
+ bool emiReady;
+ bool outOfBytes;
int offset;
ITSTATE itstate;
bigThumb = false;
offset = 0;
emi = 0;
+ emiReady = false;
+ outOfBytes = true;
}
Predecoder(ThreadContext * _tc) :
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()
//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;
}
};
{
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());
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,
ExtMachInst extMachInst;
extMachInst = predecoder.getExtMachInst(thisPC);
- pcOffset = 0;
staticInst = StaticInstPtr(extMachInst,
thisPC.instAddr());
++fetchedInsts;
if (staticInst->isMacroop())
+ {
curMacroop = staticInst;
+ }
+ else {
+ pcOffset = 0;
+ }
} else {
// We need more bytes for this instruction.
break;
}
if (curMacroop) {
staticInst = curMacroop->fetchMicroop(thisPC.microPC());
- if (staticInst->isLastMicroop())
+ if (staticInst->isLastMicroop()) {
curMacroop = NULL;
+ pcOffset = 0;
+ }
}
DynInstPtr instruction =