Project64: Add TLB_WRITE_EXCEPTION

This commit is contained in:
zilmar 2020-03-04 10:33:18 +10:30
parent 28c9118912
commit 185c6586b4
3 changed files with 78 additions and 90 deletions

View File

@ -83,6 +83,12 @@ const int32_t R4300iOp::LWR_SHIFT[4] = { 24, 16, 8, 0 };
m_JumpToLocation = (*_PROGRAM_COUNTER);\ m_JumpToLocation = (*_PROGRAM_COUNTER);\
return; return;
#define TLB_WRITE_EXCEPTION(Address) \
g_Reg->DoTLBWriteMiss(m_NextInstruction == JUMP,Address);\
m_NextInstruction = JUMP;\
m_JumpToLocation = (*_PROGRAM_COUNTER);\
return;
void R4300iOp::SPECIAL() void R4300iOp::SPECIAL()
{ {
Jump_Special[m_Opcode.funct](); Jump_Special[m_Opcode.funct]();
@ -1033,12 +1039,11 @@ void R4300iOp::LDL()
if (!g_MMU->LD_VAddr((Address & ~7), Value)) if (!g_MMU->LD_VAddr((Address & ~7), Value))
{ {
g_Notify->BreakPoint(__FILE__, __LINE__);
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_READ_EXCEPTION(Address);
} }
_GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].DW & LDL_MASK[Offset]; _GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].DW & LDL_MASK[Offset];
_GPR[m_Opcode.rt].DW += Value << LDL_SHIFT[Offset]; _GPR[m_Opcode.rt].DW += Value << LDL_SHIFT[Offset];
@ -1064,12 +1069,11 @@ void R4300iOp::LDR()
if (!g_MMU->LD_VAddr((Address & ~7), Value)) if (!g_MMU->LD_VAddr((Address & ~7), Value))
{ {
g_Notify->BreakPoint(__FILE__, __LINE__);
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_READ_EXCEPTION(Address);
} }
_GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].DW & LDR_MASK[Offset]; _GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].DW & LDR_MASK[Offset];
@ -1135,12 +1139,11 @@ void R4300iOp::LWL()
if (!g_MMU->LW_VAddr((Address & ~3), Value)) if (!g_MMU->LW_VAddr((Address & ~3), Value))
{ {
g_Notify->BreakPoint(__FILE__, __LINE__);
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_READ_EXCEPTION(Address);
} }
_GPR[m_Opcode.rt].DW = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWL_MASK[Offset]); _GPR[m_Opcode.rt].DW = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWL_MASK[Offset]);
@ -1236,12 +1239,11 @@ void R4300iOp::LWR()
if (!g_MMU->LW_VAddr((Address & ~3), Value)) if (!g_MMU->LW_VAddr((Address & ~3), Value))
{ {
g_Notify->BreakPoint(__FILE__, __LINE__);
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_READ_EXCEPTION(Address);
} }
_GPR[m_Opcode.rt].DW = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWR_MASK[Offset]); _GPR[m_Opcode.rt].DW = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWR_MASK[Offset]);
@ -1283,14 +1285,11 @@ void R4300iOp::SB()
} }
if (!g_MMU->SB_VAddr(Address, _GPR[m_Opcode.rt].UB[0])) if (!g_MMU->SB_VAddr(Address, _GPR[m_Opcode.rt].UB[0]))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1307,14 +1306,11 @@ void R4300iOp::SH()
} }
if (!g_MMU->SH_VAddr(Address, _GPR[m_Opcode.rt].UHW[0])) if (!g_MMU->SH_VAddr(Address, _GPR[m_Opcode.rt].UHW[0]))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1331,15 +1327,11 @@ void R4300iOp::SWL()
if (!g_MMU->LW_VAddr((Address & ~3), Value)) if (!g_MMU->LW_VAddr((Address & ~3), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_WRITE_EXCEPTION(Address);
} }
Value &= SWL_MASK[Offset]; Value &= SWL_MASK[Offset];
@ -1347,14 +1339,11 @@ void R4300iOp::SWL()
if (!g_MMU->SW_VAddr((Address & ~0x03), Value)) if (!g_MMU->SW_VAddr((Address & ~0x03), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1375,14 +1364,11 @@ void R4300iOp::SW()
} }
if (!g_MMU->SW_VAddr(Address, _GPR[m_Opcode.rt].UW[0])) if (!g_MMU->SW_VAddr(Address, _GPR[m_Opcode.rt].UW[0]))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1410,15 +1396,11 @@ void R4300iOp::SDL()
if (!g_MMU->LD_VAddr((Address & ~7), Value)) if (!g_MMU->LD_VAddr((Address & ~7), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_WRITE_EXCEPTION(Address);
} }
Value &= SDL_MASK[Offset]; Value &= SDL_MASK[Offset];
@ -1426,14 +1408,11 @@ void R4300iOp::SDL()
if (!g_MMU->SD_VAddr((Address & ~7), Value)) if (!g_MMU->SD_VAddr((Address & ~7), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1462,15 +1441,11 @@ void R4300iOp::SDR()
if (!g_MMU->LD_VAddr((Address & ~7), Value)) if (!g_MMU->LD_VAddr((Address & ~7), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_WRITE_EXCEPTION(Address);
} }
Value &= SDR_MASK[Offset]; Value &= SDR_MASK[Offset];
@ -1478,14 +1453,11 @@ void R4300iOp::SDR()
if (!g_MMU->SD_VAddr((Address & ~7), Value)) if (!g_MMU->SD_VAddr((Address & ~7), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1502,15 +1474,11 @@ void R4300iOp::SWR()
if (!g_MMU->LW_VAddr((Address & ~3), Value)) if (!g_MMU->LW_VAddr((Address & ~3), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_WRITE_EXCEPTION(Address);
} }
Value &= SWR_MASK[Offset]; Value &= SWR_MASK[Offset];
@ -1518,14 +1486,11 @@ void R4300iOp::SWR()
if (!g_MMU->SW_VAddr((Address & ~0x03), Value)) if (!g_MMU->SW_VAddr((Address & ~0x03), Value))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1604,11 +1569,11 @@ void R4300iOp::SC()
{ {
if (!g_MMU->SW_VAddr(Address, _GPR[m_Opcode.rt].UW[0])) if (!g_MMU->SW_VAddr(Address, _GPR[m_Opcode.rt].UW[0]))
{ {
g_Notify->BreakPoint(__FILE__, __LINE__);
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
_GPR[m_Opcode.rt].UW[0] = (*_LLBit); _GPR[m_Opcode.rt].UW[0] = (*_LLBit);
@ -1627,15 +1592,11 @@ void R4300iOp::LD()
} }
if (!g_MMU->LD_VAddr(Address, _GPR[m_Opcode.rt].UDW)) if (!g_MMU->LD_VAddr(Address, _GPR[m_Opcode.rt].UDW))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
return; TLB_WRITE_EXCEPTION(Address);
} }
#ifdef Interpreter_StackTest #ifdef Interpreter_StackTest
if (m_Opcode.rt == 29) if (m_Opcode.rt == 29)
@ -1660,14 +1621,11 @@ void R4300iOp::LDC1()
} }
if (!g_MMU->LD_VAddr(Address, *(uint64_t *)_FPR_D[m_Opcode.ft])) if (!g_MMU->LD_VAddr(Address, *(uint64_t *)_FPR_D[m_Opcode.ft]))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_READ_EXCEPTION(Address);
} }
} }
@ -1686,14 +1644,11 @@ void R4300iOp::SWC1()
if (!g_MMU->SW_VAddr(Address, *(uint32_t *)_FPR_S[m_Opcode.ft])) if (!g_MMU->SW_VAddr(Address, *(uint32_t *)_FPR_S[m_Opcode.ft]))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1713,14 +1668,11 @@ void R4300iOp::SDC1()
} }
if (!g_MMU->SD_VAddr(Address, *(int64_t *)_FPR_D[m_Opcode.ft])) if (!g_MMU->SD_VAddr(Address, *(int64_t *)_FPR_D[m_Opcode.ft]))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
@ -1737,14 +1689,11 @@ void R4300iOp::SD()
} }
if (!g_MMU->SD_VAddr(Address, _GPR[m_Opcode.rt].UDW)) if (!g_MMU->SD_VAddr(Address, _GPR[m_Opcode.rt].UDW))
{ {
if (HaveDebugger())
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (bShowTLBMisses()) if (bShowTLBMisses())
{ {
g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str());
} }
TLB_WRITE_EXCEPTION(Address);
} }
} }
/********************** R4300i OpCodes: Special **********************/ /********************** R4300i OpCodes: Special **********************/

View File

@ -454,7 +454,7 @@ void CRegisters::DoTrapException(bool DelaySlot)
} }
void CRegisters::DoCopUnusableException(bool DelaySlot, int Coprocessor) void CRegisters::DoCopUnusableException(bool DelaySlot, int32_t Coprocessor)
{ {
if (HaveDebugger()) if (HaveDebugger())
{ {
@ -564,6 +564,44 @@ void CRegisters::DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr)
} }
} }
void CRegisters::DoTLBWriteMiss(bool DelaySlot, uint32_t BadVaddr)
{
CAUSE_REGISTER = EXC_WMISS;
BAD_VADDR_REGISTER = BadVaddr;
CONTEXT_REGISTER &= 0xFF80000F;
CONTEXT_REGISTER |= (BadVaddr >> 9) & 0x007FFFF0;
ENTRYHI_REGISTER = (BadVaddr & 0xFFFFE000);
if ((STATUS_REGISTER & STATUS_EXL) == 0)
{
if (DelaySlot)
{
CAUSE_REGISTER |= CAUSE_BD;
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
}
else
{
EPC_REGISTER = m_PROGRAM_COUNTER;
}
if (g_TLB->AddressDefined(BadVaddr))
{
m_PROGRAM_COUNTER = 0x80000180;
}
else
{
m_PROGRAM_COUNTER = 0x80000000;
}
STATUS_REGISTER |= STATUS_EXL;
}
else
{
if (HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("TLBMiss - EXL Set\nBadVaddr = %X\nAddress Defined: %s", BadVaddr, g_TLB->AddressDefined(BadVaddr) ? "true" : "false").c_str());
}
m_PROGRAM_COUNTER = 0x80000180;
}
}
void CRegisters::DoSysCallException(bool DelaySlot) void CRegisters::DoSysCallException(bool DelaySlot)
{ {
if (HaveDebugger()) if (HaveDebugger())

View File

@ -628,17 +628,18 @@ public:
uint32_t m_GfxIntrReg; uint32_t m_GfxIntrReg;
uint32_t m_RspIntrReg; uint32_t m_RspIntrReg;
void CheckInterrupts (); void CheckInterrupts();
void DoAddressError ( bool DelaySlot, uint32_t BadVaddr, bool FromRead ); void DoAddressError( bool DelaySlot, uint32_t BadVaddr, bool FromRead );
void DoBreakException ( bool DelaySlot ); void DoBreakException( bool DelaySlot );
void DoTrapException ( bool DelaySlot ); void DoTrapException( bool DelaySlot );
void DoCopUnusableException ( bool DelaySlot, int32_t Coprocessor ); void DoCopUnusableException( bool DelaySlot, int32_t Coprocessor );
bool DoIntrException ( bool DelaySlot ); bool DoIntrException( bool DelaySlot );
void DoTLBReadMiss ( bool DelaySlot, uint32_t BadVaddr ); void DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr);
void DoSysCallException ( bool DelaySlot); void DoTLBWriteMiss(bool DelaySlot, uint32_t BadVaddr);
void FixFpuLocations (); void DoSysCallException ( bool DelaySlot);
void Reset (); void FixFpuLocations();
void SetAsCurrentSystem (); void Reset();
void SetAsCurrentSystem();
private: private:
CRegisters(); // Disable default constructor CRegisters(); // Disable default constructor