static_inst.hh revision 2
112837Sgabeblack@google.com/*
212837Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan
312837Sgabeblack@google.com * All rights reserved.
412837Sgabeblack@google.com *
512837Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612837Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712837Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912837Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112837Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212837Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312837Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412837Sgabeblack@google.com * this software without specific prior written permission.
1512837Sgabeblack@google.com *
1612837Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712837Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812837Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912837Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012837Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112837Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212837Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312837Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412837Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512837Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612837Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712837Sgabeblack@google.com */
2812837Sgabeblack@google.com
2912837Sgabeblack@google.com#ifndef __STATIC_INST_HH__
3012837Sgabeblack@google.com#define __STATIC_INST_HH__
3112837Sgabeblack@google.com
3212837Sgabeblack@google.com#include <bitset>
3312957Sgabeblack@google.com#include <string>
3412957Sgabeblack@google.com
3513053Sgabeblack@google.com#include "host.hh"
3612842Sgabeblack@google.com#include "hashmap.hh"
3712837Sgabeblack@google.com#include "refcnt.hh"
3812837Sgabeblack@google.com
3912957Sgabeblack@google.com#include "op_class.hh"
4012957Sgabeblack@google.com#include "isa_traits.hh"
4112957Sgabeblack@google.com
4212957Sgabeblack@google.com// forward declarations
4313091Sgabeblack@google.comclass ExecContext;
4412957Sgabeblack@google.comclass SpecExecContext;
4512957Sgabeblack@google.comclass SimpleCPU;
4612957Sgabeblack@google.comclass CPU;
4712957Sgabeblack@google.comclass DynInst;
4812837Sgabeblack@google.comclass SymbolTable;
4912837Sgabeblack@google.com
5012837Sgabeblack@google.comnamespace Trace {
5112837Sgabeblack@google.com    class InstRecord;
5212837Sgabeblack@google.com}
5312837Sgabeblack@google.com
5412837Sgabeblack@google.com/**
5512837Sgabeblack@google.com * Base, ISA-independent static instruction class.
5612837Sgabeblack@google.com *
5712837Sgabeblack@google.com * The main component of this class is the vector of flags and the
5812837Sgabeblack@google.com * associated methods for reading them.  Any object that can rely
5912837Sgabeblack@google.com * solely on these flags can process instructions without being
6012837Sgabeblack@google.com * recompiled for multiple ISAs.
6112837Sgabeblack@google.com */
6212837Sgabeblack@google.comclass StaticInstBase : public RefCounted
6312957Sgabeblack@google.com{
6412842Sgabeblack@google.com  protected:
6512842Sgabeblack@google.com
6612938Sgabeblack@google.com    /// Set of boolean static instruction properties.
6712957Sgabeblack@google.com    ///
6812957Sgabeblack@google.com    /// Notes:
6912957Sgabeblack@google.com    /// - The IsInteger and IsFloating flags are based on the class of
7012938Sgabeblack@google.com    /// registers accessed by the instruction.  Although most
7112938Sgabeblack@google.com    /// instructions will have exactly one of these two flags set, it
7212938Sgabeblack@google.com    /// is possible for an instruction to have neither (e.g., direct
7312938Sgabeblack@google.com    /// unconditional branches, memory barriers) or both (e.g., an
7412944Sgabeblack@google.com    /// FP/int conversion).
7513091Sgabeblack@google.com    /// - If IsMemRef is set, then exactly one of IsLoad or IsStore
7613091Sgabeblack@google.com    /// will be set.  Prefetches are marked as IsLoad, even if they
7712944Sgabeblack@google.com    /// prefetch exclusive copies.
7812944Sgabeblack@google.com    /// - If IsControl is set, then exactly one of IsDirectControl or
7912944Sgabeblack@google.com    /// IsIndirect Control will be set, and exactly one of
8012957Sgabeblack@google.com    /// IsCondControl or IsUncondControl will be set.
8113059Sgabeblack@google.com    ///
8213059Sgabeblack@google.com    enum Flags {
8313059Sgabeblack@google.com        IsNop,		///< Is a no-op (no effect at all).
8413059Sgabeblack@google.com
8513059Sgabeblack@google.com        IsInteger,	///< References integer regs.
8612957Sgabeblack@google.com        IsFloating,	///< References FP regs.
8712957Sgabeblack@google.com
8813053Sgabeblack@google.com        IsMemRef,	///< References memory (load, store, or prefetch).
8913053Sgabeblack@google.com        IsLoad,		///< Reads from memory (load or prefetch).
9013053Sgabeblack@google.com        IsStore,	///< Writes to memory.
9113053Sgabeblack@google.com        IsInstPrefetch,	///< Instruction-cache prefetch.
9213053Sgabeblack@google.com        IsDataPrefetch,	///< Data-cache prefetch.
9313053Sgabeblack@google.com
9412957Sgabeblack@google.com        IsControl,		///< Control transfer instruction.
9512957Sgabeblack@google.com        IsDirectControl,	///< PC relative control transfer.
9612957Sgabeblack@google.com        IsIndirectControl,	///< Register indirect control transfer.
9713053Sgabeblack@google.com        IsCondControl,		///< Conditional control transfer.
9813053Sgabeblack@google.com        IsUncondControl,	///< Unconditional control transfer.
9912837Sgabeblack@google.com        IsCall,			///< Subroutine call.
10012837Sgabeblack@google.com        IsReturn,		///< Subroutine return.
10112837Sgabeblack@google.com
10212837Sgabeblack@google.com        IsThreadSync,		///< Thread synchronization operation.
10312837Sgabeblack@google.com
10412837Sgabeblack@google.com        NumFlags
10513053Sgabeblack@google.com    };
10613053Sgabeblack@google.com
10712837Sgabeblack@google.com    /// Flag values for this instruction.
10813053Sgabeblack@google.com    std::bitset<NumFlags> flags;
10913053Sgabeblack@google.com
11012837Sgabeblack@google.com    /// See opClass().
11113090Sgabeblack@google.com    OpClass _opClass;
11213090Sgabeblack@google.com
11313090Sgabeblack@google.com    /// See numSrcRegs().
11413090Sgabeblack@google.com    int8_t _numSrcRegs;
11513090Sgabeblack@google.com
11613090Sgabeblack@google.com    /// See numDestRegs().
11713090Sgabeblack@google.com    int8_t _numDestRegs;
11813090Sgabeblack@google.com
11913090Sgabeblack@google.com    /// The following are used to track physical register usage
12013090Sgabeblack@google.com    /// for machines with separate int & FP reg files.
12113090Sgabeblack@google.com    //@{
12213090Sgabeblack@google.com    int8_t _numFPDestRegs;
12312837Sgabeblack@google.com    int8_t _numIntDestRegs;
12413090Sgabeblack@google.com    //@}
12513090Sgabeblack@google.com
12613090Sgabeblack@google.com    /// Constructor.
12713090Sgabeblack@google.com    /// It's important to initialize everything here to a sane
12813090Sgabeblack@google.com    /// default, since the decoder generally only overrides
12913090Sgabeblack@google.com    /// the fields that are meaningful for the particular
13013090Sgabeblack@google.com    /// instruction.
13113090Sgabeblack@google.com    StaticInstBase(OpClass __opClass)
13213090Sgabeblack@google.com        : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
13313090Sgabeblack@google.com          _numFPDestRegs(0), _numIntDestRegs(0)
13413090Sgabeblack@google.com    {
13513090Sgabeblack@google.com    }
13612837Sgabeblack@google.com
13713090Sgabeblack@google.com  public:
13813090Sgabeblack@google.com
13913090Sgabeblack@google.com    /// @name Register information.
14013090Sgabeblack@google.com    /// The sum of numFPDestRegs() and numIntDestRegs() equals
14113090Sgabeblack@google.com    /// numDestRegs().  The former two functions are used to track
14213090Sgabeblack@google.com    /// physical register usage for machines with separate int & FP
14313090Sgabeblack@google.com    /// reg files.
14413090Sgabeblack@google.com    //@{
14513090Sgabeblack@google.com    /// Number of source registers.
14613090Sgabeblack@google.com    int8_t numSrcRegs()  const { return _numSrcRegs; }
14713090Sgabeblack@google.com    /// Number of destination registers.
14813090Sgabeblack@google.com    int8_t numDestRegs() const { return _numDestRegs; }
14912837Sgabeblack@google.com    /// Number of floating-point destination regs.
15012837Sgabeblack@google.com    int8_t numFPDestRegs()  const { return _numFPDestRegs; }
15113059Sgabeblack@google.com    /// Number of integer destination regs.
15213059Sgabeblack@google.com    int8_t numIntDestRegs() const { return _numIntDestRegs; }
15313059Sgabeblack@google.com    //@}
15413059Sgabeblack@google.com
15512837Sgabeblack@google.com    /// @name Flag accessors.
15612842Sgabeblack@google.com    /// These functions are used to access the values of the various
15713036Sgabeblack@google.com    /// instruction property flags.  See StaticInstBase::Flags for descriptions
15812842Sgabeblack@google.com    /// of the individual flags.
15912842Sgabeblack@google.com    //@{
16012842Sgabeblack@google.com
16112842Sgabeblack@google.com    bool isNop() 	  const { return flags[IsNop]; }
16212842Sgabeblack@google.com
16312837Sgabeblack@google.com    bool isMemRef()    	  const { return flags[IsMemRef]; }
16412944Sgabeblack@google.com    bool isLoad()	  const { return flags[IsLoad]; }
16512944Sgabeblack@google.com    bool isStore()	  const { return flags[IsStore]; }
16613053Sgabeblack@google.com    bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
16712944Sgabeblack@google.com    bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
16813053Sgabeblack@google.com
16913053Sgabeblack@google.com    bool isInteger()	  const { return flags[IsInteger]; }
17013053Sgabeblack@google.com    bool isFloating()	  const { return flags[IsFloating]; }
17113053Sgabeblack@google.com
17212944Sgabeblack@google.com    bool isControl()	  const { return flags[IsControl]; }
17312944Sgabeblack@google.com    bool isCall()	  const { return flags[IsCall]; }
17412944Sgabeblack@google.com    bool isReturn()	  const { return flags[IsReturn]; }
17513053Sgabeblack@google.com    bool isDirectCtrl()	  const { return flags[IsDirectControl]; }
17612944Sgabeblack@google.com    bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
17713053Sgabeblack@google.com    bool isCondCtrl()	  const { return flags[IsCondControl]; }
17813053Sgabeblack@google.com    bool isUncondCtrl()	  const { return flags[IsUncondControl]; }
17913053Sgabeblack@google.com
18013053Sgabeblack@google.com    bool isThreadSync()   const { return flags[IsThreadSync]; }
18112944Sgabeblack@google.com    //@}
18212944Sgabeblack@google.com
18312944Sgabeblack@google.com    /// Operation class.  Used to select appropriate function unit in issue.
18412837Sgabeblack@google.com    OpClass opClass()     const { return _opClass; }
18513053Sgabeblack@google.com};
18613053Sgabeblack@google.com
18713090Sgabeblack@google.com
18813090Sgabeblack@google.com// forward declaration
18913090Sgabeblack@google.comtemplate <class ISA>
19013090Sgabeblack@google.comclass StaticInstPtr;
19113090Sgabeblack@google.com
19213090Sgabeblack@google.com/**
19313053Sgabeblack@google.com * Generic yet ISA-dependent static instruction class.
19413053Sgabeblack@google.com *
19513053Sgabeblack@google.com * This class builds on StaticInstBase, defining fields and interfaces
19613053Sgabeblack@google.com * that are generic across all ISAs but that differ in details
19713053Sgabeblack@google.com * according to the specific ISA being used.
19813053Sgabeblack@google.com */
19913053Sgabeblack@google.comtemplate <class ISA>
20013053Sgabeblack@google.comclass StaticInst : public StaticInstBase
20112837Sgabeblack@google.com{
20212837Sgabeblack@google.com  public:
20312837Sgabeblack@google.com
20412837Sgabeblack@google.com    /// Binary machine instruction type.
20512837Sgabeblack@google.com    typedef typename ISA::MachInst MachInst;
20612837Sgabeblack@google.com    /// Memory address type.
20712837Sgabeblack@google.com    typedef typename ISA::Addr	   Addr;
20812837Sgabeblack@google.com    /// Logical register index type.
20912837Sgabeblack@google.com    typedef typename ISA::RegIndex RegIndex;
21012837Sgabeblack@google.com
21112868Sgabeblack@google.com    enum {
21212842Sgabeblack@google.com        MaxInstSrcRegs = ISA::MaxInstSrcRegs,	//< Max source regs
21312842Sgabeblack@google.com        MaxInstDestRegs = ISA::MaxInstDestRegs,	//< Max dest regs
21412837Sgabeblack@google.com    };
21512868Sgabeblack@google.com
21612868Sgabeblack@google.com
21712868Sgabeblack@google.com    /// Return logical index (architectural reg num) of i'th destination reg.
21812868Sgabeblack@google.com    /// Only the entries from 0 through numDestRegs()-1 are valid.
21912868Sgabeblack@google.com    RegIndex destRegIdx(int i)	{ return _destRegIdx[i]; }
22012868Sgabeblack@google.com
22112868Sgabeblack@google.com    /// Return logical index (architectural reg num) of i'th source reg.
22212868Sgabeblack@google.com    /// Only the entries from 0 through numSrcRegs()-1 are valid.
22312868Sgabeblack@google.com    RegIndex srcRegIdx(int i)	{ return _srcRegIdx[i]; }
22412868Sgabeblack@google.com
22512868Sgabeblack@google.com    /// Pointer to a statically allocated "null" instruction object.
22612868Sgabeblack@google.com    /// Used to give eaCompInst() and memAccInst() something to return
22712868Sgabeblack@google.com    /// when called on non-memory instructions.
22812868Sgabeblack@google.com    static StaticInstPtr<ISA> nullStaticInstPtr;
22912868Sgabeblack@google.com
23012868Sgabeblack@google.com    /**
23112868Sgabeblack@google.com     * Memory references only: returns "fake" instruction representing
23212868Sgabeblack@google.com     * the effective address part of the memory operation.  Used to
23312868Sgabeblack@google.com     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
23412868Sgabeblack@google.com     * just the EA computation.
23512868Sgabeblack@google.com     */
23612868Sgabeblack@google.com    virtual StaticInstPtr<ISA> eaCompInst() { return nullStaticInstPtr; }
23712868Sgabeblack@google.com
23812868Sgabeblack@google.com    /**
23912868Sgabeblack@google.com     * Memory references only: returns "fake" instruction representing
24012868Sgabeblack@google.com     * the memory access part of the memory operation.  Used to
24112868Sgabeblack@google.com     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
24212868Sgabeblack@google.com     * just the memory access (not the EA computation).
24312868Sgabeblack@google.com     */
24412868Sgabeblack@google.com    virtual StaticInstPtr<ISA> memAccInst() { return nullStaticInstPtr; }
24512868Sgabeblack@google.com
24612868Sgabeblack@google.com    /// The binary machine instruction.
24712868Sgabeblack@google.com    const MachInst machInst;
24812868Sgabeblack@google.com
24912868Sgabeblack@google.com  protected:
25012868Sgabeblack@google.com
25112868Sgabeblack@google.com    /// See destRegIdx().
25212868Sgabeblack@google.com    RegIndex _destRegIdx[MaxInstDestRegs];
25312868Sgabeblack@google.com    /// See srcRegIdx().
25412868Sgabeblack@google.com    RegIndex _srcRegIdx[MaxInstSrcRegs];
25512842Sgabeblack@google.com
25612837Sgabeblack@google.com    /**
25712837Sgabeblack@google.com     * Base mnemonic (e.g., "add").  Used by generateDisassembly()
25812837Sgabeblack@google.com     * methods.  Also useful to readily identify instructions from
25912837Sgabeblack@google.com     * within the debugger when #cachedDisassembly has not been
26012837Sgabeblack@google.com     * initialized.
26112837Sgabeblack@google.com     */
26212837Sgabeblack@google.com    const char *mnemonic;
26312837Sgabeblack@google.com
26412837Sgabeblack@google.com    /**
26512837Sgabeblack@google.com     * String representation of disassembly (lazily evaluated via
266     * disassemble()).
267     */
268    std::string *cachedDisassembly;
269
270    /**
271     * Internal function to generate disassembly string.
272     */
273    virtual std::string generateDisassembly(Addr pc,
274                                            const SymbolTable *symtab) = 0;
275
276    /// Constructor.
277    StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass)
278        : StaticInstBase(__opClass),
279          machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
280    {
281    }
282
283  public:
284
285    virtual ~StaticInst()
286    {
287        if (cachedDisassembly)
288            delete cachedDisassembly;
289    }
290
291    /**
292     * Execute this instruction under SimpleCPU model.
293     */
294    virtual Fault execute(SimpleCPU *cpu, ExecContext *xc,
295                          Trace::InstRecord *traceData) = 0;
296
297    /**
298     * Execute this instruction under detailed CPU model.
299     */
300    virtual Fault execute(CPU *cpu, SpecExecContext *xc, DynInst *dynInst,
301                          Trace::InstRecord *traceData) = 0;
302
303    /**
304     * Return the target address for a PC-relative branch.
305     * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
306     * should be true).
307     */
308    virtual Addr branchTarget(Addr branchPC)
309    {
310        panic("StaticInst::branchTarget() called on instruction "
311              "that is not a PC-relative branch.");
312    }
313
314    /**
315     * Return the target address for an indirect branch (jump).
316     * The register value is read from the supplied execution context.
317     * Invalid if not an indirect branch (i.e. isIndirectCtrl()
318     * should be true).
319     */
320    virtual Addr branchTarget(ExecContext *xc)
321    {
322        panic("StaticInst::branchTarget() called on instruction "
323              "that is not an indirect branch.");
324    }
325
326    /**
327     * Return true if the instruction is a control transfer, and if so,
328     * return the target address as well.
329     */
330    bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt);
331
332    /**
333     * Return string representation of disassembled instruction.
334     * The default version of this function will call the internal
335     * virtual generateDisassembly() function to get the string,
336     * then cache it in #cachedDisassembly.  If the disassembly
337     * should not be cached, this function should be overridden directly.
338     */
339    virtual const std::string &disassemble(Addr pc,
340                                           const SymbolTable *symtab = 0)
341    {
342        if (!cachedDisassembly)
343            cachedDisassembly =
344                new std::string(generateDisassembly(pc, symtab));
345
346        return *cachedDisassembly;
347    }
348
349    /// Decoded instruction cache type.
350    /// For now we're using a generic hash_map; this seems to work
351    /// pretty well.
352    typedef m5::hash_map<MachInst, StaticInstPtr<ISA> > DecodeCache;
353
354    /// A cache of decoded instruction objects.
355    static DecodeCache decodeCache;
356
357    /**
358     * Dump some basic stats on the decode cache hash map.
359     * Only gets called if DECODE_CACHE_HASH_STATS is defined.
360     */
361    static void dumpDecodeCacheStats();
362
363    /// Decode a machine instruction.
364    /// @param mach_inst The binary instruction to decode.
365    /// @retval A pointer to the corresponding StaticInst object.
366    static
367    StaticInstPtr<ISA> decode(MachInst mach_inst)
368    {
369#ifdef DECODE_CACHE_HASH_STATS
370        // Simple stats on decode hash_map.  Turns out the default
371        // hash function is as good as anything I could come up with.
372        const int dump_every_n = 10000000;
373        static int decodes_til_dump = dump_every_n;
374
375        if (--decodes_til_dump == 0) {
376            dumpDecodeCacheStats();
377            decodes_til_dump = dump_every_n;
378        }
379#endif
380
381        typename DecodeCache::iterator iter = decodeCache.find(mach_inst);
382        if (iter != decodeCache.end()) {
383            return iter->second;
384        }
385
386        StaticInstPtr<ISA> si = ISA::decodeInst(mach_inst);
387        decodeCache[mach_inst] = si;
388        return si;
389    }
390};
391
392typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
393
394/// Reference-counted pointer to a StaticInst object.
395/// This type should be used instead of "StaticInst<ISA> *" so that
396/// StaticInst objects can be properly reference-counted.
397template <class ISA>
398class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> >
399{
400  public:
401    /// Constructor.
402    StaticInstPtr()
403        : RefCountingPtr<StaticInst<ISA> >()
404    {
405    }
406
407    /// Conversion from "StaticInst<ISA> *".
408    StaticInstPtr(StaticInst<ISA> *p)
409        : RefCountingPtr<StaticInst<ISA> >(p)
410    {
411    }
412
413    /// Copy constructor.
414    StaticInstPtr(const StaticInstPtr &r)
415        : RefCountingPtr<StaticInst<ISA> >(r)
416    {
417    }
418
419    /// Construct directly from machine instruction.
420    /// Calls StaticInst<ISA>::decode().
421    StaticInstPtr(typename ISA::MachInst mach_inst)
422        : RefCountingPtr<StaticInst<ISA> >(StaticInst<ISA>::decode(mach_inst))
423    {
424    }
425
426    /// Convert to pointer to StaticInstBase class.
427    operator const StaticInstBasePtr()
428    {
429        return get();
430    }
431};
432
433#endif // __STATIC_INST_HH__
434