summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/remote_gdb.cc3
-rw-r--r--src/arch/arm/remote_gdb.cc3
-rw-r--r--src/cpu/SConscript1
-rw-r--r--src/cpu/decode.cc33
-rw-r--r--src/cpu/decode.hh59
-rw-r--r--src/cpu/decode_cache.hh179
-rw-r--r--src/cpu/inorder/cpu.cc8
-rw-r--r--src/cpu/inorder/cpu.hh2
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.cc4
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.hh2
-rw-r--r--src/cpu/inorder/resources/fetch_unit.cc2
-rw-r--r--src/cpu/inorder/resources/fetch_unit.hh3
-rw-r--r--src/cpu/inorder/thread_context.hh2
-rw-r--r--src/cpu/legiontrace.cc5
-rw-r--r--src/cpu/o3/fetch.hh4
-rw-r--r--src/cpu/o3/fetch_impl.hh11
-rwxr-xr-xsrc/cpu/o3/thread_context.hh2
-rw-r--r--src/cpu/simple/base.cc2
-rw-r--r--src/cpu/simple/base.hh1
-rw-r--r--src/cpu/simple_thread.hh5
-rw-r--r--src/cpu/static_inst.cc24
-rw-r--r--src/cpu/static_inst.hh196
-rw-r--r--src/cpu/thread_context.hh5
23 files changed, 321 insertions, 235 deletions
diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc
index a060e49a8..88d453754 100644
--- a/src/arch/alpha/remote_gdb.cc
+++ b/src/arch/alpha/remote_gdb.cc
@@ -134,6 +134,7 @@
#include "base/remote_gdb.hh"
#include "base/socket.hh"
#include "base/trace.hh"
+#include "cpu/decode.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "debug/GDBAcc.hh"
@@ -282,7 +283,7 @@ RemoteGDB::setSingleStep()
// User was stopped at pc, e.g. the instruction at pc was not
// executed.
MachInst inst = read<MachInst>(pc.pc());
- StaticInstPtr si(inst, pc.pc());
+ StaticInstPtr si = context->getDecoderPtr()->decode(inst, pc.pc());
if (si->hasBranchTarget(pc, context, bpc)) {
// Don't bother setting a breakpoint on the taken branch if it
// is the same as the next pc
diff --git a/src/arch/arm/remote_gdb.cc b/src/arch/arm/remote_gdb.cc
index 4060c999a..223ff4c69 100644
--- a/src/arch/arm/remote_gdb.cc
+++ b/src/arch/arm/remote_gdb.cc
@@ -148,6 +148,7 @@
#include "base/remote_gdb.hh"
#include "base/socket.hh"
#include "base/trace.hh"
+#include "cpu/decode.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "cpu/thread_state.hh"
@@ -322,7 +323,7 @@ RemoteGDB::setSingleStep()
// User was stopped at pc, e.g. the instruction at pc was not
// executed.
MachInst inst = read<MachInst>(pc.pc());
- StaticInstPtr si(inst, pc.pc());
+ StaticInstPtr si = context->getDecoderPtr()->decode(inst, pc.pc());
if (si->hasBranchTarget(pc, context, bpc)) {
// Don't bother setting a breakpoint on the taken branch if it
// is the same as the next pc
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
index b24866ddd..a1074cb8b 100644
--- a/src/cpu/SConscript
+++ b/src/cpu/SConscript
@@ -114,6 +114,7 @@ SimObject('NativeTrace.py')
Source('activity.cc')
Source('base.cc')
Source('cpuevent.cc')
+Source('decode.cc')
Source('exetrace.cc')
Source('func_unit.cc')
Source('inteltrace.cc')
diff --git a/src/cpu/decode.cc b/src/cpu/decode.cc
new file mode 100644
index 000000000..56a484b07
--- /dev/null
+++ b/src/cpu/decode.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011 Google
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "cpu/decode.hh"
+
+DecodeCache<TheISA::decodeInst> Decoder::cache;
diff --git a/src/cpu/decode.hh b/src/cpu/decode.hh
new file mode 100644
index 000000000..653f8eea5
--- /dev/null
+++ b/src/cpu/decode.hh
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 Google
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __CPU_DECODE_HH__
+#define __CPU_DECODE_HH__
+
+#include "arch/isa_traits.hh"
+#include "arch/types.hh"
+#include "config/the_isa.hh"
+#include "cpu/decode_cache.hh"
+#include "cpu/static_inst.hh"
+
+/// The decoder class. This class doesn't do much of anything now, but in the
+/// future it will be redefinable per ISA and allow more interesting behavior.
+class Decoder
+{
+ protected:
+ /// A cache of decoded instruction objects.
+ static DecodeCache<TheISA::decodeInst> cache;
+
+ public:
+ /// Decode a machine instruction.
+ /// @param mach_inst The binary instruction to decode.
+ /// @retval A pointer to the corresponding StaticInst object.
+ StaticInstPtr
+ decode(TheISA::ExtMachInst mach_inst, Addr addr)
+ {
+ return cache.decode(mach_inst, addr);
+ }
+};
+
+#endif // __CPU_DECODE_HH__
diff --git a/src/cpu/decode_cache.hh b/src/cpu/decode_cache.hh
new file mode 100644
index 000000000..1bff315d1
--- /dev/null
+++ b/src/cpu/decode_cache.hh
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011 Google
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __CPU_DECODE_CACHE_HH__
+#define __CPU_DECODE_CACHE_HH__
+
+#include "arch/isa_traits.hh"
+#include "arch/types.hh"
+#include "base/hashmap.hh"
+#include "config/the_isa.hh"
+#include "cpu/static_inst.hh"
+
+typedef StaticInstPtr (*DecodeInstFunc)(TheISA::ExtMachInst);
+
+template <DecodeInstFunc decodeInstFunc>
+class DecodeCache
+{
+ private:
+ typedef TheISA::ExtMachInst ExtMachInst;
+
+ /// Hash of decoded instructions.
+ typedef m5::hash_map<ExtMachInst, StaticInstPtr> InstMap;
+ InstMap instMap;
+
+ /// A table of instructions which are already been decoded, indexed by
+ /// page offset.
+ class DecodePage
+ {
+ protected:
+ StaticInstPtr instructions[TheISA::PageBytes];
+
+ // A helper function to compute the index of an address in the table.
+ Addr offset(Addr addr) { return addr & (TheISA::PageBytes - 1); }
+
+ public:
+ /// Decode the given instruction. First attempt to find it in the
+ /// table, then in the generic decode cache, and finally call the
+ /// actual decode function.
+ ///
+ /// @param mach_inst The predecoded instruction to decode.
+ /// @param addr The address the instruction came from.
+ /// @param cache A cache of already decoded instructions.
+ /// @retval The decoded instruction object.
+ StaticInstPtr
+ decode(const ExtMachInst &mach_inst, Addr addr, InstMap &instMap)
+ {
+ StaticInstPtr si = instructions[offset(addr)];
+ if (si && (si->machInst == mach_inst)) {
+ return si;
+ }
+
+ InstMap::iterator iter = instMap.find(mach_inst);
+ if (iter != instMap.end()) {
+ si = iter->second;
+ } else {
+ si = decodeInstFunc(mach_inst);
+ instMap[mach_inst] = si;
+ }
+
+ instructions[offset(addr)] = si;
+ return si;
+ }
+ };
+
+ /// A store of DecodePages. Basically a slightly smarter hash_map.
+ class DecodePages
+ {
+ protected:
+ typedef typename m5::hash_map<Addr, DecodePage *> PageMap;
+ typedef typename PageMap::iterator PageIt;
+ PageIt recent[2];
+ PageMap pageMap;
+
+ /// Update the small cache of recent lookups.
+ /// @param recentest The most recent result;
+ void
+ update(PageIt recentest)
+ {
+ recent[1] = recent[0];
+ recent[0] = recentest;
+ }
+
+ public:
+ /// Constructor
+ DecodePages()
+ {
+ recent[0] = recent[1] = pageMap.end();
+ }
+
+ /// Attempt to find the DecodePage which goes with a particular
+ /// address. First check the small cache of recent results, then
+ /// actually look in the hash_map.
+ /// @param addr The address to look up.
+ DecodePage *
+ findPage(Addr addr)
+ {
+ Addr page_addr = addr & ~(TheISA::PageBytes - 1);
+
+ // Check against recent lookups.
+ if (recent[0] != pageMap.end()) {
+ if (recent[0]->first == page_addr)
+ return recent[0]->second;
+ if (recent[1] != pageMap.end() &&
+ recent[1]->first == page_addr) {
+ update(recent[1]);
+ // recent[1] has just become recent[0].
+ return recent[0]->second;
+ }
+ }
+
+ // Actually look in the has_map.
+ PageIt it = pageMap.find(page_addr);
+ if (it != pageMap.end()) {
+ update(it);
+ return it->second;
+ }
+
+ // Didn't find it so return NULL.
+ return NULL;
+ }
+
+ void
+ addPage(Addr addr, DecodePage *page)
+ {
+ Addr page_addr = addr & ~(TheISA::PageBytes - 1);
+ typename PageMap::value_type to_insert(page_addr, page);
+ update(pageMap.insert(to_insert).first);
+ }
+ } decodePages;
+
+ public:
+ /// Decode a machine instruction.
+ /// @param mach_inst The binary instruction to decode.
+ /// @retval A pointer to the corresponding StaticInst object.
+ StaticInstPtr
+ decode(ExtMachInst mach_inst, Addr addr)
+ {
+ // Try to find a matching address based table of instructions.
+ DecodePage *page = decodePages.findPage(addr);
+ if (!page) {
+ // Nothing was found, so create a new one.
+ page = new DecodePage;
+ decodePages.addPage(addr, page);
+ }
+
+ // Use the table to decode the instruction. It will fall back to other
+ // mechanisms if it needs to.
+ return page->decode(mach_inst, addr, instMap);
+ }
+};
+
+#endif // __CPU_DECODE_CACHE_HH__
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
index d8552d9d3..07a013afc 100644
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -1766,6 +1766,14 @@ InOrderCPU::getDTBPtr()
return dtb_res->tlb();
}
+Decoder *
+InOrderCPU::getDecoderPtr()
+{
+ FetchUnit *fetch_res =
+ dynamic_cast<FetchUnit*>(resPool->getResource(fetchPortIdx));
+ return &fetch_res->decoder;
+}
+
Fault
InOrderCPU::read(DynInstPtr inst, Addr addr,
uint8_t *data, unsigned size, unsigned flags)
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
index a5616f8b1..098909cb7 100644
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -305,6 +305,8 @@ class InOrderCPU : public BaseCPU
TheISA::TLB *getITBPtr();
TheISA::TLB *getDTBPtr();
+ Decoder *getDecoderPtr();
+
/** Accessor Type for the SkedCache */
typedef uint32_t SkedID;
diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc
index 5343206c1..f65d2ea9f 100644
--- a/src/cpu/inorder/inorder_dyn_inst.cc
+++ b/src/cpu/inorder/inorder_dyn_inst.cc
@@ -94,9 +94,9 @@ InOrderDynInst::cpuId()
}
void
-InOrderDynInst::setMachInst(ExtMachInst machInst)
+InOrderDynInst::setStaticInst(StaticInstPtr si)
{
- staticInst = StaticInst::decode(machInst, pc.instAddr());
+ staticInst = si;
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
_destRegIdx[i] = this->staticInst->destRegIdx(i);
diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh
index ecaf23aab..de9de5eff 100644
--- a/src/cpu/inorder/inorder_dyn_inst.hh
+++ b/src/cpu/inorder/inorder_dyn_inst.hh
@@ -324,7 +324,7 @@ class InOrderDynInst : public FastAlloc, public RefCounted
std::string instName()
{ return (staticInst) ? staticInst->getName() : "undecoded-inst"; }
- void setMachInst(ExtMachInst inst);
+ void setStaticInst(StaticInstPtr si);
ExtMachInst getMachInst() { return staticInst->machInst; }
diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc
index 8ba6bdc9a..b32134e00 100644
--- a/src/cpu/inorder/resources/fetch_unit.cc
+++ b/src/cpu/inorder/resources/fetch_unit.cc
@@ -117,7 +117,7 @@ FetchUnit::createMachInst(std::list<FetchBlock*>::iterator fetch_it,
ext_inst = predecoder[tid]->getExtMachInst(instPC);
inst->pcState(instPC);
- inst->setMachInst(ext_inst);
+ inst->setStaticInst(decoder.decode(ext_inst, instPC.instAddr()));
}
void
diff --git a/src/cpu/inorder/resources/fetch_unit.hh b/src/cpu/inorder/resources/fetch_unit.hh
index 250e53e6c..6d734d7e6 100644
--- a/src/cpu/inorder/resources/fetch_unit.hh
+++ b/src/cpu/inorder/resources/fetch_unit.hh
@@ -39,6 +39,7 @@
#include "arch/predecoder.hh"
#include "arch/tlb.hh"
#include "config/the_isa.hh"
+#include "cpu/decode.hh"
#include "cpu/inorder/resources/cache_unit.hh"
#include "cpu/inorder/inorder_dyn_inst.hh"
#include "cpu/inorder/pipeline_traits.hh"
@@ -88,6 +89,8 @@ class FetchUnit : public CacheUnit
void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+ Decoder decoder;
+
private:
void squashCacheRequest(CacheReqPtr req_ptr);
diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh
index 3b4e8dd7f..7ec17cb77 100644
--- a/src/cpu/inorder/thread_context.hh
+++ b/src/cpu/inorder/thread_context.hh
@@ -78,6 +78,8 @@ class InOrderThreadContext : public ThreadContext
/** @TODO: PERF: Should we bind this to a pointer in constructor? */
TheISA::TLB *getDTBPtr() { return cpu->getDTBPtr(); }
+ Decoder *getDecoderPtr() { return cpu->getDecoderPtr(); }
+
System *getSystemPtr() { return cpu->system; }
/** Returns a pointer to this CPU. */
diff --git a/src/cpu/legiontrace.cc b/src/cpu/legiontrace.cc
index 49b2f513c..484af1008 100644
--- a/src/cpu/legiontrace.cc
+++ b/src/cpu/legiontrace.cc
@@ -52,6 +52,7 @@
#include "arch/sparc/utility.hh"
#include "base/socket.hh"
#include "cpu/base.hh"
+#include "cpu/decode.hh"
#include "cpu/legiontrace.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
@@ -438,8 +439,8 @@ Trace::LegionTraceRecord::dump()
PCState tempPC = pc;
StaticInstPtr legionInst =
- StaticInst::decode(predecoder.getExtMachInst(tempPC),
- lgnPc);
+ thread->getDecoderPtr()->decode(
+ predecoder.getExtMachInst(tempPC), lgnPc);
outs << setfill(' ') << setw(15)
<< " Legion Inst: "
<< "0x" << setw(8) << setfill('0') << hex
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 6d93f2cc8..d09d7f680 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -48,6 +48,7 @@
#include "arch/utility.hh"
#include "base/statistics.hh"
#include "config/the_isa.hh"
+#include "cpu/decode.hh"
#include "cpu/pc_event.hh"
#include "cpu/timebuf.hh"
#include "cpu/translation.hh"
@@ -380,6 +381,9 @@ class DefaultFetch
return (addr & ~(cacheBlkMask));
}
+ /** The decoder. */
+ Decoder decoder;
+
private:
DynInstPtr buildInst(ThreadID tid, StaticInstPtr staticInst,
StaticInstPtr curMacroop, TheISA::PCState thisPC,
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 86f5df9c7..b0ec349dc 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -725,7 +725,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
DPRINTF(Fetch, "[tid:%i]: Translation faulted, building noop.\n", tid);
// We will use a nop in ordier to carry the fault.
DynInstPtr instruction = buildInst(tid,
- StaticInstPtr(TheISA::NoopMachInst, fetchPC.instAddr()),
+ decoder.decode(TheISA::NoopMachInst, fetchPC.instAddr()),
NULL, fetchPC, fetchPC, false);
instruction->setPredTarg(fetchPC);
@@ -1287,11 +1287,10 @@ DefaultFetch<Impl>::fetch(bool &status_change)
do {
if (!(curMacroop || inRom)) {
if (predecoder.extMachInstReady()) {
- ExtMachInst extMachInst;
-
- extMachInst = predecoder.getExtMachInst(thisPC);
- staticInst = StaticInstPtr(extMachInst,
- thisPC.instAddr());
+ ExtMachInst extMachInst =
+ predecoder.getExtMachInst(thisPC);
+ staticInst =
+ decoder.decode(extMachInst, thisPC.instAddr());
// Increment stat of fetched instructions.
++fetchedInsts;
diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh
index ef0fdbb4d..38c94439a 100755
--- a/src/cpu/o3/thread_context.hh
+++ b/src/cpu/o3/thread_context.hh
@@ -73,6 +73,8 @@ class O3ThreadContext : public ThreadContext
/** Returns a pointer to the DTB. */
TheISA::TLB *getDTBPtr() { return cpu->dtb; }
+ Decoder *getDecoderPtr() { return &cpu->fetch.decoder; }
+
/** Returns a pointer to this CPU. */
virtual BaseCPU *getCpuPtr() { return cpu; }
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 699e78764..70e2c39e6 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -383,7 +383,7 @@ BaseSimpleCPU::preExecute()
stayAtPC = false;
ExtMachInst machInst = predecoder.getExtMachInst(pcState);
thread->pcState(pcState);
- instPtr = StaticInst::decode(machInst, pcState.instAddr());
+ instPtr = thread->decoder.decode(machInst, pcState.instAddr());
} else {
stayAtPC = true;
fetchOffset += sizeof(MachInst);
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 0cc90645f..b27ebf998 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -38,6 +38,7 @@
#include "config/full_system.hh"
#include "config/the_isa.hh"
#include "cpu/base.hh"
+#include "cpu/decode.hh"
#include "cpu/pc_event.hh"
#include "cpu/simple_thread.hh"
#include "cpu/static_inst.hh"
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index a74616a0d..2b7b89030 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -40,6 +40,7 @@
#include "base/types.hh"
#include "config/full_system.hh"
#include "config/the_isa.hh"
+#include "cpu/decode.hh"
#include "cpu/thread_context.hh"
#include "cpu/thread_state.hh"
#include "debug/FloatRegs.hh"
@@ -129,6 +130,8 @@ class SimpleThread : public ThreadState
TheISA::TLB *itb;
TheISA::TLB *dtb;
+ Decoder decoder;
+
// constructor: initialize SimpleThread from given process structure
#if FULL_SYSTEM
SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system,
@@ -200,6 +203,8 @@ class SimpleThread : public ThreadState
TheISA::TLB *getDTBPtr() { return dtb; }
+ Decoder *getDecoderPtr() { return &decoder; }
+
System *getSystemPtr() { return system; }
#if FULL_SYSTEM
diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc
index df59d1fc3..2a7b584eb 100644
--- a/src/cpu/static_inst.cc
+++ b/src/cpu/static_inst.cc
@@ -36,11 +36,6 @@
StaticInstPtr StaticInst::nullStaticInstPtr;
-// Define the decode cache hash map.
-StaticInst::DecodeCache StaticInst::decodeCache;
-StaticInst::AddrDecodeCache StaticInst::addrDecodeCache;
-StaticInst::cacheElement StaticInst::recentDecodes[2];
-
using namespace std;
StaticInst::~StaticInst()
@@ -49,25 +44,6 @@ StaticInst::~StaticInst()
delete cachedDisassembly;
}
-void
-StaticInst::dumpDecodeCacheStats()
-{
- cerr << "Decode hash table stats @ " << curTick() << ":" << endl;
- cerr << "\tnum entries = " << decodeCache.size() << endl;
- cerr << "\tnum buckets = " << decodeCache.bucket_count() << endl;
- vector<int> hist(100, 0);
- int max_hist = 0;
- for (int i = 0; i < decodeCache.bucket_count(); ++i) {
- int count = decodeCache.elems_in_bucket(i);
- if (count > max_hist)
- max_hist = count;
- hist[count]++;
- }
- for (int i = 0; i <= max_hist; ++i) {
- cerr << "\tbuckets of size " << i << " = " << hist[i] << endl;
- }
-}
-
bool
StaticInst::hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
TheISA::PCState &tgt) const
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index c41ac38a6..b2773052e 100644
--- a/src/cpu/static_inst.hh
+++ b/src/cpu/static_inst.hh
@@ -34,10 +34,8 @@
#include <bitset>
#include <string>
-#include "arch/isa_traits.hh"
#include "arch/registers.hh"
#include "arch/types.hh"
-#include "base/hashmap.hh"
#include "base/misc.hh"
#include "base/refcnt.hh"
#include "base/types.hh"
@@ -65,7 +63,6 @@ class AtomicSimpleCPU;
class TimingSimpleCPU;
class InorderCPU;
class SymbolTable;
-class AddrDecodePage;
namespace Trace {
class InstRecord;
@@ -285,9 +282,6 @@ class StaticInstPtr;
class StaticInst : public StaticInstBase
{
public:
-
- /// Binary machine instruction type.
- typedef TheISA::MachInst MachInst;
/// Binary extended machine instruction type.
typedef TheISA::ExtMachInst ExtMachInst;
/// Logical register index type.
@@ -416,72 +410,8 @@ class StaticInst : public StaticInstBase
virtual const std::string &disassemble(Addr pc,
const SymbolTable *symtab = 0) const;
- /// Decoded instruction cache type.
- /// For now we're using a generic hash_map; this seems to work
- /// pretty well.
- typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache;
-
- /// A cache of decoded instruction objects.
- static DecodeCache decodeCache;
-
- /**
- * Dump some basic stats on the decode cache hash map.
- * Only gets called if DECODE_CACHE_HASH_STATS is defined.
- */
- static void dumpDecodeCacheStats();
-
- /// Decode a machine instruction.
- /// @param mach_inst The binary instruction to decode.
- /// @retval A pointer to the corresponding StaticInst object.
- //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;
-
- cacheElement() : decodePage(NULL) { }
- };
-
- /// 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;
@@ -510,13 +440,6 @@ class StaticInstPtr : public RefCountingPtr<StaticInst>
{
}
- /// Construct directly from machine instruction.
- /// Calls StaticInst::decode().
- explicit StaticInstPtr(TheISA::ExtMachInst mach_inst, Addr addr)
- : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst, addr))
- {
- }
-
/// Convert to pointer to StaticInstBase class.
operator const StaticInstBasePtr()
{
@@ -524,123 +447,4 @@ 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
- 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.
- 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.
- void
- insert(Addr addr, StaticInstPtr &si)
- {
- instructions[addr & lowerMask] = si;
- valid[addr & lowerMask] = true;
- }
-};
-
-
-inline StaticInstPtr
-StaticInst::decode(StaticInst::ExtMachInst mach_inst, Addr addr)
-{
-#ifdef DECODE_CACHE_HASH_STATS
- // Simple stats on decode hash_map. Turns out the default
- // hash function is as good as anything I could come up with.
- const int dump_every_n = 10000000;
- static int decodes_til_dump = dump_every_n;
-
- if (--decodes_til_dump == 0) {
- dumpDecodeCacheStats();
- decodes_til_dump = dump_every_n;
- }
-#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;
-}
-
#endif // __CPU_STATIC_INST_HH__
diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh
index 0f7228f0c..3b7f8b3c3 100644
--- a/src/cpu/thread_context.hh
+++ b/src/cpu/thread_context.hh
@@ -48,6 +48,7 @@ namespace TheISA
}
class BaseCPU;
class Checkpoint;
+class Decoder;
class EndQuiesceEvent;
class TranslatingPort;
class FunctionalPort;
@@ -120,6 +121,8 @@ class ThreadContext
virtual TheISA::TLB *getDTBPtr() = 0;
+ virtual Decoder *getDecoderPtr() = 0;
+
virtual System *getSystemPtr() = 0;
#if FULL_SYSTEM
@@ -287,6 +290,8 @@ class ProxyThreadContext : public ThreadContext
TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); }
+ Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); }
+
System *getSystemPtr() { return actualTC->getSystemPtr(); }
#if FULL_SYSTEM