ISA,CPU: Generalize and split out the components of the decode cache.
authorGabe Black <gblack@eecs.umich.edu>
Sat, 26 May 2012 20:45:12 +0000 (13:45 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sat, 26 May 2012 20:45:12 +0000 (13:45 -0700)
This will allow it to be specialized by the ISAs. The existing caching scheme
is provided by the BasicDecodeCache in the GenericISA namespace and is built
from the generalized components.

--HG--
rename : src/cpu/decode_cache.cc => src/arch/generic/decode_cache.cc

18 files changed:
src/arch/alpha/decoder.cc
src/arch/alpha/decoder.hh
src/arch/arm/decoder.cc
src/arch/arm/decoder.hh
src/arch/generic/SConscript [new file with mode: 0644]
src/arch/generic/decode_cache.cc [new file with mode: 0644]
src/arch/generic/decode_cache.hh [new file with mode: 0644]
src/arch/mips/decoder.cc
src/arch/mips/decoder.hh
src/arch/power/decoder.cc
src/arch/power/decoder.hh
src/arch/sparc/decoder.cc
src/arch/sparc/decoder.hh
src/arch/x86/decoder.cc
src/arch/x86/decoder.hh
src/cpu/SConscript
src/cpu/decode_cache.cc [deleted file]
src/cpu/decode_cache.hh

index 8cabe515dff0f50588b2a4d90b99d37e2208cdf1..e5a7663ffd921771829636999db58a078dd0dd92 100644 (file)
@@ -33,6 +33,6 @@
 namespace AlphaISA
 {
 
-DecodeCache Decoder::defaultCache;
+GenericISA::BasicDecodeCache Decoder::defaultCache;
 
 }
index 4233c2d444c0c8e7347de52115c5b362f59a556a..ef2f5856cd59e72cea9d7248a003b105d9504365 100644 (file)
 #ifndef __ARCH_ALPHA_DECODER_HH__
 #define __ARCH_ALPHA_DECODER_HH__
 
+#include "arch/generic/decode_cache.hh"
 #include "arch/types.hh"
-#include "cpu/decode_cache.hh"
-#include "cpu/static_inst_fwd.hh"
+#include "cpu/static_inst.hh"
 #include "sim/full_system.hh"
 
+class ThreadContext;
+
 namespace AlphaISA
 {
 
@@ -99,7 +101,7 @@ class Decoder
 
   protected:
     /// A cache of decoded instruction objects.
-    static DecodeCache defaultCache;
+    static GenericISA::BasicDecodeCache defaultCache;
 
   public:
     StaticInstPtr decodeInst(ExtMachInst mach_inst);
index 65badbc49595f0c59b75364cfe60848cfe286f3e..4001f7597b1e5fc1ab0b7e61b7d97147be2142b7 100644 (file)
@@ -38,7 +38,7 @@
 namespace ArmISA
 {
 
-DecodeCache Decoder::defaultCache;
+GenericISA::BasicDecodeCache Decoder::defaultCache;
 
 void
 Decoder::process()
index dd51fd08258934edb54e899f22f49a8cd0da0d21..a5f2c88a572e0cd4f8bf20ad9f9aa1bd6c880ed4 100644 (file)
@@ -35,8 +35,9 @@
 
 #include "arch/arm/miscregs.hh"
 #include "arch/arm/types.hh"
+#include "arch/generic/decode_cache.hh"
 #include "base/types.hh"
-#include "cpu/decode_cache.hh"
+#include "cpu/static_inst.hh"
 
 class ThreadContext;
 
@@ -122,7 +123,7 @@ class Decoder
 
   protected:
     /// A cache of decoded instruction objects.
-    static DecodeCache defaultCache;
+    static GenericISA::BasicDecodeCache defaultCache;
 
   public:
     StaticInstPtr decodeInst(ExtMachInst mach_inst);
diff --git a/src/arch/generic/SConscript b/src/arch/generic/SConscript
new file mode 100644 (file)
index 0000000..f2edc80
--- /dev/null
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 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
+
+Import('*')
+
+Source('decode_cache.cc')
diff --git a/src/arch/generic/decode_cache.cc b/src/arch/generic/decode_cache.cc
new file mode 100644 (file)
index 0000000..7211ba3
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011-2012 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 "arch/generic/decode_cache.hh"
+#include "arch/decoder.hh"
+#include "arch/types.hh"
+#include "config/the_isa.hh"
+#include "cpu/static_inst.hh"
+
+namespace GenericISA
+{
+
+StaticInstPtr
+BasicDecodeCache::decode(TheISA::Decoder *decoder,
+        TheISA::ExtMachInst mach_inst, Addr addr)
+{
+    StaticInstPtr &si = decodePages.lookup(addr);
+    if (si && (si->machInst == mach_inst))
+        return si;
+
+    DecodeCache::InstMap::iterator iter = instMap.find(mach_inst);
+    if (iter != instMap.end()) {
+        si = iter->second;
+        return si;
+    }
+
+    si = decoder->decodeInst(mach_inst);
+    instMap[mach_inst] = si;
+    return si;
+}
+
+} // namespace GenericISA
diff --git a/src/arch/generic/decode_cache.hh b/src/arch/generic/decode_cache.hh
new file mode 100644 (file)
index 0000000..c6bce72
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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 __ARCH_GENERIC_DECODE_CACHE_HH__
+#define __ARCH_GENERIC_DECODE_CACHE_HH__
+
+#include "arch/types.hh"
+#include "config/the_isa.hh"
+#include "cpu/decode_cache.hh"
+#include "cpu/static_inst_fwd.hh"
+
+namespace TheISA
+{
+    class Decoder;
+}
+
+namespace GenericISA
+{
+
+class BasicDecodeCache
+{
+  private:
+    DecodeCache::InstMap instMap;
+    DecodeCache::AddrMap<StaticInstPtr> decodePages;
+
+  public:
+    /// Decode a machine instruction.
+    /// @param mach_inst The binary instruction to decode.
+    /// @retval A pointer to the corresponding StaticInst object.
+    StaticInstPtr decode(TheISA::Decoder * const decoder,
+            TheISA::ExtMachInst mach_inst, Addr addr);
+};
+
+} // namespace GenericISA
+
+#endif // __ARCH_GENERIC_DECODE_CACHE_HH__
index 45b1f71846f48dab8736d2a42841f592ef1174de..dd4ba2be1f27f415d25b0f2c756c624e5d88e234 100644 (file)
@@ -33,6 +33,6 @@
 namespace MipsISA
 {
 
-DecodeCache Decoder::defaultCache;
+GenericISA::BasicDecodeCache Decoder::defaultCache;
 
 }
index 95385961d890f3b5ee499aca6b6b1cd9e98c75a9..4857eb35362e6ebbc3c142538909c9a4d20aebac 100644 (file)
 #ifndef __ARCH_MIPS_DECODER_HH__
 #define __ARCH_MIPS_DECODER_HH__
 
+#include "arch/generic/decode_cache.hh"
 #include "arch/mips/types.hh"
 #include "base/misc.hh"
 #include "base/types.hh"
-#include "cpu/decode_cache.hh"
-#include "cpu/static_inst_fwd.hh"
+#include "cpu/static_inst.hh"
 
 class ThreadContext;
 
@@ -99,7 +99,7 @@ class Decoder
 
   protected:
     /// A cache of decoded instruction objects.
-    static DecodeCache defaultCache;
+    static GenericISA::BasicDecodeCache defaultCache;
 
   public:
     StaticInstPtr decodeInst(ExtMachInst mach_inst);
index 96fd9297b5acd6bdc4fdddf71d025a368f49491d..1a6a3b38f6c2ae8173273e0601ca9e08b0cbe1fb 100644 (file)
@@ -33,6 +33,6 @@
 namespace PowerISA
 {
 
-DecodeCache Decoder::defaultCache;
+GenericISA::BasicDecodeCache Decoder::defaultCache;
 
 }
index c45473a9008b56724c240dab41ba8ecb2073d7c1..60fc8ca75c5d85a681fbc8858ada9cdfeddf2a30 100644 (file)
 #ifndef __ARCH_POWER_DECODER_HH__
 #define __ARCH_POWER_DECODER_HH__
 
+#include "arch/generic/decode_cache.hh"
 #include "arch/types.hh"
-#include "cpu/decode_cache.hh"
-#include "cpu/static_inst_fwd.hh"
+#include "cpu/static_inst.hh"
+
+class ThreadContext;
 
 namespace PowerISA
 {
@@ -105,7 +107,7 @@ class Decoder
     }
   protected:
     /// A cache of decoded instruction objects.
-    static DecodeCache defaultCache;
+    static GenericISA::BasicDecodeCache defaultCache;
 
   public:
     StaticInstPtr decodeInst(ExtMachInst mach_inst);
index e8769a57335a4cf8bb47dfdcd03f029c6546922a..a7f7704ad8f4e75936c6650bd4c153fc86e4c120 100644 (file)
@@ -33,6 +33,6 @@
 namespace SparcISA
 {
 
-DecodeCache Decoder::defaultCache;
+GenericISA::BasicDecodeCache Decoder::defaultCache;
 
 }
index 999a605a7e19add14dc7667f079d3a3038d43d9b..ea079328664f784c4f712c2210254125ea112ca5 100644 (file)
 #ifndef __ARCH_SPARC_DECODER_HH__
 #define __ARCH_SPARC_DECODER_HH__
 
+#include "arch/generic/decode_cache.hh"
 #include "arch/sparc/registers.hh"
 #include "arch/types.hh"
-#include "cpu/decode_cache.hh"
-#include "cpu/static_inst_fwd.hh"
+#include "cpu/static_inst.hh"
 #include "cpu/thread_context.hh"
 
 class ThreadContext;
@@ -109,7 +109,7 @@ class Decoder
 
   protected:
     /// A cache of decoded instruction objects.
-    static DecodeCache defaultCache;
+    static GenericISA::BasicDecodeCache defaultCache;
 
   public:
     StaticInstPtr decodeInst(ExtMachInst mach_inst);
index d7199fa8226daaa8de1067e04c934a2b7ef9ee80..5fb2dcaf4dd4c9c32adff0a6e7c3beec38df97de 100644 (file)
@@ -408,6 +408,25 @@ Decoder::State Decoder::doImmediateState()
     return nextState;
 }
 
-DecodeCache Decoder::defaultCache;
+DecodeCache::InstMap Decoder::instMap;
+DecodeCache::AddrMap<StaticInstPtr> Decoder::decodePages;
+
+StaticInstPtr
+Decoder::decode(ExtMachInst mach_inst, Addr addr)
+{
+    StaticInstPtr &si = decodePages.lookup(addr);
+    if (si && (si->machInst == mach_inst))
+        return si;
+
+    DecodeCache::InstMap::iterator iter = instMap.find(mach_inst);
+    if (iter != instMap.end()) {
+        si = iter->second;
+        return si;
+    }
+
+    si = decodeInst(mach_inst);
+    instMap[mach_inst] = si;
+    return si;
+}
 
 }
index 300e2238c512d4a626497d9a91a4f2a90cfcb3d1..725d443d6b102babb7c6cc08c1b5b6e961ee1e10 100644 (file)
@@ -40,7 +40,7 @@
 #include "base/trace.hh"
 #include "base/types.hh"
 #include "cpu/decode_cache.hh"
-#include "cpu/static_inst_fwd.hh"
+#include "cpu/static_inst.hh"
 #include "debug/Decoder.hh"
 
 class ThreadContext;
@@ -218,8 +218,9 @@ class Decoder
     }
 
   protected:
-    /// A cache of decoded instruction objects.
-    static DecodeCache defaultCache;
+    /// Caching for decoded instruction objects.
+    static DecodeCache::InstMap instMap;
+    static DecodeCache::AddrMap<StaticInstPtr> decodePages;
 
   public:
     StaticInstPtr decodeInst(ExtMachInst mach_inst);
@@ -227,11 +228,7 @@ class Decoder
     /// 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)
-    {
-        return defaultCache.decode(this, mach_inst, addr);
-    }
+    StaticInstPtr decode(ExtMachInst mach_inst, Addr addr);
 
     StaticInstPtr
     decode(X86ISA::PCState &nextPC)
index 4b327f8a11c97b9616d43183ebba97617d76007e..e1ba59b8b7a74645a7f06773ad5f8ec9c22dcda6 100644 (file)
@@ -108,7 +108,6 @@ SimObject('NativeTrace.py')
 Source('activity.cc')
 Source('base.cc')
 Source('cpuevent.cc')
-Source('decode_cache.cc')
 Source('exetrace.cc')
 Source('func_unit.cc')
 Source('inteltrace.cc')
diff --git a/src/cpu/decode_cache.cc b/src/cpu/decode_cache.cc
deleted file mode 100644 (file)
index 636bf92..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2011-2012 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 "arch/decoder.hh"
-#include "arch/isa_traits.hh"
-#include "arch/types.hh"
-#include "base/hashmap.hh"
-#include "config/the_isa.hh"
-#include "cpu/static_inst.hh"
-
-void
-DecodeCache::DecodePages::update(PageIt recentest)
-{
-    recent[1] = recent[0];
-    recent[0] = recentest;
-}
-
-void
-DecodeCache::DecodePages::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);
-}
-
-DecodeCache::DecodePages::DecodePages()
-{
-    recent[0] = recent[1] = pageMap.end();
-}
-
-DecodeCache::DecodePage *
-DecodeCache::DecodePages::getPage(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 an existing page, so add a new one.
-    DecodePage *newPage = new DecodePage;
-    addPage(page_addr, newPage);
-    return newPage;
-}
-
-StaticInstPtr
-DecodeCache::decode(TheISA::Decoder *decoder,
-        ExtMachInst mach_inst, Addr addr)
-{
-    // Try to find a matching address based table of instructions.
-    DecodePage *page = decodePages.getPage(addr);
-
-    // Use the table to decode the instruction. It will fall back to other
-    // mechanisms if it needs to.
-    Addr offset = addr & (TheISA::PageBytes - 1);
-    StaticInstPtr si = page->insts[offset];
-    if (si && (si->machInst == mach_inst))
-        return si;
-
-    InstMap::iterator iter = instMap.find(mach_inst);
-    if (iter != instMap.end()) {
-        si = iter->second;
-        page->insts[offset] = si;
-        return si;
-    }
-
-    si = decoder->decodeInst(mach_inst);
-    instMap[mach_inst] = si;
-    page->insts[offset] = si;
-    return si;
-}
index 473340586a3ee2d2b469cd78fefecf8226b551b4..34387419fb0807021b0a9a98955a8b34dc7ceb58 100644 (file)
 #include "arch/types.hh"
 #include "base/hashmap.hh"
 #include "config/the_isa.hh"
-#include "cpu/static_inst.hh"
+#include "cpu/static_inst_fwd.hh"
 
 namespace TheISA
 {
     class Decoder;
 }
 
-class DecodeCache
+namespace DecodeCache
 {
-  private:
-    typedef TheISA::ExtMachInst ExtMachInst;
 
-    /// Hash of decoded instructions.
-    typedef m5::hash_map<ExtMachInst, StaticInstPtr> InstMap;
-    InstMap instMap;
-    struct DecodePage {
-        StaticInstPtr insts[TheISA::PageBytes];
+/// Hash for decoded instructions.
+typedef m5::hash_map<TheISA::ExtMachInst, StaticInstPtr> InstMap;
+
+/// A sparse map from an Addr to a Value, stored in page chunks.
+template<class Value>
+class AddrMap
+{
+  protected:
+    // A pages worth of cache entries.
+    struct CachePage {
+        Value items[TheISA::PageBytes];
     };
+    // A map of cache pages which allows a sparse mapping.
+    typedef typename m5::hash_map<Addr, CachePage *> PageMap;
+    typedef typename PageMap::iterator PageIt;
+    // Mini cache of recent lookups.
+    PageIt recent[2];
+    PageMap pageMap;
+
+    /// Update the mini cache of recent lookups.
+    /// @param recentest The most recent result;
+    void
+    update(PageIt recentest)
+    {
+        recent[1] = recent[0];
+        recent[0] = recentest;
+    }
 
-    /// A store of DecodePages. Basically a slightly smarter hash_map.
-    class DecodePages
+    /// Attempt to find the CacheePage 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.
+    CachePage *
+    getPage(Addr addr)
     {
-      protected:
-        typedef typename m5::hash_map<Addr, DecodePage *> PageMap;
-        typedef typename PageMap::iterator PageIt;
-        PageIt recent[2];
-        PageMap pageMap;
+        Addr page_addr = addr & ~(TheISA::PageBytes - 1);
 
-        /// Update the small cache of recent lookups.
-        /// @param recentest The most recent result;
-        void update(PageIt recentest);
-        void addPage(Addr addr, DecodePage *page);
+        // 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;
+            }
+        }
 
-      public:
-        /// Constructor
-        DecodePages();
+        // Actually look in the has_map.
+        PageIt it = pageMap.find(page_addr);
+        if (it != pageMap.end()) {
+            update(it);
+            return it->second;
+        }
 
-        /// 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 *getPage(Addr addr);
-    } decodePages;
+        // Didn't find an existing page, so add a new one.
+        CachePage *newPage = new CachePage;
+        page_addr = page_addr & ~(TheISA::PageBytes - 1);
+        typename PageMap::value_type to_insert(page_addr, newPage);
+        update(pageMap.insert(to_insert).first);
+        return newPage;
+    }
 
   public:
-    /// Decode a machine instruction.
-    /// @param mach_inst The binary instruction to decode.
-    /// @retval A pointer to the corresponding StaticInst object.
-    StaticInstPtr decode(TheISA::Decoder * const decoder,
-            ExtMachInst mach_inst, Addr addr);
+    /// Constructor
+    AddrMap()
+    {
+        recent[0] = recent[1] = pageMap.end();
+    }
+
+    Value &
+    lookup(Addr addr)
+    {
+        CachePage *page = getPage(addr);
+        return page->items[addr & (TheISA::PageBytes - 1)];
+    }
 };
 
+} // namespace DecodeCache
+
 #endif // __CPU_DECODE_CACHE_HH__