summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/remote_gdb.cc2
-rw-r--r--src/cpu/base_dyn_inst_impl.hh2
-rw-r--r--src/cpu/exetrace.cc2
-rw-r--r--src/cpu/simple/base.cc5
-rw-r--r--src/cpu/static_inst.cc2
-rw-r--r--src/cpu/static_inst.hh142
6 files changed, 145 insertions, 10 deletions
diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc
index a68e5218e..ea5db36f4 100644
--- a/src/arch/alpha/remote_gdb.cc
+++ b/src/arch/alpha/remote_gdb.cc
@@ -284,7 +284,7 @@ RemoteGDB::setSingleStep()
// User was stopped at pc, e.g. the instruction at pc was not
// executed.
MachInst inst = read<MachInst>(pc);
- StaticInstPtr si(inst);
+ StaticInstPtr si(inst, 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/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 98b8c247c..9b87f2e8a 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -656,7 +656,7 @@ Trace::InstRecord::dump()
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/simple/base.cc b/src/cpu/simple/base.cc
index b97eabf33..b7f60522f 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -392,7 +392,8 @@ BaseSimpleCPU::preExecute()
thread->setNextPC(thread->readPC() + predecoder.getInstSize());
#endif // X86_ISA
stayAtPC = false;
- instPtr = StaticInst::decode(predecoder.getExtMachInst());
+ instPtr = StaticInst::decode(predecoder.getExtMachInst(),
+ thread->readPC());
} else {
stayAtPC = true;
fetchOffset += sizeof(MachInst);
@@ -437,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;
diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc
index a5580d707..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()
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index b11e74c6e..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;
@@ -349,6 +350,7 @@ class StaticInst : public StaticInstBase
: StaticInstBase(__opClass),
machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
{
+ memset(&recentDecodes, 0, 2 * sizeof(cacheElement));
}
public:
@@ -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;
}