static_inst.hh revision 2665:a124942bacb8
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/hashmap.hh"
38#include "base/misc.hh"
39#include "base/refcnt.hh"
40#include "cpu/op_class.hh"
41#include "sim/host.hh"
42#include "arch/isa_traits.hh"
43
44// forward declarations
45struct AlphaSimpleImpl;
46class ExecContext;
47class DynInst;
48class Packet;
49
50template <class Impl>
51class AlphaDynInst;
52
53class FastCPU;
54class AtomicSimpleCPU;
55class TimingSimpleCPU;
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
130        NumFlags
131    };
132
133    /// Flag values for this instruction.
134    std::bitset<NumFlags> flags;
135
136    /// See opClass().
137    OpClass _opClass;
138
139    /// See numSrcRegs().
140    int8_t _numSrcRegs;
141
142    /// See numDestRegs().
143    int8_t _numDestRegs;
144
145    /// The following are used to track physical register usage
146    /// for machines with separate int & FP reg files.
147    //@{
148    int8_t _numFPDestRegs;
149    int8_t _numIntDestRegs;
150    //@}
151
152    /// Constructor.
153    /// It's important to initialize everything here to a sane
154    /// default, since the decoder generally only overrides
155    /// the fields that are meaningful for the particular
156    /// instruction.
157    StaticInstBase(OpClass __opClass)
158        : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
159          _numFPDestRegs(0), _numIntDestRegs(0)
160    {
161    }
162
163  public:
164
165    /// @name Register information.
166    /// The sum of numFPDestRegs() and numIntDestRegs() equals
167    /// numDestRegs().  The former two functions are used to track
168    /// physical register usage for machines with separate int & FP
169    /// reg files.
170    //@{
171    /// Number of source registers.
172    int8_t numSrcRegs()  const { return _numSrcRegs; }
173    /// Number of destination registers.
174    int8_t numDestRegs() const { return _numDestRegs; }
175    /// Number of floating-point destination regs.
176    int8_t numFPDestRegs()  const { return _numFPDestRegs; }
177    /// Number of integer destination regs.
178    int8_t numIntDestRegs() const { return _numIntDestRegs; }
179    //@}
180
181    /// @name Flag accessors.
182    /// These functions are used to access the values of the various
183    /// instruction property flags.  See StaticInstBase::Flags for descriptions
184    /// of the individual flags.
185    //@{
186
187    bool isNop() 	  const { return flags[IsNop]; }
188
189    bool isMemRef()    	  const { return flags[IsMemRef]; }
190    bool isLoad()	  const { return flags[IsLoad]; }
191    bool isStore()	  const { return flags[IsStore]; }
192    bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
193    bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
194    bool isCopy()         const { return flags[IsCopy];}
195
196    bool isInteger()	  const { return flags[IsInteger]; }
197    bool isFloating()	  const { return flags[IsFloating]; }
198
199    bool isControl()	  const { return flags[IsControl]; }
200    bool isCall()	  const { return flags[IsCall]; }
201    bool isReturn()	  const { return flags[IsReturn]; }
202    bool isDirectCtrl()	  const { return flags[IsDirectControl]; }
203    bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
204    bool isCondCtrl()	  const { return flags[IsCondControl]; }
205    bool isUncondCtrl()	  const { return flags[IsUncondControl]; }
206
207    bool isThreadSync()   const { return flags[IsThreadSync]; }
208    bool isSerializing()  const { return flags[IsSerializing] ||
209                                      flags[IsSerializeBefore] ||
210                                      flags[IsSerializeAfter]; }
211    bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
212    bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
213    bool isMemBarrier()   const { return flags[IsMemBarrier]; }
214    bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
215    bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
216    //@}
217
218    /// Operation class.  Used to select appropriate function unit in issue.
219    OpClass opClass()     const { return _opClass; }
220};
221
222
223// forward declaration
224class StaticInstPtr;
225
226/**
227 * Generic yet ISA-dependent static instruction class.
228 *
229 * This class builds on StaticInstBase, defining fields and interfaces
230 * that are generic across all ISAs but that differ in details
231 * according to the specific ISA being used.
232 */
233class StaticInst : public StaticInstBase
234{
235  public:
236
237    /// Binary machine instruction type.
238    typedef TheISA::MachInst MachInst;
239    /// Binary extended machine instruction type.
240    typedef TheISA::ExtMachInst ExtMachInst;
241    /// Logical register index type.
242    typedef TheISA::RegIndex RegIndex;
243
244    enum {
245        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,	//< Max source regs
246        MaxInstDestRegs = TheISA::MaxInstDestRegs,	//< Max dest regs
247    };
248
249
250    /// Return logical index (architectural reg num) of i'th destination reg.
251    /// Only the entries from 0 through numDestRegs()-1 are valid.
252    RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
253
254    /// Return logical index (architectural reg num) of i'th source reg.
255    /// Only the entries from 0 through numSrcRegs()-1 are valid.
256    RegIndex srcRegIdx(int i)  const { return _srcRegIdx[i]; }
257
258    /// Pointer to a statically allocated "null" instruction object.
259    /// Used to give eaCompInst() and memAccInst() something to return
260    /// when called on non-memory instructions.
261    static StaticInstPtr nullStaticInstPtr;
262
263    /**
264     * Memory references only: returns "fake" instruction representing
265     * the effective address part of the memory operation.  Used to
266     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
267     * just the EA computation.
268     */
269    virtual const
270    StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; }
271
272    /**
273     * Memory references only: returns "fake" instruction representing
274     * the memory access part of the memory operation.  Used to
275     * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
276     * just the memory access (not the EA computation).
277     */
278    virtual const
279    StaticInstPtr &memAccInst() const { return nullStaticInstPtr; }
280
281    /// The binary machine instruction.
282    const ExtMachInst machInst;
283
284  protected:
285
286    /// See destRegIdx().
287    RegIndex _destRegIdx[MaxInstDestRegs];
288    /// See srcRegIdx().
289    RegIndex _srcRegIdx[MaxInstSrcRegs];
290
291    /**
292     * Base mnemonic (e.g., "add").  Used by generateDisassembly()
293     * methods.  Also useful to readily identify instructions from
294     * within the debugger when #cachedDisassembly has not been
295     * initialized.
296     */
297    const char *mnemonic;
298
299    /**
300     * String representation of disassembly (lazily evaluated via
301     * disassemble()).
302     */
303    mutable std::string *cachedDisassembly;
304
305    /**
306     * Internal function to generate disassembly string.
307     */
308    virtual std::string
309    generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
310
311    /// Constructor.
312    StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
313        : StaticInstBase(__opClass),
314          machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
315    {
316    }
317
318  public:
319
320    virtual ~StaticInst()
321    {
322        if (cachedDisassembly)
323            delete cachedDisassembly;
324    }
325
326/**
327 * The execute() signatures are auto-generated by scons based on the
328 * set of CPU models we are compiling in today.
329 */
330#include "cpu/static_inst_exec_sigs.hh"
331
332    /**
333     * Return the target address for a PC-relative branch.
334     * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
335     * should be true).
336     */
337    virtual Addr branchTarget(Addr branchPC) const
338    {
339        panic("StaticInst::branchTarget() called on instruction "
340              "that is not a PC-relative branch.");
341    }
342
343    /**
344     * Return the target address for an indirect branch (jump).  The
345     * register value is read from the supplied execution context, so
346     * the result is valid only if the execution context is about to
347     * execute the branch in question.  Invalid if not an indirect
348     * branch (i.e. isIndirectCtrl() should be true).
349     */
350    virtual Addr branchTarget(ExecContext *xc) const
351    {
352        panic("StaticInst::branchTarget() called on instruction "
353              "that is not an indirect branch.");
354    }
355
356    /**
357     * Return true if the instruction is a control transfer, and if so,
358     * return the target address as well.
359     */
360    bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const;
361
362    /**
363     * Return string representation of disassembled instruction.
364     * The default version of this function will call the internal
365     * virtual generateDisassembly() function to get the string,
366     * then cache it in #cachedDisassembly.  If the disassembly
367     * should not be cached, this function should be overridden directly.
368     */
369    virtual const std::string &disassemble(Addr pc,
370                                           const SymbolTable *symtab = 0) const
371    {
372        if (!cachedDisassembly)
373            cachedDisassembly =
374                new std::string(generateDisassembly(pc, symtab));
375
376        return *cachedDisassembly;
377    }
378
379    /// Decoded instruction cache type.
380    /// For now we're using a generic hash_map; this seems to work
381    /// pretty well.
382    typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache;
383
384    /// A cache of decoded instruction objects.
385    static DecodeCache decodeCache;
386
387    /**
388     * Dump some basic stats on the decode cache hash map.
389     * Only gets called if DECODE_CACHE_HASH_STATS is defined.
390     */
391    static void dumpDecodeCacheStats();
392
393    /// Decode a machine instruction.
394    /// @param mach_inst The binary instruction to decode.
395    /// @retval A pointer to the corresponding StaticInst object.
396    //This is defined as inline below.
397    static StaticInstPtr decode(ExtMachInst mach_inst);
398
399    //MIPS Decoder Debug Functions
400    int getOpcode() { return (machInst & 0xFC000000) >> 26 ; }//31..26
401    int getRs() {     return (machInst & 0x03E00000) >> 21; }    //25...21
402    int getRt() {     return (machInst & 0x001F0000) >> 16;  }    //20...16
403    int getRd() {     return (machInst & 0x0000F800) >> 11; }    //15...11
404    int getImm() {  return (machInst & 0x0000FFFF); }    //15...0
405    int getFunction(){  return (machInst & 0x0000003F); }//5...0
406    int getBranch(){  return (machInst & 0x0000FFFF); }//15...0
407    int getJump(){    return (machInst & 0x03FFFFFF); }//5...0
408    int getHint(){    return (machInst & 0x000007C0) >> 6; }  //10...6
409    std::string getName() { return mnemonic; }
410};
411
412typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
413
414/// Reference-counted pointer to a StaticInst object.
415/// This type should be used instead of "StaticInst *" so that
416/// StaticInst objects can be properly reference-counted.
417class StaticInstPtr : public RefCountingPtr<StaticInst>
418{
419  public:
420    /// Constructor.
421    StaticInstPtr()
422        : RefCountingPtr<StaticInst>()
423    {
424    }
425
426    /// Conversion from "StaticInst *".
427    StaticInstPtr(StaticInst *p)
428        : RefCountingPtr<StaticInst>(p)
429    {
430    }
431
432    /// Copy constructor.
433    StaticInstPtr(const StaticInstPtr &r)
434        : RefCountingPtr<StaticInst>(r)
435    {
436    }
437
438    /// Construct directly from machine instruction.
439    /// Calls StaticInst::decode().
440    StaticInstPtr(TheISA::ExtMachInst mach_inst)
441        : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
442    {
443    }
444
445    /// Convert to pointer to StaticInstBase class.
446    operator const StaticInstBasePtr()
447    {
448        return this->get();
449    }
450};
451
452inline StaticInstPtr
453StaticInst::decode(StaticInst::ExtMachInst mach_inst)
454{
455#ifdef DECODE_CACHE_HASH_STATS
456    // Simple stats on decode hash_map.  Turns out the default
457    // hash function is as good as anything I could come up with.
458    const int dump_every_n = 10000000;
459    static int decodes_til_dump = dump_every_n;
460
461    if (--decodes_til_dump == 0) {
462        dumpDecodeCacheStats();
463        decodes_til_dump = dump_every_n;
464    }
465#endif
466
467    DecodeCache::iterator iter = decodeCache.find(mach_inst);
468    if (iter != decodeCache.end()) {
469        return iter->second;
470    }
471
472    StaticInstPtr si = TheISA::decodeInst(mach_inst);
473    decodeCache[mach_inst] = si;
474    return si;
475}
476
477#endif // __CPU_STATIC_INST_HH__
478