diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/FuncUnit.py | 6 | ||||
-rw-r--r-- | src/cpu/base_dyn_inst_impl.hh | 2 | ||||
-rw-r--r-- | src/cpu/exetrace.cc | 17 | ||||
-rwxr-xr-x | src/cpu/o3/SConscript | 2 | ||||
-rw-r--r-- | src/cpu/o3/fetch_impl.hh | 13 | ||||
-rw-r--r-- | src/cpu/op_class.cc | 2 | ||||
-rw-r--r-- | src/cpu/ozone/SConscript | 2 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 6 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 54 | ||||
-rw-r--r-- | src/cpu/simple/base.hh | 9 | ||||
-rw-r--r-- | src/cpu/static_inst.cc | 6 | ||||
-rw-r--r-- | src/cpu/static_inst.hh | 160 |
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; } |