static_inst.hh revision 1464
112810Sandreas.sandberg@arm.com/*
214054Stiago.muck@arm.com * Copyright (c) 2003-2004 The Regents of The University of Michigan
312810Sandreas.sandberg@arm.com * All rights reserved.
412810Sandreas.sandberg@arm.com *
512810Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
612810Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
712810Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
812810Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
912810Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1012810Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1112810Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1212810Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1312810Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1412810Sandreas.sandberg@arm.com * this software without specific prior written permission.
1512810Sandreas.sandberg@arm.com *
1612810Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712810Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812810Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912810Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012810Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112810Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212810Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312810Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412810Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512810Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612810Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712810Sandreas.sandberg@arm.com */
2812810Sandreas.sandberg@arm.com
2912810Sandreas.sandberg@arm.com#ifndef __CPU_STATIC_INST_HH__
3012810Sandreas.sandberg@arm.com#define __CPU_STATIC_INST_HH__
3112810Sandreas.sandberg@arm.com
3212810Sandreas.sandberg@arm.com#include <bitset>
3312810Sandreas.sandberg@arm.com#include <string>
3412810Sandreas.sandberg@arm.com
3512810Sandreas.sandberg@arm.com#include "sim/host.hh"
3612810Sandreas.sandberg@arm.com#include "base/hashmap.hh"
3712810Sandreas.sandberg@arm.com#include "base/refcnt.hh"
3812810Sandreas.sandberg@arm.com
3912810Sandreas.sandberg@arm.com#include "cpu/full_cpu/op_class.hh"
4012810Sandreas.sandberg@arm.com#include "targetarch/isa_traits.hh"
4112810Sandreas.sandberg@arm.com
4212810Sandreas.sandberg@arm.com// forward declarations
4312810Sandreas.sandberg@arm.comstruct AlphaSimpleImpl;
4412810Sandreas.sandberg@arm.comstruct OoOImpl;
4512810Sandreas.sandberg@arm.comclass ExecContext;
4612810Sandreas.sandberg@arm.comclass DynInst;
4712811Sandreas.sandberg@arm.com
4812810Sandreas.sandberg@arm.comtemplate <class Impl>
4912811Sandreas.sandberg@arm.comclass AlphaDynInst;
5012811Sandreas.sandberg@arm.com
5112811Sandreas.sandberg@arm.comtemplate <class Impl>
5212811Sandreas.sandberg@arm.comclass OoODynInst;
5312811Sandreas.sandberg@arm.com
5412811Sandreas.sandberg@arm.comclass FastCPU;
5512919Sgiacomo.travaglini@arm.comclass SimpleCPU;
5612810Sandreas.sandberg@arm.comclass InorderCPU;
5712810Sandreas.sandberg@arm.comclass SymbolTable;
5812810Sandreas.sandberg@arm.com
5912810Sandreas.sandberg@arm.comnamespace Trace {
6012810Sandreas.sandberg@arm.com    class InstRecord;
6112810Sandreas.sandberg@arm.com}
6212810Sandreas.sandberg@arm.com
6312811Sandreas.sandberg@arm.com/**
6412811Sandreas.sandberg@arm.com * Base, ISA-independent static instruction class.
6512811Sandreas.sandberg@arm.com *
6612811Sandreas.sandberg@arm.com * The main component of this class is the vector of flags and the
6712811Sandreas.sandberg@arm.com * associated methods for reading them.  Any object that can rely
6812810Sandreas.sandberg@arm.com * solely on these flags can process instructions without being
6912810Sandreas.sandberg@arm.com * recompiled for multiple ISAs.
7012810Sandreas.sandberg@arm.com */
7113892Sgabeblack@google.comclass StaticInstBase : public RefCounted
7212810Sandreas.sandberg@arm.com{
7312810Sandreas.sandberg@arm.com  protected:
7412810Sandreas.sandberg@arm.com
7512810Sandreas.sandberg@arm.com    /// Set of boolean static instruction properties.
7612810Sandreas.sandberg@arm.com    ///
7712810Sandreas.sandberg@arm.com    /// Notes:
7814054Stiago.muck@arm.com    /// - The IsInteger and IsFloating flags are based on the class of
7912810Sandreas.sandberg@arm.com    /// registers accessed by the instruction.  Although most
8012810Sandreas.sandberg@arm.com    /// instructions will have exactly one of these two flags set, it
8114054Stiago.muck@arm.com    /// is possible for an instruction to have neither (e.g., direct
8212810Sandreas.sandberg@arm.com    /// unconditional branches, memory barriers) or both (e.g., an
8314207Sandreas.sandberg@arm.com    /// FP/int conversion).
8412919Sgiacomo.travaglini@arm.com    /// - If IsMemRef is set, then exactly one of IsLoad or IsStore
8512919Sgiacomo.travaglini@arm.com    /// will be set.
8612919Sgiacomo.travaglini@arm.com    /// - If IsControl is set, then exactly one of IsDirectControl or
8712919Sgiacomo.travaglini@arm.com    /// IsIndirect Control will be set, and exactly one of
8812919Sgiacomo.travaglini@arm.com    /// IsCondControl or IsUncondControl will be set.
8912919Sgiacomo.travaglini@arm.com    /// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
9012810Sandreas.sandberg@arm.com    /// implemented as flags since in the current model there's no
9112810Sandreas.sandberg@arm.com    /// other way for instructions to inject behavior into the
9212810Sandreas.sandberg@arm.com    /// pipeline outside of fetch.  Once we go to an exec-in-exec CPU
9313784Sgabeblack@google.com    /// model we should be able to get rid of these flags and
9413784Sgabeblack@google.com    /// implement this behavior via the execute() methods.
9512810Sandreas.sandberg@arm.com    ///
9612810Sandreas.sandberg@arm.com    enum Flags {
9712810Sandreas.sandberg@arm.com        IsNop,		///< Is a no-op (no effect at all).
9812810Sandreas.sandberg@arm.com
9913892Sgabeblack@google.com        IsInteger,	///< References integer regs.
10012810Sandreas.sandberg@arm.com        IsFloating,	///< References FP regs.
10112810Sandreas.sandberg@arm.com
10212810Sandreas.sandberg@arm.com        IsMemRef,	///< References memory (load, store, or prefetch).
10312810Sandreas.sandberg@arm.com        IsLoad,		///< Reads from memory (load or prefetch).
10412810Sandreas.sandberg@arm.com        IsStore,	///< Writes to memory.
10512810Sandreas.sandberg@arm.com        IsInstPrefetch,	///< Instruction-cache prefetch.
10613892Sgabeblack@google.com        IsDataPrefetch,	///< Data-cache prefetch.
10712810Sandreas.sandberg@arm.com        IsCopy,         ///< Fast Cache block copy
10812810Sandreas.sandberg@arm.com
10912810Sandreas.sandberg@arm.com        IsControl,		///< Control transfer instruction.
11012810Sandreas.sandberg@arm.com        IsDirectControl,	///< PC relative control transfer.
11112810Sandreas.sandberg@arm.com        IsIndirectControl,	///< Register indirect control transfer.
11212810Sandreas.sandberg@arm.com        IsCondControl,		///< Conditional control transfer.
11312810Sandreas.sandberg@arm.com        IsUncondControl,	///< Unconditional control transfer.
11412810Sandreas.sandberg@arm.com        IsCall,			///< Subroutine call.
11512810Sandreas.sandberg@arm.com        IsReturn,		///< Subroutine return.
11612810Sandreas.sandberg@arm.com
11712810Sandreas.sandberg@arm.com        IsThreadSync,	///< Thread synchronization operation.
11812810Sandreas.sandberg@arm.com
11912810Sandreas.sandberg@arm.com        IsSerializing,	///< Serializes pipeline: won't execute until all
12012810Sandreas.sandberg@arm.com                        /// older instructions have committed.
12112810Sandreas.sandberg@arm.com        IsMemBarrier,	///< Is a memory barrier
12212810Sandreas.sandberg@arm.com        IsWriteBarrier,	///< Is a write barrier
12312810Sandreas.sandberg@arm.com
12412810Sandreas.sandberg@arm.com        IsNonSpeculative, ///< Should not be executed speculatively
12512810Sandreas.sandberg@arm.com
12612810Sandreas.sandberg@arm.com        NumFlags
12712810Sandreas.sandberg@arm.com    };
12812810Sandreas.sandberg@arm.com
12912810Sandreas.sandberg@arm.com    /// Flag values for this instruction.
13012810Sandreas.sandberg@arm.com    std::bitset<NumFlags> flags;
13112810Sandreas.sandberg@arm.com
13212810Sandreas.sandberg@arm.com    /// See opClass().
13312810Sandreas.sandberg@arm.com    OpClass _opClass;
13412845Sgiacomo.travaglini@arm.com
13512845Sgiacomo.travaglini@arm.com    /// See numSrcRegs().
13612845Sgiacomo.travaglini@arm.com    int8_t _numSrcRegs;
13712810Sandreas.sandberg@arm.com
13812810Sandreas.sandberg@arm.com    /// See numDestRegs().
13912810Sandreas.sandberg@arm.com    int8_t _numDestRegs;
14012810Sandreas.sandberg@arm.com
14112810Sandreas.sandberg@arm.com    /// The following are used to track physical register usage
14212810Sandreas.sandberg@arm.com    /// for machines with separate int & FP reg files.
14312810Sandreas.sandberg@arm.com    //@{
14412810Sandreas.sandberg@arm.com    int8_t _numFPDestRegs;
14512810Sandreas.sandberg@arm.com    int8_t _numIntDestRegs;
14612810Sandreas.sandberg@arm.com    //@}
14712810Sandreas.sandberg@arm.com
14812810Sandreas.sandberg@arm.com    /// Constructor.
14912810Sandreas.sandberg@arm.com    /// It's important to initialize everything here to a sane
15012810Sandreas.sandberg@arm.com    /// default, since the decoder generally only overrides
15112810Sandreas.sandberg@arm.com    /// the fields that are meaningful for the particular
15212810Sandreas.sandberg@arm.com    /// instruction.
15312810Sandreas.sandberg@arm.com    StaticInstBase(OpClass __opClass)
15412845Sgiacomo.travaglini@arm.com        : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
15512845Sgiacomo.travaglini@arm.com          _numFPDestRegs(0), _numIntDestRegs(0)
15612845Sgiacomo.travaglini@arm.com    {
15712810Sandreas.sandberg@arm.com    }
15812810Sandreas.sandberg@arm.com
15912810Sandreas.sandberg@arm.com  public:
16012810Sandreas.sandberg@arm.com
16112810Sandreas.sandberg@arm.com    /// @name Register information.
16212810Sandreas.sandberg@arm.com    /// The sum of numFPDestRegs() and numIntDestRegs() equals
16312810Sandreas.sandberg@arm.com    /// numDestRegs().  The former two functions are used to track
16412810Sandreas.sandberg@arm.com    /// physical register usage for machines with separate int & FP
16512810Sandreas.sandberg@arm.com    /// reg files.
16612810Sandreas.sandberg@arm.com    //@{
16712810Sandreas.sandberg@arm.com    /// Number of source registers.
16812810Sandreas.sandberg@arm.com    int8_t numSrcRegs()  const { return _numSrcRegs; }
16912810Sandreas.sandberg@arm.com    /// Number of destination registers.
17012810Sandreas.sandberg@arm.com    int8_t numDestRegs() const { return _numDestRegs; }
17112810Sandreas.sandberg@arm.com    /// Number of floating-point destination regs.
17212810Sandreas.sandberg@arm.com    int8_t numFPDestRegs()  const { return _numFPDestRegs; }
17312810Sandreas.sandberg@arm.com    /// Number of integer destination regs.
17412810Sandreas.sandberg@arm.com    int8_t numIntDestRegs() const { return _numIntDestRegs; }
17512810Sandreas.sandberg@arm.com    //@}
17612810Sandreas.sandberg@arm.com
17712810Sandreas.sandberg@arm.com    /// @name Flag accessors.
17812810Sandreas.sandberg@arm.com    /// These functions are used to access the values of the various
17912810Sandreas.sandberg@arm.com    /// instruction property flags.  See StaticInstBase::Flags for descriptions
18012810Sandreas.sandberg@arm.com    /// of the individual flags.
18112810Sandreas.sandberg@arm.com    //@{
18212810Sandreas.sandberg@arm.com
18312919Sgiacomo.travaglini@arm.com    bool isNop() 	  const { return flags[IsNop]; }
18412919Sgiacomo.travaglini@arm.com
18512919Sgiacomo.travaglini@arm.com    bool isMemRef()    	  const { return flags[IsMemRef]; }
18612919Sgiacomo.travaglini@arm.com    bool isLoad()	  const { return flags[IsLoad]; }
18712919Sgiacomo.travaglini@arm.com    bool isStore()	  const { return flags[IsStore]; }
18812919Sgiacomo.travaglini@arm.com    bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
18912919Sgiacomo.travaglini@arm.com    bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
19012919Sgiacomo.travaglini@arm.com    bool isCopy()         const { return flags[IsCopy];}
19112919Sgiacomo.travaglini@arm.com
19212919Sgiacomo.travaglini@arm.com    bool isInteger()	  const { return flags[IsInteger]; }
19312919Sgiacomo.travaglini@arm.com    bool isFloating()	  const { return flags[IsFloating]; }
19412919Sgiacomo.travaglini@arm.com
19512919Sgiacomo.travaglini@arm.com    bool isControl()	  const { return flags[IsControl]; }
19612810Sandreas.sandberg@arm.com    bool isCall()	  const { return flags[IsCall]; }
19712810Sandreas.sandberg@arm.com    bool isReturn()	  const { return flags[IsReturn]; }
19812812Sandreas.sandberg@arm.com    bool isDirectCtrl()	  const { return flags[IsDirectControl]; }
19914207Sandreas.sandberg@arm.com    bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
20014054Stiago.muck@arm.com    bool isCondCtrl()	  const { return flags[IsCondControl]; }
20114054Stiago.muck@arm.com    bool isUncondCtrl()	  const { return flags[IsUncondControl]; }
20214054Stiago.muck@arm.com
20312810Sandreas.sandberg@arm.com    bool isThreadSync()   const { return flags[IsThreadSync]; }
20412810Sandreas.sandberg@arm.com    bool isSerializing()  const { return flags[IsSerializing]; }
20512810Sandreas.sandberg@arm.com    bool isMemBarrier()   const { return flags[IsMemBarrier]; }
20612812Sandreas.sandberg@arm.com    bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
20712810Sandreas.sandberg@arm.com    bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
20812810Sandreas.sandberg@arm.com    //@}
20912810Sandreas.sandberg@arm.com
21014207Sandreas.sandberg@arm.com    /// Operation class.  Used to select appropriate function unit in issue.
21114207Sandreas.sandberg@arm.com    OpClass opClass()     const { return _opClass; }
21212810Sandreas.sandberg@arm.com};
21314207Sandreas.sandberg@arm.com
21412810Sandreas.sandberg@arm.com
21512810Sandreas.sandberg@arm.com// forward declaration
21612810Sandreas.sandberg@arm.comtemplate <class ISA>
21712810Sandreas.sandberg@arm.comclass StaticInstPtr;
21812810Sandreas.sandberg@arm.com
21912810Sandreas.sandberg@arm.com/**
22014054Stiago.muck@arm.com * Generic yet ISA-dependent static instruction class.
22114054Stiago.muck@arm.com *
22212810Sandreas.sandberg@arm.com * This class builds on StaticInstBase, defining fields and interfaces
22312810Sandreas.sandberg@arm.com * that are generic across all ISAs but that differ in details
22412810Sandreas.sandberg@arm.com * according to the specific ISA being used.
22512810Sandreas.sandberg@arm.com */
22612810Sandreas.sandberg@arm.comtemplate <class ISA>
22712810Sandreas.sandberg@arm.comclass StaticInst : public StaticInstBase
22812810Sandreas.sandberg@arm.com{
22912810Sandreas.sandberg@arm.com  public:
23012810Sandreas.sandberg@arm.com
23112810Sandreas.sandberg@arm.com    /// Binary machine instruction type.
23212810Sandreas.sandberg@arm.com    typedef typename ISA::MachInst MachInst;
23312810Sandreas.sandberg@arm.com    /// Memory address type.
23412810Sandreas.sandberg@arm.com    typedef typename ISA::Addr	   Addr;
23512810Sandreas.sandberg@arm.com    /// Logical register index type.
23612810Sandreas.sandberg@arm.com    typedef typename ISA::RegIndex RegIndex;
23712810Sandreas.sandberg@arm.com
23812810Sandreas.sandberg@arm.com    enum {
23912810Sandreas.sandberg@arm.com        MaxInstSrcRegs = ISA::MaxInstSrcRegs,	//< Max source regs
24012810Sandreas.sandberg@arm.com        MaxInstDestRegs = ISA::MaxInstDestRegs,	//< Max dest regs
24112810Sandreas.sandberg@arm.com    };
24212810Sandreas.sandberg@arm.com
24312810Sandreas.sandberg@arm.com
24412810Sandreas.sandberg@arm.com    /// Return logical index (architectural reg num) of i'th destination reg.
24512810Sandreas.sandberg@arm.com    /// Only the entries from 0 through numDestRegs()-1 are valid.
24612810Sandreas.sandberg@arm.com    RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
24712810Sandreas.sandberg@arm.com
24812810Sandreas.sandberg@arm.com    /// Return logical index (architectural reg num) of i'th source reg.
24912810Sandreas.sandberg@arm.com    /// Only the entries from 0 through numSrcRegs()-1 are valid.
25012810Sandreas.sandberg@arm.com    RegIndex srcRegIdx(int i)  const { return _srcRegIdx[i]; }
25112810Sandreas.sandberg@arm.com
25212810Sandreas.sandberg@arm.com    /// Pointer to a statically allocated "null" instruction object.
25312810Sandreas.sandberg@arm.com    /// Used to give eaCompInst() and memAccInst() something to return
25412810Sandreas.sandberg@arm.com    /// when called on non-memory instructions.
25512810Sandreas.sandberg@arm.com    static StaticInstPtr<ISA> nullStaticInstPtr;
25612810Sandreas.sandberg@arm.com
25712810Sandreas.sandberg@arm.com    /**
25812810Sandreas.sandberg@arm.com     * Memory references only: returns "fake" instruction representing
25912810Sandreas.sandberg@arm.com     * the effective address part of the memory operation.  Used to
26012812Sandreas.sandberg@arm.com     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
26112812Sandreas.sandberg@arm.com     * just the EA computation.
26212812Sandreas.sandberg@arm.com     */
26312812Sandreas.sandberg@arm.com    virtual
26412812Sandreas.sandberg@arm.com    StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; }
26512812Sandreas.sandberg@arm.com
26612812Sandreas.sandberg@arm.com    /**
26712812Sandreas.sandberg@arm.com     * Memory references only: returns "fake" instruction representing
26812812Sandreas.sandberg@arm.com     * the memory access part of the memory operation.  Used to
26912812Sandreas.sandberg@arm.com     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
27012810Sandreas.sandberg@arm.com     * just the memory access (not the EA computation).
27112810Sandreas.sandberg@arm.com     */
27212810Sandreas.sandberg@arm.com    virtual
27312810Sandreas.sandberg@arm.com    StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; }
27412810Sandreas.sandberg@arm.com
27512810Sandreas.sandberg@arm.com    /// The binary machine instruction.
27612810Sandreas.sandberg@arm.com    const MachInst machInst;
27712810Sandreas.sandberg@arm.com
27812810Sandreas.sandberg@arm.com  protected:
27912810Sandreas.sandberg@arm.com
28012810Sandreas.sandberg@arm.com    /// See destRegIdx().
28112810Sandreas.sandberg@arm.com    RegIndex _destRegIdx[MaxInstDestRegs];
28212810Sandreas.sandberg@arm.com    /// See srcRegIdx().
28312810Sandreas.sandberg@arm.com    RegIndex _srcRegIdx[MaxInstSrcRegs];
28412810Sandreas.sandberg@arm.com
28512810Sandreas.sandberg@arm.com    /**
28612810Sandreas.sandberg@arm.com     * Base mnemonic (e.g., "add").  Used by generateDisassembly()
28712810Sandreas.sandberg@arm.com     * methods.  Also useful to readily identify instructions from
28812810Sandreas.sandberg@arm.com     * within the debugger when #cachedDisassembly has not been
28912810Sandreas.sandberg@arm.com     * initialized.
29012810Sandreas.sandberg@arm.com     */
29112810Sandreas.sandberg@arm.com    const char *mnemonic;
29214207Sandreas.sandberg@arm.com
29314054Stiago.muck@arm.com    /**
29414054Stiago.muck@arm.com     * String representation of disassembly (lazily evaluated via
29514054Stiago.muck@arm.com     * disassemble()).
29614054Stiago.muck@arm.com     */
29714054Stiago.muck@arm.com    std::string *cachedDisassembly;
29814054Stiago.muck@arm.com
29914054Stiago.muck@arm.com    /**
30014054Stiago.muck@arm.com     * Internal function to generate disassembly string.
30114054Stiago.muck@arm.com     */
30214054Stiago.muck@arm.com    virtual std::string generateDisassembly(Addr pc,
30312810Sandreas.sandberg@arm.com                                            const SymbolTable *symtab) = 0;
30412810Sandreas.sandberg@arm.com
30512810Sandreas.sandberg@arm.com    /// Constructor.
30612810Sandreas.sandberg@arm.com    StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass)
30712810Sandreas.sandberg@arm.com        : StaticInstBase(__opClass),
30812810Sandreas.sandberg@arm.com          machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
30912810Sandreas.sandberg@arm.com    {
31012810Sandreas.sandberg@arm.com    }
31112810Sandreas.sandberg@arm.com
31214207Sandreas.sandberg@arm.com  public:
31312810Sandreas.sandberg@arm.com
31412810Sandreas.sandberg@arm.com    virtual ~StaticInst()
31512810Sandreas.sandberg@arm.com    {
31612810Sandreas.sandberg@arm.com        if (cachedDisassembly)
31712810Sandreas.sandberg@arm.com            delete cachedDisassembly;
31812810Sandreas.sandberg@arm.com    }
31912810Sandreas.sandberg@arm.com
32012810Sandreas.sandberg@arm.com#include "static_inst_impl.hh"
32112810Sandreas.sandberg@arm.com
32212810Sandreas.sandberg@arm.com    /**
32312810Sandreas.sandberg@arm.com     * Return the target address for a PC-relative branch.
32412810Sandreas.sandberg@arm.com     * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
32512810Sandreas.sandberg@arm.com     * should be true).
32612810Sandreas.sandberg@arm.com     */
32712810Sandreas.sandberg@arm.com    virtual Addr branchTarget(Addr branchPC) const
32812810Sandreas.sandberg@arm.com    {
32912810Sandreas.sandberg@arm.com        panic("StaticInst::branchTarget() called on instruction "
33012810Sandreas.sandberg@arm.com              "that is not a PC-relative branch.");
33112810Sandreas.sandberg@arm.com    }
33212810Sandreas.sandberg@arm.com
33312810Sandreas.sandberg@arm.com    /**
33412810Sandreas.sandberg@arm.com     * Return the target address for an indirect branch (jump).  The
33514207Sandreas.sandberg@arm.com     * register value is read from the supplied execution context, so
33614207Sandreas.sandberg@arm.com     * the result is valid only if the execution context is about to
33714207Sandreas.sandberg@arm.com     * execute the branch in question.  Invalid if not an indirect
33814207Sandreas.sandberg@arm.com     * branch (i.e. isIndirectCtrl() should be true).
33914207Sandreas.sandberg@arm.com     */
34014207Sandreas.sandberg@arm.com    virtual Addr branchTarget(ExecContext *xc) const
34114207Sandreas.sandberg@arm.com    {
34214207Sandreas.sandberg@arm.com        panic("StaticInst::branchTarget() called on instruction "
34314207Sandreas.sandberg@arm.com              "that is not an indirect branch.");
34414207Sandreas.sandberg@arm.com    }
34514207Sandreas.sandberg@arm.com
34614207Sandreas.sandberg@arm.com    /**
34714207Sandreas.sandberg@arm.com     * Return true if the instruction is a control transfer, and if so,
34814207Sandreas.sandberg@arm.com     * return the target address as well.
34914207Sandreas.sandberg@arm.com     */
35014207Sandreas.sandberg@arm.com    bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt);
35114207Sandreas.sandberg@arm.com
35214207Sandreas.sandberg@arm.com    /**
35314207Sandreas.sandberg@arm.com     * Return string representation of disassembled instruction.
35414207Sandreas.sandberg@arm.com     * The default version of this function will call the internal
35514207Sandreas.sandberg@arm.com     * virtual generateDisassembly() function to get the string,
35612810Sandreas.sandberg@arm.com     * then cache it in #cachedDisassembly.  If the disassembly
35712810Sandreas.sandberg@arm.com     * should not be cached, this function should be overridden directly.
35812810Sandreas.sandberg@arm.com     */
35912811Sandreas.sandberg@arm.com    virtual const std::string &disassemble(Addr pc,
36012811Sandreas.sandberg@arm.com                                           const SymbolTable *symtab = 0)
36112811Sandreas.sandberg@arm.com    {
36212844Sgiacomo.travaglini@arm.com        if (!cachedDisassembly)
36312811Sandreas.sandberg@arm.com            cachedDisassembly =
36412811Sandreas.sandberg@arm.com                new std::string(generateDisassembly(pc, symtab));
36512811Sandreas.sandberg@arm.com
36612811Sandreas.sandberg@arm.com        return *cachedDisassembly;
36712811Sandreas.sandberg@arm.com    }
36812844Sgiacomo.travaglini@arm.com
36912811Sandreas.sandberg@arm.com    /// Decoded instruction cache type.
37012811Sandreas.sandberg@arm.com    /// For now we're using a generic hash_map; this seems to work
37112811Sandreas.sandberg@arm.com    /// pretty well.
37212811Sandreas.sandberg@arm.com    typedef m5::hash_map<MachInst, StaticInstPtr<ISA> > DecodeCache;
37312811Sandreas.sandberg@arm.com
37412811Sandreas.sandberg@arm.com    /// A cache of decoded instruction objects.
37512811Sandreas.sandberg@arm.com    static DecodeCache decodeCache;
37612811Sandreas.sandberg@arm.com
37712844Sgiacomo.travaglini@arm.com    /**
37812811Sandreas.sandberg@arm.com     * Dump some basic stats on the decode cache hash map.
37912811Sandreas.sandberg@arm.com     * Only gets called if DECODE_CACHE_HASH_STATS is defined.
38012844Sgiacomo.travaglini@arm.com     */
38112811Sandreas.sandberg@arm.com    static void dumpDecodeCacheStats();
38212811Sandreas.sandberg@arm.com
38312811Sandreas.sandberg@arm.com    /// Decode a machine instruction.
38412811Sandreas.sandberg@arm.com    /// @param mach_inst The binary instruction to decode.
38512811Sandreas.sandberg@arm.com    /// @retval A pointer to the corresponding StaticInst object.
38612811Sandreas.sandberg@arm.com    static
38712811Sandreas.sandberg@arm.com    StaticInstPtr<ISA> decode(MachInst mach_inst)
38812811Sandreas.sandberg@arm.com    {
38912811Sandreas.sandberg@arm.com#ifdef DECODE_CACHE_HASH_STATS
39012811Sandreas.sandberg@arm.com        // Simple stats on decode hash_map.  Turns out the default
39112844Sgiacomo.travaglini@arm.com        // hash function is as good as anything I could come up with.
39212811Sandreas.sandberg@arm.com        const int dump_every_n = 10000000;
39312811Sandreas.sandberg@arm.com        static int decodes_til_dump = dump_every_n;
39412844Sgiacomo.travaglini@arm.com
39512811Sandreas.sandberg@arm.com        if (--decodes_til_dump == 0) {
39612811Sandreas.sandberg@arm.com            dumpDecodeCacheStats();
39712811Sandreas.sandberg@arm.com            decodes_til_dump = dump_every_n;
39812811Sandreas.sandberg@arm.com        }
39912811Sandreas.sandberg@arm.com#endif
40012811Sandreas.sandberg@arm.com
40112811Sandreas.sandberg@arm.com        typename DecodeCache::iterator iter = decodeCache.find(mach_inst);
40212811Sandreas.sandberg@arm.com        if (iter != decodeCache.end()) {
40312811Sandreas.sandberg@arm.com            return iter->second;
40412811Sandreas.sandberg@arm.com        }
40512811Sandreas.sandberg@arm.com
40612811Sandreas.sandberg@arm.com        StaticInstPtr<ISA> si = ISA::decodeInst(mach_inst);
40712811Sandreas.sandberg@arm.com        decodeCache[mach_inst] = si;
40812811Sandreas.sandberg@arm.com        return si;
40912811Sandreas.sandberg@arm.com    }
41012844Sgiacomo.travaglini@arm.com};
41112811Sandreas.sandberg@arm.com
41212811Sandreas.sandberg@arm.comtypedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
41312844Sgiacomo.travaglini@arm.com
41412811Sandreas.sandberg@arm.com/// Reference-counted pointer to a StaticInst object.
41512811Sandreas.sandberg@arm.com/// This type should be used instead of "StaticInst<ISA> *" so that
41612811Sandreas.sandberg@arm.com/// StaticInst objects can be properly reference-counted.
41712811Sandreas.sandberg@arm.comtemplate <class ISA>
41812811Sandreas.sandberg@arm.comclass StaticInstPtr : public RefCountingPtr<StaticInst<ISA> >
41912811Sandreas.sandberg@arm.com{
42012811Sandreas.sandberg@arm.com  public:
42112811Sandreas.sandberg@arm.com    /// Constructor.
42212811Sandreas.sandberg@arm.com    StaticInstPtr()
42312811Sandreas.sandberg@arm.com        : RefCountingPtr<StaticInst<ISA> >()
42412811Sandreas.sandberg@arm.com    {
42512811Sandreas.sandberg@arm.com    }
42612811Sandreas.sandberg@arm.com
42712811Sandreas.sandberg@arm.com    /// Conversion from "StaticInst<ISA> *".
42812811Sandreas.sandberg@arm.com    StaticInstPtr(StaticInst<ISA> *p)
42912811Sandreas.sandberg@arm.com        : RefCountingPtr<StaticInst<ISA> >(p)
43012811Sandreas.sandberg@arm.com    {
43112811Sandreas.sandberg@arm.com    }
43212811Sandreas.sandberg@arm.com
43312811Sandreas.sandberg@arm.com    /// Copy constructor.
43412811Sandreas.sandberg@arm.com    StaticInstPtr(const StaticInstPtr &r)
43512811Sandreas.sandberg@arm.com        : RefCountingPtr<StaticInst<ISA> >(r)
43612844Sgiacomo.travaglini@arm.com    {
43712811Sandreas.sandberg@arm.com    }
43812811Sandreas.sandberg@arm.com
43912844Sgiacomo.travaglini@arm.com    /// Construct directly from machine instruction.
44012811Sandreas.sandberg@arm.com    /// Calls StaticInst<ISA>::decode().
44112811Sandreas.sandberg@arm.com    StaticInstPtr(typename ISA::MachInst mach_inst)
44212811Sandreas.sandberg@arm.com        : RefCountingPtr<StaticInst<ISA> >(StaticInst<ISA>::decode(mach_inst))
44312811Sandreas.sandberg@arm.com    {
44412811Sandreas.sandberg@arm.com    }
44512811Sandreas.sandberg@arm.com
44612811Sandreas.sandberg@arm.com    /// Convert to pointer to StaticInstBase class.
44712811Sandreas.sandberg@arm.com    operator const StaticInstBasePtr()
44812811Sandreas.sandberg@arm.com    {
44912811Sandreas.sandberg@arm.com        return this->get();
45012811Sandreas.sandberg@arm.com    }
45112811Sandreas.sandberg@arm.com};
45212811Sandreas.sandberg@arm.com
45312811Sandreas.sandberg@arm.com#endif // __CPU_STATIC_INST_HH__
45412811Sandreas.sandberg@arm.com