MIPS: Many style fixes.

White space, commented out code, some other minor fixes.
This commit is contained in:
Gabe Black 2009-07-21 01:08:53 -07:00
parent dc0a017ed0
commit 7548082d3b
28 changed files with 1017 additions and 1494 deletions

View file

@ -28,20 +28,8 @@
* 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)

View file

@ -31,11 +31,6 @@
#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"
@ -46,15 +41,9 @@ class IdleStartEvent;
*/
class BareIronMipsSystem : public MipsSystem
{
private:
public:
static const int CommandLineSize = 256;
private:
public:
BareIronMipsSystem(Params *p);
~BareIronMipsSystem();
};

View file

@ -85,7 +85,6 @@ FaultName ThreadFault::_name = "Thread Fault";
FaultVect ThreadFault::_vect = 0x00F1;
FaultStat ThreadFault::_count;
FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
FaultVect ArithmeticFault::_vect = 0x180;
FaultStat ArithmeticFault::_count;
@ -106,7 +105,6 @@ FaultName BreakpointFault::_name = "Breakpoint";
FaultVect BreakpointFault::_vect = 0x0180;
FaultStat BreakpointFault::_count;
FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
FaultVect ItbInvalidFault::_vect = 0x0180;
FaultStat ItbInvalidFault::_count;
@ -168,344 +166,366 @@ FaultVect DspStateDisabledFault::_vect = 0x001a;
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);
// 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);
// 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);
}
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));
}
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));
}
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));
}
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));
}
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);
}
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));
}
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);
}
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);
}
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());
setExceptionState(tc, 0xC);
// 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;
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 SystemCallFault::invoke(ThreadContext *tc)
void
StoreAddressErrorFault::invoke(ThreadContext *tc)
{
DPRINTF(MipsPRA,"%s encountered.\n", name());
setExceptionState(tc,0x8);
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));
// Set new PC
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
}
void
TrapFault::invoke(ThreadContext *tc)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
// 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)
{
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;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setExceptionState(tc, 0x1);
setHandlerPC(HandlerBase, tc);
}
void InterruptFault::invoke(ThreadContext *tc)
void
SystemCallFault::invoke(ThreadContext *tc)
{
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)
{
#if FULL_SYSTEM
DPRINTF(MipsPRA,"%s encountered.\n", name());
setExceptionState(tc,0x0A);
Addr HandlerBase;
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);
}
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);
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);
Addr HandlerBase;
// Offset 0x180 - General Exception Vector
HandlerBase = vect() + tc->readMiscReg(MipsISA::EBase);
setHandlerPC(HandlerBase, tc);
// warn("Status: %x, Cause: %x\n",tc->readMiscReg(MipsISA::Status),tc->readMiscReg(MipsISA::Cause));
#else
warn("%s (CP%d) encountered.\n", name(), coProcID);
#endif

View file

@ -36,10 +36,9 @@
#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
@ -54,9 +53,9 @@ 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;
@ -116,6 +115,7 @@ class AddressErrorFault : public MipsFault
#endif
};
class StoreAddressErrorFault : public MipsFault
{
private:
@ -129,8 +129,8 @@ class StoreAddressErrorFault : public MipsFault
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class UnimplementedOpcodeFault : public MipsFault
{
private:
@ -157,6 +157,7 @@ class TLBRefillIFetchFault : public MipsFault
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class TLBInvalidIFetchFault : public MipsFault
{
private:
@ -259,6 +260,7 @@ class ResetFault : public MipsFault
void invoke(ThreadContext * tc);
};
class SystemCallFault : public MipsFault
{
private:
@ -284,6 +286,7 @@ class SoftResetFault : public MipsFault
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class DebugSingleStep : public MipsFault
{
private:
@ -296,6 +299,7 @@ class DebugSingleStep : public MipsFault
FaultStat & countStat() {return _count;}
void invoke(ThreadContext * tc);
};
class DebugInterrupt : public MipsFault
{
private:
@ -350,7 +354,6 @@ class ThreadFault : public MipsFault
void invoke(ThreadContext * tc);
};
class ArithmeticFault : public MipsFault
{
protected:
@ -384,8 +387,6 @@ class InterruptFault : public MipsFault
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
//void invoke(ThreadContext * tc);
};
class TrapFault : public MipsFault
@ -432,6 +433,7 @@ class ItbRefillFault : public MipsFault
void invoke(ThreadContext * tc);
#endif
};
class DtbRefillFault : public MipsFault
{
private:
@ -475,8 +477,8 @@ class ItbInvalidFault : public MipsFault
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class TLBModifiedFault : public MipsFault
{
private:
@ -490,7 +492,6 @@ class TLBModifiedFault : public MipsFault
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class DtbInvalidFault : public MipsFault
@ -506,7 +507,6 @@ class DtbInvalidFault : public MipsFault
#if FULL_SYSTEM
void invoke(ThreadContext * tc);
#endif
};
class FloatEnableFault : public MipsFault

View file

@ -40,9 +40,4 @@ void
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();
}

View file

@ -38,201 +38,102 @@
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);
@ -240,34 +141,32 @@ bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
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);
}
}

View file

@ -31,97 +31,27 @@
#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
@ -139,7 +69,7 @@ class Interrupts
// 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
@ -148,7 +78,7 @@ class Interrupts
// 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
@ -165,27 +95,22 @@ class Interrupts
}
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 &section)
void
unserialize(Checkpoint *cp, const std::string &section)
{
fatal("Unserialization of Interrupts Unimplemented for MIPS");
//UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
//UNSERIALIZE_SCALAR(intstatus);
}
private:
bool newInfoSet;
int newIpl;
int newSummary;
};
}

View file

@ -447,12 +447,7 @@ ISA::readMiscReg(int reg_idx, ThreadContext *tc, ThreadID tid)
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
@ -486,7 +481,6 @@ ISA::setRegMask(int reg_idx, const MiscReg &val, ThreadID tid)
// (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)
@ -515,21 +509,21 @@ ISA::setMiscReg(int reg_idx, const MiscReg &val,
MiscReg
ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val)
{
MiscReg retVal = 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;
// 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
@ -586,8 +580,6 @@ ISA::CP0Event::process()
cp0->updateCPU();
break;
}
//cp0EventRemoveList.push(this);
}
const char *

View file

@ -41,133 +41,129 @@
namespace LittleEndianGuest {};
#define TARGET_MIPS
class StaticInstPtr;
namespace MipsISA
{
using namespace LittleEndianGuest;
StaticInstPtr decodeInst(ExtMachInst);
using namespace LittleEndianGuest;
// MIPS DOES have a delay slot
#define ISA_HAS_DELAY_SLOT 1
StaticInstPtr decodeInst(ExtMachInst);
const Addr PageShift = 13;
const Addr PageBytes = ULL(1) << PageShift;
const Addr Page_Mask = ~(PageBytes - 1);
const Addr PageOffset = PageBytes - 1;
// 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
//
////////////////////////////////////////////////////////////////////////
//
// Translation stuff
//
const Addr PteShift = 3;
const Addr NPtePageShift = PageShift - PteShift;
const Addr NPtePage = ULL(1) << NPtePageShift;
const Addr PteMask = NPtePage - 1;
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);
//// 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 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 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/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);
// 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);
// 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;
}
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 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;
const Addr PAddrImplMask = (ULL(1) << PABits) - 1;
////////////////////////////////////////////////////////////////////////
//
// Interrupt levels
//
enum InterruptLevels
{
INTLEVEL_SOFTWARE_MIN = 4,
INTLEVEL_SOFTWARE_MAX = 19,
////////////////////////////////////////////////////////////////////////
//
// Interrupt levels
//
enum InterruptLevels
{
INTLEVEL_SOFTWARE_MIN = 4,
INTLEVEL_SOFTWARE_MAX = 19,
INTLEVEL_EXTERNAL_MIN = 20,
INTLEVEL_EXTERNAL_MAX = 34,
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_IRQ0 = 20,
INTLEVEL_IRQ1 = 21,
INTINDEX_ETHERNET = 0,
INTINDEX_SCSI = 1,
INTLEVEL_IRQ2 = 22,
INTLEVEL_IRQ3 = 23,
INTLEVEL_SERIAL = 33,
INTLEVEL_SERIAL = 33,
NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
};
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
};
// 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;
// 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 LogVMPageSize = 13; // 8K bytes
const int VMPageSize = (1 << LogVMPageSize);
const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
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 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;
const int ANNOTE_NONE = 0;
const uint32_t ITOUCH_ANNOTE = 0xffffffff;
};
#endif // __ARCH_MIPS_ISA_TRAITS_HH__

View file

@ -32,11 +32,6 @@
#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 {

View file

@ -69,7 +69,3 @@ OpenFlagTransTable MipsLinux::openFlagTable[] = {
const int MipsLinux::NUM_OPEN_FLAGS =
(sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));

View file

@ -68,13 +68,13 @@ class MipsLinux : public Linux
//@{
/// 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
//@}
//@{

View file

@ -74,15 +74,15 @@ sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
// 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();
@ -102,15 +102,16 @@ sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
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();
@ -196,8 +197,8 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 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),
@ -241,7 +242,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 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),
@ -315,12 +316,12 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 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),
@ -406,7 +407,6 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
/* 282 */ SyscallDesc("keyctl", unimplementedFunc)
};
MipsLinuxProcess::MipsLinuxProcess(LiveProcessParams * params,
ObjectFile *objFile)
: MipsLiveProcess(params, objFile),

View file

@ -88,7 +88,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
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.
@ -105,12 +104,6 @@ LinuxMipsSystem::LinuxMipsSystem(Params *p)
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
/**

View file

@ -45,17 +45,18 @@
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)
@ -89,14 +90,17 @@ 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
@ -107,7 +111,6 @@ handleLockedWrite(XC *xc, Request *req)
return true;
}
} // namespace MipsISA
#endif

View file

@ -29,20 +29,9 @@
* 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
@ -52,61 +41,11 @@
//
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

View file

@ -44,6 +44,7 @@ class ThreadContext;
namespace MipsISA
{
inline Tick
handleIprRead(ThreadContext *xc, Packet *pkt)
{
@ -56,7 +57,6 @@ handleIprWrite(ThreadContext *xc, Packet *pkt)
panic("No implementation for handleIprWrite in MIPS\n");
}
} // namespace MipsISA
#endif

View file

@ -51,7 +51,6 @@
namespace MipsISA
{
template <class TC>
inline unsigned
getVirtProcNum(TC *tc)
@ -76,11 +75,13 @@ haltThread(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());
}
}
@ -93,14 +94,14 @@ restoreThread(TC *tc)
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());
}
}

View file

@ -37,42 +37,42 @@
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::unserialize(Checkpoint *cp, const std::string &section)
{
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::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 &section)
{
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);
}
}

View file

@ -41,59 +41,62 @@
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 &section);
};
bool Valid() { return (V0 | V1); };
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
};
#endif // __ARCH_MIPS_PAGETABLE_H__

View file

@ -40,57 +40,66 @@ class ThreadContext;
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()
{
protected:
ThreadContext * tc;
//The extended machine instruction being generated
ExtMachInst emi;
return tc;
}
public:
Predecoder(ThreadContext * _tc) : tc(_tc)
{}
void
setTC(ThreadContext *_tc)
{
tc = _tc;
}
ThreadContext * getTC()
{
return tc;
}
void
process()
{
}
void setTC(ThreadContext * _tc)
{
tc = _tc;
}
void
reset()
{}
void process()
{
}
//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;
}
void reset()
{}
bool
needMoreBytes()
{
return true;
}
//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
extMachInstReady()
{
return true;
}
bool needMoreBytes()
{
return true;
}
//This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst &
getExtMachInst()
{
return emi;
}
};
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__

View file

@ -42,35 +42,8 @@
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
@ -140,84 +113,17 @@ void
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;
}
@ -305,7 +211,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
int reg, disp;
if (decodeStack(inst, disp)) {
if (size) {
// panic("decoding frame size again");
return true;
}
size += disp;
@ -313,7 +218,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
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;
}
}
@ -327,24 +231,6 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
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

View file

@ -45,22 +45,17 @@
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;
@ -76,7 +71,7 @@ MipsSystem::MipsSystem(Params *p)
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))
@ -110,100 +105,42 @@ MipsSystem::MipsSystem(Params *p)
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);
}
@ -211,7 +148,6 @@ void
MipsSystem::unserialize(Checkpoint *cp, const std::string &section)
{
System::unserialize(cp,section);
// consoleSymtab->unserialize("console_symtab", cp, section);
}
MipsSystem *

View file

@ -54,10 +54,10 @@ class MipsSystem : public System
virtual bool breakpoint();
/**
* Serialization stuff
*/
public:
/**
* Serialization stuff
*/
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
@ -89,7 +89,8 @@ class MipsSystem : public System
#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);
}

View file

@ -56,16 +56,14 @@ using namespace MipsISA;
// 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;
@ -76,9 +74,9 @@ getOperatingMode(MiscReg Stat)
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()
@ -92,23 +90,23 @@ MipsISA::PTE *
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;
}
}
@ -118,119 +116,96 @@ TLB::lookup(Addr vpn, uint8_t asn) const
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;
}
void
TLB::insertAt(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);
}
table[Index]=pte;
// Update fast lookup table
lookupTable.insert(make_pair(table[Index].VPN, Index));
}
}
// insert a new TLB entry
void
TLB::insert(Addr addr, MipsISA::PTE &pte)
TLB::insert(Addr addr, PTE &pte)
{
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;
}
DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
lookupTable.erase(i);
}
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();
*/
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;
}
@ -328,68 +303,66 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
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())
{
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(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));
} else {
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;
}
}
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 */
Addr VPN;
if(smallPages==1){
VPN=((req->getVaddr() >> 11));
} else {
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;
}
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 */
@ -398,43 +371,36 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
/* 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);
} 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();
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
}
}
return checkCacheability(req);
return checkCacheability(req);
#endif
}
@ -457,131 +423,118 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
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();
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;
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);
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();
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
/* 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);
} 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();
/* BadVAddr must be set */
Flt->BadVAddr = req->getVaddr();
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
/* Context must be set */
Flt->Context_BadVPN2 = (VPN >> 2);
return Flt;
}
}
return checkCacheability(req);
@ -609,7 +562,7 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc,
MipsISA::PTE &
TLB::index(bool advance)
{
MipsISA::PTE *pte = &table[nlu];
PTE *pte = &table[nlu];
if (advance)
nextnlu();
@ -620,5 +573,5 @@ TLB::index(bool advance)
MipsISA::TLB *
MipsTLBParams::create()
{
return new MipsISA::TLB(this);
return new TLB(this);
}

View file

@ -35,42 +35,43 @@
namespace MipsISA
{
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
typedef uint64_t LargestRead;
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
//used in FP convert & round function
enum ConvertType{
SINGLE_TO_DOUBLE,
SINGLE_TO_WORD,
SINGLE_TO_LONG,
typedef uint64_t LargestRead;
DOUBLE_TO_SINGLE,
DOUBLE_TO_WORD,
DOUBLE_TO_LONG,
//used in FP convert & round function
enum ConvertType{
SINGLE_TO_DOUBLE,
SINGLE_TO_WORD,
SINGLE_TO_LONG,
LONG_TO_SINGLE,
LONG_TO_DOUBLE,
LONG_TO_WORD,
LONG_TO_PS,
DOUBLE_TO_SINGLE,
DOUBLE_TO_WORD,
DOUBLE_TO_LONG,
WORD_TO_SINGLE,
WORD_TO_DOUBLE,
WORD_TO_LONG,
WORD_TO_PS,
LONG_TO_SINGLE,
LONG_TO_DOUBLE,
LONG_TO_WORD,
LONG_TO_PS,
PL_TO_SINGLE,
PU_TO_SINGLE
};
WORD_TO_SINGLE,
WORD_TO_DOUBLE,
WORD_TO_LONG,
WORD_TO_PS,
//used in FP convert & round function
enum RoundMode{
RND_ZERO,
RND_DOWN,
RND_UP,
RND_NEAREST
};
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
@ -81,7 +82,8 @@ struct CoreSpecific {
-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
@ -89,7 +91,8 @@ struct CoreSpecific {
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

View file

@ -45,87 +45,88 @@ class ThreadContext;
namespace MipsISA {
uint64_t getArgument(ThreadContext *tc, int number, bool fp);
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);
////////////////////////////////////////////////////////////////////////
//
// 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 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);
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);
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;
}
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;
}
// Instruction address compression hooks
static inline Addr realPCToFetchPC(const Addr &addr) {
return addr;
}
static inline Addr fetchPCToRealPC(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);
}
// 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;
}
////////////////////////////////////////////////////////////////////////
//
// 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);
template <class CPU>
void zeroRegisters(CPU *cpu);
////////////////////////////////////////////////////////////////////////
//
// Translation stuff
//
inline Addr
TruncPage(Addr addr)
{ return addr & ~(PageBytes - 1); }
////////////////////////////////////////////////////////////////////////
//
// Translation stuff
//
inline Addr
TruncPage(Addr addr)
{ return addr & ~(PageBytes - 1); }
inline Addr
RoundPage(Addr addr)
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
inline Addr
RoundPage(Addr addr)
{ return (addr + PageBytes - 1) & ~(PageBytes - 1); }
////////////////////////////////////////////////////////////////////////
//
// CPU Utility
//
void startupCPU(ThreadContext *tc, int cpuId);
////////////////////////////////////////////////////////////////////////
//
// CPU Utility
//
void startupCPU(ThreadContext *tc, int cpuId);
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
};

View file

@ -53,7 +53,8 @@ MipsISA::vtophys(Addr vaddr)
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);
@ -63,7 +64,6 @@ MipsISA::vtophys(Addr vaddr)
Addr
MipsISA::vtophys(ThreadContext *tc, Addr addr)
{
fatal("VTOPHYS: Unimplemented on MIPS\n");
}