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