diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 5b1e34a20..4e57723d2 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -49,12 +49,6 @@ const int32_t R4300iOp::SWR_SHIFT[4] = { 24, 16, 8, 0 }; const int32_t R4300iOp::LWL_SHIFT[4] = { 0, 8, 16, 24 }; const int32_t R4300iOp::LWR_SHIFT[4] = { 24, 16, 8, 0 }; -#define ADDRESS_ERROR_EXCEPTION(Address,FromRead) \ - g_Reg->DoAddressError(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,Address,FromRead);\ - g_System->m_PipelineStage = PIPELINE_STAGE_JUMP;\ - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER);\ - return; - #define TEST_COP1_USABLE_EXCEPTION() \ if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\ g_Reg->DoCopUnusableException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,1);\ @@ -988,21 +982,12 @@ int32_t LDL_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; void R4300iOp::LDL() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP64(Address) && MemoryBreakpoint()) - { - return; - } - - uint64_t Value; - if (!g_MMU->LD_Memory((Address & ~7), Value)) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else + uint64_t MemoryValue; + if (g_MMU->LD_Memory((Address & ~7), MemoryValue)) { uint32_t Offset = Address & 7; _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 += MemoryValue << LDL_SHIFT[Offset]; } } @@ -1015,253 +1000,127 @@ int32_t LDR_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; void R4300iOp::LDR() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP64(Address) && MemoryBreakpoint()) - { - return; - } - - uint64_t Value; - if (!g_MMU->LD_Memory((Address & ~7), Value)) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else + uint64_t MemoryValue; + if (g_MMU->LD_Memory((Address & ~7), MemoryValue)) { uint32_t Offset = Address & 7; - _GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].DW & LDR_MASK[Offset]; - _GPR[m_Opcode.rt].DW += Value >> LDR_SHIFT[Offset]; + _GPR[m_Opcode.rt].DW += MemoryValue >> LDR_SHIFT[Offset]; } } void R4300iOp::LB() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP8(Address) && MemoryBreakpoint()) + uint8_t MemoryValue; + if (g_MMU->LB_Memory(Address, MemoryValue)) { - return; - } - if (!g_MMU->LB_Memory(Address, _GPR[m_Opcode.rt].UB[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].B[0]; + _GPR[m_Opcode.rt].DW = (int8_t)MemoryValue; } } void R4300iOp::LH() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 1) != 0) + uint16_t MemoryValue; + if (g_MMU->LH_Memory(Address, MemoryValue)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP16(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LH_Memory(Address, _GPR[m_Opcode.rt].UHW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].HW[0]; + _GPR[m_Opcode.rt].DW = (int16_t)MemoryValue; } } void R4300iOp::LWL() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - uint32_t Value; - if (!g_MMU->LW_Memory((Address & ~3), Value)) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->LW_Memory((Address & ~3), MemoryValue)) { uint32_t Offset = Address & 3; _GPR[m_Opcode.rt].DW = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWL_MASK[Offset]); - _GPR[m_Opcode.rt].DW += (int32_t)(Value << LWL_SHIFT[Offset]); + _GPR[m_Opcode.rt].DW += (int32_t)(MemoryValue << LWL_SHIFT[Offset]); } } void R4300iOp::LW() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->LW_Memory(Address, MemoryValue)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - - if (!g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].W[0]; + _GPR[m_Opcode.rt].DW = (int32_t)MemoryValue; } } void R4300iOp::LBU() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP8(Address) && MemoryBreakpoint()) + uint8_t MemoryValue; + if (g_MMU->LB_Memory(Address, MemoryValue)) { - return; - } - if (!g_MMU->LB_Memory(Address, _GPR[m_Opcode.rt].UB[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].UDW = _GPR[m_Opcode.rt].UB[0]; + _GPR[m_Opcode.rt].UDW = MemoryValue; } } void R4300iOp::LHU() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 1) != 0) + uint16_t MemoryValue; + if (g_MMU->LH_Memory(Address, MemoryValue)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP16(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LH_Memory(Address, _GPR[m_Opcode.rt].UHW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].UDW = _GPR[m_Opcode.rt].UHW[0]; + _GPR[m_Opcode.rt].UDW = MemoryValue; } } void R4300iOp::LWR() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - - uint32_t Value; - if (!g_MMU->LW_Memory((Address & ~3), Value)) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->LW_Memory((Address & ~3), MemoryValue)) { uint32_t Offset = Address & 3; _GPR[m_Opcode.rt].DW = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWR_MASK[Offset]); - _GPR[m_Opcode.rt].DW += (int32_t)(Value >> LWR_SHIFT[Offset]); + _GPR[m_Opcode.rt].DW += (int32_t)(MemoryValue >> LWR_SHIFT[Offset]); } } void R4300iOp::LWU() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->LW_Memory(Address, MemoryValue)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - - if (!g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].UDW = _GPR[m_Opcode.rt].UW[0]; + _GPR[m_Opcode.rt].UDW = MemoryValue; } } void R4300iOp::SB() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveWriteBP() && g_Debugger->WriteBP8(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->SB_VAddr(Address, _GPR[m_Opcode.rt].UB[0])) - { - GenerateTLBWriteException(Address, __FUNCTION__); - } + g_MMU->SB_Memory(Address, _GPR[m_Opcode.rt].UB[0]); } void R4300iOp::SH() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 1) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, false); - } - if (HaveWriteBP() && g_Debugger->WriteBP16(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->SH_VAddr(Address, _GPR[m_Opcode.rt].UHW[0])) - { - GenerateTLBWriteException(Address, __FUNCTION__); - } + g_MMU->SH_Memory(Address, _GPR[m_Opcode.rt].UHW[0]); } void R4300iOp::SWL() { - uint32_t Offset, Address, Value; - - Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint()) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->MemoryValue32(Address & ~3, MemoryValue)) { - return; + uint32_t Offset = Address & 3; + MemoryValue &= SWL_MASK[Offset]; + MemoryValue += _GPR[m_Opcode.rt].UW[0] >> SWL_SHIFT[Offset]; + g_MMU->SW_Memory(Address & ~3, MemoryValue); } - Offset = Address & 3; - - if (!g_MMU->LW_Memory((Address & ~3), Value)) + else { GenerateTLBWriteException(Address, __FUNCTION__); - return; } - - Value &= SWL_MASK[Offset]; - Value += _GPR[m_Opcode.rt].UW[0] >> SWL_SHIFT[Offset]; - g_MMU->SW_VAddr((Address & ~0x03), Value); } void R4300iOp::SW() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, false); - } - if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->SW_VAddr(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBWriteException(Address, __FUNCTION__); - } + g_MMU->SW_Memory(Address, _GPR[m_Opcode.rt].UW[0]); } uint64_t SDL_MASK[8] = { 0, 0xFF00000000000000, @@ -1276,24 +1135,19 @@ int32_t SDL_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; void R4300iOp::SDL() { - uint32_t Offset, Address; - uint64_t Value; - - Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint()) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; + uint64_t MemoryValue; + if (g_MMU->MemoryValue64((Address & ~7), MemoryValue)) { - return; + uint32_t Offset = Address & 7; + MemoryValue &= SDL_MASK[Offset]; + MemoryValue += _GPR[m_Opcode.rt].UDW >> SDL_SHIFT[Offset]; + g_MMU->SD_Memory((Address & ~7), MemoryValue); } - Offset = Address & 7; - - if (!g_MMU->LD_Memory((Address & ~7), Value)) + else { GenerateTLBWriteException(Address, __FUNCTION__); } - - Value &= SDL_MASK[Offset]; - Value += _GPR[m_Opcode.rt].UDW >> SDL_SHIFT[Offset]; - g_MMU->SD_VAddr((Address & ~7), Value); } uint64_t SDR_MASK[8] = { 0x00FFFFFFFFFFFFFF, @@ -1309,43 +1163,30 @@ int32_t SDR_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; void R4300iOp::SDR() { - uint32_t Offset, Address; - uint64_t Value; - - Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint()) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; + uint64_t MemoryValue; + if (g_MMU->MemoryValue64((Address & ~7), MemoryValue)) { - return; + uint32_t Offset = Address & 7; + MemoryValue &= SDR_MASK[Offset]; + MemoryValue += _GPR[m_Opcode.rt].UDW << SDR_SHIFT[Offset]; + g_MMU->SD_Memory((Address & ~7), MemoryValue); } - Offset = Address & 7; - - if (!g_MMU->LD_Memory((Address & ~7), Value)) + else { GenerateTLBWriteException(Address, __FUNCTION__); - return; } - - Value &= SDR_MASK[Offset]; - Value += _GPR[m_Opcode.rt].UDW << SDR_SHIFT[Offset]; - g_MMU->SD_VAddr((Address & ~7), Value); } void R4300iOp::SWR() { - uint32_t Offset, Address, Value; - - Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint()) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->MemoryValue32((Address & ~3), MemoryValue)) { - return; - } - Offset = Address & 3; - - if (g_MMU->LW_Memory((Address & ~3), Value)) - { - Value &= SWR_MASK[Offset]; - Value += _GPR[m_Opcode.rt].UW[0] << SWR_SHIFT[Offset]; - g_MMU->SW_VAddr((Address & ~0x03), Value); + uint32_t Offset = Address & 3; + MemoryValue &= SWR_MASK[Offset]; + MemoryValue += _GPR[m_Opcode.rt].UW[0] << SWR_SHIFT[Offset]; + g_MMU->SW_Memory((Address & ~0x03), MemoryValue); } else { @@ -1365,165 +1206,70 @@ void R4300iOp::CACHE() void R4300iOp::LL() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->LW_Memory(Address, MemoryValue)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - - if (!g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rt].W[0]; + _GPR[m_Opcode.rt].DW = (int32_t)MemoryValue; (*_LLBit) = 1; } } void R4300iOp::LWC1() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (uint32_t)((int16_t)m_Opcode.offset); TEST_COP1_USABLE_EXCEPTION(); - if ((Address & 3) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LW_Memory(Address, *(uint32_t *)_FPR_S[m_Opcode.ft])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (uint32_t)((int16_t)m_Opcode.offset); + g_MMU->LW_Memory(Address, *(uint32_t *)_FPR_S[m_Opcode.ft]); } void R4300iOp::SC() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) + if ((*_LLBit) != 1 || g_MMU->SW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) { - ADDRESS_ERROR_EXCEPTION(Address, false); + _GPR[m_Opcode.rt].UW[0] = (*_LLBit); } - if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint()) - { - return; - } - if ((*_LLBit) == 1) - { - if (!g_MMU->SW_VAddr(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBWriteException(Address, __FUNCTION__); - return; - } - } - _GPR[m_Opcode.rt].UW[0] = (*_LLBit); } void R4300iOp::LD() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 7) != 0) + if (g_MMU->LD_Memory(Address, _GPR[m_Opcode.rt].UDW)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP64(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LD_Memory(Address, _GPR[m_Opcode.rt].UDW)) - { - GenerateTLBWriteException(Address, __FUNCTION__); - return; - } #ifdef Interpreter_StackTest - if (m_Opcode.rt == 29) - { - StackValue = _GPR[m_Opcode.rt].W[0]; - } + if (m_Opcode.rt == 29) + { + StackValue = _GPR[m_Opcode.rt].W[0]; + } #endif + } } void R4300iOp::LDC1() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - TEST_COP1_USABLE_EXCEPTION(); - if ((Address & 7) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP64(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LD_Memory(Address, *(uint64_t *)_FPR_D[m_Opcode.ft])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; + g_MMU->LD_Memory(Address, *(uint64_t *)_FPR_D[m_Opcode.ft]); } void R4300iOp::SWC1() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; TEST_COP1_USABLE_EXCEPTION(); - if ((Address & 3) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, false); - } - if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->SW_VAddr(Address, *(uint32_t *)_FPR_S[m_Opcode.ft])) - { - GenerateTLBWriteException(Address, __FUNCTION__); - } + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; + g_MMU->SW_Memory(Address, *(uint32_t *)_FPR_S[m_Opcode.ft]); } void R4300iOp::SDC1() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - TEST_COP1_USABLE_EXCEPTION(); - if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint()) - { - return; - } - - if ((Address & 7) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, false); - } - if (!g_MMU->SD_VAddr(Address, *(int64_t *)_FPR_D[m_Opcode.ft])) - { - GenerateTLBWriteException(Address, __FUNCTION__); - } + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; + g_MMU->SD_Memory(Address, *((uint64_t *)_FPR_D[m_Opcode.ft])); } void R4300iOp::SD() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 7) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, false); - } - if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->SD_VAddr(Address, _GPR[m_Opcode.rt].UDW)) - { - GenerateTLBWriteException(Address, __FUNCTION__); - } + g_MMU->SD_Memory(Address, _GPR[m_Opcode.rt].UDW); } // R4300i opcodes: Special @@ -2890,6 +2636,13 @@ bool R4300iOp::MemoryBreakpoint() return false; } +void R4300iOp::GenerateAddressErrorException(uint32_t VAddr, bool FromRead) +{ + g_Reg->DoAddressError(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP, VAddr, FromRead); + g_System->m_PipelineStage = PIPELINE_STAGE_JUMP; + g_System->m_JumpToLocation = (*_PROGRAM_COUNTER); +} + void R4300iOp::GenerateTLBReadException(uint32_t VAddr, const char * function) { if (bShowTLBMisses()) diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h index 642e9d319..3a8de54db 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h @@ -238,6 +238,7 @@ protected: static Func Jump_CoP1_W[64]; static Func Jump_CoP1_L[64]; + static void GenerateAddressErrorException(uint32_t VAddr, bool FromRead); static void GenerateTLBReadException(uint32_t VAddr, const char * function); static void GenerateTLBWriteException(uint32_t VAddr, const char * function); diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp index 722a984b1..163c49dc4 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp @@ -10,12 +10,6 @@ bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2); -#define ADDRESS_ERROR_EXCEPTION(Address,FromRead) \ - g_Reg->DoAddressError(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,Address,FromRead);\ - g_System->m_PipelineStage = PIPELINE_STAGE_JUMP;\ - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER);\ - return; - #define TEST_COP1_USABLE_EXCEPTION \ if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\ g_Reg->DoCopUnusableException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,1);\ @@ -878,184 +872,82 @@ void R4300iOp32::BGTZL() void R4300iOp32::LB() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP8(Address) && MemoryBreakpoint()) + uint8_t MemoryValue; + if (g_MMU->LB_Memory(Address, MemoryValue)) { - return; - } - if (!g_MMU->LB_Memory(Address, _GPR[m_Opcode.rt].UB[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].W[0] = _GPR[m_Opcode.rt].B[0]; + _GPR[m_Opcode.rt].W[0] = (int8_t)MemoryValue; } } void R4300iOp32::LH() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 1) != 0) + uint16_t MemoryValue; + if (g_MMU->LH_Memory(Address, MemoryValue)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP16(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LH_Memory(Address, _GPR[m_Opcode.rt].UHW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].W[0] = _GPR[m_Opcode.rt].HW[0]; + _GPR[m_Opcode.rt].W[0] = (int16_t)MemoryValue; } } void R4300iOp32::LWL() { - uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - uint32_t Value; - if (!g_MMU->LW_Memory((Address & ~3), Value)) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->LW_Memory((Address & ~3), MemoryValue)) { uint32_t Offset = Address & 3; _GPR[m_Opcode.rt].W[0] = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWL_MASK[Offset]); - _GPR[m_Opcode.rt].W[0] += (int32_t)(Value << LWL_SHIFT[Offset]); + _GPR[m_Opcode.rt].W[0] += (int32_t)(MemoryValue << LWL_SHIFT[Offset]); } } void R4300iOp32::LW() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].W[0] = _GPR[m_Opcode.rt].W[0]; - } + g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0]); } void R4300iOp32::LBU() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if (HaveReadBP() && g_Debugger->ReadBP8(Address) && MemoryBreakpoint()) + uint8_t MemoryValue; + if (g_MMU->LB_Memory(Address, MemoryValue)) { - return; - } - if (!g_MMU->LB_Memory(Address, _GPR[m_Opcode.rt].UB[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].UW[0] = _GPR[m_Opcode.rt].UB[0]; + _GPR[m_Opcode.rt].UW[0] = MemoryValue; } } void R4300iOp32::LHU() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 1) != 0) + uint16_t MemoryValue; + if (g_MMU->LH_Memory(Address, MemoryValue)) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP16(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LH_Memory(Address, _GPR[m_Opcode.rt].UHW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].UW[0] = _GPR[m_Opcode.rt].UHW[0]; + _GPR[m_Opcode.rt].UW[0] = MemoryValue; } } void R4300iOp32::LWR() { - uint32_t Offset, Address, Value; - - Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - Offset = Address & 3; - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) + uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue; + if (g_MMU->LW_Memory((Address & ~3), MemoryValue)) { - return; + uint32_t Offset = Address & 3; + _GPR[m_Opcode.rt].W[0] = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWR_MASK[Offset]); + _GPR[m_Opcode.rt].W[0] += (int32_t)(MemoryValue >> LWR_SHIFT[Offset]); } - if (!g_MMU->LW_Memory((Address & ~3), Value)) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - if (bShowTLBMisses()) - { - g_Notify->DisplayError(stdstr_f("%s TLB: %X", __FUNCTION__, Address).c_str()); - } - return; - } - - _GPR[m_Opcode.rt].W[0] = (int32_t)(_GPR[m_Opcode.rt].W[0] & LWR_MASK[Offset]); - _GPR[m_Opcode.rt].W[0] += (int32_t)(Value >> LWR_SHIFT[Offset]); } void R4300iOp32::LWU() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) - { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].UW[0] = _GPR[m_Opcode.rt].UW[0]; - } + g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0]); } void R4300iOp32::LL() { uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; - if ((Address & 3) != 0) + if (g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) { - ADDRESS_ERROR_EXCEPTION(Address, true); - } - if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) - { - return; - } - if (!g_MMU->LW_Memory(Address, _GPR[m_Opcode.rt].UW[0])) - { - GenerateTLBReadException(Address, __FUNCTION__); - } - else - { - _GPR[m_Opcode.rt].W[0] = _GPR[m_Opcode.rt].W[0]; (*_LLBit) = 1; } } diff --git a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp index b648ca024..4694ad544 100755 --- a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp +++ b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -266,27 +267,27 @@ void CMipsMemoryVM::FreeMemory() CPifRam::Reset(); } -uint8_t * CMipsMemoryVM::MemoryPtr(uint32_t VAddr, uint32_t size, bool Read) +uint8_t * CMipsMemoryVM::MemoryPtr(uint32_t VAddr, uint32_t Size, bool Read) { if (m_TLB_ReadMap[VAddr >> 12] == -1) { return nullptr; } uint32_t PAddr = m_TLB_ReadMap[VAddr >> 12] + VAddr; - if ((PAddr + size) < m_AllocatedRdramSize) + if ((PAddr + Size) < m_AllocatedRdramSize) { return (uint8_t*)(m_RDRAM + PAddr); } - if (PAddr >= 0x04000000 && (PAddr + size) < 0x04001000) + if (PAddr >= 0x04000000 && (PAddr + Size) < 0x04001000) { return (uint8_t*)(m_DMEM + (PAddr - 0x04000000)); } - if (PAddr >= 0x04001000 && (PAddr + size) < 0x04002000) + if (PAddr >= 0x04001000 && (PAddr + Size) < 0x04002000) { return (uint8_t*)(m_IMEM + (PAddr - 0x04001000)); } - if (Read && PAddr >= 0x10000000 && (PAddr + size) < (0x10000000 + m_Rom.GetRomSize())) + if (Read && PAddr >= 0x10000000 && (PAddr + Size) < (0x10000000 + m_Rom.GetRomSize())) { return (uint8_t *)&m_Rom.GetRomAddress()[PAddr - 0x10000000]; } @@ -329,6 +330,17 @@ bool CMipsMemoryVM::MemoryValue32(uint32_t VAddr, uint32_t & Value) return true; } +bool CMipsMemoryVM::MemoryValue64(uint32_t VAddr, uint64_t & Value) +{ + uint8_t * ptr = MemoryPtr(VAddr, 8, true); + if (ptr == nullptr) + { + return false; + } + Value = *(uint64_t*)(ptr); + return true; +} + bool CMipsMemoryVM::UpdateMemoryValue8(uint32_t VAddr, uint8_t Value) { uint8_t * ptr = MemoryPtr(VAddr ^ 3, 1, false); @@ -364,6 +376,10 @@ bool CMipsMemoryVM::UpdateMemoryValue32(uint32_t VAddr, uint32_t Value) bool CMipsMemoryVM::LB_Memory(uint32_t VAddr, uint8_t& Value) { + if (HaveReadBP() && g_Debugger->ReadBP8(VAddr) && MemoryBreakpoint()) + { + return false; + } uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12]; if (MemoryPtr != (uint8_t*)-1) { @@ -373,6 +389,7 @@ bool CMipsMemoryVM::LB_Memory(uint32_t VAddr, uint8_t& Value) uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12]; if (BaseAddress == -1) { + GenerateTLBReadException(VAddr, __FUNCTION__); return false; } return LB_NonMemory(VAddr, Value); @@ -380,6 +397,15 @@ bool CMipsMemoryVM::LB_Memory(uint32_t VAddr, uint8_t& Value) bool CMipsMemoryVM::LH_Memory(uint32_t VAddr, uint16_t & Value) { + if ((VAddr & 1) != 0) + { + GenerateAddressErrorException(VAddr, true); + return false; + } + if (HaveReadBP() && g_Debugger->ReadBP16(VAddr) && MemoryBreakpoint()) + { + return false; + } uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12]; if (MemoryPtr != (uint8_t*)-1) { @@ -389,6 +415,7 @@ bool CMipsMemoryVM::LH_Memory(uint32_t VAddr, uint16_t & Value) uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12]; if (BaseAddress == -1) { + GenerateTLBReadException(VAddr, __FUNCTION__); return false; } return LH_NonMemory(VAddr, Value); @@ -396,6 +423,15 @@ bool CMipsMemoryVM::LH_Memory(uint32_t VAddr, uint16_t & Value) bool CMipsMemoryVM::LW_Memory(uint32_t VAddr, uint32_t & Value) { + if ((VAddr & 3) != 0) + { + GenerateAddressErrorException(VAddr, true); + return false; + } + if (HaveReadBP() && g_Debugger->ReadBP32(VAddr) && MemoryBreakpoint()) + { + return false; + } uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12]; if (MemoryPtr != (uint8_t *)-1) { @@ -405,6 +441,7 @@ bool CMipsMemoryVM::LW_Memory(uint32_t VAddr, uint32_t & Value) uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12]; if (BaseAddress == -1) { + GenerateTLBReadException(VAddr, __FUNCTION__); return false; } return LW_NonMemory(VAddr, Value); @@ -412,6 +449,15 @@ bool CMipsMemoryVM::LW_Memory(uint32_t VAddr, uint32_t & Value) bool CMipsMemoryVM::LD_Memory(uint32_t VAddr, uint64_t& Value) { + if ((VAddr & 7) != 0) + { + GenerateAddressErrorException(VAddr, true); + return false; + } + if (HaveReadBP() && g_Debugger->ReadBP64(VAddr) && MemoryBreakpoint()) + { + return false; + } uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12]; if (MemoryPtr != (uint8_t *)-1) { @@ -427,8 +473,12 @@ bool CMipsMemoryVM::LD_Memory(uint32_t VAddr, uint64_t& Value) return LD_NonMemory(VAddr, Value); } -bool CMipsMemoryVM::SB_VAddr(uint32_t VAddr, uint8_t Value) +bool CMipsMemoryVM::SB_Memory(uint32_t VAddr, uint8_t Value) { + if (HaveWriteBP() && g_Debugger->WriteBP8(VAddr) && MemoryBreakpoint()) + { + return false; + } uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12]; if (MemoryPtr != (uint8_t *)-1) { @@ -437,13 +487,23 @@ bool CMipsMemoryVM::SB_VAddr(uint32_t VAddr, uint8_t Value) } if (m_TLB_WriteMap[VAddr >> 12] == -1) { + GenerateTLBWriteException(VAddr, __FUNCTION__); return false; } return SB_NonMemory(VAddr, Value); } -bool CMipsMemoryVM::SH_VAddr(uint32_t VAddr, uint16_t Value) +bool CMipsMemoryVM::SH_Memory(uint32_t VAddr, uint16_t Value) { + if ((VAddr & 1) != 0) + { + GenerateAddressErrorException(VAddr, false); + return false; + } + if (HaveWriteBP() && g_Debugger->WriteBP16(VAddr) && MemoryBreakpoint()) + { + return false; + } uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12]; if (MemoryPtr != (uint8_t *)-1) { @@ -453,13 +513,23 @@ bool CMipsMemoryVM::SH_VAddr(uint32_t VAddr, uint16_t Value) uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12]; if (BaseAddress == -1) { + GenerateTLBWriteException(VAddr, __FUNCTION__); return false; } return SH_NonMemory(VAddr, Value); } -bool CMipsMemoryVM::SW_VAddr(uint32_t VAddr, uint32_t Value) +bool CMipsMemoryVM::SW_Memory(uint32_t VAddr, uint32_t Value) { + if ((VAddr & 3) != 0) + { + GenerateAddressErrorException(VAddr, false); + return false; + } + if (HaveWriteBP() && g_Debugger->WriteBP32(VAddr) && MemoryBreakpoint()) + { + return false; + } uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12]; if (MemoryPtr != (uint8_t *)-1) { @@ -469,13 +539,24 @@ bool CMipsMemoryVM::SW_VAddr(uint32_t VAddr, uint32_t Value) uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12]; if (BaseAddress == -1) { + GenerateTLBWriteException(VAddr, __FUNCTION__); return false; } return SW_NonMemory(VAddr, Value); } -bool CMipsMemoryVM::SD_VAddr(uint32_t VAddr, uint64_t Value) +bool CMipsMemoryVM::SD_Memory(uint32_t VAddr, uint64_t Value) { + if ((VAddr & 7) != 0) + { + GenerateAddressErrorException(VAddr, false); + return false; + } + if (HaveWriteBP() && g_Debugger->WriteBP64(VAddr) && MemoryBreakpoint()) + { + return false; + } + uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12]; if (MemoryPtr != (uint8_t *)-1) { @@ -485,6 +566,7 @@ bool CMipsMemoryVM::SD_VAddr(uint32_t VAddr, uint64_t Value) } if (m_TLB_WriteMap[VAddr >> 12] == -1) { + GenerateTLBWriteException(VAddr, __FUNCTION__); return false; } return SD_NonMemory(VAddr, Value); diff --git a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h index e171e9e0f..8269fad51 100644 --- a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h +++ b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h @@ -73,11 +73,12 @@ public: CSram & GetSram() { return m_CartridgeDomain2Address2Handler.Sram(); } CFlashRam & GetFlashRam() { return m_CartridgeDomain2Address2Handler.FlashRam(); } - uint8_t * MemoryPtr(uint32_t VAddr, uint32_t size, bool Read); + uint8_t * MemoryPtr(uint32_t VAddr, uint32_t Size, bool Read); bool MemoryValue8(uint32_t VAddr, uint8_t & Value); bool MemoryValue16(uint32_t VAddr, uint16_t & Value); bool MemoryValue32(uint32_t VAddr, uint32_t & Value); + bool MemoryValue64(uint32_t VAddr, uint64_t & Value); bool UpdateMemoryValue8(uint32_t VAddr, uint8_t Value); bool UpdateMemoryValue16(uint32_t VAddr, uint16_t Value); @@ -88,10 +89,10 @@ public: bool LW_Memory(uint32_t VAddr, uint32_t & Value); bool LD_Memory(uint32_t VAddr, uint64_t & Value); - bool SB_VAddr(uint32_t VAddr, uint8_t Value); - bool SH_VAddr(uint32_t VAddr, uint16_t Value); - bool SW_VAddr(uint32_t VAddr, uint32_t Value); - bool SD_VAddr(uint32_t VAddr, uint64_t Value); + bool SB_Memory(uint32_t VAddr, uint8_t Value); + bool SH_Memory(uint32_t VAddr, uint16_t Value); + bool SW_Memory(uint32_t VAddr, uint32_t Value); + bool SD_Memory(uint32_t VAddr, uint64_t Value); int32_t MemoryFilter(uint32_t dwExptCode, void * lpExceptionPointer);