static_inst.hh revision 2680:246e7104f744
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 */
30
31#ifndef __CPU_STATIC_INST_HH__
32#define __CPU_STATIC_INST_HH__
33
34#include <bitset>
35#include <string>
36
37#include "base/hashmap.hh"
38#include "base/misc.hh"
39#include "base/refcnt.hh"
40#include "cpu/op_class.hh"
41#include "sim/host.hh"
42#include "arch/isa_traits.hh"
43
44// forward declarations
45struct AlphaSimpleImpl;
46struct OzoneImpl;
47struct SimpleImpl;
48class ThreadContext;
49class DynInst;
50class Packet;
51
52template <class Impl>
53class AlphaDynInst;
54
55template <class Impl>
56class OzoneDynInst;
57
58class CheckerCPU;
59class FastCPU;
60class AtomicSimpleCPU;
61class TimingSimpleCPU;
62class InorderCPU;
63class SymbolTable;
64
65namespace Trace {
66    class InstRecord;
67}
68
69/**
70 * Base, ISA-independent static instruction class.
71 *
72 * The main component of this class is the vector of flags and the
73 * associated methods for reading them.  Any object that can rely
74 * solely on these flags can process instructions without being
75 * recompiled for multiple ISAs.
76 */
77class StaticInstBase : public RefCounted
78{
79  protected:
80
81    /// Set of boolean static instruction properties.
82    ///
83    /// Notes:
84    /// - The IsInteger and IsFloating flags are based on the class of
85    /// registers accessed by the instruction.  Although most
86    /// instructions will have exactly one of these two flags set, it
87    /// is possible for an instruction to have neither (e.g., direct
88    /// unconditional branches, memory barriers) or both (e.g., an
89    /// FP/int conversion).
90    /// - If IsMemRef is set, then exactly one of IsLoad or IsStore
91    /// will be set.
92    /// - If IsControl is set, then exactly one of IsDirectControl or
93    /// IsIndirect Control will be set, and exactly one of
94    /// IsCondControl or IsUncondControl will be set.
95    /// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
96    /// implemented as flags since in the current model there's no
97    /// other way for instructions to inject behavior into the
98    /// pipeline outside of fetch.  Once we go to an exec-in-exec CPU
99    /// model we should be able to get rid of these flags and
100    /// implement this behavior via the execute() methods.
101    ///
102    enum Flags {
103        IsNop,		///< Is a no-op (no effect at all).
104
105        IsInteger,	///< References integer regs.
106        IsFloating,	///< References FP regs.
107
108        IsMemRef,	///< References memory (load, store, or prefetch).
109        IsLoad,		///< Reads from memory (load or prefetch).
110        IsStore,	///< Writes to memory.
111        IsStoreConditional,    ///< Store conditional instruction.
112        IsInstPrefetch,	///< Instruction-cache prefetch.
113        IsDataPrefetch,	///< Data-cache prefetch.
114        IsCopy,         ///< Fast Cache block copy
115
116        IsControl,		///< Control transfer instruction.
117        IsDirectControl,	///< PC relative control transfer.
118        IsIndirectControl,	///< Register indirect control transfer.
119        IsCondControl,		///< Conditional control transfer.
120        IsUncondControl,	///< Unconditional control transfer.
121        IsCall,			///< Subroutine call.
122        IsReturn,		///< Subroutine return.
123
124        IsCondDelaySlot,///< Conditional Delay-Slot Instruction
125
126        IsThreadSync,	///< Thread synchronization operation.
127
128        IsSerializing,	///< Serializes pipeline: won't execute until all
129                        /// older instructions have committed.
130        IsSerializeBefore,
131        IsSerializeAfter,
132        IsMemBarrier,	///< Is a memory barrier
133        IsWriteBarrier,	///< Is a write barrier
134
135        IsNonSpeculative, ///< Should not be executed speculatively
136        IsQuiesce,      ///< Is a quiesce instruction
137
138        IsIprAccess,    ///< Accesses IPRs
139        IsUnverifiable, ///< Can't be verified by a checker
140
141        NumFlags
142    };
143
144    /// Flag values for this instruction.
145    std::bitset<NumFlags> flags;
146
147    /// See opClass().
148    OpClass _opClass;
149
150    /// See numSrcRegs().
151    int8_t _numSrcRegs;
152
153    /// See numDestRegs().
154    int8_t _numDestRegs;
155
156    /// The following are used to track physical register usage
157    /// for machines with separate int & FP reg files.
158    //@{
159    int8_t _numFPDestRegs;
160    int8_t _numIntDestRegs;
161    //@}
162
163    /// Constructor.
164    /// It's important to initialize everything here to a sane
165    /// default, since the decoder generally only overrides
166    /// the fields that are meaningful for the particular
167    /// instruction.
168    StaticInstBase(OpClass __opClass)
169        : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
170          _numFPDestRegs(0), _numIntDestRegs(0)
171    {
172    }
173
174  public:
175
176    /// @name Register information.
177    /// The sum of numFPDestRegs() and numIntDestRegs() equals
178    /// numDestRegs().  The former two functions are used to track
179    /// physical register usage for machines with separate int & FP
180    /// reg files.
181    //@{
182    /// Number of source registers.
183    int8_t numSrcRegs()  const { return _numSrcRegs; }
184    /// Number of destination registers.
185    int8_t numDestRegs() const { return _numDestRegs; }
186    /// Number of floating-point destination regs.
187    int8_t numFPDestRegs()  const { return _numFPDestRegs; }
188    /// Number of integer destination regs.
189    int8_t numIntDestRegs() const { return _numIntDestRegs; }
190    //@}
191
192    /// @name Flag accessors.
193    /// These functions are used to access the values of the various
194    /// instruction property flags.  See StaticInstBase::Flags for descriptions
195    /// of the individual flags.
196    //@{
197
198    bool isNop() 	  const { return flags[IsNop]; }
199
200    bool isMemRef()    	  const { return flags[IsMemRef]; }
201    bool isLoad()	  const { return flags[IsLoad]; }
202    bool isStore()	  const { return flags[IsStore]; }
203    bool isStoreConditional()	  const { return flags[IsStoreConditional]; }
204    bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
205    bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
206    bool isCopy()         const { return flags[IsCopy];}
207
208    bool isInteger()	  const { return flags[IsInteger]; }
209    bool isFloating()	  const { return flags[IsFloating]; }
210
211    bool isControl()	  const { return flags[IsControl]; }
212    bool isCall()	  const { return flags[IsCall]; }
213    bool isReturn()	  const { return flags[IsReturn]; }
214    bool isDirectCtrl()	  const { return flags[IsDirectControl]; }
215    bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
216    bool isCondCtrl()	  const { return flags[IsCondControl]; }
217    bool isUncondCtrl()	  const { return flags[IsUncondControl]; }
218
219    bool isThreadSync()   const { return flags[IsThreadSync]; }
220    bool isSerializing()  const { return flags[IsSerializing] ||
221                                      flags[IsSerializeBefore] ||
222                                      flags[IsSerializeAfter]; }
223    bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
224    bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
225    bool isMemBarrier()   const { return flags[IsMemBarrier]; }
226    bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
227    bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
228    bool isQuiesce() const { return flags[IsQuiesce]; }
229    bool isIprAccess() const { return flags[IsIprAccess]; }
230    bool isUnverifiable() const { return flags[IsUnverifiable]; }
231    //@}
232
233    /// Operation class.  Used to select appropriate function unit in issue.
234    OpClass opClass()     const { return _opClass; }
235};
236
237
238// forward declaration
239class StaticInstPtr;
240
241/**
242 * Generic yet ISA-dependent static instruction class.
243 *
244 * This class builds on StaticInstBase, defining fields and interfaces
245 * that are generic across all ISAs but that differ in details
246 * according to the specific ISA being used.
247 */
248class StaticInst : public StaticInstBase
249{
250  public:
251
252    /// Binary machine instruction type.
253    typedef TheISA::MachInst MachInst;
254    /// Binary extended machine instruction type.
255    typedef TheISA::ExtMachInst ExtMachInst;
256    /// Logical register index type.
257    typedef TheISA::RegIndex RegIndex;
258
259    enum {
260        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,	//< Max source regs
261        MaxInstDestRegs = TheISA::MaxInstDestRegs,	//< Max dest regs
262    };
263
264
265    /// Return logical index (architectural reg num) of i'th destination reg.
266    /// Only the entries from 0 through numDestRegs()-1 are valid.
267    RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
268
269    /// Return logical index (architectural reg num) of i'th source reg.
270    /// Only the entries from 0 through numSrcRegs()-1 are valid.
271    RegIndex srcRegIdx(int i)  const { return _srcRegIdx[i]; }
272
273    /// Pointer to a statically allocated "null" instruction object.
274    /// Used to give eaCompInst() and memAccInst() something to return
275    /// when called on non-memory instructions.
276    static StaticInstPtr nullStaticInstPtr;
277
278    /**
279     * Memory references only: returns "fake" instruction representing
280     * the effective address part of the memory operation.  Used to
281     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
282     * just the EA computation.
283     */
284    virtual const
285    StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; }
286
287    /**
288     * Memory references only: returns "fake" instruction representing
289     * the memory access part of the memory operation.  Used to
290     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
291     * just the memory access (not the EA computation).
292     */
293    virtual const
294    StaticInstPtr &memAccInst() const { return nullStaticInstPtr; }
295
296    /// The binary machine instruction.
297    const ExtMachInst machInst;
298
299  protected:
300
301    /// See destRegIdx().
302    RegIndex _destRegIdx[MaxInstDestRegs];
303    /// See srcRegIdx().
304    RegIndex _srcRegIdx[MaxInstSrcRegs];
305
306    /**
307     * Base mnemonic (e.g., "add").  Used by generateDisassembly()
308     * methods.  Also useful to readily identify instructions from
309     * within the debugger when #cachedDisassembly has not been
310     * initialized.
311     */
312    const char *mnemonic;
313
314    /**
315     * String representation of disassembly (lazily evaluated via
316     * disassemble()).
317     */
318    mutable std::string *cachedDisassembly;
319
320    /**
321     * Internal function to generate disassembly string.
322     */
323    virtual std::string
324    generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
325
326    /// Constructor.
327    StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
328        : StaticInstBase(__opClass),
329          machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
330    {
331    }
332
333  public:
334
335    virtual ~StaticInst()
336    {
337        if (cachedDisassembly)
338            delete cachedDisassembly;
339    }
340
341/**
342 * The execute() signatures are auto-generated by scons based on the
343 * set of CPU models we are compiling in today.
344 */
345#include "cpu/static_inst_exec_sigs.hh"
346
347    /**
348     * Return the target address for a PC-relative branch.
349     * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
350     * should be true).
351     */
352    virtual Addr branchTarget(Addr branchPC) const
353    {
354        panic("StaticInst::branchTarget() called on instruction "
355              "that is not a PC-relative branch.");
356    }
357
358    /**
359     * Return the target address for an indirect branch (jump).  The
360     * register value is read from the supplied thread context, so
361     * the result is valid only if the thread context is about to
362     * execute the branch in question.  Invalid if not an indirect
363     * branch (i.e. isIndirectCtrl() should be true).
364     */
365    virtual Addr branchTarget(ThreadContext *tc) const
366    {
367        panic("StaticInst::branchTarget() called on instruction "
368              "that is not an indirect branch.");
369    }
370
371    /**
372     * Return true if the instruction is a control transfer, and if so,
373     * return the target address as well.
374     */
375    bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const;
376
377    /**
378     * Return string representation of disassembled instruction.
379     * The default version of this function will call the internal
380     * virtual generateDisassembly() function to get the string,
381     * then cache it in #cachedDisassembly.  If the disassembly
382     * should not be cached, this function should be overridden directly.
383     */
384    virtual const std::string &disassemble(Addr pc,
385                                           const SymbolTable *symtab = 0) const
386    {
387        if (!cachedDisassembly)
388            cachedDisassembly =
389                new std::string(generateDisassembly(pc, symtab));
390
391        return *cachedDisassembly;
392    }
393
394    /// Decoded instruction cache type.
395    /// For now we're using a generic hash_map; this seems to work
396    /// pretty well.
397    typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache;
398
399    /// A cache of decoded instruction objects.
400    static DecodeCache decodeCache;
401
402    /**
403     * Dump some basic stats on the decode cache hash map.
404     * Only gets called if DECODE_CACHE_HASH_STATS is defined.
405     */
406    static void dumpDecodeCacheStats();
407
408    /// Decode a machine instruction.
409    /// @param mach_inst The binary instruction to decode.
410    /// @retval A pointer to the corresponding StaticInst object.
411    //This is defined as inline below.
412    static StaticInstPtr decode(ExtMachInst mach_inst);
413
414    //MIPS Decoder Debug Functions
415    int getOpcode() { return (machInst & 0xFC000000) >> 26 ; }//31..26
416    int getRs() {     return (machInst & 0x03E00000) >> 21; }    //25...21
417    int getRt() {     return (machInst & 0x001F0000) >> 16;  }    //20...16
418    int getRd() {     return (machInst & 0x0000F800) >> 11; }    //15...11
419    int getImm() {  return (machInst & 0x0000FFFF); }    //15...0
420    int getFunction(){  return (machInst & 0x0000003F); }//5...0
421    int getBranch(){  return (machInst & 0x0000FFFF); }//15...0
422    int getJump(){    return (machInst & 0x03FFFFFF); }//5...0
423    int getHint(){    return (machInst & 0x000007C0) >> 6; }  //10...6
424    std::string getName() { return mnemonic; }
425};
426
427typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
428
429/// Reference-counted pointer to a StaticInst object.
430/// This type should be used instead of "StaticInst *" so that
431/// StaticInst objects can be properly reference-counted.
432class StaticInstPtr : public RefCountingPtr<StaticInst>
433{
434  public:
435    /// Constructor.
436    StaticInstPtr()
437        : RefCountingPtr<StaticInst>()
438    {
439    }
440
441    /// Conversion from "StaticInst *".
442    StaticInstPtr(StaticInst *p)
443        : RefCountingPtr<StaticInst>(p)
444    {
445    }
446
447    /// Copy constructor.
448    StaticInstPtr(const StaticInstPtr &r)
449        : RefCountingPtr<StaticInst>(r)
450    {
451    }
452
453    /// Construct directly from machine instruction.
454    /// Calls StaticInst::decode().
455    StaticInstPtr(TheISA::ExtMachInst mach_inst)
456        : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
457    {
458    }
459
460    /// Convert to pointer to StaticInstBase class.
461    operator const StaticInstBasePtr()
462    {
463        return this->get();
464    }
465};
466
467inline StaticInstPtr
468StaticInst::decode(StaticInst::ExtMachInst mach_inst)
469{
470#ifdef DECODE_CACHE_HASH_STATS
471    // Simple stats on decode hash_map.  Turns out the default
472    // hash function is as good as anything I could come up with.
473    const int dump_every_n = 10000000;
474    static int decodes_til_dump = dump_every_n;
475
476    if (--decodes_til_dump == 0) {
477        dumpDecodeCacheStats();
478        decodes_til_dump = dump_every_n;
479    }
480#endif
481
482    DecodeCache::iterator iter = decodeCache.find(mach_inst);
483    if (iter != decodeCache.end()) {
484        return iter->second;
485    }
486
487    StaticInstPtr si = TheISA::decodeInst(mach_inst);
488    decodeCache[mach_inst] = si;
489    return si;
490}
491
492#endif // __CPU_STATIC_INST_HH__
493