dyn_inst.hh revision 13611:c8b7847b4171
1/*
2 * Copyright (c) 2010, 2016 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder.  You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2004-2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 */
43
44#ifndef __CPU_O3_DYN_INST_HH__
45#define __CPU_O3_DYN_INST_HH__
46
47#include <array>
48
49#include "arch/isa_traits.hh"
50#include "config/the_isa.hh"
51#include "cpu/o3/cpu.hh"
52#include "cpu/o3/isa_specific.hh"
53#include "cpu/base_dyn_inst.hh"
54#include "cpu/inst_seq.hh"
55#include "cpu/reg_class.hh"
56
57class Packet;
58
59template <class Impl>
60class BaseO3DynInst : public BaseDynInst<Impl>
61{
62  public:
63    /** Typedef for the CPU. */
64    typedef typename Impl::O3CPU O3CPU;
65
66    /** Binary machine instruction type. */
67    typedef TheISA::MachInst MachInst;
68    /** Register types. */
69    typedef TheISA::CCReg   CCReg;
70    using VecRegContainer = TheISA::VecRegContainer;
71    using VecElem = TheISA::VecElem;
72    static constexpr auto NumVecElemPerVecReg = TheISA::NumVecElemPerVecReg;
73    using VecPredRegContainer = TheISA::VecPredRegContainer;
74
75    enum {
76        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,        //< Max source regs
77        MaxInstDestRegs = TheISA::MaxInstDestRegs       //< Max dest regs
78    };
79
80  public:
81    /** BaseDynInst constructor given a binary instruction. */
82    BaseO3DynInst(const StaticInstPtr &staticInst, const StaticInstPtr
83            &macroop, TheISA::PCState pc, TheISA::PCState predPC,
84            InstSeqNum seq_num, O3CPU *cpu);
85
86    /** BaseDynInst constructor given a static inst pointer. */
87    BaseO3DynInst(const StaticInstPtr &_staticInst,
88                  const StaticInstPtr &_macroop);
89
90    ~BaseO3DynInst();
91
92    /** Executes the instruction.*/
93    Fault execute();
94
95    /** Initiates the access.  Only valid for memory operations. */
96    Fault initiateAcc();
97
98    /** Completes the access.  Only valid for memory operations. */
99    Fault completeAcc(PacketPtr pkt);
100
101  private:
102    /** Initializes variables. */
103    void initVars();
104
105  protected:
106    /** Explicitation of dependent names. */
107    using BaseDynInst<Impl>::cpu;
108    using BaseDynInst<Impl>::_srcRegIdx;
109    using BaseDynInst<Impl>::_destRegIdx;
110
111    /** Values to be written to the destination misc. registers. */
112    std::array<RegVal, TheISA::MaxMiscDestRegs> _destMiscRegVal;
113
114    /** Indexes of the destination misc. registers. They are needed to defer
115     * the write accesses to the misc. registers until the commit stage, when
116     * the instruction is out of its speculative state.
117     */
118    std::array<short, TheISA::MaxMiscDestRegs> _destMiscRegIdx;
119
120    /** Number of destination misc. registers. */
121    uint8_t _numDestMiscRegs;
122
123
124  public:
125#if TRACING_ON
126    /** Tick records used for the pipeline activity viewer. */
127    Tick fetchTick;      // instruction fetch is completed.
128    int32_t decodeTick;  // instruction enters decode phase
129    int32_t renameTick;  // instruction enters rename phase
130    int32_t dispatchTick;
131    int32_t issueTick;
132    int32_t completeTick;
133    int32_t commitTick;
134    int32_t storeTick;
135#endif
136
137    /** Reads a misc. register, including any side-effects the read
138     * might have as defined by the architecture.
139     */
140    RegVal
141    readMiscReg(int misc_reg)
142    {
143        return this->cpu->readMiscReg(misc_reg, this->threadNumber);
144    }
145
146    /** Sets a misc. register, including any side-effects the write
147     * might have as defined by the architecture.
148     */
149    void
150    setMiscReg(int misc_reg, RegVal val)
151    {
152        /** Writes to misc. registers are recorded and deferred until the
153         * commit stage, when updateMiscRegs() is called. First, check if
154         * the misc reg has been written before and update its value to be
155         * committed instead of making a new entry. If not, make a new
156         * entry and record the write.
157         */
158        for (int idx = 0; idx < _numDestMiscRegs; idx++) {
159            if (_destMiscRegIdx[idx] == misc_reg) {
160               _destMiscRegVal[idx] = val;
161               return;
162            }
163        }
164
165        assert(_numDestMiscRegs < TheISA::MaxMiscDestRegs);
166        _destMiscRegIdx[_numDestMiscRegs] = misc_reg;
167        _destMiscRegVal[_numDestMiscRegs] = val;
168        _numDestMiscRegs++;
169    }
170
171    /** Reads a misc. register, including any side-effects the read
172     * might have as defined by the architecture.
173     */
174    RegVal
175    readMiscRegOperand(const StaticInst *si, int idx)
176    {
177        const RegId& reg = si->srcRegIdx(idx);
178        assert(reg.isMiscReg());
179        return this->cpu->readMiscReg(reg.index(), this->threadNumber);
180    }
181
182    /** Sets a misc. register, including any side-effects the write
183     * might have as defined by the architecture.
184     */
185    void
186    setMiscRegOperand(const StaticInst *si, int idx, RegVal val)
187    {
188        const RegId& reg = si->destRegIdx(idx);
189        assert(reg.isMiscReg());
190        setMiscReg(reg.index(), val);
191    }
192
193    /** Called at the commit stage to update the misc. registers. */
194    void
195    updateMiscRegs()
196    {
197        // @todo: Pretty convoluted way to avoid squashing from happening when
198        // using the TC during an instruction's execution (specifically for
199        // instructions that have side-effects that use the TC).  Fix this.
200        // See cpu/o3/dyn_inst_impl.hh.
201        bool no_squash_from_TC = this->thread->noSquashFromTC;
202        this->thread->noSquashFromTC = true;
203
204        for (int i = 0; i < _numDestMiscRegs; i++)
205            this->cpu->setMiscReg(
206                _destMiscRegIdx[i], _destMiscRegVal[i], this->threadNumber);
207
208        this->thread->noSquashFromTC = no_squash_from_TC;
209    }
210
211    void forwardOldRegs()
212    {
213
214        for (int idx = 0; idx < this->numDestRegs(); idx++) {
215            PhysRegIdPtr prev_phys_reg = this->prevDestRegIdx(idx);
216            const RegId& original_dest_reg =
217                this->staticInst->destRegIdx(idx);
218            switch (original_dest_reg.classValue()) {
219              case IntRegClass:
220                this->setIntRegOperand(this->staticInst.get(), idx,
221                               this->cpu->readIntReg(prev_phys_reg));
222                break;
223              case FloatRegClass:
224                this->setFloatRegOperandBits(this->staticInst.get(), idx,
225                               this->cpu->readFloatReg(prev_phys_reg));
226                break;
227              case VecRegClass:
228                this->setVecRegOperand(this->staticInst.get(), idx,
229                               this->cpu->readVecReg(prev_phys_reg));
230                break;
231              case VecElemClass:
232                this->setVecElemOperand(this->staticInst.get(), idx,
233                               this->cpu->readVecElem(prev_phys_reg));
234                break;
235              case VecPredRegClass:
236                this->setVecPredRegOperand(this->staticInst.get(), idx,
237                               this->cpu->readVecPredReg(prev_phys_reg));
238                break;
239              case CCRegClass:
240                this->setCCRegOperand(this->staticInst.get(), idx,
241                               this->cpu->readCCReg(prev_phys_reg));
242                break;
243              case MiscRegClass:
244                // no need to forward misc reg values
245                break;
246              default:
247                panic("Unknown register class: %d",
248                        (int)original_dest_reg.classValue());
249            }
250        }
251    }
252    /** Calls hardware return from error interrupt. */
253    Fault hwrei();
254    /** Traps to handle specified fault. */
255    void trap(const Fault &fault);
256    bool simPalCheck(int palFunc);
257
258    /** Emulates a syscall. */
259    void syscall(int64_t callnum, Fault *fault);
260
261  public:
262
263    // The register accessor methods provide the index of the
264    // instruction's operand (e.g., 0 or 1), not the architectural
265    // register index, to simplify the implementation of register
266    // renaming.  We find the architectural register index by indexing
267    // into the instruction's own operand index table.  Note that a
268    // raw pointer to the StaticInst is provided instead of a
269    // ref-counted StaticInstPtr to redice overhead.  This is fine as
270    // long as these methods don't copy the pointer into any long-term
271    // storage (which is pretty hard to imagine they would have reason
272    // to do).
273
274    RegVal
275    readIntRegOperand(const StaticInst *si, int idx)
276    {
277        return this->cpu->readIntReg(this->_srcRegIdx[idx]);
278    }
279
280    RegVal
281    readFloatRegOperandBits(const StaticInst *si, int idx)
282    {
283        return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
284    }
285
286    const VecRegContainer&
287    readVecRegOperand(const StaticInst *si, int idx) const
288    {
289        return this->cpu->readVecReg(this->_srcRegIdx[idx]);
290    }
291
292    /**
293     * Read destination vector register operand for modification.
294     */
295    VecRegContainer&
296    getWritableVecRegOperand(const StaticInst *si, int idx)
297    {
298        return this->cpu->getWritableVecReg(this->_destRegIdx[idx]);
299    }
300
301    /** Vector Register Lane Interfaces. */
302    /** @{ */
303    /** Reads source vector 8bit operand. */
304    ConstVecLane8
305    readVec8BitLaneOperand(const StaticInst *si, int idx) const
306    {
307        return cpu->template readVecLane<uint8_t>(_srcRegIdx[idx]);
308    }
309
310    /** Reads source vector 16bit operand. */
311    ConstVecLane16
312    readVec16BitLaneOperand(const StaticInst *si, int idx) const
313    {
314        return cpu->template readVecLane<uint16_t>(_srcRegIdx[idx]);
315    }
316
317    /** Reads source vector 32bit operand. */
318    ConstVecLane32
319    readVec32BitLaneOperand(const StaticInst *si, int idx) const
320    {
321        return cpu->template readVecLane<uint32_t>(_srcRegIdx[idx]);
322    }
323
324    /** Reads source vector 64bit operand. */
325    ConstVecLane64
326    readVec64BitLaneOperand(const StaticInst *si, int idx) const
327    {
328        return cpu->template readVecLane<uint64_t>(_srcRegIdx[idx]);
329    }
330
331    /** Write a lane of the destination vector operand. */
332    template <typename LD>
333    void
334    setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
335    {
336        return cpu->template setVecLane(_destRegIdx[idx], val);
337    }
338    virtual void
339    setVecLaneOperand(const StaticInst *si, int idx,
340            const LaneData<LaneSize::Byte>& val)
341    {
342        return setVecLaneOperandT(si, idx, val);
343    }
344    virtual void
345    setVecLaneOperand(const StaticInst *si, int idx,
346            const LaneData<LaneSize::TwoByte>& val)
347    {
348        return setVecLaneOperandT(si, idx, val);
349    }
350    virtual void
351    setVecLaneOperand(const StaticInst *si, int idx,
352            const LaneData<LaneSize::FourByte>& val)
353    {
354        return setVecLaneOperandT(si, idx, val);
355    }
356    virtual void
357    setVecLaneOperand(const StaticInst *si, int idx,
358            const LaneData<LaneSize::EightByte>& val)
359    {
360        return setVecLaneOperandT(si, idx, val);
361    }
362    /** @} */
363
364    VecElem readVecElemOperand(const StaticInst *si, int idx) const
365    {
366        return this->cpu->readVecElem(this->_srcRegIdx[idx]);
367    }
368
369    const VecPredRegContainer&
370    readVecPredRegOperand(const StaticInst *si, int idx) const override
371    {
372        return this->cpu->readVecPredReg(this->_srcRegIdx[idx]);
373    }
374
375    VecPredRegContainer&
376    getWritableVecPredRegOperand(const StaticInst *si, int idx) override
377    {
378        return this->cpu->getWritableVecPredReg(this->_destRegIdx[idx]);
379    }
380
381    CCReg readCCRegOperand(const StaticInst *si, int idx)
382    {
383        return this->cpu->readCCReg(this->_srcRegIdx[idx]);
384    }
385
386    /** @todo: Make results into arrays so they can handle multiple dest
387     *  registers.
388     */
389    void
390    setIntRegOperand(const StaticInst *si, int idx, RegVal val)
391    {
392        this->cpu->setIntReg(this->_destRegIdx[idx], val);
393        BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
394    }
395
396    void
397    setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val)
398    {
399        this->cpu->setFloatReg(this->_destRegIdx[idx], val);
400        BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
401    }
402
403    void
404    setVecRegOperand(const StaticInst *si, int idx,
405                     const VecRegContainer& val)
406    {
407        this->cpu->setVecReg(this->_destRegIdx[idx], val);
408        BaseDynInst<Impl>::setVecRegOperand(si, idx, val);
409    }
410
411    void setVecElemOperand(const StaticInst *si, int idx,
412                           const VecElem val)
413    {
414        int reg_idx = idx;
415        this->cpu->setVecElem(this->_destRegIdx[reg_idx], val);
416        BaseDynInst<Impl>::setVecElemOperand(si, idx, val);
417    }
418
419    void
420    setVecPredRegOperand(const StaticInst *si, int idx,
421                         const VecPredRegContainer& val) override
422    {
423        this->cpu->setVecPredReg(this->_destRegIdx[idx], val);
424        BaseDynInst<Impl>::setVecPredRegOperand(si, idx, val);
425    }
426
427    void setCCRegOperand(const StaticInst *si, int idx, CCReg val)
428    {
429        this->cpu->setCCReg(this->_destRegIdx[idx], val);
430        BaseDynInst<Impl>::setCCRegOperand(si, idx, val);
431    }
432
433#if THE_ISA == MIPS_ISA
434    RegVal
435    readRegOtherThread(const RegId& misc_reg, ThreadID tid)
436    {
437        panic("MIPS MT not defined for O3 CPU.\n");
438        return 0;
439    }
440
441    void
442    setRegOtherThread(const RegId& misc_reg, RegVal val, ThreadID tid)
443    {
444        panic("MIPS MT not defined for O3 CPU.\n");
445    }
446#endif
447};
448
449#endif // __CPU_O3_ALPHA_DYN_INST_HH__
450
451