Core: Move memory exceptions out of interrupter ops and in to Memory Manager

This commit is contained in:
zilmar 2022-06-13 11:24:36 +09:30
parent d2b33022fb
commit 86aa483a38
5 changed files with 210 additions and 481 deletions

View File

@ -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())

View File

@ -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);

View File

@ -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;
}
}

View File

@ -7,6 +7,7 @@
#include <Project64-core\N64System\Recompiler\RecompilerCodeLog.h>
#include <Project64-core\N64System\Mips\OpcodeName.h>
#include <Project64-core\N64System\Mips\Disk.h>
#include <Project64-core\Debugger.h>
#include <Project64-core\ExceptionHandler.h>
#include <Common\MemoryManagement.h>
#include <stdio.h>
@ -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);

View File

@ -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);