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