diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index d70241b6f..69d5ea5d3 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -83,6 +83,12 @@ const int32_t R4300iOp::LWR_SHIFT[4] = { 24, 16, 8, 0 }; m_JumpToLocation = (*_PROGRAM_COUNTER);\ return; +#define TLB_WRITE_EXCEPTION(Address) \ + g_Reg->DoTLBWriteMiss(m_NextInstruction == JUMP,Address);\ + m_NextInstruction = JUMP;\ + m_JumpToLocation = (*_PROGRAM_COUNTER);\ + return; + void R4300iOp::SPECIAL() { Jump_Special[m_Opcode.funct](); @@ -1033,12 +1039,11 @@ void R4300iOp::LDL() if (!g_MMU->LD_VAddr((Address & ~7), Value)) { - g_Notify->BreakPoint(__FILE__, __LINE__); if (bShowTLBMisses()) { 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 += Value << LDL_SHIFT[Offset]; @@ -1064,12 +1069,11 @@ void R4300iOp::LDR() if (!g_MMU->LD_VAddr((Address & ~7), Value)) { - g_Notify->BreakPoint(__FILE__, __LINE__); if (bShowTLBMisses()) { 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]; @@ -1135,12 +1139,11 @@ void R4300iOp::LWL() if (!g_MMU->LW_VAddr((Address & ~3), Value)) { - g_Notify->BreakPoint(__FILE__, __LINE__); if (bShowTLBMisses()) { 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]); @@ -1236,12 +1239,11 @@ void R4300iOp::LWR() if (!g_MMU->LW_VAddr((Address & ~3), Value)) { - g_Notify->BreakPoint(__FILE__, __LINE__); if (bShowTLBMisses()) { 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]); @@ -1283,14 +1285,11 @@ void R4300iOp::SB() } if (!g_MMU->SB_VAddr(Address, _GPR[m_Opcode.rt].UB[0])) { - if (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); } - return; + TLB_WRITE_EXCEPTION(Address); } Value &= SWL_MASK[Offset]; @@ -1347,14 +1339,11 @@ void R4300iOp::SWL() if (!g_MMU->SW_VAddr((Address & ~0x03), Value)) { - if (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); } - return; + TLB_WRITE_EXCEPTION(Address); } Value &= SDL_MASK[Offset]; @@ -1426,14 +1408,11 @@ void R4300iOp::SDL() if (!g_MMU->SD_VAddr((Address & ~7), Value)) { - if (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); } - return; + TLB_WRITE_EXCEPTION(Address); } Value &= SDR_MASK[Offset]; @@ -1478,14 +1453,11 @@ void R4300iOp::SDR() if (!g_MMU->SD_VAddr((Address & ~7), Value)) { - if (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); } - return; + TLB_WRITE_EXCEPTION(Address); } Value &= SWR_MASK[Offset]; @@ -1518,14 +1486,11 @@ void R4300iOp::SWR() if (!g_MMU->SW_VAddr((Address & ~0x03), Value)) { - if (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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])) { - g_Notify->BreakPoint(__FILE__, __LINE__); if (bShowTLBMisses()) { g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); } + TLB_WRITE_EXCEPTION(Address); } } _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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); } - return; + TLB_WRITE_EXCEPTION(Address); } #ifdef Interpreter_StackTest 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { 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 (HaveDebugger()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } if (bShowTLBMisses()) { g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); } + TLB_WRITE_EXCEPTION(Address); } } /********************** R4300i OpCodes: Special **********************/ diff --git a/Source/Project64-core/N64System/Mips/RegisterClass.cpp b/Source/Project64-core/N64System/Mips/RegisterClass.cpp index 9716f325d..bbe541e95 100644 --- a/Source/Project64-core/N64System/Mips/RegisterClass.cpp +++ b/Source/Project64-core/N64System/Mips/RegisterClass.cpp @@ -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()) { @@ -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) { if (HaveDebugger()) diff --git a/Source/Project64-core/N64System/Mips/RegisterClass.h b/Source/Project64-core/N64System/Mips/RegisterClass.h index ae266cd06..61a24e6aa 100644 --- a/Source/Project64-core/N64System/Mips/RegisterClass.h +++ b/Source/Project64-core/N64System/Mips/RegisterClass.h @@ -628,17 +628,18 @@ public: uint32_t m_GfxIntrReg; uint32_t m_RspIntrReg; - void CheckInterrupts (); - void DoAddressError ( bool DelaySlot, uint32_t BadVaddr, bool FromRead ); - void DoBreakException ( bool DelaySlot ); - void DoTrapException ( bool DelaySlot ); - void DoCopUnusableException ( bool DelaySlot, int32_t Coprocessor ); - bool DoIntrException ( bool DelaySlot ); - void DoTLBReadMiss ( bool DelaySlot, uint32_t BadVaddr ); - void DoSysCallException ( bool DelaySlot); - void FixFpuLocations (); - void Reset (); - void SetAsCurrentSystem (); + void CheckInterrupts(); + void DoAddressError( bool DelaySlot, uint32_t BadVaddr, bool FromRead ); + void DoBreakException( bool DelaySlot ); + void DoTrapException( bool DelaySlot ); + void DoCopUnusableException( bool DelaySlot, int32_t Coprocessor ); + bool DoIntrException( bool DelaySlot ); + void DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr); + void DoTLBWriteMiss(bool DelaySlot, uint32_t BadVaddr); + void DoSysCallException ( bool DelaySlot); + void FixFpuLocations(); + void Reset(); + void SetAsCurrentSystem(); private: CRegisters(); // Disable default constructor