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