summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/FuncUnit.py6
-rw-r--r--src/cpu/base_dyn_inst_impl.hh2
-rw-r--r--src/cpu/exetrace.cc17
-rwxr-xr-xsrc/cpu/o3/SConscript2
-rw-r--r--src/cpu/o3/fetch_impl.hh13
-rw-r--r--src/cpu/op_class.cc2
-rw-r--r--src/cpu/ozone/SConscript2
-rw-r--r--src/cpu/simple/atomic.cc6
-rw-r--r--src/cpu/simple/base.cc54
-rw-r--r--src/cpu/simple/base.hh9
-rw-r--r--src/cpu/static_inst.cc6
-rw-r--r--src/cpu/static_inst.hh160
12 files changed, 225 insertions, 54 deletions
diff --git a/src/cpu/FuncUnit.py b/src/cpu/FuncUnit.py
index 541bdbd83..ad2d1b87b 100644
--- a/src/cpu/FuncUnit.py
+++ b/src/cpu/FuncUnit.py
@@ -29,15 +29,15 @@
from m5.SimObject import SimObject
from m5.params import *
-class OpType(Enum):
- vals = ['(null)', 'IntAlu', 'IntMult', 'IntDiv', 'FloatAdd',
+class OpClass(Enum):
+ vals = ['No_OpClass', 'IntAlu', 'IntMult', 'IntDiv', 'FloatAdd',
'FloatCmp', 'FloatCvt', 'FloatMult', 'FloatDiv', 'FloatSqrt',
'MemRead', 'MemWrite', 'IprAccess', 'InstPrefetch']
class OpDesc(SimObject):
type = 'OpDesc'
issueLat = Param.Int(1, "cycles until another can be issued")
- opClass = Param.OpType("type of operation")
+ opClass = Param.OpClass("type of operation")
opLat = Param.Int(1, "cycles until result is available")
class FUDesc(SimObject):
diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh
index a1c866336..216cc08ea 100644
--- a/src/cpu/base_dyn_inst_impl.hh
+++ b/src/cpu/base_dyn_inst_impl.hh
@@ -66,7 +66,7 @@ BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst machInst,
Addr inst_PC, Addr inst_NPC,
Addr pred_PC, Addr pred_NPC,
InstSeqNum seq_num, ImplCPU *cpu)
- : staticInst(machInst), traceData(NULL), cpu(cpu)
+ : staticInst(machInst, inst_PC), traceData(NULL), cpu(cpu)
{
seqNum = seq_num;
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index 3e2b0f03e..9b87f2e8a 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -162,7 +162,7 @@ Trace::InstRecord::dump()
static int fd = 0;
//Don't print what happens for each micro-op, just print out
//once at the last op, and for regular instructions.
- if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
+ if(!staticInst->isMicroop() || staticInst->isLastMicroop())
{
if(!cosim_listener)
{
@@ -245,7 +245,7 @@ Trace::InstRecord::dump()
#if 0 //THE_ISA == SPARC_ISA
//Don't print what happens for each micro-op, just print out
//once at the last op, and for regular instructions.
- if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
+ if(!staticInst->isMicroop() || staticInst->isLastMicroop())
{
static uint64_t regs[32] = {
0, 0, 0, 0, 0, 0, 0, 0,
@@ -432,7 +432,7 @@ Trace::InstRecord::dump()
setupSharedData();
// We took a trap on a micro-op...
- if (wasMicro && !staticInst->isMicroOp())
+ if (wasMicro && !staticInst->isMicroop())
{
// let's skip comparing this tick
while (!compared)
@@ -444,13 +444,13 @@ Trace::InstRecord::dump()
wasMicro = false;
}
- if (staticInst->isLastMicroOp())
+ if (staticInst->isLastMicroop())
wasMicro = false;
- else if (staticInst->isMicroOp())
+ else if (staticInst->isMicroop())
wasMicro = true;
- if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
+ if(!staticInst->isMicroop() || staticInst->isLastMicroop()) {
while (!compared) {
if (shared_data->flags == OWN_M5) {
m5Pc = PC & TheISA::PAddrImplMask;
@@ -650,12 +650,13 @@ Trace::InstRecord::dump()
<< endl;
predecoder.setTC(thread);
- predecoder.moreBytes(m5Pc, 0, shared_data->instruction);
+ predecoder.moreBytes(m5Pc, m5Pc, 0,
+ shared_data->instruction);
assert(predecoder.extMachInstReady());
StaticInstPtr legionInst =
- StaticInst::decode(predecoder.getExtMachInst());
+ StaticInst::decode(predecoder.getExtMachInst(), lgnPc);
outs << setfill(' ') << setw(15)
<< " Legion Inst: "
<< "0x" << setw(8) << setfill('0') << hex
diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript
index a1af620be..ad61ad228 100755
--- a/src/cpu/o3/SConscript
+++ b/src/cpu/o3/SConscript
@@ -75,7 +75,7 @@ if 'O3CPU' in env['CPU_MODELS']:
sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA'])
if env['USE_CHECKER']:
- SimObject('m5/objects/O3Checker.py')
+ SimObject('O3Checker.py')
Source('checker_builder.cc')
if 'O3CPU' in env['CPU_MODELS'] or 'OzoneCPU' in env['CPU_MODELS']:
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index e16f97558..ab55ec744 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -29,6 +29,9 @@
* Korey Sewell
*/
+#include <algorithm>
+#include <cstring>
+
#include "config/use_checker.hh"
#include "arch/isa_traits.hh"
@@ -48,8 +51,6 @@
#include "sim/system.hh"
#endif // FULL_SYSTEM
-#include <algorithm>
-
template<class Impl>
void
DefaultFetch<Impl>::IcachePort::setPeer(Port *port)
@@ -374,7 +375,7 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
return;
}
- memcpy(cacheData[tid], pkt->getPtr<uint8_t *>(), cacheBlkSize);
+ memcpy(cacheData[tid], pkt->getPtr<uint8_t>(), cacheBlkSize);
cacheDataValid[tid] = true;
if (!drainPending) {
@@ -1127,7 +1128,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
(&cacheData[tid][offset]));
predecoder.setTC(cpu->thread[tid]->getTC());
- predecoder.moreBytes(fetch_PC, 0, inst);
+ predecoder.moreBytes(fetch_PC, fetch_PC, 0, inst);
ext_inst = predecoder.getExtMachInst();
@@ -1151,10 +1152,14 @@ DefaultFetch<Impl>::fetch(bool &status_change)
DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n",
tid, instruction->staticInst->disassemble(fetch_PC));
+#if TRACING_ON
instruction->traceData =
Trace::getInstRecord(curTick, cpu->tcBase(tid),
instruction->staticInst,
instruction->readPC());
+#else
+ instruction->traceData = NULL;
+#endif
///FIXME This needs to be more robust in dealing with delay slots
#if !ISA_HAS_DELAY_SLOT
diff --git a/src/cpu/op_class.cc b/src/cpu/op_class.cc
index f7ef49c0f..02cb4a08a 100644
--- a/src/cpu/op_class.cc
+++ b/src/cpu/op_class.cc
@@ -34,7 +34,7 @@
const char *
opClassStrings[Num_OpClasses] =
{
- "(null)",
+ "No_OpClass",
"IntAlu",
"IntMult",
"IntDiv",
diff --git a/src/cpu/ozone/SConscript b/src/cpu/ozone/SConscript
index 601e80a72..cb2006456 100644
--- a/src/cpu/ozone/SConscript
+++ b/src/cpu/ozone/SConscript
@@ -45,5 +45,5 @@ if 'OzoneCPU' in env['CPU_MODELS']:
Source('lw_lsq.cc')
Source('rename_table.cc')
if env['USE_CHECKER']:
- SimObject('m5/objects/OzoneChecker.py')
+ SimObject('OzoneChecker.py')
Source('checker_builder.cc')
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index b0a01c3a3..ea1c7d87f 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -540,8 +540,8 @@ AtomicSimpleCPU::tick()
}
// @todo remove me after debugging with legion done
- if (curStaticInst && (!curStaticInst->isMicroOp() ||
- curStaticInst->isFirstMicroOp()))
+ if (curStaticInst && (!curStaticInst->isMicroop() ||
+ curStaticInst->isFirstMicroop()))
instCnt++;
if (simulate_stalls) {
@@ -557,7 +557,7 @@ AtomicSimpleCPU::tick()
}
}
- if(predecoder.needMoreBytes() || fault != NoFault)
+ if(fault != NoFault || !stayAtPC)
advancePC(fault);
}
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 4fed2059b..b7f60522f 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -70,7 +70,7 @@ using namespace std;
using namespace TheISA;
BaseSimpleCPU::BaseSimpleCPU(Params *p)
- : BaseCPU(p), thread(NULL), predecoder(NULL)
+ : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL)
{
#if FULL_SYSTEM
thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
@@ -91,6 +91,9 @@ BaseSimpleCPU::BaseSimpleCPU(Params *p)
lastDcacheStall = 0;
threadContexts.push_back(tc);
+
+ fetchOffset = 0;
+ stayAtPC = false;
}
BaseSimpleCPU::~BaseSimpleCPU()
@@ -326,18 +329,19 @@ BaseSimpleCPU::checkForInterrupts()
Fault
BaseSimpleCPU::setupFetchRequest(Request *req)
{
+ Addr threadPC = thread->readPC();
+
// set up memory request for instruction fetch
#if ISA_HAS_DELAY_SLOT
- DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(),
+ DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC,
thread->readNextPC(),thread->readNextNPC());
#else
- DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p",thread->readPC(),
+ DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC,
thread->readNextPC());
#endif
- req->setVirt(0, thread->readPC() & ~3, sizeof(MachInst),
- (FULL_SYSTEM && (thread->readPC() & 1)) ? PHYSICAL : 0,
- thread->readPC());
+ Addr fetchPC = (threadPC & PCMask) + fetchOffset;
+ req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC);
Fault fault = thread->translateInstReq(req);
@@ -365,8 +369,10 @@ BaseSimpleCPU::preExecute()
// decode the instruction
inst = gtoh(inst);
+
//If we're not in the middle of a macro instruction
if (!curMacroStaticInst) {
+
StaticInstPtr instPtr = NULL;
//Predecode, ie bundle up an ExtMachInst
@@ -374,36 +380,50 @@ BaseSimpleCPU::preExecute()
predecoder.setTC(thread->getTC());
//If more fetch data is needed, pass it in.
if(predecoder.needMoreBytes())
- predecoder.moreBytes(thread->readPC(), 0, inst);
+ predecoder.moreBytes(thread->readPC(),
+ (thread->readPC() & PCMask) + fetchOffset, 0, inst);
else
predecoder.process();
- //If an instruction is ready, decode it
- if (predecoder.extMachInstReady())
- instPtr = StaticInst::decode(predecoder.getExtMachInst());
+
+ //If an instruction is ready, decode it. Otherwise, we'll have to
+ //fetch beyond the MachInst at the current pc.
+ if (predecoder.extMachInstReady()) {
+#if THE_ISA == X86_ISA
+ thread->setNextPC(thread->readPC() + predecoder.getInstSize());
+#endif // X86_ISA
+ stayAtPC = false;
+ instPtr = StaticInst::decode(predecoder.getExtMachInst(),
+ thread->readPC());
+ } else {
+ stayAtPC = true;
+ fetchOffset += sizeof(MachInst);
+ }
//If we decoded an instruction and it's microcoded, start pulling
//out micro ops
- if (instPtr && instPtr->isMacroOp()) {
+ if (instPtr && instPtr->isMacroop()) {
curMacroStaticInst = instPtr;
curStaticInst = curMacroStaticInst->
- fetchMicroOp(thread->readMicroPC());
+ fetchMicroop(thread->readMicroPC());
} else {
curStaticInst = instPtr;
}
} else {
//Read the next micro op from the macro op
curStaticInst = curMacroStaticInst->
- fetchMicroOp(thread->readMicroPC());
+ fetchMicroop(thread->readMicroPC());
}
//If we decoded an instruction this "tick", record information about it.
if(curStaticInst)
{
+#if TRACING_ON
traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
thread->readPC());
DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
curStaticInst->getName(), curStaticInst->machInst);
+#endif // TRACING_ON
#if FULL_SYSTEM
thread->setInst(inst);
@@ -418,7 +438,7 @@ BaseSimpleCPU::postExecute()
if (thread->profile) {
bool usermode = TheISA::inUserMode(tc);
thread->profilePC = usermode ? 1 : thread->readPC();
- StaticInstPtr si(inst);
+ StaticInstPtr si(inst, thread->readPC());
ProfileNode *node = thread->profile->consume(tc, si);
if (node)
thread->profileNode = node;
@@ -447,14 +467,16 @@ BaseSimpleCPU::postExecute()
void
BaseSimpleCPU::advancePC(Fault fault)
{
+ //Since we're moving to a new pc, zero out the offset
+ fetchOffset = 0;
if (fault != NoFault) {
curMacroStaticInst = StaticInst::nullStaticInstPtr;
fault->invoke(tc);
thread->setMicroPC(0);
thread->setNextMicroPC(1);
- } else if (predecoder.needMoreBytes()) {
+ } else {
//If we're at the last micro op for this instruction
- if (curStaticInst && curStaticInst->isLastMicroOp()) {
+ if (curStaticInst && curStaticInst->isLastMicroop()) {
//We should be working with a macro op
assert(curMacroStaticInst);
//Close out this macro op, and clean up the
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 787259c96..d221baca8 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -137,6 +137,12 @@ class BaseSimpleCPU : public BaseCPU
StaticInstPtr curStaticInst;
StaticInstPtr curMacroStaticInst;
+ //This is the offset from the current pc that fetch should be performed at
+ Addr fetchOffset;
+ //This flag says to stay at the current pc. This is useful for
+ //instructions which go beyond MachInst boundaries.
+ bool stayAtPC;
+
void checkForInterrupts();
Fault setupFetchRequest(Request *req);
void preExecute();
@@ -160,6 +166,9 @@ class BaseSimpleCPU : public BaseCPU
return numInst - startNumInst;
}
+ // Mask to align PCs to MachInst sized boundaries
+ static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
+
// number of simulated memory references
Stats::Scalar<> numMemRefs;
diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc
index 64fcc0580..52a7ede03 100644
--- a/src/cpu/static_inst.cc
+++ b/src/cpu/static_inst.cc
@@ -37,6 +37,8 @@ StaticInstPtr StaticInst::nullStaticInstPtr;
// Define the decode cache hash map.
StaticInst::DecodeCache StaticInst::decodeCache;
+StaticInst::AddrDecodeCache StaticInst::addrDecodeCache;
+StaticInst::cacheElement StaticInst::recentDecodes[2];
void
StaticInst::dumpDecodeCacheStats()
@@ -76,9 +78,9 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const
}
StaticInstPtr
-StaticInst::fetchMicroOp(MicroPC micropc)
+StaticInst::fetchMicroop(MicroPC micropc)
{
- panic("StaticInst::fetchMicroOp() called on instruction "
+ panic("StaticInst::fetchMicroop() called on instruction "
"that is not microcoded.");
}
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index a58ac85d6..b0a19c151 100644
--- a/src/cpu/static_inst.hh
+++ b/src/cpu/static_inst.hh
@@ -63,6 +63,7 @@ class AtomicSimpleCPU;
class TimingSimpleCPU;
class InorderCPU;
class SymbolTable;
+class AddrDecodePage;
namespace Trace {
class InstRecord;
@@ -143,11 +144,11 @@ class StaticInstBase : public RefCounted
IsUnverifiable, ///< Can't be verified by a checker
//Flags for microcode
- IsMacroOp, ///< Is a macroop containing microops
- IsMicroOp, ///< Is a microop
+ IsMacroop, ///< Is a macroop containing microops
+ IsMicroop, ///< Is a microop
IsDelayedCommit, ///< This microop doesn't commit right away
- IsLastMicroOp, ///< This microop ends a microop sequence
- IsFirstMicroOp, ///< This microop begins a microop sequence
+ IsLastMicroop, ///< This microop ends a microop sequence
+ IsFirstMicroop, ///< This microop begins a microop sequence
//This flag doesn't do anything yet
IsMicroBranch, ///< This microop branches within the microcode for a macroop
@@ -242,11 +243,11 @@ class StaticInstBase : public RefCounted
bool isQuiesce() const { return flags[IsQuiesce]; }
bool isIprAccess() const { return flags[IsIprAccess]; }
bool isUnverifiable() const { return flags[IsUnverifiable]; }
- bool isMacroOp() const { return flags[IsMacroOp]; }
- bool isMicroOp() const { return flags[IsMicroOp]; }
+ bool isMacroop() const { return flags[IsMacroop]; }
+ bool isMicroop() const { return flags[IsMicroop]; }
bool isDelayedCommit() const { return flags[IsDelayedCommit]; }
- bool isLastMicroOp() const { return flags[IsLastMicroOp]; }
- bool isFirstMicroOp() const { return flags[IsFirstMicroOp]; }
+ bool isLastMicroop() const { return flags[IsLastMicroop]; }
+ bool isFirstMicroop() const { return flags[IsFirstMicroop]; }
//This flag doesn't do anything yet
bool isMicroBranch() const { return flags[IsMicroBranch]; }
//@}
@@ -349,6 +350,7 @@ class StaticInst : public StaticInstBase
: StaticInstBase(__opClass),
machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
{
+ memset(&recentDecodes, 0, 2 * sizeof(cacheElement));
}
public:
@@ -369,7 +371,7 @@ class StaticInst : public StaticInstBase
* Return the microop that goes with a particular micropc. This should
* only be defined/used in macroops which will contain microops
*/
- virtual StaticInstPtr fetchMicroOp(MicroPC micropc);
+ virtual StaticInstPtr fetchMicroop(MicroPC micropc);
/**
* Return the target address for a PC-relative branch.
@@ -437,11 +439,52 @@ class StaticInst : public StaticInstBase
/// Decode a machine instruction.
/// @param mach_inst The binary instruction to decode.
/// @retval A pointer to the corresponding StaticInst object.
- //This is defined as inline below.
- static StaticInstPtr decode(ExtMachInst mach_inst);
+ //This is defined as inlined below.
+ static StaticInstPtr decode(ExtMachInst mach_inst, Addr addr);
/// Return name of machine instruction
std::string getName() { return mnemonic; }
+
+ /// Decoded instruction cache type, for address decoding.
+ /// A generic hash_map is used.
+ typedef m5::hash_map<Addr, AddrDecodePage *> AddrDecodeCache;
+
+ /// A cache of decoded instruction objects from addresses.
+ static AddrDecodeCache addrDecodeCache;
+
+ struct cacheElement {
+ Addr page_addr;
+ AddrDecodePage *decodePage;
+ } ;
+
+ /// An array of recently decoded instructions.
+ // might not use an array if there is only two elements
+ static struct cacheElement recentDecodes[2];
+
+ /// Updates the recently decoded instructions entries
+ /// @param page_addr The page address recently used.
+ /// @param decodePage Pointer to decoding page containing the decoded
+ /// instruction.
+ static inline void
+ updateCache(Addr page_addr, AddrDecodePage *decodePage)
+ {
+ recentDecodes[1].page_addr = recentDecodes[0].page_addr;
+ recentDecodes[1].decodePage = recentDecodes[0].decodePage;
+ recentDecodes[0].page_addr = page_addr;
+ recentDecodes[0].decodePage = decodePage;
+ }
+
+ /// Searches the decoded instruction cache for instruction decoding.
+ /// If it is not found, then we decode the instruction.
+ /// Otherwise, we get the instruction from the cache and move it into
+ /// the address-to-instruction decoding page.
+ /// @param mach_inst The binary instruction to decode.
+ /// @param addr The address that contained the binary instruction.
+ /// @param decodePage Pointer to decoding page containing the instruction.
+ /// @retval A pointer to the corresponding StaticInst object.
+ //This is defined as inlined below.
+ static StaticInstPtr searchCache(ExtMachInst mach_inst, Addr addr,
+ AddrDecodePage * decodePage);
};
typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
@@ -472,8 +515,8 @@ class StaticInstPtr : public RefCountingPtr<StaticInst>
/// Construct directly from machine instruction.
/// Calls StaticInst::decode().
- explicit StaticInstPtr(TheISA::ExtMachInst mach_inst)
- : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
+ explicit StaticInstPtr(TheISA::ExtMachInst mach_inst, Addr addr)
+ : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst, addr))
{
}
@@ -484,8 +527,55 @@ class StaticInstPtr : public RefCountingPtr<StaticInst>
}
};
+/// A page of a list of decoded instructions from an address.
+class AddrDecodePage
+{
+ typedef TheISA::ExtMachInst ExtMachInst;
+ protected:
+ StaticInstPtr instructions[TheISA::PageBytes];
+ bool valid[TheISA::PageBytes];
+ Addr lowerMask;
+
+ public:
+ /// Constructor
+ AddrDecodePage() {
+ lowerMask = TheISA::PageBytes - 1;
+ memset(valid, 0, TheISA::PageBytes);
+ }
+
+ /// Checks if the instruction is already decoded and the machine
+ /// instruction in the cache matches the current machine instruction
+ /// related to the address
+ /// @param mach_inst The binary instruction to check
+ /// @param addr The address containing the instruction
+ inline bool decoded(ExtMachInst mach_inst, Addr addr)
+ {
+ return (valid[addr & lowerMask] &&
+ (instructions[addr & lowerMask]->machInst == mach_inst));
+ }
+
+ /// Returns the instruction object. decoded should be called first
+ /// to check if the instruction is valid.
+ /// @param addr The address of the instruction.
+ /// @retval A pointer to the corresponding StaticInst object.
+ inline StaticInstPtr getInst(Addr addr)
+ { return instructions[addr & lowerMask]; }
+
+ /// Inserts a pointer to a StaticInst object into the list of decoded
+ /// instructions on the page.
+ /// @param addr The address of the instruction.
+ /// @param si A pointer to the corresponding StaticInst object.
+ inline void insert(Addr addr, StaticInstPtr &si)
+ {
+ instructions[addr & lowerMask] = si;
+ valid[addr & lowerMask] = true;
+ }
+
+};
+
+
inline StaticInstPtr
-StaticInst::decode(StaticInst::ExtMachInst mach_inst)
+StaticInst::decode(StaticInst::ExtMachInst mach_inst, Addr addr)
{
#ifdef DECODE_CACHE_HASH_STATS
// Simple stats on decode hash_map. Turns out the default
@@ -499,12 +589,54 @@ StaticInst::decode(StaticInst::ExtMachInst mach_inst)
}
#endif
+ Addr page_addr = addr & ~(TheISA::PageBytes - 1);
+
+ // checks recently decoded addresses
+ if (recentDecodes[0].decodePage &&
+ page_addr == recentDecodes[0].page_addr) {
+ if (recentDecodes[0].decodePage->decoded(mach_inst, addr))
+ return recentDecodes[0].decodePage->getInst(addr);
+
+ return searchCache(mach_inst, addr, recentDecodes[0].decodePage);
+ }
+
+ if (recentDecodes[1].decodePage &&
+ page_addr == recentDecodes[1].page_addr) {
+ if (recentDecodes[1].decodePage->decoded(mach_inst, addr))
+ return recentDecodes[1].decodePage->getInst(addr);
+
+ return searchCache(mach_inst, addr, recentDecodes[1].decodePage);
+ }
+
+ // searches the page containing the address to decode
+ AddrDecodeCache::iterator iter = addrDecodeCache.find(page_addr);
+ if (iter != addrDecodeCache.end()) {
+ updateCache(page_addr, iter->second);
+ if (iter->second->decoded(mach_inst, addr))
+ return iter->second->getInst(addr);
+
+ return searchCache(mach_inst, addr, iter->second);
+ }
+
+ // creates a new object for a page of decoded instructions
+ AddrDecodePage * decodePage = new AddrDecodePage;
+ addrDecodeCache[page_addr] = decodePage;
+ updateCache(page_addr, decodePage);
+ return searchCache(mach_inst, addr, decodePage);
+}
+
+inline StaticInstPtr
+StaticInst::searchCache(ExtMachInst mach_inst, Addr addr,
+ AddrDecodePage * decodePage)
+{
DecodeCache::iterator iter = decodeCache.find(mach_inst);
if (iter != decodeCache.end()) {
+ decodePage->insert(addr, iter->second);
return iter->second;
}
StaticInstPtr si = TheISA::decodeInst(mach_inst);
+ decodePage->insert(addr, si);
decodeCache[mach_inst] = si;
return si;
}