/*
+ * 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.
* 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;
//@{
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; }
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]; }
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()
* 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
* 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.
* 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__