exec_context.hh revision 11608:6319a1125f1c
1/*
2 * Copyright (c) 2011-2014 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) 2002-2005 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: Steve Reinhardt
42 *          Dave Greene
43 *          Nathan Binkert
44 *          Andrew Bardsley
45 */
46
47/**
48 * @file
49 *
50 *  ExecContext bears the exec_context interface for Minor.
51 */
52
53#ifndef __CPU_MINOR_EXEC_CONTEXT_HH__
54#define __CPU_MINOR_EXEC_CONTEXT_HH__
55
56#include "cpu/exec_context.hh"
57#include "cpu/minor/execute.hh"
58#include "cpu/minor/pipeline.hh"
59#include "cpu/base.hh"
60#include "cpu/simple_thread.hh"
61#include "mem/request.hh"
62#include "debug/MinorExecute.hh"
63
64namespace Minor
65{
66
67/* Forward declaration of Execute */
68class Execute;
69
70/** ExecContext bears the exec_context interface for Minor.  This nicely
71 *  separates that interface from other classes such as Pipeline, MinorCPU
72 *  and DynMinorInst and makes it easier to see what state is accessed by it.
73 */
74class ExecContext : public ::ExecContext
75{
76  public:
77    MinorCPU &cpu;
78
79    /** ThreadState object, provides all the architectural state. */
80    SimpleThread &thread;
81
82    /** The execute stage so we can peek at its contents. */
83    Execute &execute;
84
85    /** Instruction for the benefit of memory operations and for PC */
86    MinorDynInstPtr inst;
87
88    ExecContext (
89        MinorCPU &cpu_,
90        SimpleThread &thread_, Execute &execute_,
91        MinorDynInstPtr inst_) :
92        cpu(cpu_),
93        thread(thread_),
94        execute(execute_),
95        inst(inst_)
96    {
97        DPRINTF(MinorExecute, "ExecContext setting PC: %s\n", inst->pc);
98        pcState(inst->pc);
99        setPredicate(true);
100        thread.setIntReg(TheISA::ZeroReg, 0);
101#if THE_ISA == ALPHA_ISA
102        thread.setFloatReg(TheISA::ZeroReg, 0.0);
103#endif
104    }
105
106    Fault
107    initiateMemRead(Addr addr, unsigned int size, Request::Flags flags)
108    {
109        execute.getLSQ().pushRequest(inst, true /* load */, nullptr,
110            size, addr, flags, NULL);
111        return NoFault;
112    }
113
114    Fault
115    writeMem(uint8_t *data, unsigned int size, Addr addr,
116             Request::Flags flags, uint64_t *res)
117    {
118        execute.getLSQ().pushRequest(inst, false /* store */, data,
119            size, addr, flags, res);
120        return NoFault;
121    }
122
123    IntReg
124    readIntRegOperand(const StaticInst *si, int idx)
125    {
126        return thread.readIntReg(si->srcRegIdx(idx));
127    }
128
129    TheISA::FloatReg
130    readFloatRegOperand(const StaticInst *si, int idx)
131    {
132        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Reg_Base;
133        return thread.readFloatReg(reg_idx);
134    }
135
136    TheISA::FloatRegBits
137    readFloatRegOperandBits(const StaticInst *si, int idx)
138    {
139        int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Reg_Base;
140        return thread.readFloatRegBits(reg_idx);
141    }
142
143    void
144    setIntRegOperand(const StaticInst *si, int idx, IntReg val)
145    {
146        thread.setIntReg(si->destRegIdx(idx), val);
147    }
148
149    void
150    setFloatRegOperand(const StaticInst *si, int idx,
151        TheISA::FloatReg val)
152    {
153        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Reg_Base;
154        thread.setFloatReg(reg_idx, val);
155    }
156
157    void
158    setFloatRegOperandBits(const StaticInst *si, int idx,
159        TheISA::FloatRegBits val)
160    {
161        int reg_idx = si->destRegIdx(idx) - TheISA::FP_Reg_Base;
162        thread.setFloatRegBits(reg_idx, val);
163    }
164
165    bool
166    readPredicate()
167    {
168        return thread.readPredicate();
169    }
170
171    void
172    setPredicate(bool val)
173    {
174        thread.setPredicate(val);
175    }
176
177    TheISA::PCState
178    pcState() const
179    {
180        return thread.pcState();
181    }
182
183    void
184    pcState(const TheISA::PCState &val)
185    {
186        thread.pcState(val);
187    }
188
189    TheISA::MiscReg
190    readMiscRegNoEffect(int misc_reg) const
191    {
192        return thread.readMiscRegNoEffect(misc_reg);
193    }
194
195    TheISA::MiscReg
196    readMiscReg(int misc_reg)
197    {
198        return thread.readMiscReg(misc_reg);
199    }
200
201    void
202    setMiscReg(int misc_reg, const TheISA::MiscReg &val)
203    {
204        thread.setMiscReg(misc_reg, val);
205    }
206
207    TheISA::MiscReg
208    readMiscRegOperand(const StaticInst *si, int idx)
209    {
210        int reg_idx = si->srcRegIdx(idx) - TheISA::Misc_Reg_Base;
211        return thread.readMiscReg(reg_idx);
212    }
213
214    void
215    setMiscRegOperand(const StaticInst *si, int idx,
216        const TheISA::MiscReg &val)
217    {
218        int reg_idx = si->destRegIdx(idx) - TheISA::Misc_Reg_Base;
219        return thread.setMiscReg(reg_idx, val);
220    }
221
222    Fault
223    hwrei()
224    {
225#if THE_ISA == ALPHA_ISA
226        return thread.hwrei();
227#else
228        return NoFault;
229#endif
230    }
231
232    bool
233    simPalCheck(int palFunc)
234    {
235#if THE_ISA == ALPHA_ISA
236        return thread.simPalCheck(palFunc);
237#else
238        return false;
239#endif
240    }
241
242    void
243    syscall(int64_t callnum)
244    {
245        if (FullSystem)
246            panic("Syscall emulation isn't available in FS mode.\n");
247
248        thread.syscall(callnum);
249    }
250
251    ThreadContext *tcBase() { return thread.getTC(); }
252
253    /* @todo, should make stCondFailures persistent somewhere */
254    unsigned int readStCondFailures() const { return 0; }
255    void setStCondFailures(unsigned int st_cond_failures) {}
256
257    ContextID contextId() { return thread.contextId(); }
258    /* ISA-specific (or at least currently ISA singleton) functions */
259
260    /* X86: TLB twiddling */
261    void
262    demapPage(Addr vaddr, uint64_t asn)
263    {
264        thread.getITBPtr()->demapPage(vaddr, asn);
265        thread.getDTBPtr()->demapPage(vaddr, asn);
266    }
267
268    TheISA::CCReg
269    readCCRegOperand(const StaticInst *si, int idx)
270    {
271        int reg_idx = si->srcRegIdx(idx) - TheISA::CC_Reg_Base;
272        return thread.readCCReg(reg_idx);
273    }
274
275    void
276    setCCRegOperand(const StaticInst *si, int idx, TheISA::CCReg val)
277    {
278        int reg_idx = si->destRegIdx(idx) - TheISA::CC_Reg_Base;
279        thread.setCCReg(reg_idx, val);
280    }
281
282    void
283    demapInstPage(Addr vaddr, uint64_t asn)
284    {
285        thread.getITBPtr()->demapPage(vaddr, asn);
286    }
287
288    void
289    demapDataPage(Addr vaddr, uint64_t asn)
290    {
291        thread.getDTBPtr()->demapPage(vaddr, asn);
292    }
293
294    /* ALPHA/POWER: Effective address storage */
295    void setEA(Addr ea)
296    {
297        inst->ea = ea;
298    }
299
300    BaseCPU *getCpuPtr() { return &cpu; }
301
302    /* POWER: Effective address storage */
303    Addr getEA() const
304    {
305        return inst->ea;
306    }
307
308    /* MIPS: other thread register reading/writing */
309    uint64_t
310    readRegOtherThread(int idx, ThreadID tid = InvalidThreadID)
311    {
312        SimpleThread *other_thread = (tid == InvalidThreadID
313            ? &thread : cpu.threads[tid]);
314
315        if (idx < TheISA::FP_Reg_Base) { /* Integer */
316            return other_thread->readIntReg(idx);
317        } else if (idx < TheISA::Misc_Reg_Base) { /* Float */
318            return other_thread->readFloatRegBits(idx
319                - TheISA::FP_Reg_Base);
320        } else { /* Misc */
321            return other_thread->readMiscReg(idx
322                - TheISA::Misc_Reg_Base);
323        }
324    }
325
326    void
327    setRegOtherThread(int idx, const TheISA::MiscReg &val,
328        ThreadID tid = InvalidThreadID)
329    {
330        SimpleThread *other_thread = (tid == InvalidThreadID
331            ? &thread : cpu.threads[tid]);
332
333        if (idx < TheISA::FP_Reg_Base) { /* Integer */
334            return other_thread->setIntReg(idx, val);
335        } else if (idx < TheISA::Misc_Reg_Base) { /* Float */
336            return other_thread->setFloatRegBits(idx
337                - TheISA::FP_Reg_Base, val);
338        } else { /* Misc */
339            return other_thread->setMiscReg(idx
340                - TheISA::Misc_Reg_Base, val);
341        }
342    }
343
344  public:
345    // monitor/mwait funtions
346    void armMonitor(Addr address)
347    { getCpuPtr()->armMonitor(inst->id.threadId, address); }
348
349    bool mwait(PacketPtr pkt)
350    { return getCpuPtr()->mwait(inst->id.threadId, pkt); }
351
352    void mwaitAtomic(ThreadContext *tc)
353    { return getCpuPtr()->mwaitAtomic(inst->id.threadId, tc, thread.dtb); }
354
355    AddressMonitor *getAddrMonitor()
356    { return getCpuPtr()->getCpuAddrMonitor(inst->id.threadId); }
357};
358
359}
360
361#endif /* __CPU_MINOR_EXEC_CONTEXT_HH__ */
362