O3: Generaize the O3 dynamic instruction class so it isn't split out by ISA.

--HG--
rename : src/cpu/o3/dyn_inst.hh => src/cpu/o3/dyn_inst_decl.hh
rename : src/cpu/o3/alpha/dyn_inst_impl.hh => src/cpu/o3/dyn_inst_impl.hh
This commit is contained in:
Gabe Black 2008-10-09 00:09:26 -07:00
parent e09c403d32
commit f57c286d2c
17 changed files with 361 additions and 1182 deletions

View file

@ -49,11 +49,10 @@ template <class XC>
inline void
handleLockedRead(XC *xc, Request *req)
{
unsigned tid = req->getThreadNum();
xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf, tid);
xc->setMiscRegNoEffect(LLFlag, true, tid);
xc->setMiscRegNoEffect(LLAddr, req->getPaddr() & ~0xf);
xc->setMiscRegNoEffect(LLFlag, true);
DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link Address set to %x.\n",
tid, req->getPaddr() & ~0xf);
req->getThreadNum(), req->getPaddr() & ~0xf);
}
@ -61,22 +60,20 @@ template <class XC>
inline bool
handleLockedWrite(XC *xc, Request *req)
{
unsigned tid = req->getThreadNum();
if (req->isUncacheable()) {
// Funky Turbolaser mailbox access...don't update
// result register (see stq_c in decoder.isa)
req->setExtraData(2);
} else {
// standard store conditional
bool lock_flag = xc->readMiscRegNoEffect(LLFlag, tid);
Addr lock_addr = xc->readMiscRegNoEffect(LLAddr, tid);
bool lock_flag = xc->readMiscRegNoEffect(LLFlag);
Addr lock_addr = xc->readMiscRegNoEffect(LLAddr);
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
// Lock flag not set or addr mismatch in CPU;
// don't even bother sending to memory system
req->setExtraData(0);
xc->setMiscRegNoEffect(LLFlag, false, tid);
xc->setMiscRegNoEffect(LLFlag, false);
// the rest of this code is not architectural;
// it's just a debugging aid to help detect
@ -97,10 +94,10 @@ handleLockedWrite(XC *xc, Request *req)
if (!lock_flag){
DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n",
tid);
req->getThreadNum());
} else if ((req->getPaddr() & ~0xf) != lock_addr) {
DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, Store Conditional Failed.\n",
tid);
req->getThreadNum());
}
// store conditional failed already, so don't issue it to mem
return false;

View file

@ -28,9 +28,9 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha/dyn_inst_impl.hh"
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/dyn_inst_impl.hh"
// Force instantiation of AlphaDynInst for all the implementations that
// are needed.
template class AlphaDynInst<AlphaSimpleImpl>;
template class BaseO3DynInst<AlphaSimpleImpl>;

View file

@ -1,277 +0,0 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
*/
#ifndef __CPU_O3_ALPHA_DYN_INST_HH__
#define __CPU_O3_ALPHA_DYN_INST_HH__
#include "arch/isa_traits.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/cpu.hh"
class Packet;
/**
* Mostly implementation & ISA specific AlphaDynInst. As with most
* other classes in the new CPU model, it is templated on the Impl to
* allow for passing in of all types, such as the CPU type and the ISA
* type. The AlphaDynInst serves as the primary interface to the CPU
* for instructions that are executing.
*/
template <class Impl>
class AlphaDynInst : public BaseDynInst<Impl>
{
public:
/** Typedef for the CPU. */
typedef typename Impl::O3CPU O3CPU;
/** Binary machine instruction type. */
typedef TheISA::MachInst MachInst;
/** Extended machine instruction type. */
typedef TheISA::ExtMachInst ExtMachInst;
/** Logical register index type. */
typedef TheISA::RegIndex RegIndex;
/** Integer register index type. */
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
/** Misc register index type. */
typedef TheISA::MiscReg MiscReg;
enum {
MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
};
public:
/** BaseDynInst constructor given a binary instruction. */
AlphaDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a binary instruction. */
AlphaDynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
AlphaDynInst(StaticInstPtr &_staticInst);
/** Executes the instruction.*/
Fault execute();
/** Initiates the access. Only valid for memory operations. */
Fault initiateAcc();
/** Completes the access. Only valid for memory operations. */
Fault completeAcc(PacketPtr pkt);
private:
/** Initializes variables. */
void initVars();
public:
/** Reads a miscellaneous register. */
MiscReg readMiscRegNoEffect(int misc_reg)
{
return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
MiscReg readMiscReg(int misc_reg)
{
return this->cpu->readMiscReg(misc_reg, this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
this->instResult.integer = val;
return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscReg(int misc_reg, const MiscReg &val)
{
return this->cpu->setMiscReg(misc_reg, val,
this->threadNumber);
}
/** Reads a miscellaneous register. */
TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx)
{
return this->cpu->readMiscRegNoEffect(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readMiscReg(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val)
{
this->instResult.integer = val;
return this->cpu->setMiscRegNoEffect(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscRegOperand(const StaticInst *si, int idx,
const MiscReg &val)
{
return this->cpu->setMiscReg(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
#if FULL_SYSTEM
/** Calls hardware return from error interrupt. */
Fault hwrei();
/** Traps to handle specified fault. */
void trap(Fault fault);
bool simPalCheck(int palFunc);
#else
/** Calls a syscall. */
void syscall(int64_t callnum);
#endif
public:
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to redice overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
uint64_t readIntRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readIntReg(this->_srcRegIdx[idx]);
}
FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx], width);
}
FloatReg readFloatRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
}
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx,
int width)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width);
}
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
}
/** @todo: Make results into arrays so they can handle multiple dest
* registers.
*/
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
{
this->cpu->setIntReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
int width)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val, width);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val, int width)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
public:
/** Calculates EA part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault calcEA()
{
return this->staticInst->eaCompInst()->execute(this, this->traceData);
}
/** Does the memory access part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault memAccess()
{
return this->staticInst->memAccInst()->execute(this, this->traceData);
}
};
#endif // __CPU_O3_ALPHA_DYN_INST_HH__

View file

@ -38,7 +38,7 @@
// Forward declarations.
template <class Impl>
class AlphaDynInst;
class BaseO3DynInst;
template <class Impl>
class FullO3CPU;
@ -60,7 +60,7 @@ struct AlphaSimpleImpl
typedef SimpleCPUPolicy<AlphaSimpleImpl> CPUPol;
/** The DynInst type to be used. */
typedef AlphaDynInst<AlphaSimpleImpl> DynInst;
typedef BaseO3DynInst<AlphaSimpleImpl> DynInst;
/** The refcounted DynInst pointer to be used. In most cases this is
* what should be used, and not DynInst *.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,36 +25,266 @@
* (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: Korey Sewell
* Authors: Kevin Lim
*/
#ifndef __CPU_O3_DYN_INST_HH__
#define __CPU_O3_DYN_INST_HH__
#include "arch/isa_specific.hh"
#include "arch/isa_traits.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/cpu.hh"
#include "cpu/o3/isa_specific.hh"
#if THE_ISA == ALPHA_ISA
template <class Impl> class AlphaDynInst;
struct AlphaSimpleImpl;
typedef AlphaDynInst<AlphaSimpleImpl> O3DynInst;
#elif THE_ISA == MIPS_ISA
template <class Impl> class MipsDynInst;
struct MipsSimpleImpl;
typedef MipsDynInst<MipsSimpleImpl> O3DynInst;
#elif THE_ISA == SPARC_ISA
template <class Impl> class SparcDynInst;
struct SparcSimpleImpl;
typedef SparcDynInst<SparcSimpleImpl> O3DynInst;
#elif THE_ISA == X86_ISA
template <class Impl> class X86DynInst;
struct X86SimpleImpl;
typedef X86DynInst<X86SimpleImpl> O3DynInst;
#elif THE_ISA == ARM_ISA
template <class Impl> class ArmDynInst;
struct ArmSimpleImpl;
typedef ArmDynInst<ArmSimpleImpl> O3DynInst;
class Packet;
/**
* Mostly implementation & ISA specific AlphaDynInst. As with most
* other classes in the new CPU model, it is templated on the Impl to
* allow for passing in of all types, such as the CPU type and the ISA
* type. The AlphaDynInst serves as the primary interface to the CPU
* for instructions that are executing.
*/
template <class Impl>
class BaseO3DynInst : public BaseDynInst<Impl>
{
public:
/** Typedef for the CPU. */
typedef typename Impl::O3CPU O3CPU;
/** Binary machine instruction type. */
typedef TheISA::MachInst MachInst;
/** Extended machine instruction type. */
typedef TheISA::ExtMachInst ExtMachInst;
/** Logical register index type. */
typedef TheISA::RegIndex RegIndex;
/** Integer register index type. */
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
/** Misc register index type. */
typedef TheISA::MiscReg MiscReg;
enum {
MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
};
public:
/** BaseDynInst constructor given a binary instruction. */
BaseO3DynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a binary instruction. */
BaseO3DynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
BaseO3DynInst(StaticInstPtr &_staticInst);
/** Executes the instruction.*/
Fault execute();
/** Initiates the access. Only valid for memory operations. */
Fault initiateAcc();
/** Completes the access. Only valid for memory operations. */
Fault completeAcc(PacketPtr pkt);
private:
/** Initializes variables. */
void initVars();
public:
/** Reads a miscellaneous register. */
MiscReg readMiscRegNoEffect(int misc_reg)
{
return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
MiscReg readMiscReg(int misc_reg)
{
return this->cpu->readMiscReg(misc_reg, this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
this->instResult.integer = val;
return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscReg(int misc_reg, const MiscReg &val)
{
return this->cpu->setMiscReg(misc_reg, val,
this->threadNumber);
}
/** Reads a miscellaneous register. */
TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx)
{
return this->cpu->readMiscRegNoEffect(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readMiscReg(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val)
{
this->instResult.integer = val;
return this->cpu->setMiscRegNoEffect(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscRegOperand(const StaticInst *si, int idx,
const MiscReg &val)
{
return this->cpu->setMiscReg(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
#if FULL_SYSTEM
/** Calls hardware return from error interrupt. */
Fault hwrei();
/** Traps to handle specified fault. */
void trap(Fault fault);
bool simPalCheck(int palFunc);
#else
#error "O3DynInst not defined for this ISA"
/** Calls a syscall. */
void syscall(int64_t callnum);
#endif
#endif // __CPU_O3_DYN_INST_HH__
public:
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to redice overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
uint64_t readIntRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readIntReg(this->_srcRegIdx[idx]);
}
FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx], width);
}
FloatReg readFloatRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
}
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx,
int width)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width);
}
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
}
/** @todo: Make results into arrays so they can handle multiple dest
* registers.
*/
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
{
this->cpu->setIntReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
int width)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val, width);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val, int width)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
#if THE_ISA == MIPS_ISA
uint64_t readRegOtherThread(int misc_reg)
{
panic("MIPS MT not defined for O3 CPU.\n");
return 0;
}
void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val)
{
panic("MIPS MT not defined for O3 CPU.\n");
}
#endif
public:
/** Calculates EA part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault calcEA()
{
return this->staticInst->eaCompInst()->execute(this, this->traceData);
}
/** Does the memory access part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault memAccess()
{
return this->staticInst->memAccInst()->execute(this, this->traceData);
}
};
#endif // __CPU_O3_ALPHA_DYN_INST_HH__

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2006 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: Korey Sewell
*/
#ifndef __CPU_O3_DYN_INST_DECL_HH__
#define __CPU_O3_DYN_INST_DECL_HH__
#include "arch/isa_specific.hh"
template <class Impl> class BaseO3DynInst;
#if THE_ISA == ALPHA_ISA
struct AlphaSimpleImpl;
typedef BaseO3DynInst<AlphaSimpleImpl> O3DynInst;
#elif THE_ISA == MIPS_ISA
struct MipsSimpleImpl;
typedef BaseO3DynInst<MipsSimpleImpl> O3DynInst;
#elif THE_ISA == SPARC_ISA
struct SparcSimpleImpl;
typedef BaseO3DynInst<SparcSimpleImpl> O3DynInst;
#elif THE_ISA == X86_ISA
struct X86SimpleImpl;
typedef BaseO3DynInst<X86SimpleImpl> O3DynInst;
#elif THE_ISA == ARM_ISA
struct ArmSimpleImpl;
typedef BaseO3DynInst<ArmSimpleImpl> O3DynInst;
#else
#error "O3DynInst not defined for this ISA"
#endif
#endif // __CPU_O3_DYN_INST_DECL_HH__

View file

@ -28,34 +28,34 @@
* Authors: Kevin Lim
*/
#include "cpu/o3/alpha/dyn_inst.hh"
#include "cpu/o3/dyn_inst.hh"
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr staticInst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC,
Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
BaseO3DynInst<Impl>::BaseO3DynInst(StaticInstPtr staticInst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC,
Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(staticInst, PC, NPC, microPC,
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
{
initVars();
}
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(ExtMachInst inst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC,
Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
BaseO3DynInst<Impl>::BaseO3DynInst(ExtMachInst inst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC,
Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(inst, PC, NPC, microPC,
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
{
initVars();
}
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr &_staticInst)
BaseO3DynInst<Impl>::BaseO3DynInst(StaticInstPtr &_staticInst)
: BaseDynInst<Impl>(_staticInst)
{
initVars();
@ -63,7 +63,7 @@ AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr &_staticInst)
template <class Impl>
void
AlphaDynInst<Impl>::initVars()
BaseO3DynInst<Impl>::initVars()
{
// Make sure to have the renamed register entries set to the same
// as the normal register entries. It will allow the IQ to work
@ -80,7 +80,7 @@ AlphaDynInst<Impl>::initVars()
template <class Impl>
Fault
AlphaDynInst<Impl>::execute()
BaseO3DynInst<Impl>::execute()
{
// @todo: Pretty convoluted way to avoid squashing from happening
// when using the TC during an instruction's execution
@ -98,7 +98,7 @@ AlphaDynInst<Impl>::execute()
template <class Impl>
Fault
AlphaDynInst<Impl>::initiateAcc()
BaseO3DynInst<Impl>::initiateAcc()
{
// @todo: Pretty convoluted way to avoid squashing from happening
// when using the TC during an instruction's execution
@ -116,7 +116,7 @@ AlphaDynInst<Impl>::initiateAcc()
template <class Impl>
Fault
AlphaDynInst<Impl>::completeAcc(PacketPtr pkt)
BaseO3DynInst<Impl>::completeAcc(PacketPtr pkt)
{
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
@ -126,8 +126,9 @@ AlphaDynInst<Impl>::completeAcc(PacketPtr pkt)
#if FULL_SYSTEM
template <class Impl>
Fault
AlphaDynInst<Impl>::hwrei()
BaseO3DynInst<Impl>::hwrei()
{
#if THE_ISA == ALPHA_ISA
// Can only do a hwrei when in pal mode.
if (!(this->readPC() & 0x3))
return new AlphaISA::UnimplementedOpcodeFault;
@ -138,28 +139,33 @@ AlphaDynInst<Impl>::hwrei()
// Tell CPU to clear any state it needs to if a hwrei is taken.
this->cpu->hwrei(this->threadNumber);
#else
#endif
// FIXME: XXX check for interrupts? XXX
return NoFault;
}
template <class Impl>
void
AlphaDynInst<Impl>::trap(Fault fault)
BaseO3DynInst<Impl>::trap(Fault fault)
{
this->cpu->trap(fault, this->threadNumber);
}
template <class Impl>
bool
AlphaDynInst<Impl>::simPalCheck(int palFunc)
BaseO3DynInst<Impl>::simPalCheck(int palFunc)
{
#if THE_ISA != ALPHA_ISA
panic("simPalCheck called, but PAL only exists in Alpha!\n");
#endif
return this->cpu->simPalCheck(palFunc, this->threadNumber);
}
#else
template <class Impl>
void
AlphaDynInst<Impl>::syscall(int64_t callnum)
BaseO3DynInst<Impl>::syscall(int64_t callnum)
{
// HACK: check CPU's nextPC before and after syscall. If it
// changes, update this instruction's nextPC because the syscall

View file

@ -32,13 +32,11 @@
#if THE_ISA == ALPHA_ISA
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
#elif THE_ISA == MIPS_ISA
#include "cpu/o3/mips/impl.hh"
#include "cpu/o3/mips/dyn_inst.hh"
#elif THE_ISA == SPARC_ISA
#include "cpu/o3/sparc/impl.hh"
#include "cpu/o3/sparc/dyn_inst.hh"
#else
#error "ISA-specific header files O3CPU not defined ISA"
#endif
#include "cpu/o3/dyn_inst.hh"

View file

@ -29,9 +29,9 @@
* Korey Sewell
*/
#include "cpu/o3/mips/dyn_inst_impl.hh"
#include "cpu/o3/dyn_inst_impl.hh"
#include "cpu/o3/mips/impl.hh"
// Force instantiation of MipsDynInst for all the implementations that
// are needed.
template class MipsDynInst<MipsSimpleImpl>;
template class BaseO3DynInst<MipsSimpleImpl>;

View file

@ -1,281 +0,0 @@
/*
* Copyright (c) 2006 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: Kevin Lim
* Korey Sewell
*/
#ifndef __CPU_O3_MIPS_DYN_INST_HH__
#define __CPU_O3_MIPS_DYN_INST_HH__
#include "arch/isa_traits.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/cpu.hh"
#include "cpu/o3/mips/impl.hh"
class Packet;
/**
* Mostly implementation & ISA specific MipsDynInst. As with most
* other classes in the new CPU model, it is templated on the Impl to
* allow for passing in of all types, such as the CPU type and the ISA
* type. The MipsDynInst serves as the primary interface to the CPU
* for instructions that are executing.
*/
template <class Impl>
class MipsDynInst : public BaseDynInst<Impl>
{
public:
/** Typedef for the CPU. */
typedef typename Impl::O3CPU O3CPU;
/** Logical register index type. */
typedef TheISA::RegIndex RegIndex;
/** Integer register index type. */
typedef TheISA::IntReg IntReg;
typedef TheISA::FloatReg FloatReg;
typedef TheISA::FloatRegBits FloatRegBits;
/** Misc register index type. */
typedef TheISA::MiscReg MiscReg;
enum {
MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
};
public:
/** BaseDynInst constructor given a binary instruction. */
MipsDynInst(StaticInstPtr staticInst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a binary instruction. */
MipsDynInst(ExtMachInst inst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
MipsDynInst(StaticInstPtr &_staticInst);
/** Executes the instruction.*/
Fault execute();
/** Initiates the access. Only valid for memory operations. */
Fault initiateAcc();
/** Completes the access. Only valid for memory operations. */
Fault completeAcc(PacketPtr pkt);
private:
/** Initializes variables. */
void initVars();
public:
/** Reads a miscellaneous register. */
/** TODO: Use thread number from argument if given, will probably not work for MIPS MT as is */
MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid = 0)
{
return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
MiscReg readMiscReg(int misc_reg, unsigned tid = 0)
{
return this->cpu->readMiscReg(misc_reg, this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0)
{
this->instResult.integer = val;
this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid = 0)
{
return this->cpu->setMiscReg(misc_reg, val,
this->threadNumber);
}
/** Calls a syscall. */
void syscall(int64_t callnum);
public:
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to redice overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
uint64_t readIntRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readIntReg(this->_srcRegIdx[idx]);
}
FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx], width);
}
FloatReg readFloatRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
}
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx,
int width)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width);
}
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
}
/** @todo: Make results into arrays so they can handle multiple dest
* registers.
*/
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
{
this->cpu->setIntReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val,
int width)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val, width);
}
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val, int width)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
/** Reads a miscellaneous register. */
TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx)
{
return this->cpu->readMiscRegNoEffect(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readMiscReg(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val)
{
this->instResult.integer = val;
return this->cpu->setMiscRegNoEffect(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscRegOperand(const StaticInst *si, int idx,
const MiscReg &val)
{
return this->cpu->setMiscReg(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
uint64_t readRegOtherThread(int misc_reg)
{
panic("MIPS MT not defined for O3 CPU.\n");
return 0;
}
void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val)
{
panic("MIPS MT not defined for O3 CPU.\n");
}
public:
/** Calculates EA part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault calcEA()
{
return this->staticInst->eaCompInst()->execute(this, this->traceData);
}
/** Does the memory access part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault memAccess()
{
return this->staticInst->memAccInst()->execute(this, this->traceData);
}
};
#endif // __CPU_O3_MIPS_DYN_INST_HH__

View file

@ -1,130 +0,0 @@
/*
* Copyright (c) 2004-2006 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: Kevin Lim
*/
#include "cpu/o3/mips/dyn_inst.hh"
template <class Impl>
MipsDynInst<Impl>::MipsDynInst(StaticInstPtr staticInst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(staticInst, PC, NPC, microPC,
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
{
initVars();
}
template <class Impl>
MipsDynInst<Impl>::MipsDynInst(ExtMachInst inst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(inst, PC, NPC, microPC,
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
{
initVars();
}
template <class Impl>
MipsDynInst<Impl>::MipsDynInst(StaticInstPtr &_staticInst)
: BaseDynInst<Impl>(_staticInst)
{
initVars();
}
template <class Impl>
void
MipsDynInst<Impl>::initVars()
{
// Make sure to have the renamed register entries set to the same
// as the normal register entries. It will allow the IQ to work
// without any modifications.
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
this->_destRegIdx[i] = this->staticInst->destRegIdx(i);
}
for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i);
this->_readySrcRegIdx[i] = 0;
}
}
template <class Impl>
Fault
MipsDynInst<Impl>::execute()
{
// @todo: Pretty convoluted way to avoid squashing from happening
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
bool in_syscall = this->thread->inSyscall;
this->thread->inSyscall = true;
this->fault = this->staticInst->execute(this, this->traceData);
this->thread->inSyscall = in_syscall;
return this->fault;
}
template <class Impl>
Fault
MipsDynInst<Impl>::initiateAcc()
{
// @todo: Pretty convoluted way to avoid squashing from happening
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
bool in_syscall = this->thread->inSyscall;
this->thread->inSyscall = true;
this->fault = this->staticInst->initiateAcc(this, this->traceData);
this->thread->inSyscall = in_syscall;
return this->fault;
}
template <class Impl>
Fault
MipsDynInst<Impl>::completeAcc(PacketPtr pkt)
{
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
return this->fault;
}
template <class Impl>
void
MipsDynInst<Impl>::syscall(int64_t callnum)
{
this->cpu->syscall(callnum, this->threadNumber);
}

View file

@ -36,10 +36,9 @@
#include "cpu/o3/cpu_policy.hh"
// Forward declarations.
template <class Impl>
class MipsDynInst;
class BaseO3DynInst;
template <class Impl>
class FullO3CPU;
@ -61,7 +60,7 @@ struct MipsSimpleImpl
typedef SimpleCPUPolicy<MipsSimpleImpl> CPUPol;
/** The DynInst type to be used. */
typedef MipsDynInst<MipsSimpleImpl> DynInst;
typedef BaseO3DynInst<MipsSimpleImpl> DynInst;
/** The refcounted DynInst pointer to be used. In most cases this is
* what should be used, and not DynInst *.

View file

@ -28,9 +28,9 @@
* Authors: Gabe Black
*/
#include "cpu/o3/sparc/dyn_inst_impl.hh"
#include "cpu/o3/dyn_inst_impl.hh"
#include "cpu/o3/sparc/impl.hh"
// Force instantiation of SparcDynInst for all the implementations that
// are needed.
template class SparcDynInst<SparcSimpleImpl>;
template class BaseO3DynInst<SparcSimpleImpl>;

View file

@ -1,265 +0,0 @@
/*
* Copyright (c) 2004-2006 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: Gabe Black
*/
#ifndef __CPU_O3_SPARC_DYN_INST_HH__
#define __CPU_O3_SPARC_DYN_INST_HH__
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/cpu.hh"
#include "cpu/o3/sparc/impl.hh"
class Packet;
/**
* Mostly implementation & ISA specific SparcDynInst. As with most
* other classes in the new CPU model, it is templated on the Impl to
* allow for passing in of all types, such as the CPU type and the ISA
* type. The SparcDynInst serves as the primary interface to the CPU
* for instructions that are executing.
*/
template <class Impl>
class SparcDynInst : public BaseDynInst<Impl>
{
public:
/** Typedef for the CPU. */
typedef typename Impl::O3CPU O3CPU;
public:
/** BaseDynInst constructor given a binary instruction. */
SparcDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a binary instruction. */
SparcDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
SparcDynInst(StaticInstPtr &_staticInst);
/** Executes the instruction.*/
Fault execute();
/** Initiates the access. Only valid for memory operations. */
Fault initiateAcc();
/** Completes the access. Only valid for memory operations. */
Fault completeAcc(PacketPtr pkt);
private:
/** Initializes variables. */
void initVars();
public:
/** Reads a miscellaneous register. */
TheISA::MiscReg readMiscRegNoEffect(int misc_reg)
{
return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
TheISA::MiscReg readMiscReg(int misc_reg)
{
return this->cpu->readMiscReg(misc_reg, this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val)
{
this->instResult.integer = val;
return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscReg(int misc_reg, const TheISA::MiscReg &val)
{
return this->cpu->setMiscReg(misc_reg, val,
this->threadNumber);
}
/** Reads a miscellaneous register. */
TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx)
{
return this->cpu->readMiscRegNoEffect(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Reads a misc. register, including any side-effects the read
* might have as defined by the architecture.
*/
TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readMiscReg(
si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
this->threadNumber);
}
/** Sets a misc. register. */
void setMiscRegOperandNoEffect(const StaticInst * si,
int idx, const TheISA::MiscReg &val)
{
this->instResult.integer = val;
return this->cpu->setMiscRegNoEffect(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
/** Sets a misc. register, including any side-effects the write
* might have as defined by the architecture.
*/
void setMiscRegOperand(
const StaticInst *si, int idx, const TheISA::MiscReg &val)
{
return this->cpu->setMiscReg(
si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag,
val, this->threadNumber);
}
#if FULL_SYSTEM
/** Calls hardware return from error interrupt. */
Fault hwrei();
/** Traps to handle specified fault. */
void trap(Fault fault);
bool simPalCheck(int palFunc);
#else
/** Calls a syscall. */
void syscall(int64_t callnum);
#endif
public:
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to redice overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
uint64_t readIntRegOperand(const StaticInst *si, int idx)
{
uint64_t val = this->cpu->readIntReg(this->_srcRegIdx[idx]);
DPRINTF(Sparc, "Reading int reg %d (%d, %d) as %x\n", (int)this->_flatSrcRegIdx[idx], (int)this->_srcRegIdx[idx], idx, val);
return val;
}
TheISA::FloatReg readFloatRegOperand(const StaticInst *si,
int idx, int width)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx], width);
}
TheISA::FloatReg readFloatRegOperand(const StaticInst *si, int idx)
{
return this->cpu->readFloatReg(this->_srcRegIdx[idx]);
}
TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si,
int idx, int width)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx], width);
}
TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
{
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
}
/** @todo: Make results into arrays so they can handle multiple dest
* registers.
*/
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
{
DPRINTF(Sparc, "Setting int reg %d (%d, %d) to %x\n", (int)this->_flatDestRegIdx[idx], (int)this->_destRegIdx[idx], idx, val);
this->cpu->setIntReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
}
void setFloatRegOperand(const StaticInst *si, int idx,
TheISA::FloatReg val, int width)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val, width);
}
void setFloatRegOperand(const StaticInst *si, int idx, TheISA::FloatReg val)
{
this->cpu->setFloatReg(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperand(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si, int idx,
TheISA::FloatRegBits val, int width)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val, width);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
void setFloatRegOperandBits(const StaticInst *si,
int idx, TheISA::FloatRegBits val)
{
this->cpu->setFloatRegBits(this->_destRegIdx[idx], val);
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
}
public:
/** Calculates EA part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault calcEA()
{
return this->staticInst->eaCompInst()->execute(this, this->traceData);
}
/** Does the memory access part of a memory instruction. Currently unused,
* though it may be useful in the future if we want to split
* memory operations into EA calculation and memory access parts.
*/
Fault memAccess()
{
return this->staticInst->memAccInst()->execute(this, this->traceData);
}
};
#endif // __CPU_O3_SPARC_DYN_INST_HH__

View file

@ -1,154 +0,0 @@
/*
* Copyright (c) 2004-2006 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: Gabe Black
*/
#include "cpu/o3/sparc/dyn_inst.hh"
template <class Impl>
SparcDynInst<Impl>::SparcDynInst(StaticInstPtr staticInst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(staticInst, PC, NPC, microPC,
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
{
initVars();
}
template <class Impl>
SparcDynInst<Impl>::SparcDynInst(TheISA::ExtMachInst inst,
Addr PC, Addr NPC, Addr microPC,
Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
InstSeqNum seq_num, O3CPU *cpu)
: BaseDynInst<Impl>(inst, PC, NPC, microPC,
Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
{
initVars();
}
template <class Impl>
SparcDynInst<Impl>::SparcDynInst(StaticInstPtr &_staticInst)
: BaseDynInst<Impl>(_staticInst)
{
initVars();
}
template <class Impl>
void
SparcDynInst<Impl>::initVars()
{
// Make sure to have the renamed register entries set to the same
// as the normal register entries. It will allow the IQ to work
// without any modifications.
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
this->_destRegIdx[i] = this->staticInst->destRegIdx(i);
}
for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
this->_srcRegIdx[i] = this->staticInst->srcRegIdx(i);
this->_readySrcRegIdx[i] = 0;
}
}
template <class Impl>
Fault
SparcDynInst<Impl>::execute()
{
// @todo: Pretty convoluted way to avoid squashing from happening
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
bool in_syscall = this->thread->inSyscall;
this->thread->inSyscall = true;
this->fault = this->staticInst->execute(this, this->traceData);
this->thread->inSyscall = in_syscall;
return this->fault;
}
template <class Impl>
Fault
SparcDynInst<Impl>::initiateAcc()
{
// @todo: Pretty convoluted way to avoid squashing from happening
// when using the TC during an instruction's execution
// (specifically for instructions that have side-effects that use
// the TC). Fix this.
bool in_syscall = this->thread->inSyscall;
this->thread->inSyscall = true;
this->fault = this->staticInst->initiateAcc(this, this->traceData);
this->thread->inSyscall = in_syscall;
return this->fault;
}
template <class Impl>
Fault
SparcDynInst<Impl>::completeAcc(PacketPtr pkt)
{
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
return this->fault;
}
#if FULL_SYSTEM
template <class Impl>
Fault
SparcDynInst<Impl>::hwrei()
{
return NoFault;
}
template <class Impl>
void
SparcDynInst<Impl>::trap(Fault fault)
{
this->cpu->trap(fault, this->threadNumber);
}
template <class Impl>
bool
SparcDynInst<Impl>::simPalCheck(int palFunc)
{
panic("simPalCheck called, but there's no PAL in SPARC!\n");
return false;
}
#else
template <class Impl>
void
SparcDynInst<Impl>::syscall(int64_t callnum)
{
this->cpu->syscall(callnum, this->threadNumber);
}
#endif

View file

@ -38,7 +38,7 @@
// Forward declarations.
template <class Impl>
class SparcDynInst;
class BaseO3DynInst;
template <class Impl>
class FullO3CPU;
@ -60,7 +60,7 @@ struct SparcSimpleImpl
typedef SimpleCPUPolicy<SparcSimpleImpl> CPUPol;
/** The DynInst type to be used. */
typedef SparcDynInst<SparcSimpleImpl> DynInst;
typedef BaseO3DynInst<SparcSimpleImpl> DynInst;
/** The refcounted DynInst pointer to be used. In most cases this is
* what should be used, and not DynInst *.

View file

@ -42,7 +42,7 @@
#include "base/misc.hh"
#include "base/refcnt.hh"
#include "cpu/op_class.hh"
#include "cpu/o3/dyn_inst.hh"
#include "cpu/o3/dyn_inst_decl.hh"
#include "sim/faults.hh"
#include "sim/host.hh"