arch-arm,cpu: Introduce a getEMI virtual method on StaticInst.
[gem5.git] / src / cpu / static_inst.hh
index 2e1ebd76633a9dd08c5df5791859cef06adf0fe8..b2cd50851bf6256527052b920ec5127d466ef99e 100644 (file)
@@ -1,5 +1,18 @@
 /*
+ * Copyright (c) 2017, 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2013 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * 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: Steve Reinhardt
  */
 
 #ifndef __CPU_STATIC_INST_HH__
 #define __CPU_STATIC_INST_HH__
 
 #include <bitset>
+#include <memory>
 #include <string>
 
-#include "arch/isa_traits.hh"
-#include "arch/utility.hh"
-#include "sim/faults.hh"
-#include "base/bitfield.hh"
-#include "base/hashmap.hh"
-#include "base/misc.hh"
+#include "arch/registers.hh"
+#include "arch/types.hh"
+#include "base/logging.hh"
 #include "base/refcnt.hh"
+#include "base/types.hh"
+#include "config/the_isa.hh"
 #include "cpu/op_class.hh"
-#include "cpu/o3/dyn_inst.hh"
-#include "sim/faults.hh"
-#include "sim/host.hh"
+#include "cpu/reg_class.hh"
+#include "cpu/static_inst_fwd.hh"
+#include "cpu/thread_context.hh"
+#include "enums/StaticInstFlags.hh"
+#include "sim/byteswap.hh"
 
 // forward declarations
-struct AlphaSimpleImpl;
-struct OzoneImpl;
-struct SimpleImpl;
-class ThreadContext;
-class DynInst;
 class Packet;
 
-template <class Impl>
-class OzoneDynInst;
+class ExecContext;
 
-class CheckerCPU;
-class FastCPU;
-class AtomicSimpleCPU;
-class TimingSimpleCPU;
-class InorderCPU;
+namespace Loader
+{
 class SymbolTable;
-class AddrDecodePage;
-
-namespace Trace {
-    class InstRecord;
-}
+} // namespace Loader
 
-typedef uint32_t MicroPC;
+namespace Trace
+{
+class InstRecord;
+} // namespace Trace
 
 /**
  * Base, ISA-independent static instruction class.
@@ -79,87 +82,22 @@ typedef uint32_t MicroPC;
  * solely on these flags can process instructions without being
  * recompiled for multiple ISAs.
  */
-class StaticInstBase : public RefCounted
+class StaticInst : public RefCounted, public StaticInstFlags
 {
-  protected:
+  public:
+    using RegIdArrayPtr = RegId (StaticInst:: *)[];
 
-    /// Set of boolean static instruction properties.
-    ///
-    /// Notes:
-    /// - The IsInteger and IsFloating flags are based on the class of
-    /// registers accessed by the instruction.  Although most
-    /// instructions will have exactly one of these two flags set, it
-    /// is possible for an instruction to have neither (e.g., direct
-    /// unconditional branches, memory barriers) or both (e.g., an
-    /// FP/int conversion).
-    /// - If IsMemRef is set, then exactly one of IsLoad or IsStore
-    /// will be set.
-    /// - If IsControl is set, then exactly one of IsDirectControl or
-    /// IsIndirect Control will be set, and exactly one of
-    /// IsCondControl or IsUncondControl will be set.
-    /// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
-    /// implemented as flags since in the current model there's no
-    /// other way for instructions to inject behavior into the
-    /// pipeline outside of fetch.  Once we go to an exec-in-exec CPU
-    /// model we should be able to get rid of these flags and
-    /// implement this behavior via the execute() methods.
-    ///
-    enum Flags {
-        IsNop,         ///< Is a no-op (no effect at all).
-
-        IsInteger,     ///< References integer regs.
-        IsFloating,    ///< References FP regs.
-
-        IsMemRef,      ///< References memory (load, store, or prefetch).
-        IsLoad,                ///< Reads from memory (load or prefetch).
-        IsStore,       ///< Writes to memory.
-        IsStoreConditional,    ///< Store conditional instruction.
-        IsInstPrefetch,        ///< Instruction-cache prefetch.
-        IsDataPrefetch,        ///< Data-cache prefetch.
-        IsCopy,         ///< Fast Cache block copy
-
-        IsControl,             ///< Control transfer instruction.
-        IsDirectControl,       ///< PC relative control transfer.
-        IsIndirectControl,     ///< Register indirect control transfer.
-        IsCondControl,         ///< Conditional control transfer.
-        IsUncondControl,       ///< Unconditional control transfer.
-        IsCall,                        ///< Subroutine call.
-        IsReturn,              ///< Subroutine return.
-
-        IsCondDelaySlot,///< Conditional Delay-Slot Instruction
-
-        IsThreadSync,  ///< Thread synchronization operation.
-
-        IsSerializing, ///< Serializes pipeline: won't execute until all
-                        /// older instructions have committed.
-        IsSerializeBefore,
-        IsSerializeAfter,
-        IsMemBarrier,  ///< Is a memory barrier
-        IsWriteBarrier,        ///< Is a write barrier
-
-        IsNonSpeculative, ///< Should not be executed speculatively
-        IsQuiesce,      ///< Is a quiesce instruction
-
-        IsIprAccess,    ///< Accesses IPRs
-        IsUnverifiable, ///< Can't be verified by a checker
-
-        IsSyscall,      ///< Causes a system call to be emulated in syscall
-                        /// emulation mode.
-
-        //Flags for microcode
-        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
-        //This flag doesn't do anything yet
-        IsMicroBranch, ///< This microop branches within the microcode for a macroop
-
-        NumFlags
-    };
+  private:
+    /// See srcRegIdx().
+    RegIdArrayPtr _srcRegIdxPtr = nullptr;
+
+    /// See destRegIdx().
+    RegIdArrayPtr _destRegIdxPtr = nullptr;
+
+  protected:
 
     /// Flag values for this instruction.
-    std::bitset<NumFlags> flags;
+    std::bitset<Num_Flags> flags;
 
     /// See opClass().
     OpClass _opClass;
@@ -175,26 +113,24 @@ class StaticInstBase : public RefCounted
     //@{
     int8_t _numFPDestRegs;
     int8_t _numIntDestRegs;
+    int8_t _numCCDestRegs;
     //@}
 
-    /// Constructor.
-    /// It's important to initialize everything here to a sane
-    /// default, since the decoder generally only overrides
-    /// the fields that are meaningful for the particular
-    /// instruction.
-    StaticInstBase(OpClass __opClass)
-        : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
-          _numFPDestRegs(0), _numIntDestRegs(0)
-    {
-    }
+    /** To use in architectures with vector register file. */
+    /** @{ */
+    int8_t _numVecDestRegs;
+    int8_t _numVecElemDestRegs;
+    int8_t _numVecPredDestRegs;
+    /** @} */
 
   public:
 
     /// @name Register information.
-    /// The sum of numFPDestRegs() and numIntDestRegs() equals
-    /// numDestRegs().  The former two functions are used to track
-    /// physical register usage for machines with separate int & FP
-    /// reg files.
+    /// The sum of numFPDestRegs(), numIntDestRegs(), numVecDestRegs(),
+    /// numVecElemDestRegs() and numVecPredDestRegs() equals numDestRegs().
+    /// The former two functions are used to track physical register usage for
+    /// machines with separate int & FP reg files, the next three are for
+    /// machines with vector and predicate register files.
     //@{
     /// Number of source registers.
     int8_t numSrcRegs()  const { return _numSrcRegs; }
@@ -204,47 +140,65 @@ class StaticInstBase : public RefCounted
     int8_t numFPDestRegs()  const { return _numFPDestRegs; }
     /// Number of integer destination regs.
     int8_t numIntDestRegs() const { return _numIntDestRegs; }
+    /// Number of vector destination regs.
+    int8_t numVecDestRegs() const { return _numVecDestRegs; }
+    /// Number of vector element destination regs.
+    int8_t numVecElemDestRegs() const { return _numVecElemDestRegs; }
+    /// Number of predicate destination regs.
+    int8_t numVecPredDestRegs() const { return _numVecPredDestRegs; }
+    /// Number of coprocesor destination regs.
+    int8_t numCCDestRegs() const { return _numCCDestRegs; }
     //@}
 
     /// @name Flag accessors.
     /// These functions are used to access the values of the various
-    /// instruction property flags.  See StaticInstBase::Flags for descriptions
+    /// instruction property flags.  See StaticInst::Flags for descriptions
     /// of the individual flags.
     //@{
 
-    bool isNop()         const { return flags[IsNop]; }
+    bool isNop()          const { return flags[IsNop]; }
 
-    bool isMemRef()              const { return flags[IsMemRef]; }
-    bool isLoad()        const { return flags[IsLoad]; }
-    bool isStore()       const { return flags[IsStore]; }
-    bool isStoreConditional()    const { return flags[IsStoreConditional]; }
+    bool
+    isMemRef() const
+    {
+        return flags[IsLoad] || flags[IsStore] || flags[IsAtomic];
+    }
+    bool isLoad()         const { return flags[IsLoad]; }
+    bool isStore()        const { return flags[IsStore]; }
+    bool isAtomic()       const { return flags[IsAtomic]; }
+    bool isStoreConditional()     const { return flags[IsStoreConditional]; }
     bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
     bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
-    bool isCopy()         const { return flags[IsCopy];}
+    bool isPrefetch()     const { return isInstPrefetch() ||
+                                         isDataPrefetch(); }
 
-    bool isInteger()     const { return flags[IsInteger]; }
-    bool isFloating()    const { return flags[IsFloating]; }
+    bool isInteger()      const { return flags[IsInteger]; }
+    bool isFloating()     const { return flags[IsFloating]; }
+    bool isVector()       const { return flags[IsVector]; }
 
-    bool isControl()     const { return flags[IsControl]; }
-    bool isCall()        const { return flags[IsCall]; }
-    bool isReturn()      const { return flags[IsReturn]; }
-    bool isDirectCtrl()          const { return flags[IsDirectControl]; }
+    bool isControl()      const { return flags[IsControl]; }
+    bool isCall()         const { return flags[IsCall]; }
+    bool isReturn()       const { return flags[IsReturn]; }
+    bool isDirectCtrl()   const { return flags[IsDirectControl]; }
     bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
-    bool isCondCtrl()    const { return flags[IsCondControl]; }
-    bool isUncondCtrl()          const { return flags[IsUncondControl]; }
-    bool isCondDelaySlot() const { return flags[IsCondDelaySlot]; }
+    bool isCondCtrl()     const { return flags[IsCondControl]; }
+    bool isUncondCtrl()   const { return flags[IsUncondControl]; }
 
-    bool isThreadSync()   const { return flags[IsThreadSync]; }
     bool isSerializing()  const { return flags[IsSerializing] ||
                                       flags[IsSerializeBefore] ||
                                       flags[IsSerializeAfter]; }
     bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
     bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
-    bool isMemBarrier()   const { return flags[IsMemBarrier]; }
+    bool isSquashAfter() const { return flags[IsSquashAfter]; }
+    bool
+    isFullMemBarrier() const
+    {
+        return flags[IsReadBarrier] && flags[IsWriteBarrier];
+    }
+    bool isReadBarrier() const { return flags[IsReadBarrier]; }
     bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
     bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
     bool isQuiesce() const { return flags[IsQuiesce]; }
-    bool isIprAccess() const { return flags[IsIprAccess]; }
     bool isUnverifiable() const { return flags[IsUnverifiable]; }
     bool isSyscall() const { return flags[IsSyscall]; }
     bool isMacroop() const { return flags[IsMacroop]; }
@@ -252,82 +206,74 @@ class StaticInstBase : public RefCounted
     bool isDelayedCommit() const { return flags[IsDelayedCommit]; }
     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]; }
+    // hardware transactional memory
+    // HtmCmds must be identified as such in order
+    // to provide them with necessary memory ordering semantics.
+    bool isHtmStart() const { return flags[IsHtmStart]; }
+    bool isHtmStop() const { return flags[IsHtmStop]; }
+    bool isHtmCancel() const { return flags[IsHtmCancel]; }
+
+    bool
+    isHtmCmd() const
+    {
+        return isHtmStart() || isHtmStop() || isHtmCancel();
+    }
     //@}
 
+    void setFirstMicroop() { flags[IsFirstMicroop] = true; }
+    void setLastMicroop() { flags[IsLastMicroop] = true; }
+    void setDelayedCommit() { flags[IsDelayedCommit] = true; }
+    void setFlag(Flags f) { flags[f] = true; }
+
     /// Operation class.  Used to select appropriate function unit in issue.
     OpClass opClass()     const { return _opClass; }
-};
-
-
-// forward declaration
-class StaticInstPtr;
-
-/**
- * Generic yet ISA-dependent static instruction class.
- *
- * This class builds on StaticInstBase, defining fields and interfaces
- * that are generic across all ISAs but that differ in details
- * according to the specific ISA being used.
- */
-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.
-    typedef TheISA::RegIndex RegIndex;
-
-    enum {
-        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,       //< Max source regs
-        MaxInstDestRegs = TheISA::MaxInstDestRegs,     //< Max dest regs
-    };
 
 
     /// Return logical index (architectural reg num) of i'th destination reg.
     /// Only the entries from 0 through numDestRegs()-1 are valid.
-    RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
+    const RegId &destRegIdx(int i) const { return (this->*_destRegIdxPtr)[i]; }
+
+    void
+    setDestRegIdx(int i, const RegId &val)
+    {
+        (this->*_destRegIdxPtr)[i] = val;
+    }
 
     /// Return logical index (architectural reg num) of i'th source reg.
     /// Only the entries from 0 through numSrcRegs()-1 are valid.
-    RegIndex srcRegIdx(int i)  const { return _srcRegIdx[i]; }
+    const RegId &srcRegIdx(int i) const { return (this->*_srcRegIdxPtr)[i]; }
+
+    void
+    setSrcRegIdx(int i, const RegId &val)
+    {
+        (this->*_srcRegIdxPtr)[i] = val;
+    }
 
     /// Pointer to a statically allocated "null" instruction object.
-    /// Used to give eaCompInst() and memAccInst() something to return
-    /// when called on non-memory instructions.
     static StaticInstPtr nullStaticInstPtr;
 
-    /**
-     * Memory references only: returns "fake" instruction representing
-     * the effective address part of the memory operation.  Used to
-     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
-     * just the EA computation.
-     */
-    virtual const
-    StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; }
-
-    /**
-     * Memory references only: returns "fake" instruction representing
-     * the memory access part of the memory operation.  Used to
-     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
-     * just the memory access (not the EA computation).
-     */
-    virtual const
-    StaticInstPtr &memAccInst() const { return nullStaticInstPtr; }
+    /// Pointer to a statically allocated generic "nop" instruction object.
+    static StaticInstPtr nopStaticInstPtr;
 
     /// The binary machine instruction.
-    const ExtMachInst machInst;
+    const TheISA::ExtMachInst machInst;
+
+    virtual uint64_t getEMI() const { return 0; }
 
   protected:
 
-    /// See destRegIdx().
-    RegIndex _destRegIdx[MaxInstDestRegs];
-    /// See srcRegIdx().
-    RegIndex _srcRegIdx[MaxInstSrcRegs];
+    /**
+     * Set the pointers which point to the arrays of source and destination
+     * register indices. These will be defined in derived classes which know
+     * what size they need to be, and installed here so they can be accessed
+     * with the base class accessors.
+     */
+    void
+    setRegIdxArrays(RegIdArrayPtr src, RegIdArrayPtr dest)
+    {
+        _srcRegIdxPtr = src;
+        _destRegIdxPtr = dest;
+    }
 
     /**
      * Base mnemonic (e.g., "add").  Used by generateDisassembly()
@@ -347,45 +293,54 @@ class StaticInst : public StaticInstBase
      * Internal function to generate disassembly string.
      */
     virtual std::string
-    generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
+    generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const = 0;
 
     /// Constructor.
-    StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
-        : StaticInstBase(__opClass),
-          machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
+    /// It's important to initialize everything here to a sane
+    /// default, since the decoder generally only overrides
+    /// the fields that are meaningful for the particular
+    /// instruction.
+    StaticInst(const char *_mnemonic, TheISA::ExtMachInst _machInst,
+            OpClass __opClass)
+        : _opClass(__opClass),
+          _numSrcRegs(0), _numDestRegs(0), _numFPDestRegs(0),
+          _numIntDestRegs(0), _numCCDestRegs(0), _numVecDestRegs(0),
+          _numVecElemDestRegs(0), _numVecPredDestRegs(0), machInst(_machInst),
+          mnemonic(_mnemonic), cachedDisassembly(0)
     { }
 
   public:
+    virtual ~StaticInst();
 
-    virtual ~StaticInst()
+    virtual Fault execute(ExecContext *xc,
+                          Trace::InstRecord *traceData) const = 0;
+
+    virtual Fault initiateAcc(ExecContext *xc,
+                              Trace::InstRecord *traceData) const
     {
-        if (cachedDisassembly)
-            delete cachedDisassembly;
+        panic("initiateAcc not defined!");
     }
 
-/**
- * The execute() signatures are auto-generated by scons based on the
- * set of CPU models we are compiling in today.
- */
-#include "cpu/static_inst_exec_sigs.hh"
+    virtual Fault completeAcc(Packet *pkt, ExecContext *xc,
+                              Trace::InstRecord *traceData) const
+    {
+        panic("completeAcc not defined!");
+    }
+
+    virtual void advancePC(TheISA::PCState &pcState) const = 0;
 
     /**
      * 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 upc) const;
 
     /**
      * Return the target address for a PC-relative branch.
      * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
      * should be true).
      */
-    virtual Addr branchTarget(Addr branchPC) const
-    {
-        panic("StaticInst::branchTarget() called on instruction "
-              "that is not a PC-relative branch.");
-        M5_DUMMY_RETURN
-    }
+    virtual TheISA::PCState branchTarget(const TheISA::PCState &pc) const;
 
     /**
      * Return the target address for an indirect branch (jump).  The
@@ -394,18 +349,14 @@ class StaticInst : public StaticInstBase
      * execute the branch in question.  Invalid if not an indirect
      * branch (i.e. isIndirectCtrl() should be true).
      */
-    virtual Addr branchTarget(ThreadContext *tc) const
-    {
-        panic("StaticInst::branchTarget() called on instruction "
-              "that is not an indirect branch.");
-    }
-        M5_DUMMY_RETURN
+    virtual TheISA::PCState branchTarget(ThreadContext *tc) const;
 
     /**
      * Return true if the instruction is a control transfer, and if so,
      * return the target address as well.
      */
-    bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const;
+    bool hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
+                         TheISA::PCState &tgt) const;
 
     /**
      * Return string representation of disassembled instruction.
@@ -415,235 +366,41 @@ class StaticInst : public StaticInstBase
      * should not be cached, this function should be overridden directly.
      */
     virtual const std::string &disassemble(Addr pc,
-                                           const SymbolTable *symtab = 0) const
-    {
-        if (!cachedDisassembly)
-            cachedDisassembly =
-                new std::string(generateDisassembly(pc, symtab));
-
-        return *cachedDisassembly;
-    }
-
-    /// 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;
+        const Loader::SymbolTable *symtab=nullptr) const;
 
     /**
-     * Dump some basic stats on the decode cache hash map.
-     * Only gets called if DECODE_CACHE_HASH_STATS is defined.
+     * Print a separator separated list of this instruction's set flag
+     * names on the given stream.
      */
-    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);
+    void printFlags(std::ostream &outs, const std::string &separator) const;
 
     /// 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;
-
-/// Reference-counted pointer to a StaticInst object.
-/// This type should be used instead of "StaticInst *" so that
-/// StaticInst objects can be properly reference-counted.
-class StaticInstPtr : public RefCountingPtr<StaticInst>
-{
-  public:
-    /// Constructor.
-    StaticInstPtr()
-        : RefCountingPtr<StaticInst>()
-    {
-    }
-
-    /// Conversion from "StaticInst *".
-    StaticInstPtr(StaticInst *p)
-        : RefCountingPtr<StaticInst>(p)
-    {
-    }
-
-    /// Copy constructor.
-    StaticInstPtr(const StaticInstPtr &r)
-        : RefCountingPtr<StaticInst>(r)
-    {
-    }
-
-    /// 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()
-    {
-        return this->get();
-    }
-};
-
-/// 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)
+    template<typename T>
+    size_t
+    simpleAsBytes(void *buf, size_t max_size, const T &t)
     {
-        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;
+        size_t size = sizeof(T);
+        if (size <= max_size)
+            *reinterpret_cast<T *>(buf) = htole<T>(t);
+        return size;
     }
 
+  public:
+    /**
+     * Instruction classes can override this function to return a
+     * a representation of themselves as a blob of bytes, generally assumed to
+     * be that instructions ExtMachInst.
+     *
+     * buf is a buffer to hold the bytes.
+     * max_size is the size allocated for that buffer by the caller.
+     * The return value is how much data was actually put into the buffer,
+     * zero if no data was put in the buffer, or the necessary size of the
+     * buffer if there wasn't enough space.
+     */
+    virtual size_t asBytes(void *buf, size_t max_size) { return 0; }
 };
 
-
-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__