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