/* * Copyright (c) 2011-2014, 2016 ARM Limited * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall * not be construed as granting a license to any other intellectual * property including but not limited to intellectual property relating * to a hardware implementation of the functionality of the software * licensed hereunder. You may use the software subject to the license * terms below provided that you ensure that this notice is replicated * unmodified and in its entirety in all distributions of the software, * modified or unmodified, in source code or in binary form. * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Steve Reinhardt * Dave Greene * Nathan Binkert * Andrew Bardsley */ /** * @file * * ExecContext bears the exec_context interface for Minor. */ #ifndef __CPU_MINOR_EXEC_CONTEXT_HH__ #define __CPU_MINOR_EXEC_CONTEXT_HH__ #include "cpu/exec_context.hh" #include "cpu/minor/execute.hh" #include "cpu/minor/pipeline.hh" #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "mem/request.hh" #include "debug/MinorExecute.hh" namespace Minor { /* Forward declaration of Execute */ class Execute; /** ExecContext bears the exec_context interface for Minor. This nicely * separates that interface from other classes such as Pipeline, MinorCPU * and DynMinorInst and makes it easier to see what state is accessed by it. */ class ExecContext : public ::ExecContext { public: MinorCPU &cpu; /** ThreadState object, provides all the architectural state. */ SimpleThread &thread; /** The execute stage so we can peek at its contents. */ Execute &execute; /** Instruction for the benefit of memory operations and for PC */ MinorDynInstPtr inst; ExecContext ( MinorCPU &cpu_, SimpleThread &thread_, Execute &execute_, MinorDynInstPtr inst_) : cpu(cpu_), thread(thread_), execute(execute_), inst(inst_) { DPRINTF(MinorExecute, "ExecContext setting PC: %s\n", inst->pc); pcState(inst->pc); setPredicate(true); thread.setIntReg(TheISA::ZeroReg, 0); #if THE_ISA == ALPHA_ISA thread.setFloatReg(TheISA::ZeroReg, 0.0); #endif } Fault initiateMemRead(Addr addr, unsigned int size, Request::Flags flags) override { execute.getLSQ().pushRequest(inst, true /* load */, nullptr, size, addr, flags, NULL); return NoFault; } Fault writeMem(uint8_t *data, unsigned int size, Addr addr, Request::Flags flags, uint64_t *res) override { execute.getLSQ().pushRequest(inst, false /* store */, data, size, addr, flags, res); return NoFault; } IntReg readIntRegOperand(const StaticInst *si, int idx) override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isIntReg()); return thread.readIntReg(reg.index()); } TheISA::FloatReg readFloatRegOperand(const StaticInst *si, int idx) override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isFloatReg()); return thread.readFloatReg(reg.index()); } TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isFloatReg()); return thread.readFloatRegBits(reg.index()); } const TheISA::VecRegContainer& readVecRegOperand(const StaticInst *si, int idx) const override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isVecReg()); return thread.readVecReg(reg); } TheISA::VecRegContainer& getWritableVecRegOperand(const StaticInst *si, int idx) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isVecReg()); return thread.getWritableVecReg(reg); } TheISA::VecElem readVecElemOperand(const StaticInst *si, int idx) const override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isVecReg()); return thread.readVecElem(reg); } void setIntRegOperand(const StaticInst *si, int idx, IntReg val) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isIntReg()); thread.setIntReg(reg.index(), val); } void setFloatRegOperand(const StaticInst *si, int idx, TheISA::FloatReg val) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isFloatReg()); thread.setFloatReg(reg.index(), val); } void setFloatRegOperandBits(const StaticInst *si, int idx, TheISA::FloatRegBits val) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isFloatReg()); thread.setFloatRegBits(reg.index(), val); } void setVecRegOperand(const StaticInst *si, int idx, const TheISA::VecRegContainer& val) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isVecReg()); thread.setVecReg(reg, val); } /** Vector Register Lane Interfaces. */ /** @{ */ /** Reads source vector 8bit operand. */ ConstVecLane8 readVec8BitLaneOperand(const StaticInst *si, int idx) const override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isVecReg()); return thread.readVec8BitLaneReg(reg); } /** Reads source vector 16bit operand. */ ConstVecLane16 readVec16BitLaneOperand(const StaticInst *si, int idx) const override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isVecReg()); return thread.readVec16BitLaneReg(reg); } /** Reads source vector 32bit operand. */ ConstVecLane32 readVec32BitLaneOperand(const StaticInst *si, int idx) const override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isVecReg()); return thread.readVec32BitLaneReg(reg); } /** Reads source vector 64bit operand. */ ConstVecLane64 readVec64BitLaneOperand(const StaticInst *si, int idx) const override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isVecReg()); return thread.readVec64BitLaneReg(reg); } /** Write a lane of the destination vector operand. */ template void setVecLaneOperandT(const StaticInst *si, int idx, const LD& val) { const RegId& reg = si->destRegIdx(idx); assert(reg.isVecReg()); return thread.setVecLane(reg, val); } virtual void setVecLaneOperand(const StaticInst *si, int idx, const LaneData& val) override { setVecLaneOperandT(si, idx, val); } virtual void setVecLaneOperand(const StaticInst *si, int idx, const LaneData& val) override { setVecLaneOperandT(si, idx, val); } virtual void setVecLaneOperand(const StaticInst *si, int idx, const LaneData& val) override { setVecLaneOperandT(si, idx, val); } virtual void setVecLaneOperand(const StaticInst *si, int idx, const LaneData& val) override { setVecLaneOperandT(si, idx, val); } /** @} */ void setVecElemOperand(const StaticInst *si, int idx, const TheISA::VecElem val) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isVecReg()); thread.setVecElem(reg, val); } bool readPredicate() const override { return thread.readPredicate(); } void setPredicate(bool val) override { thread.setPredicate(val); } TheISA::PCState pcState() const override { return thread.pcState(); } void pcState(const TheISA::PCState &val) override { thread.pcState(val); } TheISA::MiscReg readMiscRegNoEffect(int misc_reg) const { return thread.readMiscRegNoEffect(misc_reg); } TheISA::MiscReg readMiscReg(int misc_reg) override { return thread.readMiscReg(misc_reg); } void setMiscReg(int misc_reg, const TheISA::MiscReg &val) override { thread.setMiscReg(misc_reg, val); } TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isMiscReg()); return thread.readMiscReg(reg.index()); } void setMiscRegOperand(const StaticInst *si, int idx, const TheISA::MiscReg &val) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isMiscReg()); return thread.setMiscReg(reg.index(), val); } Fault hwrei() override { #if THE_ISA == ALPHA_ISA return thread.hwrei(); #else return NoFault; #endif } bool simPalCheck(int palFunc) override { #if THE_ISA == ALPHA_ISA return thread.simPalCheck(palFunc); #else return false; #endif } void syscall(int64_t callnum, Fault *fault) override { if (FullSystem) panic("Syscall emulation isn't available in FS mode.\n"); thread.syscall(callnum, fault); } ThreadContext *tcBase() override { return thread.getTC(); } /* @todo, should make stCondFailures persistent somewhere */ unsigned int readStCondFailures() const override { return 0; } void setStCondFailures(unsigned int st_cond_failures) override {} ContextID contextId() { return thread.contextId(); } /* ISA-specific (or at least currently ISA singleton) functions */ /* X86: TLB twiddling */ void demapPage(Addr vaddr, uint64_t asn) override { thread.getITBPtr()->demapPage(vaddr, asn); thread.getDTBPtr()->demapPage(vaddr, asn); } TheISA::CCReg readCCRegOperand(const StaticInst *si, int idx) override { const RegId& reg = si->srcRegIdx(idx); assert(reg.isCCReg()); return thread.readCCReg(reg.index()); } void setCCRegOperand(const StaticInst *si, int idx, TheISA::CCReg val) override { const RegId& reg = si->destRegIdx(idx); assert(reg.isCCReg()); thread.setCCReg(reg.index(), val); } void demapInstPage(Addr vaddr, uint64_t asn) { thread.getITBPtr()->demapPage(vaddr, asn); } void demapDataPage(Addr vaddr, uint64_t asn) { thread.getDTBPtr()->demapPage(vaddr, asn); } BaseCPU *getCpuPtr() { return &cpu; } /* MIPS: other thread register reading/writing */ uint64_t readRegOtherThread(const RegId& reg, ThreadID tid = InvalidThreadID) { SimpleThread *other_thread = (tid == InvalidThreadID ? &thread : cpu.threads[tid]); switch (reg.classValue()) { case IntRegClass: return other_thread->readIntReg(reg.index()); break; case FloatRegClass: return other_thread->readFloatRegBits(reg.index()); break; case MiscRegClass: return other_thread->readMiscReg(reg.index()); default: panic("Unexpected reg class! (%s)", reg.className()); return 0; } } void setRegOtherThread(const RegId& reg, const TheISA::MiscReg &val, ThreadID tid = InvalidThreadID) { SimpleThread *other_thread = (tid == InvalidThreadID ? &thread : cpu.threads[tid]); switch (reg.classValue()) { case IntRegClass: return other_thread->setIntReg(reg.index(), val); break; case FloatRegClass: return other_thread->setFloatRegBits(reg.index(), val); break; case MiscRegClass: return other_thread->setMiscReg(reg.index(), val); default: panic("Unexpected reg class! (%s)", reg.className()); } } public: // monitor/mwait funtions void armMonitor(Addr address) override { getCpuPtr()->armMonitor(inst->id.threadId, address); } bool mwait(PacketPtr pkt) override { return getCpuPtr()->mwait(inst->id.threadId, pkt); } void mwaitAtomic(ThreadContext *tc) override { return getCpuPtr()->mwaitAtomic(inst->id.threadId, tc, thread.dtb); } AddressMonitor *getAddrMonitor() override { return getCpuPtr()->getCpuAddrMonitor(inst->id.threadId); } }; } #endif /* __CPU_MINOR_EXEC_CONTEXT_HH__ */