White space, commented out code, some other minor fixes.
* Authors: Jaidev Patwardhan
*/
-#include "arch/vtophys.hh"
#include "arch/mips/bare_iron/system.hh"
-#include "arch/mips/system.hh"
-#include "cpu/thread_context.hh"
-#include "cpu/base.hh"
-#include "dev/platform.hh"
-#include "mem/physical.hh"
-#include "mem/port.hh"
#include "params/BareIronMipsSystem.hh"
-#include "sim/byteswap.hh"
-
-using namespace std;
-using namespace MipsISA;
-
BareIronMipsSystem::BareIronMipsSystem(Params *p)
: MipsSystem(p)
#ifndef __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
#define __ARCH_MIPS_BARE_IRON_SYSTEM_HH__
-class ThreadContext;
-
-class BreakPCEvent;
-class IdleStartEvent;
-
#include "arch/mips/system.hh"
#include "params/BareIronMipsSystem.hh"
*/
class BareIronMipsSystem : public MipsSystem
{
- private:
-
-
public:
static const int CommandLineSize = 256;
- private:
-
- public:
BareIronMipsSystem(Params *p);
~BareIronMipsSystem();
};
FaultVect ThreadFault::_vect = 0x00F1;
FaultStat ThreadFault::_count;
-
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
FaultVect ArithmeticFault::_vect = 0x180;
FaultStat ArithmeticFault::_count;
FaultVect BreakpointFault::_vect = 0x0180;
FaultStat BreakpointFault::_count;
-
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
FaultVect ItbInvalidFault::_vect = 0x0180;
FaultStat ItbInvalidFault::_count;
FaultStat DspStateDisabledFault::_count;
#if FULL_SYSTEM
-void MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
+void
+MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
{
- tc->setPC(HandlerBase);
- tc->setNextPC(HandlerBase+sizeof(MachInst));
- tc->setNextNPC(HandlerBase+2*sizeof(MachInst));
+ tc->setPC(HandlerBase);
+ tc->setNextPC(HandlerBase + sizeof(MachInst));
+ tc->setNextNPC(HandlerBase + 2 * sizeof(MachInst));
}
-void MipsFault::setExceptionState(ThreadContext *tc,uint8_t ExcCode)
+void
+MipsFault::setExceptionState(ThreadContext *tc, uint8_t ExcCode)
{
- // modify SRS Ctl - Save CSS, put ESS into CSS
- MiscReg stat = tc->readMiscReg(MipsISA::Status);
- if(bits(stat,Status_EXL) != 1 && bits(stat,Status_BEV) != 1)
- {
- // SRS Ctl is modified only if Status_EXL and Status_BEV are not set
- MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl);
- uint8_t CSS,ESS;
- CSS = bits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO);
- ESS = bits(srs,SRSCtl_ESS_HI,SRSCtl_ESS_LO);
- // Move CSS to PSS
- replaceBits(srs,SRSCtl_PSS_HI,SRSCtl_PSS_LO,CSS);
- // Move ESS to CSS
- replaceBits(srs,SRSCtl_CSS_HI,SRSCtl_CSS_LO,ESS);
- tc->setMiscRegNoEffect(MipsISA::SRSCtl,srs);
- //tc->setShadowSet(ESS);
+ // modify SRS Ctl - Save CSS, put ESS into CSS
+ MiscReg stat = tc->readMiscReg(MipsISA::Status);
+ if (bits(stat, Status_EXL) != 1 && bits(stat, Status_BEV) != 1) {
+ // SRS Ctl is modified only if Status_EXL and Status_BEV are not set
+ MiscReg srs = tc->readMiscReg(MipsISA::SRSCtl);
+ uint8_t CSS, ESS;
+ CSS = bits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO);
+ ESS = bits(srs, SRSCtl_ESS_HI, SRSCtl_ESS_LO);
+ // Move CSS to PSS
+ replaceBits(srs, SRSCtl_PSS_HI, SRSCtl_PSS_LO, CSS);
+ // Move ESS to CSS
+ replaceBits(srs, SRSCtl_CSS_HI, SRSCtl_CSS_LO, ESS);
+ tc->setMiscRegNoEffect(MipsISA::SRSCtl, srs);
}
- // set EXL bit (don't care if it is already set!)
- replaceBits(stat,Status_EXL_HI,Status_EXL_LO,1);
- tc->setMiscRegNoEffect(MipsISA::Status,stat);
-
- // write EPC
- // warn("Set EPC to %x\n",tc->readPC());
- // CHECK ME or FIXME or FIX ME or POSSIBLE HACK
- // Check to see if the exception occurred in the branch delay slot
- DPRINTF(MipsPRA,"PC: %x, NextPC: %x, NNPC: %x\n",tc->readPC(),tc->readNextPC(),tc->readNextNPC());
- int C_BD=0;
- if(tc->readPC() + sizeof(MachInst) != tc->readNextPC()){
- tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC()-sizeof(MachInst));
- // In the branch delay slot? set CAUSE_31
- C_BD = 1;
- } else {
- tc->setMiscRegNoEffect(MipsISA::EPC,tc->readPC());
- // In the branch delay slot? reset CAUSE_31
- C_BD = 0;
- }
-
- // Set Cause_EXCCODE field
- MiscReg cause = tc->readMiscReg(MipsISA::Cause);
- replaceBits(cause,Cause_EXCCODE_HI,Cause_EXCCODE_LO,ExcCode);
- replaceBits(cause,Cause_BD_HI,Cause_BD_LO,C_BD);
- replaceBits(cause,Cause_CE_HI,Cause_CE_LO,0);
- tc->setMiscRegNoEffect(MipsISA::Cause,cause);
+ // set EXL bit (don't care if it is already set!)
+ replaceBits(stat, Status_EXL_HI, Status_EXL_LO, 1);
+ tc->setMiscRegNoEffect(MipsISA::Status, stat);
+
+ // write EPC
+ // CHECK ME or FIXME or FIX ME or POSSIBLE HACK
+ // Check to see if the exception occurred in the branch delay slot
+ DPRINTF(MipsPRA, "PC: %x, NextPC: %x, NNPC: %x\n",
+ tc->readPC(), tc->readNextPC(), tc->readNextNPC());
+ int C_BD = 0;
+ if (tc->readPC() + sizeof(MachInst) != tc->readNextPC()) {
+ tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC() - sizeof(MachInst));
+ // In the branch delay slot? set CAUSE_31
+ C_BD = 1;
+ } else {
+ tc->setMiscRegNoEffect(MipsISA::EPC, tc->readPC());
+ // In the branch delay slot? reset CAUSE_31
+ C_BD = 0;
+ }
+ // Set Cause_EXCCODE field
+ MiscReg cause = tc->readMiscReg(MipsISA::Cause);
+ replaceBits(cause, Cause_EXCCODE_HI, Cause_EXCCODE_LO, ExcCode);
+ replaceBits(cause, Cause_BD_HI, Cause_BD_LO,C_BD);
+ replaceBits(cause, Cause_CE_HI, Cause_CE_LO,0);
+ tc->setMiscRegNoEffect(MipsISA::Cause, cause);
}
-void ArithmeticFault::invoke(ThreadContext *tc)
+void
+ArithmeticFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0xC);
-
- // Set new PC
- Addr HandlerBase;
- MiscReg stat = tc->readMiscReg(MipsISA::Status);
- // Here, the handler is dependent on BEV, which is not modified by setExceptionState()
- if(bits(stat,Status_BEV)==0){ // See MIPS ARM Vol 3, Revision 2, Page 38
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase);
- }else{
- HandlerBase = 0xBFC00200;
- }
- setHandlerPC(HandlerBase,tc);
- // warn("Exception Handler At: %x \n",HandlerBase);
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0xC);
+
+ // Set new PC
+ Addr HandlerBase;
+ MiscReg stat = tc->readMiscReg(MipsISA::Status);
+ // Here, the handler is dependent on BEV, which is not modified by
+ // setExceptionState()
+ if (bits(stat, Status_BEV) == 0 ) {
+ // See MIPS ARM Vol 3, Revision 2, Page 38
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ } else {
+ HandlerBase = 0xBFC00200;
+ }
+ setHandlerPC(HandlerBase, tc);
}
-void StoreAddressErrorFault::invoke(ThreadContext *tc)
+void
+StoreAddressErrorFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0x5);
- tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
-
- // Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
- // warn("Exception Handler At: %x \n",HandlerBase);
- // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0x5);
+ tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
+ // Set new PC
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase, tc);
}
-void TrapFault::invoke(ThreadContext *tc)
+void
+TrapFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- // warn("%s encountered.\n", name());
- setExceptionState(tc,0xD);
-
- // Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
- // warn("Exception Handler At: %x \n",HandlerBase);
- // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0xD);
+
+ // Set new PC
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase, tc);
}
-void BreakpointFault::invoke(ThreadContext *tc)
+void
+BreakpointFault::invoke(ThreadContext *tc)
{
- setExceptionState(tc,0x9);
-
- // Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
- // warn("Exception Handler At: %x \n",HandlerBase);
- // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
+ setExceptionState(tc, 0x9);
+ // Set new PC
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase, tc);
}
-void DtbInvalidFault::invoke(ThreadContext *tc)
+void
+DtbInvalidFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- // warn("%s encountered.\n", name());
- tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
- MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
- replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
- replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
- replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
- tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
- MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
- replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
- tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
- setExceptionState(tc,0x3);
-
-
- // Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
- // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+
+ tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
+ MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
+ replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
+ replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
+ replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
+ tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
+ MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
+ replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
+ tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
+ setExceptionState(tc, 0x3);
+
+
+ // Set new PC
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase,tc);
}
-void AddressErrorFault::invoke(ThreadContext *tc)
+void
+AddressErrorFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0x4);
- tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
-
- // Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0x4);
+ tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
+
+ // Set new PC
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase, tc);
}
-void ItbInvalidFault::invoke(ThreadContext *tc)
+void
+ItbInvalidFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0x2);
- tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
- MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
- replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
- replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
- replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
- tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
- MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
- replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
- tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
-
-
- // Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
- DPRINTF(MipsPRA,"Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0x2);
+ tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
+ MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
+ replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
+ replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
+ replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
+ tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
+ MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
+ replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
+ tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
+
+
+ // Set new PC
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase,tc);
+ DPRINTF(MipsPRA,"Exception Handler At: %x , EPC set to %x\n",
+ HandlerBase, tc->readMiscReg(MipsISA::EPC));
}
-void ItbRefillFault::invoke(ThreadContext *tc)
+void
+ItbRefillFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered (%x).\n", name(),BadVAddr);
- Addr HandlerBase;
- tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
- MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
- replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
- replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
- replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
- tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
- MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
- replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
- tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
-
- MiscReg stat = tc->readMiscReg(MipsISA::Status);
- // Since handler depends on EXL bit, must check EXL bit before setting it!!
- if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- }else{
- HandlerBase = tc->readMiscReg(MipsISA::EBase); // Offset 0x000
- }
-
- setExceptionState(tc,0x2);
- setHandlerPC(HandlerBase,tc);
+ DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), BadVAddr);
+ Addr HandlerBase;
+ tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
+ MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
+ replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
+ replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
+ replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
+ tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
+ MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
+ replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
+ tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
+
+ MiscReg stat = tc->readMiscReg(MipsISA::Status);
+ // Since handler depends on EXL bit, must check EXL bit before setting it!!
+ // See MIPS ARM Vol 3, Revision 2, Page 38
+ if (bits(stat, Status_EXL) == 1) {
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ } else {
+ // Offset 0x000
+ HandlerBase = tc->readMiscReg(MipsISA::EBase);
+ }
+
+ setExceptionState(tc, 0x2);
+ setHandlerPC(HandlerBase, tc);
}
-void DtbRefillFault::invoke(ThreadContext *tc)
+void
+DtbRefillFault::invoke(ThreadContext *tc)
{
- // Set new PC
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- Addr HandlerBase;
- tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
- MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
- replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
- replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
- replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
- tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
- MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
- replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
- tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
-
- MiscReg stat = tc->readMiscReg(MipsISA::Status);
- // Since handler depends on EXL bit, must check EXL bit before setting it!!
- if(bits(stat,Status_EXL)==1){ // See MIPS ARM Vol 3, Revision 2, Page 38
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- }else{
- HandlerBase = tc->readMiscReg(MipsISA::EBase); // Offset 0x000
- }
-
-
- setExceptionState(tc,0x3);
-
- setHandlerPC(HandlerBase,tc);
+ // Set new PC
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ Addr HandlerBase;
+ tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
+ MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
+ replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
+ replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
+ replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
+ tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
+ MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
+ replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
+ tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
+
+ MiscReg stat = tc->readMiscReg(MipsISA::Status);
+ // Since handler depends on EXL bit, must check EXL bit before setting it!!
+ // See MIPS ARM Vol 3, Revision 2, Page 38
+ if(bits(stat, Status_EXL) == 1) {
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ } else {
+ // Offset 0x000
+ HandlerBase = tc->readMiscReg(MipsISA::EBase);
+ }
+
+ setExceptionState(tc, 0x3);
+
+ setHandlerPC(HandlerBase, tc);
}
-void TLBModifiedFault::invoke(ThreadContext *tc)
+void
+TLBModifiedFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- tc->setMiscRegNoEffect(MipsISA::BadVAddr,BadVAddr);
- MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
- replaceBits(eh,EntryHi_ASID_HI,EntryHi_ASID_LO,EntryHi_Asid);
- replaceBits(eh,EntryHi_VPN2_HI,EntryHi_VPN2_LO,EntryHi_VPN2);
- replaceBits(eh,EntryHi_VPN2X_HI,EntryHi_VPN2X_LO,EntryHi_VPN2X);
- tc->setMiscRegNoEffect(MipsISA::EntryHi,eh);
- MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
- replaceBits(ctxt,Context_BadVPN2_HI,Context_BadVPN2_LO,Context_BadVPN2);
- tc->setMiscRegNoEffect(MipsISA::Context,ctxt);
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ tc->setMiscRegNoEffect(MipsISA::BadVAddr, BadVAddr);
+ MiscReg eh = tc->readMiscReg(MipsISA::EntryHi);
+ replaceBits(eh, EntryHi_ASID_HI, EntryHi_ASID_LO, EntryHi_Asid);
+ replaceBits(eh, EntryHi_VPN2_HI, EntryHi_VPN2_LO, EntryHi_VPN2);
+ replaceBits(eh, EntryHi_VPN2X_HI, EntryHi_VPN2X_LO, EntryHi_VPN2X);
+ tc->setMiscRegNoEffect(MipsISA::EntryHi, eh);
+ MiscReg ctxt = tc->readMiscReg(MipsISA::Context);
+ replaceBits(ctxt, Context_BadVPN2_HI, Context_BadVPN2_LO, Context_BadVPN2);
+ tc->setMiscRegNoEffect(MipsISA::Context, ctxt);
// Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setExceptionState(tc,0x1);
- setHandlerPC(HandlerBase,tc);
- // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setExceptionState(tc, 0x1);
+ setHandlerPC(HandlerBase, tc);
}
-void SystemCallFault::invoke(ThreadContext *tc)
+void
+SystemCallFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0x8);
-
- // Set new PC
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
- // warn("Exception Handler At: %x \n",HandlerBase);
- // warn("Exception Handler At: %x , EPC set to %x\n",HandlerBase,tc->readMiscReg(MipsISA::EPC));
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0x8);
+ // Set new PC
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase, tc);
}
-void InterruptFault::invoke(ThreadContext *tc)
+void
+InterruptFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0x0A);
- Addr HandlerBase;
-
-
- uint8_t IV = bits(tc->readMiscRegNoEffect(MipsISA::Cause),Cause_IV);
- if (IV)// Offset 200 for release 2
- HandlerBase= 0x20 + vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
- else//Ofset at 180 for release 1
- HandlerBase= vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0x0A);
+ Addr HandlerBase;
+
+ uint8_t IV = bits(tc->readMiscRegNoEffect(MipsISA::Cause), Cause_IV);
+ if (IV) {
+ // Offset 200 for release 2
+ HandlerBase = 0x20 + vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
+ } else {
+ //Ofset at 180 for release 1
+ HandlerBase = vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
+ }
- setHandlerPC(HandlerBase,tc);
+ setHandlerPC(HandlerBase, tc);
#endif
}
#endif // FULL_SYSTEM
-void ResetFault::invoke(ThreadContext *tc)
+void
+ResetFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- /* All reset activity must be invoked from here */
- tc->setPC(vect());
- tc->setNextPC(vect()+sizeof(MachInst));
- tc->setNextNPC(vect()+sizeof(MachInst)+sizeof(MachInst));
- DPRINTF(MipsPRA,"(%x) - ResetFault::invoke : PC set to %x",(unsigned)tc,(unsigned)tc->readPC());
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ /* All reset activity must be invoked from here */
+ tc->setPC(vect());
+ tc->setNextPC(vect() + sizeof(MachInst));
+ tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst));
+ DPRINTF(MipsPRA, "(%x) - ResetFault::invoke : PC set to %x",
+ (unsigned)tc, (unsigned)tc->readPC());
#endif
- // Set Coprocessor 1 (Floating Point) To Usable
- tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000);
+ // Set Coprocessor 1 (Floating Point) To Usable
+ tc->setMiscReg(MipsISA::Status, MipsISA::Status | 0x20000000);
}
-void ReservedInstructionFault::invoke(ThreadContext *tc)
+void
+ReservedInstructionFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0x0A);
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscRegNoEffect(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0x0A);
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscRegNoEffect(MipsISA::EBase);
+ setHandlerPC(HandlerBase, tc);
#else
panic("%s encountered.\n", name());
#endif
}
-void ThreadFault::invoke(ThreadContext *tc)
+void
+ThreadFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- panic("%s encountered.\n", name());
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ panic("%s encountered.\n", name());
}
-void DspStateDisabledFault::invoke(ThreadContext *tc)
+void
+DspStateDisabledFault::invoke(ThreadContext *tc)
{
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- panic("%s encountered.\n", name());
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ panic("%s encountered.\n", name());
}
-void CoprocessorUnusableFault::invoke(ThreadContext *tc)
+void
+CoprocessorUnusableFault::invoke(ThreadContext *tc)
{
#if FULL_SYSTEM
- DPRINTF(MipsPRA,"%s encountered.\n", name());
- setExceptionState(tc,0xb);
- /* The ID of the coprocessor causing the exception is stored in CoprocessorUnusableFault::coProcID */
- MiscReg cause = tc->readMiscReg(MipsISA::Cause);
- replaceBits(cause,Cause_CE_HI,Cause_CE_LO,coProcID);
- tc->setMiscRegNoEffect(MipsISA::Cause,cause);
-
- Addr HandlerBase;
- HandlerBase= vect() + tc->readMiscReg(MipsISA::EBase); // Offset 0x180 - General Exception Vector
- setHandlerPC(HandlerBase,tc);
-
- // warn("Status: %x, Cause: %x\n",tc->readMiscReg(MipsISA::Status),tc->readMiscReg(MipsISA::Cause));
+ DPRINTF(MipsPRA, "%s encountered.\n", name());
+ setExceptionState(tc, 0xb);
+ // The ID of the coprocessor causing the exception is stored in
+ // CoprocessorUnusableFault::coProcID
+ MiscReg cause = tc->readMiscReg(MipsISA::Cause);
+ replaceBits(cause, Cause_CE_HI, Cause_CE_LO, coProcID);
+ tc->setMiscRegNoEffect(MipsISA::Cause, cause);
+
+ Addr HandlerBase;
+ // Offset 0x180 - General Exception Vector
+ HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
+ setHandlerPC(HandlerBase, tc);
+
#else
warn("%s (CP%d) encountered.\n", name(), coProcID);
#endif
#include "sim/faults.hh"
-// The design of the "name" and "vect" functions is in sim/faults.hh
-
namespace MipsISA
{
+
typedef const Addr FaultVect;
class MipsFault : public FaultBase
Addr EntryHi_VPN2X;
Addr Context_BadVPN2;
#if FULL_SYSTEM
- void invoke(ThreadContext * tc) {};
- void setExceptionState(ThreadContext *,uint8_t);
- void setHandlerPC(Addr,ThreadContext *);
+ void invoke(ThreadContext * tc) {};
+ void setExceptionState(ThreadContext *, uint8_t);
+ void setHandlerPC(Addr, ThreadContext *);
#endif
virtual FaultVect vect() = 0;
virtual FaultStat & countStat() = 0;
#endif
};
+
class StoreAddressErrorFault : public MipsFault
{
private:
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
-
};
+
class UnimplementedOpcodeFault : public MipsFault
{
private:
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
+
class TLBInvalidIFetchFault : public MipsFault
{
private:
void invoke(ThreadContext * tc);
};
+
class SystemCallFault : public MipsFault
{
private:
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
+
class DebugSingleStep : public MipsFault
{
private:
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
+
class DebugInterrupt : public MipsFault
{
private:
void invoke(ThreadContext * tc);
};
-
class ArithmeticFault : public MipsFault
{
protected:
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
-
- //void invoke(ThreadContext * tc);
};
class TrapFault : public MipsFault
void invoke(ThreadContext * tc);
#endif
};
+
class DtbRefillFault : public MipsFault
{
private:
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
-
};
+
class TLBModifiedFault : public MipsFault
{
private:
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
-
};
class DtbInvalidFault : public MipsFault
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
-
};
class FloatEnableFault : public MipsFault
IdleStartEvent::process(ThreadContext *tc)
{
fatal("Idle Start Event Not Defined for MIPS ISA ");
-
- // if (tc->getKernelStats())
- // tc->getKernelStats()->setIdleProcess(
- // tc->readMiscRegNoEffect(MipsISA::IPR_PALtemp23), tc);
- //remove();
}
namespace MipsISA
{
-static inline uint8_t getCauseIP_(ThreadContext *tc) {
+
+static inline uint8_t
+getCauseIP(ThreadContext *tc) {
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
- uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
- return IP_;
+ return bits(cause, Cause_IP7, Cause_IP0);
}
-static inline void setCauseIP_(ThreadContext *tc, uint8_t val) {
+static inline void
+setCauseIP_(ThreadContext *tc, uint8_t val) {
MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
- replaceBits(cause,Cause_IP7,Cause_IP0,val);
- tc->setMiscRegNoEffect(MipsISA::Cause,cause);
+ replaceBits(cause, Cause_IP7, Cause_IP0, val);
+ tc->setMiscRegNoEffect(MipsISA::Cause, cause);
}
-/*
- void Interrupts::post(int int_num, int index)
- {
- DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
-
- //index should not be used
- assert(index == 0);
-
- if (int_num < 0 || int_num >= NumInterruptLevels)
- panic("int_num out of bounds\n");
- intstatus |= 1 << int_num;
- }
-
- void Interrupts::clear(int int_num, int index)
- {
- DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
-
- //index should not be used
- assert(index == 0);
-
- if (int_num < 0 || int_num >= NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- intstatus &= ~(1 << int_num);
- }
-
- void Interrupts::clearAll()
- {
- DPRINTF(Interrupt, "Interrupts all cleared\n");
- intstatus = 0;
- }
-
-
-
- Fault Interrupts::getInterrupt(ThreadContext * tc)
- {
- DPRINTF(Interrupt, "Interrupts getInterrupt\n");
- // If a timer interrupt has occured, check to see if a
- // mtc0 to Compare register caused this interrupt to
- // be cleared. If this is the case, clear intstatus
- // bit for timer interrupt
- if (oncputimerintr){
- DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n");
- MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
- uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
- MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
- uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
- //mtc0 to compare must have cleared bit in IP
- if ( ((1 << IPTI) & IP_) == 0){
- clear(IPTI, 0);
- oncputimerintr=false;
- }
- }
- //if there is a on cpu timer interrupt (i.e. Compare == Count)
- //update intstatus before proceeding to interrupt
- if (onCpuTimerInterrupt(tc)){
- DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
- //determine timer interrupt IP #
- MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
- uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
- //set intstatus to correspond
- post(IPTI, 0);
- oncputimerintr=true;
- }
-
- //Check if there are any outstanding interrupts
- MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
- if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
- bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited
- bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited
- {
- // Software interrupts & hardware interrupts are handled in software.
- // So if any interrupt that isn't masked is detected, jump to interrupt
- // handler
- uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
- IM = bits(status,Status_IM7,Status_IM0);
- IP = intstatus;
- //IM and IP are already correctly aligned
- if (IM & IP){
- DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
- IM, IP);
- return new InterruptFault;
- }
- }
-
- return NoFault;
-
- }
-
- void Interrupts::updateIntrInfo(ThreadContext *tc) const
- {
- //Merge Interrupts.intstatus with mips MipISA::Status
- MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
- replaceBits(cause,Cause_IP7,Cause_IP0,intstatus);
- tc->setMiscRegNoEffect(MipsISA::Cause,cause);
- }
-
- bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
- {
- MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
- MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
- if (compare == count)
- return true;
- return false;
- }
-
-*/
-void Interrupts::post(int int_num, ThreadContext* tc)
+void
+Interrupts::post(int int_num, ThreadContext* tc)
{
DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n");
- uint8_t intstatus= getCauseIP_(tc);
+ uint8_t intstatus = getCauseIP(tc);
intstatus |= 1 << int_num;
- setCauseIP_(tc, intstatus);
+ setCauseIP(tc, intstatus);
}
-void Interrupts::post(int int_num, int index)
+void
+Interrupts::post(int int_num, int index)
{
- fatal("Must use Thread COntext when posting MIPS Interrupts in M5");
+ fatal("Must use Thread Context when posting MIPS Interrupts in M5");
}
-void Interrupts::clear(int int_num, ThreadContext* tc)
+void
+Interrupts::clear(int int_num, ThreadContext* tc)
{
DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
if (int_num < 0 || int_num >= NumInterruptLevels)
panic("int_num out of bounds\n");
- uint8_t intstatus = getCauseIP_(tc);
+ uint8_t intstatus = getCauseIP(tc);
intstatus &= ~(1 << int_num);
- setCauseIP_(tc, intstatus);
+ setCauseIP(tc, intstatus);
}
-void Interrupts::clear(int int_num, int index)
+void
+Interrupts::clear(int int_num, int index)
{
- fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
+ fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
}
-void Interrupts::clearAll(ThreadContext *tc)
+void
+Interrupts::clearAll(ThreadContext *tc)
{
DPRINTF(Interrupt, "Interrupts all cleared\n");
uint8_t intstatus = 0;
- setCauseIP_(tc, intstatus);
+ setCauseIP(tc, intstatus);
}
-void Interrupts::clearAll()
+void
+Interrupts::clearAll()
{
- fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
+ fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
}
-Fault Interrupts::getInterrupt(ThreadContext * tc)
+Fault
+Interrupts::getInterrupt(ThreadContext * tc)
{
DPRINTF(Interrupt, "Interrupts getInterrupt\n");
-
-
//Check if there are any outstanding interrupts
MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
- if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
- bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited
- bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited
- {
+ // Interrupts must be enabled, error level must be 0 or interrupts
+ // inhibited, and exception level must be 0 or interrupts inhibited
+ if (bits(status, Status_IE_LO) == 1 &&
+ bits(status, Status_ERL_HI, Status_ERL_LO) == 0 &&
+ bits(status, Status_EXL_HI, Status_EXL_LO) == 0) {
// Software interrupts & hardware interrupts are handled in software.
// So if any interrupt that isn't masked is detected, jump to interrupt
// handler
- uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
- IM = bits(status,Status_IM7,Status_IM0);
- IP = getCauseIP_(tc);
- //IM and IP are already correctly aligned
- if (IM & IP){
+ uint8_t InterruptMask = bits(status, Status_IM7, Status_IM0);
+ uint8_t InterruptPending = getCauseIP(tc);
+ // InterruptMask and InterruptPending are already correctly aligned
+ if (InterruptMask && InterruptPending){
DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
- IM, IP);
+ InterruptMask, InterruptPending);
return new InterruptFault;
}
}
return NoFault;
-
}
-bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
+
+bool
+Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
{
MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
return true;
return false;
}
-void Interrupts::updateIntrInfo(ThreadContext *tc) const
+
+void
+Interrupts::updateIntrInfo(ThreadContext *tc) const
{
//Nothing needs to be done.
- ;
}
-bool Interrupts::interruptsPending(ThreadContext *tc) const
+bool
+Interrupts::interruptsPending(ThreadContext *tc) const
{
//if there is a on cpu timer interrupt (i.e. Compare == Count)
//update CauseIP before proceeding to interrupt
- if (onCpuTimerInterrupt(tc)){
- DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
+ if (onCpuTimerInterrupt(tc)) {
+ DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc) == true\n");
//determine timer interrupt IP #
MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
//set intstatus to correspond
//post(IPTI, tc);
- uint8_t intstatus= getCauseIP_(tc);
+ uint8_t intstatus = getCauseIP(tc);
intstatus |= 1 << IPTI;
- setCauseIP_(tc, intstatus);
+ setCauseIP(tc, intstatus);
}
- return (getCauseIP_(tc) != 0);
+ return (getCauseIP(tc) != 0);
}
-
-
-
-
}
#ifndef __ARCH_MIPS_INTERRUPT_HH__
#define __ARCH_MIPS_INTERRUPT_HH__
-
#include "arch/mips/faults.hh"
#include "base/compiler.hh"
-
-
namespace MipsISA
{
+
class Interrupts
{
- /*
- protected:
- uint8_t intstatus;
- bool oncputimerintr;
- public:
- Interrupts()
- {
- intstatus = 0;
- newInfoSet = false;
- oncputimerintr = false;
-
- }
- // post(int int_num, int index) is responsible
- // for posting an interrupt. It sets a bit
- // in intstatus corresponding to Cause IP*. The
- // MIPS register Cause is updated by updateIntrInfo
- // which is called by checkInterrupts
- //
- void post(int int_num, int index);
- // clear(int int_num, int index) is responsible
- // for clearing an interrupt. It clear a bit
- // in intstatus corresponding to Cause IP*. The
- // MIPS register Cause is updated by updateIntrInfo
- // which is called by checkInterrupts
- //
- void clear(int int_num, int index);
- // clearAll() is responsible
- // for clearing all interrupts. It clears all bits
- // in intstatus corresponding to Cause IP*. The
- // MIPS register Cause is updated by updateIntrInfo
- // which is called by checkInterrupts
- //
- void clearAll();
-
- // getInterrupt(ThreadContext * tc) checks if an interrupt
- // should be returned. It ands the interrupt mask and
- // and interrupt pending bits to see if one exists. It
- // also makes sure interrupts are enabled (IE) and
- // that ERL and ERX are not set
- //
- Fault getInterrupt(ThreadContext * tc);
-
- // updateIntrInfo(ThreadContext *tc) const syncs the
- // MIPS cause register with the instatus variable. instatus
- // is essentially a copy of the MIPS cause[IP7:IP0]
- //
- void updateIntrInfo(ThreadContext *tc) const;
- void updateIntrInfoCpuTimerIntr(ThreadContext *tc) const;
- bool onCpuTimerInterrupt(ThreadContext *tc) const;
-
- bool checkInterrupts(ThreadContext *tc) const {
- //return (intstatus != 0) && !(tc->readPC() & 0x3);
- if (oncputimerintr == false){
- updateIntrInfo(tc);
- return ((intstatus != 0) || onCpuTimerInterrupt(tc));
- }
- else
- return true;
-
- }
- */
-
-
- protected:
- //uint8_t intstatus;
- //bool oncputimerintr;
public:
Interrupts()
{
- //intstatus = 0;
newInfoSet = false;
- //oncputimerintr = false;
-
}
+
// post(int int_num, int index) is responsible
// for posting an interrupt. It sets a bit
// in intstatus corresponding to Cause IP*. The
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
- void post(int int_num, ThreadContext* tc);
+ void post(int int_num, ThreadContext *tc);
void post(int int_num, int index);
// clear(int int_num, int index) is responsible
// MIPS register Cause is updated by updateIntrInfo
// which is called by checkInterrupts
//
- void clearAll(ThreadContext* tc);
+ void clearAll(ThreadContext *tc);
void clearAll();
// getInterrupt(ThreadContext * tc) checks if an interrupt
// also makes sure interrupts are enabled (IE) and
// that ERL and ERX are not set
//
- Fault getInterrupt(ThreadContext * tc);
+ Fault getInterrupt(ThreadContext *tc);
// updateIntrInfo(ThreadContext *tc) const syncs the
// MIPS cause register with the instatus variable. instatus
}
- void serialize(std::ostream &os)
+ void
+ serialize(std::ostream &os)
{
fatal("Serialization of Interrupts Unimplemented for MIPS");
- //SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
- //SERIALIZE_SCALAR(intstatus);
}
- void unserialize(Checkpoint *cp, const std::string §ion)
+ void
+ unserialize(Checkpoint *cp, const std::string §ion)
{
fatal("Unserialization of Interrupts Unimplemented for MIPS");
- //UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
- //UNSERIALIZE_SCALAR(intstatus);
}
-
-
private:
bool newInfoSet;
int newIpl;
int newSummary;
-
};
}
misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg],
miscRegFile[misc_reg][reg_sel]);
-
- switch (misc_reg)
- {
- default:
- return miscRegFile[misc_reg][reg_sel];
- }
+ return miscRegFile[misc_reg][reg_sel];
}
void
// (1) Some CP0 Registers have fields that cannot
// be overwritten. Make sure to handle those particular registers
// with care!
-//template <class TC>
void
ISA::setMiscReg(int reg_idx, const MiscReg &val,
ThreadContext *tc, ThreadID tid)
MiscReg
ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val)
{
- MiscReg retVal = val;
-
- // Mask off read-only regions
- retVal &= miscRegFile_WriteMask[misc_reg][reg_sel];
- MiscReg curVal = miscRegFile[misc_reg][reg_sel];
- // Mask off current alue with inverse mask (clear writeable bits)
- curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]);
- retVal |= curVal; // Combine the two
- DPRINTF(MipsPRA,
- "filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, "
- "current val: %lx, written val: %x\n",
- miscRegFile_WriteMask[misc_reg][reg_sel],
- ~miscRegFile_WriteMask[misc_reg][reg_sel],
- val, miscRegFile[misc_reg][reg_sel], retVal);
- return retVal;
+ MiscReg retVal = val;
+
+ // Mask off read-only regions
+ retVal &= miscRegFile_WriteMask[misc_reg][reg_sel];
+ MiscReg curVal = miscRegFile[misc_reg][reg_sel];
+ // Mask off current alue with inverse mask (clear writeable bits)
+ curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]);
+ retVal |= curVal; // Combine the two
+ DPRINTF(MipsPRA,
+ "filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, "
+ "current val: %lx, written val: %x\n",
+ miscRegFile_WriteMask[misc_reg][reg_sel],
+ ~miscRegFile_WriteMask[misc_reg][reg_sel],
+ val, miscRegFile[misc_reg][reg_sel], retVal);
+ return retVal;
}
void
cp0->updateCPU();
break;
}
-
- //cp0EventRemoveList.push(this);
}
const char *
namespace LittleEndianGuest {};
-#define TARGET_MIPS
-
class StaticInstPtr;
namespace MipsISA
{
- using namespace LittleEndianGuest;
-
- StaticInstPtr decodeInst(ExtMachInst);
-
- // MIPS DOES have a delay slot
- #define ISA_HAS_DELAY_SLOT 1
-
- const Addr PageShift = 13;
- const Addr PageBytes = ULL(1) << PageShift;
- const Addr Page_Mask = ~(PageBytes - 1);
- const Addr PageOffset = PageBytes - 1;
-
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Translation stuff
- //
-
- const Addr PteShift = 3;
- const Addr NPtePageShift = PageShift - PteShift;
- const Addr NPtePage = ULL(1) << NPtePageShift;
- const Addr PteMask = NPtePage - 1;
-
- //// All 'Mapped' segments go through the TLB
- //// All other segments are translated by dropping the MSB, to give
- //// the corresponding physical address
- // User Segment - Mapped
- const Addr USegBase = ULL(0x0);
- const Addr USegEnd = ULL(0x7FFFFFFF);
-
- // Kernel Segment 0 - Unmapped
- const Addr KSeg0End = ULL(0x9FFFFFFF);
- const Addr KSeg0Base = ULL(0x80000000);
- const Addr KSeg0Mask = ULL(0x1FFFFFFF);
-
- // Kernel Segment 1 - Unmapped, Uncached
- const Addr KSeg1End = ULL(0xBFFFFFFF);
- const Addr KSeg1Base = ULL(0xA0000000);
- const Addr KSeg1Mask = ULL(0x1FFFFFFF);
-
- // Kernel/Supervisor Segment - Mapped
- const Addr KSSegEnd = ULL(0xDFFFFFFF);
- const Addr KSSegBase = ULL(0xC0000000);
-
- // Kernel Segment 3 - Mapped
- const Addr KSeg3End = ULL(0xFFFFFFFF);
- const Addr KSeg3Base = ULL(0xE0000000);
-
-
- // For loading... XXX This maybe could be USegEnd?? --ali
- const Addr LoadAddrMask = ULL(0xffffffffff);
-
- inline Addr Phys2K0Seg(Addr addr)
- {
- // if (addr & PAddrUncachedBit43) {
-// addr &= PAddrUncachedMask;
-// addr |= PAddrUncachedBit40;
-// }
- return addr | KSeg0Base;
- }
-
-
- const unsigned VABits = 32;
- const unsigned PABits = 32; // Is this correct?
- const Addr VAddrImplMask = (ULL(1) << VABits) - 1;
- const Addr VAddrUnImplMask = ~VAddrImplMask;
- inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
- inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; }
- inline Addr VAddrOffset(Addr a) { return a & MipsISA::PageOffset; }
-
- const Addr PAddrImplMask = (ULL(1) << PABits) - 1;
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Interrupt levels
- //
- enum InterruptLevels
- {
- INTLEVEL_SOFTWARE_MIN = 4,
- INTLEVEL_SOFTWARE_MAX = 19,
-
- INTLEVEL_EXTERNAL_MIN = 20,
- INTLEVEL_EXTERNAL_MAX = 34,
-
- INTLEVEL_IRQ0 = 20,
- INTLEVEL_IRQ1 = 21,
- INTINDEX_ETHERNET = 0,
- INTINDEX_SCSI = 1,
- INTLEVEL_IRQ2 = 22,
- INTLEVEL_IRQ3 = 23,
-
- INTLEVEL_SERIAL = 33,
-
- NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
- };
-
- // MIPS modes
- enum mode_type
- {
- mode_kernel = 0, // kernel
- mode_supervisor = 1, // supervisor
- mode_user = 2, // user mode
- mode_debug = 3, // debug mode
- mode_number // number of modes
- };
-
- // return a no-op instruction... used for instruction fetch faults
- const ExtMachInst NoopMachInst = 0x00000000;
-
- const int LogVMPageSize = 13; // 8K bytes
- const int VMPageSize = (1 << LogVMPageSize);
-
- const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
-
- const int MachineBytes = 4;
- const int WordBytes = 4;
- const int HalfwordBytes = 2;
- const int ByteBytes = 1;
-
- const int ANNOTE_NONE = 0;
- const uint32_t ITOUCH_ANNOTE = 0xffffffff;
+
+using namespace LittleEndianGuest;
+
+StaticInstPtr decodeInst(ExtMachInst);
+
+// MIPS DOES have a delay slot
+#define ISA_HAS_DELAY_SLOT 1
+
+const Addr PageShift = 13;
+const Addr PageBytes = ULL(1) << PageShift;
+const Addr Page_Mask = ~(PageBytes - 1);
+const Addr PageOffset = PageBytes - 1;
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// Translation stuff
+//
+
+const Addr PteShift = 3;
+const Addr NPtePageShift = PageShift - PteShift;
+const Addr NPtePage = ULL(1) << NPtePageShift;
+const Addr PteMask = NPtePage - 1;
+
+//// All 'Mapped' segments go through the TLB
+//// All other segments are translated by dropping the MSB, to give
+//// the corresponding physical address
+// User Segment - Mapped
+const Addr USegBase = ULL(0x0);
+const Addr USegEnd = ULL(0x7FFFFFFF);
+
+// Kernel Segment 0 - Unmapped
+const Addr KSeg0End = ULL(0x9FFFFFFF);
+const Addr KSeg0Base = ULL(0x80000000);
+const Addr KSeg0Mask = ULL(0x1FFFFFFF);
+
+// Kernel Segment 1 - Unmapped, Uncached
+const Addr KSeg1End = ULL(0xBFFFFFFF);
+const Addr KSeg1Base = ULL(0xA0000000);
+const Addr KSeg1Mask = ULL(0x1FFFFFFF);
+
+// Kernel/Supervisor Segment - Mapped
+const Addr KSSegEnd = ULL(0xDFFFFFFF);
+const Addr KSSegBase = ULL(0xC0000000);
+
+// Kernel Segment 3 - Mapped
+const Addr KSeg3End = ULL(0xFFFFFFFF);
+const Addr KSeg3Base = ULL(0xE0000000);
+
+
+// For loading... XXX This maybe could be USegEnd?? --ali
+const Addr LoadAddrMask = ULL(0xffffffffff);
+
+inline Addr Phys2K0Seg(Addr addr)
+{
+ return addr | KSeg0Base;
+}
+
+
+const unsigned VABits = 32;
+const unsigned PABits = 32; // Is this correct?
+const Addr VAddrImplMask = (ULL(1) << VABits) - 1;
+const Addr VAddrUnImplMask = ~VAddrImplMask;
+inline Addr VAddrImpl(Addr a) { return a & VAddrImplMask; }
+inline Addr VAddrVPN(Addr a) { return a >> MipsISA::PageShift; }
+inline Addr VAddrOffset(Addr a) { return a & MipsISA::PageOffset; }
+
+const Addr PAddrImplMask = (ULL(1) << PABits) - 1;
+
+////////////////////////////////////////////////////////////////////////
+//
+// Interrupt levels
+//
+enum InterruptLevels
+{
+ INTLEVEL_SOFTWARE_MIN = 4,
+ INTLEVEL_SOFTWARE_MAX = 19,
+
+ INTLEVEL_EXTERNAL_MIN = 20,
+ INTLEVEL_EXTERNAL_MAX = 34,
+
+ INTLEVEL_IRQ0 = 20,
+ INTLEVEL_IRQ1 = 21,
+ INTINDEX_ETHERNET = 0,
+ INTINDEX_SCSI = 1,
+ INTLEVEL_IRQ2 = 22,
+ INTLEVEL_IRQ3 = 23,
+
+ INTLEVEL_SERIAL = 33,
+
+ NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
+};
+
+// MIPS modes
+enum mode_type
+{
+ mode_kernel = 0, // kernel
+ mode_supervisor = 1, // supervisor
+ mode_user = 2, // user mode
+ mode_debug = 3, // debug mode
+ mode_number // number of modes
+};
+
+// return a no-op instruction... used for instruction fetch faults
+const ExtMachInst NoopMachInst = 0x00000000;
+
+const int LogVMPageSize = 13; // 8K bytes
+const int VMPageSize = (1 << LogVMPageSize);
+
+const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
+
+const int MachineBytes = 4;
+const int WordBytes = 4;
+const int HalfwordBytes = 2;
+const int ByteBytes = 1;
+
+const int ANNOTE_NONE = 0;
+const uint32_t ITOUCH_ANNOTE = 0xffffffff;
+
};
#endif // __ARCH_MIPS_ISA_TRAITS_HH__
#ifndef __ARCH_MIPS_KERNEL_STATS_HH__
#define __ARCH_MIPS_KERNEL_STATS_HH__
-#include <map>
-#include <stack>
-#include <string>
-#include <vector>
-
#include "kern/kernel_stats.hh"
namespace MipsISA {
const int MipsLinux::NUM_OPEN_FLAGS =
(sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));
-
-
-
-
//@{
/// For getsysinfo().
- static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
- static const unsigned GSI_CPU_INFO = 59; //!< CPU information
- static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
- static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
- static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
- static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
- static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
+ static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
+ static const unsigned GSI_CPU_INFO = 59; //!< CPU information
+ static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
+ static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
+ static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
+ static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
+ static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
//@}
//@{
// unsigned nbytes = process->getSyscallArg(tc, 2);
switch (op) {
-
- case 45: { // GSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
- // I don't think this exactly matches the HW FPCR
- *fpcr = 0;
- fpcr.copyOut(tc->getMemPort());
- return 0;
- }
-
+ case 45:
+ {
+ // GSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
+ // I don't think this exactly matches the HW FPCR
+ *fpcr = 0;
+ fpcr.copyOut(tc->getMemPort());
+ return 0;
+ }
default:
cerr << "sys_getsysinfo: unknown op " << op << endl;
abort();
switch (op) {
- case 14: { // SSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
- // I don't think this exactly matches the HW FPCR
- fpcr.copyIn(tc->getMemPort());
- DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
+ case 14:
+ {
+ // SSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(process->getSyscallArg(tc, 1));
+ // I don't think this exactly matches the HW FPCR
+ fpcr.copyIn(tc->getMemPort());
+ DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): "
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
- return 0;
- }
-
+ return 0;
+ }
default:
cerr << "sys_setsysinfo: unknown op " << op << endl;
abort();
/* 72 */ SyscallDesc("sigsuspend", unimplementedFunc),
/* 73 */ SyscallDesc("sigpending", unimplementedFunc),
/* 74 */ SyscallDesc("sethostname", ignoreFunc),
- /* 75 */ SyscallDesc("setrlimit", unimplementedFunc/*setrlimitFunc<MipsLinux>*/),
- /* 76 */ SyscallDesc("getrlimit", unimplementedFunc/*getrlimitFunc<MipsLinux>*/),
+ /* 75 */ SyscallDesc("setrlimit", unimplementedFunc),
+ /* 76 */ SyscallDesc("getrlimit", unimplementedFunc),
/* 77 */ SyscallDesc("getrusage", getrusageFunc<MipsLinux>),
/* 78 */ SyscallDesc("gettimeofday", unimplementedFunc),
/* 79 */ SyscallDesc("settimeofday", unimplementedFunc),
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
- /* 120 */ SyscallDesc("clone", unimplementedFunc/*cloneFunc<MipsLinux>*/),
+ /* 120 */ SyscallDesc("clone", unimplementedFunc),
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
/* 122 */ SyscallDesc("uname", unameFunc),
/* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
/* 191 */ SyscallDesc("getresgid", unimplementedFunc),
/* 192 */ SyscallDesc("prctl", unimplementedFunc),
/* 193 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
- /* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc/*rt_sigactionFunc<MipsLinux>*/),
- /* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc/*rt_sigprocmaskFunc<MipsLinux>*/),
+ /* 194 */ SyscallDesc("rt_sigaction", unimplementedFunc),
+ /* 195 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
/* 196 */ SyscallDesc("rt_sigpending", unimplementedFunc),
/* 197 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
/* 198 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
- /* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc/*rt_sigsuspendFunc<MipsLinux>*/),
+ /* 199 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
/* 200 */ SyscallDesc("pread64", unimplementedFunc),
/* 201 */ SyscallDesc("pwrite64", unimplementedFunc),
/* 202 */ SyscallDesc("chown", unimplementedFunc),
/* 282 */ SyscallDesc("keyctl", unimplementedFunc)
};
-
MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
ObjectFile *objFile)
: MipsLiveProcess(params, objFile),
virtPort.write(addr, (uint64_t)(Clock::Frequency /
p->boot_cpu_frequency));
-
/**
* EV5 only supports 127 ASNs so we are going to tell the kernel that the
* paritiuclar EV6 we have only supports 127 asns.
if (!kernelPanicEvent)
panic("could not find kernel symbol \'panic\'");
-#if 0
- kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
- if (!kernelDieEvent)
- panic("could not find kernel symbol \'die_if_kernel\'");
-#endif
-
#endif
/**
namespace MipsISA
{
+
template <class XC>
inline void
handleLockedRead(XC *xc, Request *req)
{
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",
+ DPRINTF(LLSC, "[tid:%i]: Load-Link Flag Set & Load-Link"
+ " Address set to %x.\n",
req->threadId(), req->getPaddr() & ~0xf);
}
-
template <class XC>
inline bool
handleLockedWrite(XC *xc, Request *req)
}
if (stCondFailures == 5000) {
- panic("Max (5000) Store Conditional Fails Reached. Check Code For Deadlock.\n");
+ panic("Max (5000) Store Conditional Fails Reached. "
+ "Check Code For Deadlock.\n");
}
if (!lock_flag){
- DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, Store Conditional Failed.\n",
+ DPRINTF(LLSC, "[tid:%i]: Lock Flag Set, "
+ "Store Conditional Failed.\n",
req->threadId());
} else if ((req->getPaddr() & ~0xf) != lock_addr) {
- DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, Store Conditional Failed.\n",
+ DPRINTF(LLSC, "[tid:%i]: Load-Link Address Mismatch, "
+ "Store Conditional Failed.\n",
req->threadId());
}
// store conditional failed already, so don't issue it to mem
return true;
}
-
} // namespace MipsISA
#endif
* Steve Reinhardt
*/
-#include "arch/mips/faults.hh"
-#include "arch/mips/isa_traits.hh"
-#include "arch/mips/tlb.hh"
-//#include "base/kgdb.h"
-#include "base/remote_gdb.hh"
-#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
-#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
-#include "kern/kernel_stats.hh"
-#include "sim/debug.hh"
-#include "sim/sim_exit.hh"
-#include "arch/mips/mips_core_specific.hh"
#if FULL_SYSTEM
//
void
MipsISA::initCPU(ThreadContext *tc, int cpuId)
-{
-
- // MipsFault *reset = new ResetFault;
-// tc->setPC(reset->vect());
-// tc->setNextPC(tc->readPC() + sizeof(MachInst));
-
-// delete reset;
-}
+{}
template <class CPU>
void
MipsISA::processInterrupts(CPU *cpu)
-{
- //Check if there are any outstanding interrupts
- //Handle the interrupts
- /* int ipl = 0;
- int summary = 0;
-
- cpu->checkInterrupts = false;
-
- if (cpu->readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (cpu->readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = cpu->intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
- cpu->setMiscReg(IPR_ISR, summary);
- cpu->setMiscReg(IPR_INTID, ipl);
- cpu->trap(new InterruptFault);
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- cpu->readMiscReg(IPR_IPLR), ipl, summary);
- }
- */
-}
+{}
#endif // FULL_SYSTEM || BARE_IRON
namespace MipsISA
{
+
inline Tick
handleIprRead(ThreadContext *xc, Packet *pkt)
{
panic("No implementation for handleIprWrite in MIPS\n");
}
-
} // namespace MipsISA
#endif
namespace MipsISA
{
-
template <class TC>
inline unsigned
getVirtProcNum(TC *tc)
tc->halt();
// Save last known PC in TCRestart
- // @TODO: Needs to check if this is a branch and if so, take previous instruction
+ // @TODO: Needs to check if this is a branch and if so,
+ // take previous instruction
tc->setMiscReg(TCRestart, tc->readNextPC());
- warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(),
- tc->readPC(), tc->readNextPC());
+ warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
+ curTick, tc->threadId(), tc->getCpuPtr()->name(),
+ tc->readPC(), tc->readNextPC());
}
}
IntReg pc = tc->readMiscRegNoEffect(TCRestart);
// TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
- // tc->setPCEvent(pc, pc + 4, pc + 8);
tc->setPC(pc);
tc->setNextPC(pc + 4);
tc->setNextNPC(pc + 8);
tc->activate(0);
- warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->threadId(), tc->getCpuPtr()->name(),
- tc->readPC());
+ warn("%i: Restoring thread %i in %s @ PC %x",
+ curTick, tc->threadId(), tc->getCpuPtr()->name(),
+ tc->readPC());
}
}
namespace MipsISA
{
+void
+PTE::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(Mask);
+ SERIALIZE_SCALAR(VPN);
+ SERIALIZE_SCALAR(asid);
+ SERIALIZE_SCALAR(G);
+ SERIALIZE_SCALAR(PFN0);
+ SERIALIZE_SCALAR(D0);
+ SERIALIZE_SCALAR(V0);
+ SERIALIZE_SCALAR(C0);
+ SERIALIZE_SCALAR(PFN1);
+ SERIALIZE_SCALAR(D1);
+ SERIALIZE_SCALAR(V1);
+ SERIALIZE_SCALAR(C1);
+ SERIALIZE_SCALAR(AddrShiftAmount);
+ SERIALIZE_SCALAR(OffsetMask);
+}
- void
- PTE::serialize(std::ostream &os)
- {
- SERIALIZE_SCALAR(Mask);
- SERIALIZE_SCALAR(VPN);
- SERIALIZE_SCALAR(asid);
- SERIALIZE_SCALAR(G);
- SERIALIZE_SCALAR(PFN0);
- SERIALIZE_SCALAR(D0);
- SERIALIZE_SCALAR(V0);
- SERIALIZE_SCALAR(C0);
- SERIALIZE_SCALAR(PFN1);
- SERIALIZE_SCALAR(D1);
- SERIALIZE_SCALAR(V1);
- SERIALIZE_SCALAR(C1);
- SERIALIZE_SCALAR(AddrShiftAmount);
- SERIALIZE_SCALAR(OffsetMask);
- }
+void
+PTE::unserialize(Checkpoint *cp, const std::string §ion)
+{
+ UNSERIALIZE_SCALAR(Mask);
+ UNSERIALIZE_SCALAR(VPN);
+ UNSERIALIZE_SCALAR(asid);
+ UNSERIALIZE_SCALAR(G);
+ UNSERIALIZE_SCALAR(PFN0);
+ UNSERIALIZE_SCALAR(D0);
+ UNSERIALIZE_SCALAR(V0);
+ UNSERIALIZE_SCALAR(C0);
+ UNSERIALIZE_SCALAR(PFN1);
+ UNSERIALIZE_SCALAR(D1);
+ UNSERIALIZE_SCALAR(V1);
+ UNSERIALIZE_SCALAR(C1);
+ UNSERIALIZE_SCALAR(AddrShiftAmount);
+ UNSERIALIZE_SCALAR(OffsetMask);
+}
- void
- PTE::unserialize(Checkpoint *cp, const std::string §ion)
- {
- UNSERIALIZE_SCALAR(Mask);
- UNSERIALIZE_SCALAR(VPN);
- UNSERIALIZE_SCALAR(asid);
- UNSERIALIZE_SCALAR(G);
- UNSERIALIZE_SCALAR(PFN0);
- UNSERIALIZE_SCALAR(D0);
- UNSERIALIZE_SCALAR(V0);
- UNSERIALIZE_SCALAR(C0);
- UNSERIALIZE_SCALAR(PFN1);
- UNSERIALIZE_SCALAR(D1);
- UNSERIALIZE_SCALAR(V1);
- UNSERIALIZE_SCALAR(C1);
- UNSERIALIZE_SCALAR(AddrShiftAmount);
- UNSERIALIZE_SCALAR(OffsetMask);
- }
}
namespace MipsISA {
- struct VAddr
- {
- static const int ImplBits = 43;
- static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
- static const Addr UnImplMask = ~ImplMask;
+struct VAddr
+{
+ static const int ImplBits = 43;
+ static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
+ static const Addr UnImplMask = ~ImplMask;
- VAddr(Addr a) : addr(a) {}
- Addr addr;
- operator Addr() const { return addr; }
- const VAddr &operator=(Addr a) { addr = a; return *this; }
+ VAddr(Addr a) : addr(a) {}
+ Addr addr;
+ operator Addr() const { return addr; }
+ const VAddr &operator=(Addr a) { addr = a; return *this; }
- Addr vpn() const { return (addr & ImplMask) >> PageShift; }
- Addr page() const { return addr & Page_Mask; }
- Addr offset() const { return addr & PageOffset; }
+ Addr vpn() const { return (addr & ImplMask) >> PageShift; }
+ Addr page() const { return addr & Page_Mask; }
+ Addr offset() const { return addr & PageOffset; }
- Addr level3() const
- { return MipsISA::PteAddr(addr >> PageShift); }
- Addr level2() const
- { return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
- Addr level1() const
- { return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
- };
+ Addr level3() const
+ { return MipsISA::PteAddr(addr >> PageShift); }
+ Addr level2() const
+ { return MipsISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
+ Addr level1() const
+ { return MipsISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
+};
- // ITB/DTB page table entry
- struct PTE
- {
- Addr Mask; // What parts of the VAddr (from bits 28..11) should be used in translation (includes Mask and MaskX from PageMask)
- Addr VPN; // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 from EntryHi)
- uint8_t asid; // Address Space ID (8 bits) // Lower 8 bits of EntryHi
+// ITB/DTB page table entry
+struct PTE
+{
+ Addr Mask;
+ Addr VPN;
+ uint8_t asid;
- bool G; // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit
+ bool G;
- /* Contents of Entry Lo0 */
- Addr PFN0; // Physical Frame Number - Even
- bool D0; // Even entry Dirty Bit
- bool V0; // Even entry Valid Bit
- uint8_t C0; // Cache Coherency Bits - Even
+ /* Contents of Entry Lo0 */
+ Addr PFN0; // Physical Frame Number - Even
+ bool D0; // Even entry Dirty Bit
+ bool V0; // Even entry Valid Bit
+ uint8_t C0; // Cache Coherency Bits - Even
- /* Contents of Entry Lo1 */
- Addr PFN1; // Physical Frame Number - Odd
- bool D1; // Odd entry Dirty Bit
- bool V1; // Odd entry Valid Bit
- uint8_t C1; // Cache Coherency Bits (3 bits)
+ /* Contents of Entry Lo1 */
+ Addr PFN1; // Physical Frame Number - Odd
+ bool D1; // Odd entry Dirty Bit
+ bool V1; // Odd entry Valid Bit
+ uint8_t C1; // Cache Coherency Bits (3 bits)
- /* The next few variables are put in as optimizations to reduce TLB lookup overheads */
- /* For a given Mask, what is the address shift amount, and what is the OffsetMask */
- int AddrShiftAmount;
- int OffsetMask;
+ /*
+ * The next few variables are put in as optimizations to reduce
+ * TLB lookup overheads. For a given Mask, what is the address shift
+ * amount, and what is the OffsetMask
+ */
+ int AddrShiftAmount;
+ int OffsetMask;
- bool Valid() { return (V0 | V1);};
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string §ion);
- };
+ bool Valid() { return (V0 | V1); };
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string §ion);
+};
};
#endif // __ARCH_MIPS_PAGETABLE_H__
namespace MipsISA
{
- class Predecoder
+
+class Predecoder
+{
+ protected:
+ ThreadContext * tc;
+ //The extended machine instruction being generated
+ ExtMachInst emi;
+
+ public:
+ Predecoder(ThreadContext * _tc) : tc(_tc)
+ {}
+
+ ThreadContext *getTC()
+ {
+ return tc;
+ }
+
+ void
+ setTC(ThreadContext *_tc)
+ {
+ tc = _tc;
+ }
+
+ void
+ process()
{
- protected:
- ThreadContext * tc;
- //The extended machine instruction being generated
- ExtMachInst emi;
-
- public:
- Predecoder(ThreadContext * _tc) : tc(_tc)
- {}
-
- ThreadContext * getTC()
- {
- return tc;
- }
-
- void setTC(ThreadContext * _tc)
- {
- tc = _tc;
- }
-
- void process()
- {
- }
-
- void reset()
- {}
-
- //Use this to give data to the predecoder. This should be used
- //when there is control flow.
- void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
- {
- emi = inst;
- }
-
- bool needMoreBytes()
- {
- return true;
- }
-
- bool extMachInstReady()
- {
- return true;
- }
-
- //This returns a constant reference to the ExtMachInst to avoid a copy
- const ExtMachInst & getExtMachInst()
- {
- return emi;
- }
- };
+ }
+
+ void
+ reset()
+ {}
+
+ //Use this to give data to the predecoder. This should be used
+ //when there is control flow.
+ void
+ moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+ {
+ emi = inst;
+ }
+
+ bool
+ needMoreBytes()
+ {
+ return true;
+ }
+
+ bool
+ extMachInstReady()
+ {
+ return true;
+ }
+
+ //This returns a constant reference to the ExtMachInst to avoid a copy
+ const ExtMachInst &
+ getExtMachInst()
+ {
+ return emi;
+ }
+};
+
};
#endif // __ARCH_MIPS_PREDECODER_HH__
using namespace std;
using namespace MipsISA;
-ProcessInfo::ProcessInfo(ThreadContext *_tc)
- : tc(_tc)
-{
-// Addr addr = 0;
-
- VirtualPort *vp;
-
- vp = tc->getVirtPort();
-
-// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
-// panic("thread info not compiled into kernel\n");
-// thread_info_size = vp->readGtoH<int32_t>(addr);
-
-// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
-// panic("thread info not compiled into kernel\n");
-// task_struct_size = vp->readGtoH<int32_t>(addr);
-
-// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
-// panic("thread info not compiled into kernel\n");
-// task_off = vp->readGtoH<int32_t>(addr);
-
-// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
-// panic("thread info not compiled into kernel\n");
-// pid_off = vp->readGtoH<int32_t>(addr);
-
-// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
-// panic("thread info not compiled into kernel\n");
-// name_off = vp->readGtoH<int32_t>(addr);
-}
+ProcessInfo::ProcessInfo(ThreadContext *_tc) : tc(_tc)
+{}
Addr
ProcessInfo::task(Addr ksp) const
StackTrace::trace(ThreadContext *_tc, bool is_call)
{
tc = _tc;
- /* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */
bool usermode = 0;
- //(tc->readMiscReg(MipsISA::IPR_DTB_CM) & 0x18) != 0;
-
-// Addr pc = tc->readNextPC();
-// bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
-// pc <= tc->getSystemPtr()->kernelEnd;
if (usermode) {
stack.push_back(user);
return;
}
-
-// if (!kernel) {
-// stack.push_back(console);
-// return;
-// }
-
-// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
-// Addr ksp = tc->readIntReg(MipsISA::StackPointerReg);
-// Addr bottom = ksp & ~0x3fff;
-// Addr addr;
-
-// if (is_call) {
-// if (!symtab->findNearestAddr(pc, addr))
-// panic("could not find address %#x", pc);
-
-// stack.push_back(addr);
-// pc = tc->readPC();
-// }
-
-// Addr ra;
-// int size;
-
-// while (ksp > bottom) {
-// if (!symtab->findNearestAddr(pc, addr))
-// panic("could not find symbol for pc=%#x", pc);
-// assert(pc >= addr && "symbol botch: callpc < func");
-
-// stack.push_back(addr);
-
-// if (isEntry(addr))
-// return;
-
-// if (decodePrologue(ksp, pc, addr, size, ra)) {
-// if (!ra)
-// return;
-
-// if (size <= 0) {
-// stack.push_back(unknown);
-// return;
-// }
-
-// pc = ra;
-// ksp += size;
-// } else {
-// stack.push_back(unknown);
-// return;
-// }
-
-// bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
-// pc <= tc->getSystemPtr()->kernelEnd;
-// if (!kernel)
-// return;
-
-// if (stack.size() >= 1000)
-// panic("unwinding too far");
-// }
-
-// panic("unwinding too far");
}
bool
StackTrace::isEntry(Addr addr)
{
- /* if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2))
- return true;*/
-
return false;
}
int reg, disp;
if (decodeStack(inst, disp)) {
if (size) {
- // panic("decoding frame size again");
return true;
}
size += disp;
if (!ra && reg == ReturnAddressReg) {
CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
if (!ra) {
- // panic("no return address value pc=%#x\n", pc);
return false;
}
}
void
StackTrace::dump()
{
- StringWrap name(tc->getCpuPtr()->name());
-// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
-
- DPRINTFN("------ Stack ------\n");
-
-// string symbol;
-// for (int i = 0, size = stack.size(); i < size; ++i) {
-// Addr addr = stack[size - i - 1];
-// if (addr == user)
-// symbol = "user";
-// else if (addr == console)
-// symbol = "console";
-// else if (addr == unknown)
-// symbol = "unknown";
-// else
-// symtab->findSymbol(addr, symbol);
-
-// DPRINTFN("%#x: %s\n", addr, symbol);
-// }
+ panic("Stack trace dump not implemented.\n");
}
#endif
using namespace LittleEndianGuest;
-MipsSystem::MipsSystem(Params *p)
- : System(p)
+MipsSystem::MipsSystem(Params *p) : System(p)
{
#if FULL_SYSTEM
if (p->bare_iron == true) {
hexFile = new HexFile(params()->hex_file_name);
- if(!hexFile->loadSections(&functionalPort,MipsISA::LoadAddrMask))
+ if (!hexFile->loadSections(&functionalPort, MipsISA::LoadAddrMask))
panic("Could not load hex file\n");
}
Addr addr = 0;
- /* Comment out old Alpha Based Code
-
- Don't need the console before we start looking at booting linux */
-
consoleSymtab = new SymbolTable;
if (console == NULL)
fatal("Could not load console file %s", params()->console);
//Load program sections into memory
- console->loadSections(&functionalPort, MipsISA::LoadAddrMask);
+ console->loadSections(&functionalPort, MipsISA::LoadAddrMask);
//load symbols
if (!console->loadGlobalSymbols(consoleSymtab))
if (consoleSymtab->findAddress("m5_rpb", addr)) {
uint64_t data;
data = htog(params()->system_type);
- virtPort.write(addr+0x50, data);
+ virtPort.write(addr + 0x50, data);
data = htog(params()->system_rev);
- virtPort.write(addr+0x58, data);
- } else
+ virtPort.write(addr + 0x58, data);
+ } else {
panic("could not find hwrpb\n");
+ }
#endif
}
MipsSystem::~MipsSystem()
{
}
-#if FULL_SYSTEM
-/**
- * This function fixes up addresses that are used to match PCs for
- * hooking simulator events on to target function executions.
- *
- * Mips binaries may have multiple global offset table (GOT)
- * sections. A function that uses the GOT starts with a
- * two-instruction prolog which sets the global pointer (gp == r29) to
- * the appropriate GOT section. The proper gp value is calculated
- * based on the function address, which must be passed by the caller
- * in the procedure value register (pv aka t12 == r27). This sequence
- * looks like the following:
- *
- * opcode Ra Rb offset
- * ldah gp,X(pv) 09 29 27 X
- * lda gp,Y(gp) 08 29 29 Y
- *
- * for some constant offsets X and Y. The catch is that the linker
- * (or maybe even the compiler, I'm not sure) may recognize that the
- * caller and callee are using the same GOT section, making this
- * prolog redundant, and modify the call target to skip these
- * instructions. If we check for execution of the first instruction
- * of a function (the one the symbol points to) to detect when to skip
- * it, we'll miss all these modified calls. It might work to
- * unconditionally check for the third instruction, but not all
- * functions have this prolog, and there's some chance that those
- * first two instructions could have undesired consequences. So we do
- * the Right Thing and pattern-match the first two instructions of the
- * function to decide where to patch.
- *
- * Eventually this code should be moved into an ISA-specific file.
- */
+#if FULL_SYSTEM
Addr
MipsSystem::fixFuncEventAddr(Addr addr)
{
- /*
- // mask for just the opcode, Ra, and Rb fields (not the offset)
- const uint32_t inst_mask = 0xffff0000;
- // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
- const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
- // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
- const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
-
- uint32_t i1 = virtPort.read<uint32_t>(addr);
- uint32_t i2 = virtPort.read<uint32_t>(addr + sizeof(MipsISA::MachInst));
-
- if ((i1 & inst_mask) == gp_ldah_pattern &&
- (i2 & inst_mask) == gp_lda_pattern) {
- Addr new_addr = addr + 2* sizeof(MipsISA::MachInst);
- DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
- return new_addr;
- } else {
- return addr;
- }*/
- return addr;
+ return addr;
}
-
void
MipsSystem::setMipsAccess(Addr access)
-{
- Addr addr = 0;
- if (consoleSymtab->findAddress("m5MipsAccess", addr)) {
- // virtPort.write(addr, htog(AlphaISA::Phys2K0Seg(access)));
- } else
- panic("could not find m5MipsAccess\n");
- }
+{}
#endif
bool
MipsSystem::breakpoint()
{
- return 0;
- // return remoteGDB[0]->trap(MIPS_KENTRY_INT);
+ return 0;
}
void
MipsSystem::serialize(std::ostream &os)
{
System::serialize(os);
- // consoleSymtab->serialize("console_symtab", os);
}
MipsSystem::unserialize(Checkpoint *cp, const std::string §ion)
{
System::unserialize(cp,section);
- // consoleSymtab->unserialize("console_symtab", cp, section);
}
MipsSystem *
virtual bool breakpoint();
-/**
- * Serialization stuff
- */
public:
+ /**
+ * Serialization stuff
+ */
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string §ion);
#if FULL_SYSTEM
/** Add a function-based event to the console code. */
template <class T>
- T *addConsoleFuncEvent(const char *lbl)
+ T *
+ addConsoleFuncEvent(const char *lbl)
{
return addFuncEvent<T>(consoleSymtab, lbl);
}
// MIPS TLB
//
-#define MODE2MASK(X) (1 << (X))
-
static inline mode_type
getOperatingMode(MiscReg Stat)
{
- if((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
+ if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
return mode_kernel;
- } else if((Stat & 0x18) == 0x8) {
+ } else if ((Stat & 0x18) == 0x8) {
return mode_supervisor;
- } else if((Stat & 0x18) == 0x10) {
+ } else if ((Stat & 0x18) == 0x10) {
return mode_user;
} else {
return mode_number;
TLB::TLB(const Params *p)
: BaseTLB(p), size(p->size), nlu(0)
{
- table = new MipsISA::PTE[size];
- memset(table, 0, sizeof(MipsISA::PTE[size]));
- smallPages=0;
+ table = new PTE[size];
+ memset(table, 0, sizeof(PTE[size]));
+ smallPages = 0;
}
TLB::~TLB()
TLB::lookup(Addr vpn, uint8_t asn) const
{
// assume not found...
- MipsISA::PTE *retval = NULL;
+ PTE *retval = NULL;
PageTable::const_iterator i = lookupTable.find(vpn);
if (i != lookupTable.end()) {
while (i->first == vpn) {
int index = i->second;
- MipsISA::PTE *pte = &table[index];
+ PTE *pte = &table[index];
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
Addr Mask = pte->Mask;
Addr InvMask = ~Mask;
Addr VPN = pte->VPN;
- // warn("Valid: %d - %d\n",pte->V0,pte->V1);
- if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
- { // We have a VPN + ASID Match
+ if (((vpn & InvMask) == (VPN & InvMask)) &&
+ (pte->G || (asn == pte->asid))) {
+ // We have a VPN + ASID Match
retval = pte;
break;
- }
+ }
++i;
}
}
return retval;
}
-MipsISA::PTE* TLB::getEntry(unsigned Index) const
+MipsISA::PTE*
+TLB::getEntry(unsigned Index) const
{
// Make sure that Index is valid
assert(Index<size);
return &table[Index];
}
-int TLB::probeEntry(Addr vpn,uint8_t asn) const
+int
+TLB::probeEntry(Addr vpn, uint8_t asn) const
{
// assume not found...
- MipsISA::PTE *retval = NULL;
- int Ind=-1;
+ PTE *retval = NULL;
+ int Ind = -1;
PageTable::const_iterator i = lookupTable.find(vpn);
if (i != lookupTable.end()) {
while (i->first == vpn) {
int index = i->second;
- MipsISA::PTE *pte = &table[index];
+ PTE *pte = &table[index];
/* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
Addr Mask = pte->Mask;
Addr InvMask = ~Mask;
- Addr VPN = pte->VPN;
- if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
- { // We have a VPN + ASID Match
+ Addr VPN = pte->VPN;
+ if (((vpn & InvMask) == (VPN & InvMask)) &&
+ (pte->G || (asn == pte->asid))) {
+ // We have a VPN + ASID Match
retval = pte;
Ind = index;
break;
- }
-
+ }
++i;
}
}
DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
return Ind;
}
-Fault inline
+
+inline Fault
TLB::checkCacheability(RequestPtr &req)
{
- Addr VAddrUncacheable = 0xA0000000;
- // In MIPS, cacheability is controlled by certain bits of the virtual address
- // or by the TLB entry
- if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
- // mark request as uncacheable
- req->setFlags(Request::UNCACHEABLE);
- }
- return NoFault;
-}
-void TLB::insertAt(MipsISA::PTE &pte, unsigned Index, int _smallPages)
-{
- smallPages=_smallPages;
- if(Index > size){
- warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size);
- } else {
- // Update TLB
- DPRINTF(TLB,"TLB[%d]: %x %x %x %x\n",Index,pte.Mask<<11,((pte.VPN << 11) | pte.asid),((pte.PFN0 <<6) | (pte.C0 << 3) | (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
- ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
- if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid
- PageTable::iterator i = lookupTable.find(table[Index].VPN);
- lookupTable.erase(i);
+ Addr VAddrUncacheable = 0xA0000000;
+ // In MIPS, cacheability is controlled by certain bits of the virtual
+ // address or by the TLB entry
+ if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
+ // mark request as uncacheable
+ req->setFlags(Request::UNCACHEABLE);
}
- table[Index]=pte;
- // Update fast lookup table
- lookupTable.insert(make_pair(table[Index].VPN, Index));
- // int TestIndex=probeEntry(pte.VPN,pte.asid);
- // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
- }
-
+ return NoFault;
}
-// insert a new TLB entry
void
-TLB::insert(Addr addr, MipsISA::PTE &pte)
+TLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
{
- fatal("TLB Insert not yet implemented\n");
-
-
- /* MipsISA::VAddr vaddr = addr;
- if (table[nlu].valid) {
- Addr oldvpn = table[nlu].tag;
- PageTable::iterator i = lookupTable.find(oldvpn);
-
- if (i == lookupTable.end())
- panic("TLB entry not found in lookupTable");
-
- int index;
- while ((index = i->second) != nlu) {
- if (table[index].tag != oldvpn)
- panic("TLB entry not found in lookupTable");
-
- ++i;
+ smallPages = _smallPages;
+ if (Index > size) {
+ warn("Attempted to write at index (%d) beyond TLB size (%d)",
+ Index, size);
+ } else {
+ // Update TLB
+ DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
+ Index, pte.Mask << 11,
+ ((pte.VPN << 11) | pte.asid),
+ ((pte.PFN0 << 6) | (pte.C0 << 3) |
+ (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
+ ((pte.PFN1 <<6) | (pte.C1 << 3) |
+ (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
+ if (table[Index].V0 == true || table[Index].V1 == true) {
+ // Previous entry is valid
+ PageTable::iterator i = lookupTable.find(table[Index].VPN);
+ lookupTable.erase(i);
}
-
- DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
-
- lookupTable.erase(i);
+ table[Index]=pte;
+ // Update fast lookup table
+ lookupTable.insert(make_pair(table[Index].VPN, Index));
}
+}
- DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
-
- table[nlu] = pte;
- table[nlu].tag = vaddr.vpn();
- table[nlu].valid = true;
-
- lookupTable.insert(make_pair(vaddr.vpn(), nlu));
- nextnlu();
- */
+// insert a new TLB entry
+void
+TLB::insert(Addr addr, PTE &pte)
+{
+ fatal("TLB Insert not yet implemented\n");
}
void
TLB::flushAll()
{
DPRINTF(TLB, "flushAll\n");
- memset(table, 0, sizeof(MipsISA::PTE[size]));
+ memset(table, 0, sizeof(PTE[size]));
lookupTable.clear();
nlu = 0;
}
Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req);
- if(fault != NoFault)
+ if (fault != NoFault)
return fault;
return NoFault;
#else
- if(MipsISA::IsKSeg0(req->getVaddr()))
- {
- // Address will not be translated through TLB, set response, and go!
- req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
- if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
- {
- AddressErrorFault *Flt = new AddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
- return Flt;
+ if (IsKSeg0(req->getVaddr())) {
+ // Address will not be translated through TLB, set response, and go!
+ req->setPaddr(KSeg02Phys(req->getVaddr()));
+ if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
+ req->isMisaligned()) {
+ AddressErrorFault *Flt = new AddressErrorFault();
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+ return Flt;
}
- }
- else if(MipsISA::IsKSeg1(req->getVaddr()))
- {
- // Address will not be translated through TLB, set response, and go!
- req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
- }
- else
- {
- /* This is an optimization - smallPages is updated every time a TLB operation is performed
- That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
- do a TLB lookup */
+ } else if(IsKSeg1(req->getVaddr())) {
+ // Address will not be translated through TLB, set response, and go!
+ req->setPaddr(KSeg02Phys(req->getVaddr()));
+ } else {
+ /*
+ * This is an optimization - smallPages is updated every time a TLB
+ * operation is performed. That way, we don't need to look at
+ * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
+ */
Addr VPN;
- if(smallPages==1){
- VPN=((req->getVaddr() >> 11));
+ if (smallPages == 1) {
+ VPN = ((req->getVaddr() >> 11));
} else {
- VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
+ VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
}
uint8_t Asid = req->getAsid();
- if(req->isMisaligned()){ // Unaligned address!
- AddressErrorFault *Flt = new AddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
- return Flt;
+ if (req->isMisaligned()) {
+ // Unaligned address!
+ AddressErrorFault *Flt = new AddressErrorFault();
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+ return Flt;
}
- MipsISA::PTE *pte = lookup(VPN,Asid);
- if(pte != NULL)
- {// Ok, found something
+ PTE *pte = lookup(VPN,Asid);
+ if (pte != NULL) {
+ // Ok, found something
/* Check for valid bits */
int EvenOdd;
bool Valid;
- if((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) ==0){
- // Check even bits
- Valid = pte->V0;
- EvenOdd = 0;
+ if ((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) == 0) {
+ // Check even bits
+ Valid = pte->V0;
+ EvenOdd = 0;
} else {
- // Check odd bits
- Valid = pte->V1;
- EvenOdd = 1;
+ // Check odd bits
+ Valid = pte->V1;
+ EvenOdd = 1;
}
- if(Valid == false)
- {//Invalid entry
+ if (Valid == false) {
+ //Invalid entry
ItbInvalidFault *Flt = new ItbInvalidFault();
/* EntryHi VPN, ASID fields must be set */
Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN>>2);
+ Flt->EntryHi_VPN2 = (VPN >> 2);
Flt->EntryHi_VPN2X = (VPN & 0x3);
/* BadVAddr must be set */
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
- }
- else
- {// Ok, this is really a match, set paddr
- // hits++;
+ } else {
+ // Ok, this is really a match, set paddr
Addr PAddr;
- if(EvenOdd == 0){
+ if (EvenOdd == 0) {
PAddr = pte->PFN0;
- }else{
+ } else {
PAddr = pte->PFN1;
}
- PAddr >>= (pte->AddrShiftAmount-12);
+ PAddr >>= (pte->AddrShiftAmount - 12);
PAddr <<= pte->AddrShiftAmount;
PAddr |= ((req->getVaddr()) & pte->OffsetMask);
req->setPaddr(PAddr);
-
-
}
- }
- else
- { // Didn't find any match, return a TLB Refill Exception
- // misses++;
- ItbRefillFault *Flt=new ItbRefillFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN>>2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
- return Flt;
+ } else {
+ // Didn't find any match, return a TLB Refill Exception
+ ItbRefillFault *Flt=new ItbRefillFault();
+ /* EntryHi VPN, ASID fields must be set */
+ Flt->EntryHi_Asid = Asid;
+ Flt->EntryHi_VPN2 = (VPN >> 2);
+ Flt->EntryHi_VPN2X = (VPN & 0x3);
+
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+
+ /* Context must be set */
+ Flt->Context_BadVPN2 = (VPN >> 2);
+ return Flt;
}
}
- return checkCacheability(req);
+ return checkCacheability(req);
#endif
}
Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req);
- if(fault != NoFault)
+ if (fault != NoFault)
return fault;
return NoFault;
#else
- if(MipsISA::IsKSeg0(req->getVaddr()))
- {
- // Address will not be translated through TLB, set response, and go!
- req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
- if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
- {
- StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- return Flt;
+ if (IsKSeg0(req->getVaddr())) {
+ // Address will not be translated through TLB, set response, and go!
+ req->setPaddr(KSeg02Phys(req->getVaddr()));
+ if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
+ req->isMisaligned()) {
+ StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+
+ return Flt;
}
- }
- else if(MipsISA::IsKSeg1(req->getVaddr()))
- {
+ } else if(IsKSeg1(req->getVaddr())) {
// Address will not be translated through TLB, set response, and go!
- req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
- }
- else
- {
- /* This is an optimization - smallPages is updated every time a TLB operation is performed
- That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
- do a TLB lookup */
- Addr VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
- if(smallPages==1){
- VPN=((req->getVaddr() >> 11));
- }
- uint8_t Asid = req->getAsid();
- MipsISA::PTE *pte = lookup(VPN,Asid);
- if(req->isMisaligned()){ // Unaligned address!
- StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
- return Flt;
- }
- if(pte != NULL)
- {// Ok, found something
- /* Check for valid bits */
- int EvenOdd;
- bool Valid;
- bool Dirty;
- if(((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) ==0){
- // Check even bits
- Valid = pte->V0;
- Dirty = pte->D0;
- EvenOdd = 0;
-
- } else {
- // Check odd bits
- Valid = pte->V1;
- Dirty = pte->D1;
- EvenOdd = 1;
- }
-
- if(Valid == false)
- {//Invalid entry
- // invalids++;
- DtbInvalidFault *Flt = new DtbInvalidFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN>>2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
-
- return Flt;
+ req->setPaddr(KSeg02Phys(req->getVaddr()));
+ } else {
+ /*
+ * This is an optimization - smallPages is updated every time a TLB
+ * operation is performed. That way, we don't need to look at
+ * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
+ */
+ Addr VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
+ if (smallPages == 1) {
+ VPN = ((req->getVaddr() >> 11));
+ }
+ uint8_t Asid = req->getAsid();
+ PTE *pte = lookup(VPN, Asid);
+ if (req->isMisaligned()) {
+ // Unaligned address!
+ StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+ return Flt;
+ }
+ if (pte != NULL) {
+ // Ok, found something
+ /* Check for valid bits */
+ int EvenOdd;
+ bool Valid;
+ bool Dirty;
+ if (((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) == 0) {
+ // Check even bits
+ Valid = pte->V0;
+ Dirty = pte->D0;
+ EvenOdd = 0;
+ } else {
+ // Check odd bits
+ Valid = pte->V1;
+ Dirty = pte->D1;
+ EvenOdd = 1;
}
- else
- {// Ok, this is really a match, set paddr
- // hits++;
- if(!Dirty)
- {
- TLBModifiedFault *Flt = new TLBModifiedFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN>>2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
- return Flt;
+ if (Valid == false) {
+ //Invalid entry
+ DtbInvalidFault *Flt = new DtbInvalidFault();
+ /* EntryHi VPN, ASID fields must be set */
+ Flt->EntryHi_Asid = Asid;
+ Flt->EntryHi_VPN2 = (VPN>>2);
+ Flt->EntryHi_VPN2X = (VPN & 0x3);
+
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+
+ /* Context must be set */
+ Flt->Context_BadVPN2 = (VPN >> 2);
+
+ return Flt;
+ } else {
+ // Ok, this is really a match, set paddr
+ if (!Dirty) {
+ TLBModifiedFault *Flt = new TLBModifiedFault();
+ /* EntryHi VPN, ASID fields must be set */
+ Flt->EntryHi_Asid = Asid;
+ Flt->EntryHi_VPN2 = (VPN >> 2);
+ Flt->EntryHi_VPN2X = (VPN & 0x3);
+
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+
+ /* Context must be set */
+ Flt->Context_BadVPN2 = (VPN >> 2);
+ return Flt;
}
- Addr PAddr;
- if(EvenOdd == 0){
- PAddr = pte->PFN0;
- }else{
- PAddr = pte->PFN1;
- }
- PAddr >>= (pte->AddrShiftAmount-12);
- PAddr <<= pte->AddrShiftAmount;
- PAddr |= ((req->getVaddr()) & pte->OffsetMask);
- req->setPaddr(PAddr);
+ Addr PAddr;
+ if (EvenOdd == 0) {
+ PAddr = pte->PFN0;
+ } else {
+ PAddr = pte->PFN1;
+ }
+ PAddr >>= (pte->AddrShiftAmount - 12);
+ PAddr <<= pte->AddrShiftAmount;
+ PAddr |= ((req->getVaddr()) & pte->OffsetMask);
+ req->setPaddr(PAddr);
}
- }
- else
- { // Didn't find any match, return a TLB Refill Exception
- // misses++;
- DtbRefillFault *Flt=new DtbRefillFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN>>2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
- return Flt;
+ } else {
+ // Didn't find any match, return a TLB Refill Exception
+ DtbRefillFault *Flt = new DtbRefillFault();
+ /* EntryHi VPN, ASID fields must be set */
+ Flt->EntryHi_Asid = Asid;
+ Flt->EntryHi_VPN2 = (VPN >> 2);
+ Flt->EntryHi_VPN2X = (VPN & 0x3);
+
+ /* BadVAddr must be set */
+ Flt->BadVAddr = req->getVaddr();
+
+ /* Context must be set */
+ Flt->Context_BadVPN2 = (VPN >> 2);
+ return Flt;
}
}
return checkCacheability(req);
MipsISA::PTE &
TLB::index(bool advance)
{
- MipsISA::PTE *pte = &table[nlu];
+ PTE *pte = &table[nlu];
if (advance)
nextnlu();
MipsISA::TLB *
MipsTLBParams::create()
{
- return new MipsISA::TLB(this);
+ return new TLB(this);
}
namespace MipsISA
{
- typedef uint32_t MachInst;
- typedef uint64_t ExtMachInst;
-
- typedef uint64_t LargestRead;
-
- //used in FP convert & round function
- enum ConvertType{
- SINGLE_TO_DOUBLE,
- SINGLE_TO_WORD,
- SINGLE_TO_LONG,
-
- DOUBLE_TO_SINGLE,
- DOUBLE_TO_WORD,
- DOUBLE_TO_LONG,
-
- LONG_TO_SINGLE,
- LONG_TO_DOUBLE,
- LONG_TO_WORD,
- LONG_TO_PS,
-
- WORD_TO_SINGLE,
- WORD_TO_DOUBLE,
- WORD_TO_LONG,
- WORD_TO_PS,
-
- PL_TO_SINGLE,
- PU_TO_SINGLE
- };
-
- //used in FP convert & round function
- enum RoundMode{
- RND_ZERO,
- RND_DOWN,
- RND_UP,
- RND_NEAREST
- };
+
+typedef uint32_t MachInst;
+typedef uint64_t ExtMachInst;
+
+typedef uint64_t LargestRead;
+
+//used in FP convert & round function
+enum ConvertType{
+ SINGLE_TO_DOUBLE,
+ SINGLE_TO_WORD,
+ SINGLE_TO_LONG,
+
+ DOUBLE_TO_SINGLE,
+ DOUBLE_TO_WORD,
+ DOUBLE_TO_LONG,
+
+ LONG_TO_SINGLE,
+ LONG_TO_DOUBLE,
+ LONG_TO_WORD,
+ LONG_TO_PS,
+
+ WORD_TO_SINGLE,
+ WORD_TO_DOUBLE,
+ WORD_TO_LONG,
+ WORD_TO_PS,
+
+ PL_TO_SINGLE,
+ PU_TO_SINGLE
+};
+
+//used in FP convert & round function
+enum RoundMode{
+ RND_ZERO,
+ RND_DOWN,
+ RND_UP,
+ RND_NEAREST
+};
struct CoreSpecific {
/* Note: It looks like it will be better to allow simulator users
-jpp
*/
// MIPS CP0 State - First individual variables
- // Page numbers refer to revision 2.50 (July 2005) of the MIPS32 ARM, Volume III (PRA)
+ // Page numbers refer to revision 2.50 (July 2005) of the MIPS32 ARM,
+ // Volume III (PRA)
unsigned CP0_IntCtl_IPTI; // Page 93, IP Timer Interrupt
unsigned CP0_IntCtl_IPPCI; // Page 94, IP Performance Counter Interrupt
unsigned CP0_SrsCtl_HSS; // Page 95, Highest Implemented Shadow Set
unsigned CP0_PRId_CompanyID; // Page 105, Company ID - (0-255, 1=>MIPS)
unsigned CP0_PRId_ProcessorID; // Page 105
unsigned CP0_PRId_Revision; // Page 105
- unsigned CP0_EBase_CPUNum; // Page 106, CPU Number in a multiprocessor system
+ unsigned CP0_EBase_CPUNum; // Page 106, CPU Number in a multiprocessor
+ //system
unsigned CP0_Config_BE; // Page 108, Big/Little Endian mode
unsigned CP0_Config_AT; //Page 109
unsigned CP0_Config_AR; //Page 109
namespace MipsISA {
- uint64_t getArgument(ThreadContext *tc, int number, bool fp);
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Floating Point Utility Functions
- //
- uint64_t fpConvert(ConvertType cvt_type, double fp_val);
- double roundFP(double val, int digits);
- double truncFP(double val);
-
- bool getCondCode(uint32_t fcsr, int cc);
- uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
- uint32_t genInvalidVector(uint32_t fcsr);
-
- bool isNan(void *val_ptr, int size);
- bool isQnan(void *val_ptr, int size);
- bool isSnan(void *val_ptr, int size);
-
- static inline bool
- inUserMode(ThreadContext *tc)
- {
- MiscReg Stat = tc->readMiscReg(MipsISA::Status);
- MiscReg Dbg = tc->readMiscReg(MipsISA::Debug);
-
- if((Stat & 0x10000006) == 0 // EXL, ERL or CU0 set, CP0 accessible
- && (Dbg & 0x40000000) == 0 // DM bit set, CP0 accessible
- && (Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode
- // Unable to use Status_CU0, etc directly, using bitfields & masks
- return true;
- } else {
- return false;
- }
+uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+
+////////////////////////////////////////////////////////////////////////
+//
+// Floating Point Utility Functions
+//
+uint64_t fpConvert(ConvertType cvt_type, double fp_val);
+double roundFP(double val, int digits);
+double truncFP(double val);
+
+bool getCondCode(uint32_t fcsr, int cc);
+uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
+uint32_t genInvalidVector(uint32_t fcsr);
+
+bool isNan(void *val_ptr, int size);
+bool isQnan(void *val_ptr, int size);
+bool isSnan(void *val_ptr, int size);
+
+static inline bool
+inUserMode(ThreadContext *tc)
+{
+ MiscReg Stat = tc->readMiscReg(MipsISA::Status);
+ MiscReg Dbg = tc->readMiscReg(MipsISA::Debug);
+
+ if ((Stat & 0x10000006) == 0 && // EXL, ERL or CU0 set, CP0 accessible
+ (Dbg & 0x40000000) == 0 && // DM bit set, CP0 accessible
+ (Stat & 0x00000018) != 0) { // KSU = 0, kernel mode is base mode
+ // Unable to use Status_CU0, etc directly, using bitfields & masks
+ return true;
+ } else {
+ return false;
}
+}
+
+// Instruction address compression hooks
+static inline Addr realPCToFetchPC(const Addr &addr) {
+ return addr;
+}
+
+static inline Addr fetchPCToRealPC(const Addr &addr) {
+ return addr;
+}
+
+// the size of "fetched" instructions (not necessarily the size
+// of real instructions for PISA)
+static inline size_t fetchInstSize() {
+ return sizeof(MachInst);
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+// Register File Utility Functions
+//
+static inline MachInst makeRegisterCopy(int dest, int src) {
+ panic("makeRegisterCopy not implemented");
+ return 0;
+}
+
+template <class CPU>
+void zeroRegisters(CPU *cpu);
+
+////////////////////////////////////////////////////////////////////////
+//
+// Translation stuff
+//
+inline Addr
+TruncPage(Addr addr)
+{ return addr & ~(PageBytes - 1); }
+
+inline Addr
+RoundPage(Addr addr)
+{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
+
+////////////////////////////////////////////////////////////////////////
+//
+// CPU Utility
+//
+void startupCPU(ThreadContext *tc, int cpuId);
+
+void copyRegs(ThreadContext *src, ThreadContext *dest);
+void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
- // Instruction address compression hooks
- static inline Addr realPCToFetchPC(const Addr &addr) {
- return addr;
- }
-
- static inline Addr fetchPCToRealPC(const Addr &addr) {
- return addr;
- }
-
- // the size of "fetched" instructions (not necessarily the size
- // of real instructions for PISA)
- static inline size_t fetchInstSize() {
- return sizeof(MachInst);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Register File Utility Functions
- //
- static inline MachInst makeRegisterCopy(int dest, int src) {
- panic("makeRegisterCopy not implemented");
- return 0;
- }
-
- template <class CPU>
- void zeroRegisters(CPU *cpu);
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Translation stuff
- //
- inline Addr
- TruncPage(Addr addr)
- { return addr & ~(PageBytes - 1); }
-
- inline Addr
- RoundPage(Addr addr)
- { return (addr + PageBytes - 1) & ~(PageBytes - 1); }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // CPU Utility
- //
- void startupCPU(ThreadContext *tc, int cpuId);
-
- void copyRegs(ThreadContext *src, ThreadContext *dest);
- void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
};
else if(MipsISA::IsKSeg1(vaddr))
paddr = MipsISA::KSeg12Phys(vaddr);
else
- panic("vtophys: ptbr is not set on virtual lookup for vaddr %#x", vaddr);
+ panic("vtophys: ptbr is not set on "
+ "virtual lookup for vaddr %#x", vaddr);
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
Addr
MipsISA::vtophys(ThreadContext *tc, Addr addr)
{
-
fatal("VTOPHYS: Unimplemented on MIPS\n");
}