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