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
|
void
|
||||||
Predecoder::process()
|
Predecoder::process()
|
||||||
{
|
{
|
||||||
|
// emi is typically ready, with some caveats below...
|
||||||
|
emiReady = true;
|
||||||
|
|
||||||
if (!emi.thumb) {
|
if (!emi.thumb) {
|
||||||
emi.instBits = data;
|
emi.instBits = data;
|
||||||
emi.sevenAndFour = bits(data, 7) && bits(data, 4);
|
emi.sevenAndFour = bits(data, 7) && bits(data, 4);
|
||||||
emi.isMisc = (bits(data, 24, 23) == 0x2 &&
|
emi.isMisc = (bits(data, 24, 23) == 0x2 &&
|
||||||
bits(data, 20) == 0);
|
bits(data, 20) == 0);
|
||||||
|
consumeBytes(4);
|
||||||
DPRINTF(Predecoder, "Arm inst: %#x.\n", (uint64_t)emi);
|
DPRINTF(Predecoder, "Arm inst: %#x.\n", (uint64_t)emi);
|
||||||
} else {
|
} else {
|
||||||
uint16_t word = (data >> (offset * 8));
|
uint16_t word = (data >> (offset * 8));
|
||||||
|
@ -86,7 +90,7 @@ Predecoder::process()
|
||||||
// A 32 bit thumb inst is half collected.
|
// A 32 bit thumb inst is half collected.
|
||||||
emi.instBits = emi.instBits | word;
|
emi.instBits = emi.instBits | word;
|
||||||
bigThumb = false;
|
bigThumb = false;
|
||||||
offset += 2;
|
consumeBytes(2);
|
||||||
DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n",
|
DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n",
|
||||||
emi.instBits);
|
emi.instBits);
|
||||||
if (itstate.mask) {
|
if (itstate.mask) {
|
||||||
|
@ -105,7 +109,7 @@ Predecoder::process()
|
||||||
emi.instBits = (data >> 16) | (data << 16);
|
emi.instBits = (data >> 16) | (data << 16);
|
||||||
DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n",
|
DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n",
|
||||||
emi.instBits);
|
emi.instBits);
|
||||||
offset += 4;
|
consumeBytes(4);
|
||||||
if (itstate.mask) {
|
if (itstate.mask) {
|
||||||
emi.itstate = itstate;
|
emi.itstate = itstate;
|
||||||
advanceThumbCond();
|
advanceThumbCond();
|
||||||
|
@ -117,11 +121,13 @@ Predecoder::process()
|
||||||
"First half of 32 bit Thumb.\n");
|
"First half of 32 bit Thumb.\n");
|
||||||
emi.instBits = (uint32_t)word << 16;
|
emi.instBits = (uint32_t)word << 16;
|
||||||
bigThumb = true;
|
bigThumb = true;
|
||||||
offset += 2;
|
consumeBytes(2);
|
||||||
|
// emi not ready yet.
|
||||||
|
emiReady = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// A 16 bit thumb inst.
|
// A 16 bit thumb inst.
|
||||||
offset += 2;
|
consumeBytes(2);
|
||||||
emi.instBits = word;
|
emi.instBits = word;
|
||||||
// Set the condition code field artificially.
|
// Set the condition code field artificially.
|
||||||
emi.condCode = COND_UC;
|
emi.condCode = COND_UC;
|
||||||
|
@ -159,6 +165,7 @@ Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
|
||||||
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
||||||
itstate.top6 = cpsr.it2;
|
itstate.top6 = cpsr.it2;
|
||||||
itstate.bottom2 = cpsr.it1;
|
itstate.bottom2 = cpsr.it1;
|
||||||
|
outOfBytes = false;
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@
|
||||||
#ifndef __ARCH_ARM_PREDECODER_HH__
|
#ifndef __ARCH_ARM_PREDECODER_HH__
|
||||||
#define __ARCH_ARM_PREDECODER_HH__
|
#define __ARCH_ARM_PREDECODER_HH__
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "arch/arm/types.hh"
|
#include "arch/arm/types.hh"
|
||||||
#include "arch/arm/miscregs.hh"
|
#include "arch/arm/miscregs.hh"
|
||||||
#include "base/types.hh"
|
#include "base/types.hh"
|
||||||
|
@ -61,6 +63,8 @@ namespace ArmISA
|
||||||
ExtMachInst emi;
|
ExtMachInst emi;
|
||||||
MachInst data;
|
MachInst data;
|
||||||
bool bigThumb;
|
bool bigThumb;
|
||||||
|
bool emiReady;
|
||||||
|
bool outOfBytes;
|
||||||
int offset;
|
int offset;
|
||||||
ITSTATE itstate;
|
ITSTATE itstate;
|
||||||
|
|
||||||
|
@ -70,6 +74,8 @@ namespace ArmISA
|
||||||
bigThumb = false;
|
bigThumb = false;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
emi = 0;
|
emi = 0;
|
||||||
|
emiReady = false;
|
||||||
|
outOfBytes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Predecoder(ThreadContext * _tc) :
|
Predecoder(ThreadContext * _tc) :
|
||||||
|
@ -103,16 +109,22 @@ namespace ArmISA
|
||||||
moreBytes(0, 0, machInst);
|
moreBytes(0, 0, machInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void consumeBytes(int numBytes)
|
||||||
|
{
|
||||||
|
offset += numBytes;
|
||||||
|
assert(offset <= sizeof(MachInst));
|
||||||
|
if (offset == sizeof(MachInst))
|
||||||
|
outOfBytes = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool needMoreBytes()
|
bool needMoreBytes()
|
||||||
{
|
{
|
||||||
return sizeof(MachInst) > offset;
|
return outOfBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool extMachInstReady()
|
bool extMachInstReady()
|
||||||
{
|
{
|
||||||
// The only way an instruction wouldn't be ready is if this is a
|
return emiReady;
|
||||||
// 32 bit ARM instruction that's not 32 bit aligned.
|
|
||||||
return !bigThumb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getInstSize()
|
int getInstSize()
|
||||||
|
@ -123,9 +135,11 @@ namespace ArmISA
|
||||||
//This returns a constant reference to the ExtMachInst to avoid a copy
|
//This returns a constant reference to the ExtMachInst to avoid a copy
|
||||||
ExtMachInst getExtMachInst(PCState &pc)
|
ExtMachInst getExtMachInst(PCState &pc)
|
||||||
{
|
{
|
||||||
|
assert(emiReady);
|
||||||
ExtMachInst thisEmi = emi;
|
ExtMachInst thisEmi = emi;
|
||||||
pc.npc(pc.pc() + getInstSize());
|
pc.npc(pc.pc() + getInstSize());
|
||||||
emi = 0;
|
emi = 0;
|
||||||
|
emiReady = false;
|
||||||
return thisEmi;
|
return thisEmi;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -384,7 +384,7 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
|
||||||
{
|
{
|
||||||
ThreadID tid = pkt->req->threadId();
|
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());
|
assert(!pkt->wasNacked());
|
||||||
|
|
||||||
|
@ -1011,7 +1011,7 @@ DefaultFetch<Impl>::buildInst(ThreadID tid, StaticInstPtr staticInst,
|
||||||
instruction->setThreadState(cpu->thread[tid]);
|
instruction->setThreadState(cpu->thread[tid]);
|
||||||
|
|
||||||
DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created "
|
DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created "
|
||||||
"[sn:%lli]\n", tid, thisPC.instAddr(),
|
"[sn:%lli].\n", tid, thisPC.instAddr(),
|
||||||
thisPC.microPC(), seq);
|
thisPC.microPC(), seq);
|
||||||
|
|
||||||
DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid,
|
DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid,
|
||||||
|
@ -1180,7 +1180,6 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
ExtMachInst extMachInst;
|
ExtMachInst extMachInst;
|
||||||
|
|
||||||
extMachInst = predecoder.getExtMachInst(thisPC);
|
extMachInst = predecoder.getExtMachInst(thisPC);
|
||||||
pcOffset = 0;
|
|
||||||
staticInst = StaticInstPtr(extMachInst,
|
staticInst = StaticInstPtr(extMachInst,
|
||||||
thisPC.instAddr());
|
thisPC.instAddr());
|
||||||
|
|
||||||
|
@ -1188,7 +1187,12 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
++fetchedInsts;
|
++fetchedInsts;
|
||||||
|
|
||||||
if (staticInst->isMacroop())
|
if (staticInst->isMacroop())
|
||||||
|
{
|
||||||
curMacroop = staticInst;
|
curMacroop = staticInst;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pcOffset = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// We need more bytes for this instruction.
|
// We need more bytes for this instruction.
|
||||||
break;
|
break;
|
||||||
|
@ -1196,8 +1200,10 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
}
|
}
|
||||||
if (curMacroop) {
|
if (curMacroop) {
|
||||||
staticInst = curMacroop->fetchMicroop(thisPC.microPC());
|
staticInst = curMacroop->fetchMicroop(thisPC.microPC());
|
||||||
if (staticInst->isLastMicroop())
|
if (staticInst->isLastMicroop()) {
|
||||||
curMacroop = NULL;
|
curMacroop = NULL;
|
||||||
|
pcOffset = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DynInstPtr instruction =
|
DynInstPtr instruction =
|
||||||
|
|
Loading…
Reference in a new issue