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