exec_context.hh revision 10259
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/minor/execute.hh"
57#include "cpu/minor/pipeline.hh"
58#include "cpu/base.hh"
59#include "cpu/simple_thread.hh"
60#include "debug/MinorExecute.hh"
61
62namespace Minor
63{
64
65/* Forward declaration of Execute */
66class Execute;
67
68/** ExecContext bears the exec_context interface for Minor.  This nicely
69 *  separates that interface from other classes such as Pipeline, MinorCPU
70 *  and DynMinorInst and makes it easier to see what state is accessed by it.
71 */
72class ExecContext
73{
74  public:
75    MinorCPU &cpu;
76
77    /** ThreadState object, provides all the architectural state. */
78    SimpleThread &thread;
79
80    /** The execute stage so we can peek at its contents. */
81    Execute &execute;
82
83    /** Instruction for the benefit of memory operations and for PC */
84    MinorDynInstPtr inst;
85
86    ExecContext (
87        MinorCPU &cpu_,
88        SimpleThread &thread_, Execute &execute_,
89        MinorDynInstPtr inst_) :
90        cpu(cpu_),
91        thread(thread_),
92        execute(execute_),
93        inst(inst_)
94    {
95        DPRINTF(MinorExecute, "ExecContext setting PC: %s\n", inst->pc);
96        pcState(inst->pc);
97        setPredicate(true);
98        thread.setIntReg(TheISA::ZeroReg, 0);
99#if THE_ISA == ALPHA_ISA
100        thread.setFloatReg(TheISA::ZeroReg, 0.0);
101#endif
102    }
103
104    Fault
105    readMem(Addr addr, uint8_t *data, unsigned int size,
106        unsigned int flags)
107    {
108        execute.getLSQ().pushRequest(inst, true /* load */, data,
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    uint64_t
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, uint64_t 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()
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)
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() { return 0; }
254    unsigned int
255    setStCondFailures(unsigned int st_cond_failures)
256    {
257        return 0;
258    }
259
260    int contextId() { return thread.contextId(); }
261    /* ISA-specific (or at least currently ISA singleton) functions */
262
263    /* X86: TLB twiddling */
264    void
265    demapPage(Addr vaddr, uint64_t asn)
266    {
267        thread.getITBPtr()->demapPage(vaddr, asn);
268        thread.getDTBPtr()->demapPage(vaddr, asn);
269    }
270
271    TheISA::CCReg
272    readCCRegOperand(const StaticInst *si, int idx)
273    {
274        int reg_idx = si->srcRegIdx(idx) - TheISA::CC_Reg_Base;
275        return thread.readCCReg(reg_idx);
276    }
277
278    void
279    setCCRegOperand(const StaticInst *si, int idx, TheISA::CCReg val)
280    {
281        int reg_idx = si->destRegIdx(idx) - TheISA::CC_Reg_Base;
282        thread.setCCReg(reg_idx, val);
283    }
284
285    void
286    demapInstPage(Addr vaddr, uint64_t asn)
287    {
288        thread.getITBPtr()->demapPage(vaddr, asn);
289    }
290
291    void
292    demapDataPage(Addr vaddr, uint64_t asn)
293    {
294        thread.getDTBPtr()->demapPage(vaddr, asn);
295    }
296
297    /* ALPHA/POWER: Effective address storage */
298    void setEA(Addr &ea)
299    {
300        inst->ea = ea;
301    }
302
303    BaseCPU *getCpuPtr() { return &cpu; }
304
305    /* POWER: Effective address storage */
306    Addr getEA()
307    {
308        return inst->ea;
309    }
310
311    /* MIPS: other thread register reading/writing */
312    uint64_t
313    readRegOtherThread(unsigned idx, ThreadID tid = InvalidThreadID)
314    {
315        SimpleThread *other_thread = (tid == InvalidThreadID
316            ? &thread : cpu.threads[tid]);
317
318        if (idx < TheISA::FP_Reg_Base) { /* Integer */
319            return other_thread->readIntReg(idx);
320        } else if (idx < TheISA::Misc_Reg_Base) { /* Float */
321            return other_thread->readFloatRegBits(idx
322                - TheISA::FP_Reg_Base);
323        } else { /* Misc */
324            return other_thread->readMiscReg(idx
325                - TheISA::Misc_Reg_Base);
326        }
327    }
328
329    void
330    setRegOtherThread(unsigned idx, const TheISA::MiscReg &val,
331        ThreadID tid = InvalidThreadID)
332    {
333        SimpleThread *other_thread = (tid == InvalidThreadID
334            ? &thread : cpu.threads[tid]);
335
336        if (idx < TheISA::FP_Reg_Base) { /* Integer */
337            return other_thread->setIntReg(idx, val);
338        } else if (idx < TheISA::Misc_Reg_Base) { /* Float */
339            return other_thread->setFloatRegBits(idx
340                - TheISA::FP_Reg_Base, val);
341        } else { /* Misc */
342            return other_thread->setMiscReg(idx
343                - TheISA::Misc_Reg_Base, val);
344        }
345    }
346};
347
348}
349
350#endif /* __CPU_MINOR_EXEC_CONTEXT_HH__ */
351