static_inst.hh revision 2935:d1223a6c9156
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    bool isCondDelaySlot() const { return flags[IsCondDelaySlot]; }
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    /// Return opcode of machine instruction
415    uint32_t getOpcode() { return bits(machInst, 31, 26);}
416
417    /// Return name of machine instruction
418    std::string getName() { return mnemonic; }
419};
420
421typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
422
423/// Reference-counted pointer to a StaticInst object.
424/// This type should be used instead of "StaticInst *" so that
425/// StaticInst objects can be properly reference-counted.
426class StaticInstPtr : public RefCountingPtr<StaticInst>
427{
428  public:
429    /// Constructor.
430    StaticInstPtr()
431        : RefCountingPtr<StaticInst>()
432    {
433    }
434
435    /// Conversion from "StaticInst *".
436    StaticInstPtr(StaticInst *p)
437        : RefCountingPtr<StaticInst>(p)
438    {
439    }
440
441    /// Copy constructor.
442    StaticInstPtr(const StaticInstPtr &r)
443        : RefCountingPtr<StaticInst>(r)
444    {
445    }
446
447    /// Construct directly from machine instruction.
448    /// Calls StaticInst::decode().
449    StaticInstPtr(TheISA::ExtMachInst mach_inst)
450        : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
451    {
452    }
453
454    /// Convert to pointer to StaticInstBase class.
455    operator const StaticInstBasePtr()
456    {
457        return this->get();
458    }
459};
460
461inline StaticInstPtr
462StaticInst::decode(StaticInst::ExtMachInst mach_inst)
463{
464#ifdef DECODE_CACHE_HASH_STATS
465    // Simple stats on decode hash_map.  Turns out the default
466    // hash function is as good as anything I could come up with.
467    const int dump_every_n = 10000000;
468    static int decodes_til_dump = dump_every_n;
469
470    if (--decodes_til_dump == 0) {
471        dumpDecodeCacheStats();
472        decodes_til_dump = dump_every_n;
473    }
474#endif
475
476    DecodeCache::iterator iter = decodeCache.find(mach_inst);
477    if (iter != decodeCache.end()) {
478        return iter->second;
479    }
480
481    StaticInstPtr si = TheISA::decodeInst(mach_inst);
482    decodeCache[mach_inst] = si;
483    return si;
484}
485
486#endif // __CPU_STATIC_INST_HH__
487