exec_context.hh revision 12104
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,
108                    Request::Flags flags) override
109    {
110        execute.getLSQ().pushRequest(inst, true /* load */, nullptr,
111            size, addr, flags, NULL);
112        return NoFault;
113    }
114
115    Fault
116    writeMem(uint8_t *data, unsigned int size, Addr addr,
117             Request::Flags flags, uint64_t *res) override
118    {
119        execute.getLSQ().pushRequest(inst, false /* store */, data,
120            size, addr, flags, res);
121        return NoFault;
122    }
123
124    IntReg
125    readIntRegOperand(const StaticInst *si, int idx) override
126    {
127        RegId reg = si->srcRegIdx(idx);
128        assert(reg.regClass == IntRegClass);
129        return thread.readIntReg(reg.regIdx);
130    }
131
132    TheISA::FloatReg
133    readFloatRegOperand(const StaticInst *si, int idx) override
134    {
135        RegId reg = si->srcRegIdx(idx);
136        assert(reg.regClass == FloatRegClass);
137        return thread.readFloatReg(reg.regIdx);
138    }
139
140    TheISA::FloatRegBits
141    readFloatRegOperandBits(const StaticInst *si, int idx) override
142    {
143        RegId reg = si->srcRegIdx(idx);
144        assert(reg.regClass == FloatRegClass);
145        return thread.readFloatRegBits(reg.regIdx);
146    }
147
148    void
149    setIntRegOperand(const StaticInst *si, int idx, IntReg val) override
150    {
151        RegId reg = si->destRegIdx(idx);
152        assert(reg.regClass == IntRegClass);
153        thread.setIntReg(reg.regIdx, val);
154    }
155
156    void
157    setFloatRegOperand(const StaticInst *si, int idx,
158        TheISA::FloatReg val) override
159    {
160        RegId reg = si->destRegIdx(idx);
161        assert(reg.regClass == FloatRegClass);
162        thread.setFloatReg(reg.regIdx, val);
163    }
164
165    void
166    setFloatRegOperandBits(const StaticInst *si, int idx,
167        TheISA::FloatRegBits val) override
168    {
169        RegId reg = si->destRegIdx(idx);
170        assert(reg.regClass == FloatRegClass);
171        thread.setFloatRegBits(reg.regIdx, val);
172    }
173
174    bool
175    readPredicate() override
176    {
177        return thread.readPredicate();
178    }
179
180    void
181    setPredicate(bool val) override
182    {
183        thread.setPredicate(val);
184    }
185
186    TheISA::PCState
187    pcState() const override
188    {
189        return thread.pcState();
190    }
191
192    void
193    pcState(const TheISA::PCState &val) override
194    {
195        thread.pcState(val);
196    }
197
198    TheISA::MiscReg
199    readMiscRegNoEffect(int misc_reg) const
200    {
201        return thread.readMiscRegNoEffect(misc_reg);
202    }
203
204    TheISA::MiscReg
205    readMiscReg(int misc_reg) override
206    {
207        return thread.readMiscReg(misc_reg);
208    }
209
210    void
211    setMiscReg(int misc_reg, const TheISA::MiscReg &val) override
212    {
213        thread.setMiscReg(misc_reg, val);
214    }
215
216    TheISA::MiscReg
217    readMiscRegOperand(const StaticInst *si, int idx) override
218    {
219        RegId reg = si->srcRegIdx(idx);
220        assert(reg.regClass == MiscRegClass);
221        return thread.readMiscReg(reg.regIdx);
222    }
223
224    void
225    setMiscRegOperand(const StaticInst *si, int idx,
226        const TheISA::MiscReg &val) override
227    {
228        RegId reg = si->destRegIdx(idx);
229        assert(reg.regClass == MiscRegClass);
230        return thread.setMiscReg(reg.regIdx, val);
231    }
232
233    Fault
234    hwrei() override
235    {
236#if THE_ISA == ALPHA_ISA
237        return thread.hwrei();
238#else
239        return NoFault;
240#endif
241    }
242
243    bool
244    simPalCheck(int palFunc) override
245    {
246#if THE_ISA == ALPHA_ISA
247        return thread.simPalCheck(palFunc);
248#else
249        return false;
250#endif
251    }
252
253    void
254    syscall(int64_t callnum, Fault *fault) override
255     {
256        if (FullSystem)
257            panic("Syscall emulation isn't available in FS mode.\n");
258
259        thread.syscall(callnum, fault);
260    }
261
262    ThreadContext *tcBase() override { return thread.getTC(); }
263
264    /* @todo, should make stCondFailures persistent somewhere */
265    unsigned int readStCondFailures() const override { return 0; }
266    void setStCondFailures(unsigned int st_cond_failures) override {}
267
268    ContextID contextId() { return thread.contextId(); }
269    /* ISA-specific (or at least currently ISA singleton) functions */
270
271    /* X86: TLB twiddling */
272    void
273    demapPage(Addr vaddr, uint64_t asn) override
274    {
275        thread.getITBPtr()->demapPage(vaddr, asn);
276        thread.getDTBPtr()->demapPage(vaddr, asn);
277    }
278
279    TheISA::CCReg
280    readCCRegOperand(const StaticInst *si, int idx) override
281    {
282        RegId reg = si->srcRegIdx(idx);
283        assert(reg.regClass == CCRegClass);
284        return thread.readCCReg(reg.regIdx);
285    }
286
287    void
288    setCCRegOperand(const StaticInst *si, int idx, TheISA::CCReg val) override
289    {
290        RegId reg = si->destRegIdx(idx);
291        assert(reg.regClass == CCRegClass);
292        thread.setCCReg(reg.regIdx, val);
293    }
294
295    void
296    demapInstPage(Addr vaddr, uint64_t asn)
297    {
298        thread.getITBPtr()->demapPage(vaddr, asn);
299    }
300
301    void
302    demapDataPage(Addr vaddr, uint64_t asn)
303    {
304        thread.getDTBPtr()->demapPage(vaddr, asn);
305    }
306
307    /* ALPHA/POWER: Effective address storage */
308    void setEA(Addr ea) override
309    {
310        inst->ea = ea;
311    }
312
313    BaseCPU *getCpuPtr() { return &cpu; }
314
315    /* POWER: Effective address storage */
316    Addr getEA() const override
317    {
318        return inst->ea;
319    }
320
321    /* MIPS: other thread register reading/writing */
322    uint64_t
323    readRegOtherThread(RegId reg, ThreadID tid = InvalidThreadID)
324    {
325        SimpleThread *other_thread = (tid == InvalidThreadID
326            ? &thread : cpu.threads[tid]);
327
328        switch(reg.regClass) {
329            case IntRegClass:
330                return other_thread->readIntReg(reg.regIdx);
331                break;
332            case FloatRegClass:
333                return other_thread->readFloatRegBits(reg.regIdx);
334                break;
335            case MiscRegClass:
336                return other_thread->readMiscReg(reg.regIdx);
337            default:
338                panic("Unexpected reg class! (%s)",
339                      RegClassStrings[reg.regClass]);
340                return 0;
341        }
342    }
343
344    void
345    setRegOtherThread(RegId reg, const TheISA::MiscReg &val,
346        ThreadID tid = InvalidThreadID)
347    {
348        SimpleThread *other_thread = (tid == InvalidThreadID
349            ? &thread : cpu.threads[tid]);
350
351         switch(reg.regClass) {
352            case IntRegClass:
353                return other_thread->setIntReg(reg.regIdx, val);
354                break;
355            case FloatRegClass:
356                return other_thread->setFloatRegBits(reg.regIdx, val);
357                break;
358            case MiscRegClass:
359                return other_thread->setMiscReg(reg.regIdx, val);
360            default:
361                panic("Unexpected reg class! (%s)",
362                      RegClassStrings[reg.regClass]);
363        }
364    }
365
366  public:
367    // monitor/mwait funtions
368    void armMonitor(Addr address) override
369    { getCpuPtr()->armMonitor(inst->id.threadId, address); }
370
371    bool mwait(PacketPtr pkt) override
372    { return getCpuPtr()->mwait(inst->id.threadId, pkt); }
373
374    void mwaitAtomic(ThreadContext *tc) override
375    { return getCpuPtr()->mwaitAtomic(inst->id.threadId, tc, thread.dtb); }
376
377    AddressMonitor *getAddrMonitor() override
378    { return getCpuPtr()->getCpuAddrMonitor(inst->id.threadId); }
379};
380
381}
382
383#endif /* __CPU_MINOR_EXEC_CONTEXT_HH__ */
384