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::LWL_SHIFT[4] = { 0, 8, 16, 24 };
const int32_t R4300iOp::LWR_SHIFT[4] = { 24, 16, 8, 0 }; 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() \ #define TEST_COP1_USABLE_EXCEPTION() \
if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\ if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\
g_Reg->DoCopUnusableException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,1);\ 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() void R4300iOp::LDL()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveReadBP() && g_Debugger->ReadBP64(Address) && MemoryBreakpoint()) uint64_t MemoryValue;
{ if (g_MMU->LD_Memory((Address & ~7), MemoryValue))
return;
}
uint64_t Value;
if (!g_MMU->LD_Memory((Address & ~7), Value))
{
GenerateTLBReadException(Address, __FUNCTION__);
}
else
{ {
uint32_t Offset = Address & 7; uint32_t Offset = Address & 7;
_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 += MemoryValue << LDL_SHIFT[Offset];
} }
} }
@ -1015,253 +1000,127 @@ int32_t LDR_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 };
void R4300iOp::LDR() void R4300iOp::LDR()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveReadBP() && g_Debugger->ReadBP64(Address) && MemoryBreakpoint()) uint64_t MemoryValue;
{ if (g_MMU->LD_Memory((Address & ~7), MemoryValue))
return;
}
uint64_t Value;
if (!g_MMU->LD_Memory((Address & ~7), Value))
{
GenerateTLBReadException(Address, __FUNCTION__);
}
else
{ {
uint32_t Offset = Address & 7; uint32_t Offset = Address & 7;
_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];
_GPR[m_Opcode.rt].DW += Value >> LDR_SHIFT[Offset]; _GPR[m_Opcode.rt].DW += MemoryValue >> LDR_SHIFT[Offset];
} }
} }
void R4300iOp::LB() void R4300iOp::LB()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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; _GPR[m_Opcode.rt].DW = (int8_t)MemoryValue;
}
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];
} }
} }
void R4300iOp::LH() void R4300iOp::LH()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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); _GPR[m_Opcode.rt].DW = (int16_t)MemoryValue;
}
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];
} }
} }
void R4300iOp::LWL() void R4300iOp::LWL()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) if (g_MMU->LW_Memory((Address & ~3), MemoryValue))
{
return;
}
uint32_t Value;
if (!g_MMU->LW_Memory((Address & ~3), Value))
{
GenerateTLBReadException(Address, __FUNCTION__);
}
else
{ {
uint32_t Offset = Address & 3; 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)(_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() void R4300iOp::LW()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if ((Address & 3) != 0) if (g_MMU->LW_Memory(Address, MemoryValue))
{ {
ADDRESS_ERROR_EXCEPTION(Address, true); _GPR[m_Opcode.rt].DW = (int32_t)MemoryValue;
}
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];
} }
} }
void R4300iOp::LBU() void R4300iOp::LBU()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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; _GPR[m_Opcode.rt].UDW = MemoryValue;
}
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];
} }
} }
void R4300iOp::LHU() void R4300iOp::LHU()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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); _GPR[m_Opcode.rt].UDW = MemoryValue;
}
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];
} }
} }
void R4300iOp::LWR() void R4300iOp::LWR()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) if (g_MMU->LW_Memory((Address & ~3), MemoryValue))
{
return;
}
uint32_t Value;
if (!g_MMU->LW_Memory((Address & ~3), Value))
{
GenerateTLBReadException(Address, __FUNCTION__);
}
else
{ {
uint32_t Offset = Address & 3; 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)(_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() void R4300iOp::LWU()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if ((Address & 3) != 0) if (g_MMU->LW_Memory(Address, MemoryValue))
{ {
ADDRESS_ERROR_EXCEPTION(Address, true); _GPR[m_Opcode.rt].UDW = MemoryValue;
}
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];
} }
} }
void R4300iOp::SB() void R4300iOp::SB()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP8(Address) && MemoryBreakpoint()) g_MMU->SB_Memory(Address, _GPR[m_Opcode.rt].UB[0]);
{
return;
}
if (!g_MMU->SB_VAddr(Address, _GPR[m_Opcode.rt].UB[0]))
{
GenerateTLBWriteException(Address, __FUNCTION__);
}
} }
void R4300iOp::SH() void R4300iOp::SH()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if ((Address & 1) != 0) g_MMU->SH_Memory(Address, _GPR[m_Opcode.rt].UHW[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__);
}
} }
void R4300iOp::SWL() void R4300iOp::SWL()
{ {
uint32_t Offset, Address, Value; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if (g_MMU->MemoryValue32(Address & ~3, MemoryValue))
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint())
{ {
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; else
if (!g_MMU->LW_Memory((Address & ~3), Value))
{ {
GenerateTLBWriteException(Address, __FUNCTION__); 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() void R4300iOp::SW()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if ((Address & 3) != 0) g_MMU->SW_Memory(Address, _GPR[m_Opcode.rt].UW[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__);
}
} }
uint64_t SDL_MASK[8] = { 0, 0xFF00000000000000, 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() void R4300iOp::SDL()
{ {
uint32_t Offset, Address; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
uint64_t Value; uint64_t MemoryValue;
if (g_MMU->MemoryValue64((Address & ~7), MemoryValue))
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint())
{ {
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; else
if (!g_MMU->LD_Memory((Address & ~7), Value))
{ {
GenerateTLBWriteException(Address, __FUNCTION__); 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, 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() void R4300iOp::SDR()
{ {
uint32_t Offset, Address; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
uint64_t Value; uint64_t MemoryValue;
if (g_MMU->MemoryValue64((Address & ~7), MemoryValue))
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint())
{ {
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; else
if (!g_MMU->LD_Memory((Address & ~7), Value))
{ {
GenerateTLBWriteException(Address, __FUNCTION__); 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() void R4300iOp::SWR()
{ {
uint32_t Offset, Address, Value; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if (g_MMU->MemoryValue32((Address & ~3), MemoryValue))
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint())
{ {
return; uint32_t Offset = Address & 3;
} MemoryValue &= SWR_MASK[Offset];
Offset = Address & 3; MemoryValue += _GPR[m_Opcode.rt].UW[0] << SWR_SHIFT[Offset];
g_MMU->SW_Memory((Address & ~0x03), MemoryValue);
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);
} }
else else
{ {
@ -1365,165 +1206,70 @@ void R4300iOp::CACHE()
void R4300iOp::LL() void R4300iOp::LL()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if ((Address & 3) != 0) if (g_MMU->LW_Memory(Address, MemoryValue))
{ {
ADDRESS_ERROR_EXCEPTION(Address, true); _GPR[m_Opcode.rt].DW = (int32_t)MemoryValue;
}
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];
(*_LLBit) = 1; (*_LLBit) = 1;
} }
} }
void R4300iOp::LWC1() void R4300iOp::LWC1()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (uint32_t)((int16_t)m_Opcode.offset);
TEST_COP1_USABLE_EXCEPTION(); TEST_COP1_USABLE_EXCEPTION();
if ((Address & 3) != 0) 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]);
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__);
}
} }
void R4300iOp::SC() void R4300iOp::SC()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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() void R4300iOp::LD()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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 #ifdef Interpreter_StackTest
if (m_Opcode.rt == 29) if (m_Opcode.rt == 29)
{ {
StackValue = _GPR[m_Opcode.rt].W[0]; StackValue = _GPR[m_Opcode.rt].W[0];
} }
#endif #endif
}
} }
void R4300iOp::LDC1() void R4300iOp::LDC1()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
TEST_COP1_USABLE_EXCEPTION(); TEST_COP1_USABLE_EXCEPTION();
if ((Address & 7) != 0) 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]);
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__);
}
} }
void R4300iOp::SWC1() void R4300iOp::SWC1()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
TEST_COP1_USABLE_EXCEPTION(); 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])) 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]);
GenerateTLBWriteException(Address, __FUNCTION__);
}
} }
void R4300iOp::SDC1() void R4300iOp::SDC1()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
TEST_COP1_USABLE_EXCEPTION(); TEST_COP1_USABLE_EXCEPTION();
if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint()) 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]));
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__);
}
} }
void R4300iOp::SD() void R4300iOp::SD()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if ((Address & 7) != 0) g_MMU->SD_Memory(Address, _GPR[m_Opcode.rt].UDW);
{
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__);
}
} }
// R4300i opcodes: Special // R4300i opcodes: Special
@ -2890,6 +2636,13 @@ bool R4300iOp::MemoryBreakpoint()
return false; 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) void R4300iOp::GenerateTLBReadException(uint32_t VAddr, const char * function)
{ {
if (bShowTLBMisses()) if (bShowTLBMisses())

View File

@ -238,6 +238,7 @@ protected:
static Func Jump_CoP1_W[64]; static Func Jump_CoP1_W[64];
static Func Jump_CoP1_L[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 GenerateTLBReadException(uint32_t VAddr, const char * function);
static void GenerateTLBWriteException(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); 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 \ #define TEST_COP1_USABLE_EXCEPTION \
if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\ if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\
g_Reg->DoCopUnusableException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,1);\ g_Reg->DoCopUnusableException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,1);\
@ -878,184 +872,82 @@ void R4300iOp32::BGTZL()
void R4300iOp32::LB() void R4300iOp32::LB()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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; _GPR[m_Opcode.rt].W[0] = (int8_t)MemoryValue;
}
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];
} }
} }
void R4300iOp32::LH() void R4300iOp32::LH()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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); _GPR[m_Opcode.rt].W[0] = (int16_t)MemoryValue;
}
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];
} }
} }
void R4300iOp32::LWL() void R4300iOp32::LWL()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint()) if (g_MMU->LW_Memory((Address & ~3), MemoryValue))
{
return;
}
uint32_t Value;
if (!g_MMU->LW_Memory((Address & ~3), Value))
{
GenerateTLBReadException(Address, __FUNCTION__);
}
else
{ {
uint32_t Offset = Address & 3; 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)(_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() void R4300iOp32::LW()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if ((Address & 3) != 0) 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];
}
} }
void R4300iOp32::LBU() void R4300iOp32::LBU()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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; _GPR[m_Opcode.rt].UW[0] = MemoryValue;
}
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];
} }
} }
void R4300iOp32::LHU() void R4300iOp32::LHU()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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); _GPR[m_Opcode.rt].UW[0] = MemoryValue;
}
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];
} }
} }
void R4300iOp32::LWR() void R4300iOp32::LWR()
{ {
uint32_t Offset, Address, Value; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset, MemoryValue;
if (g_MMU->LW_Memory((Address & ~3), MemoryValue))
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
Offset = Address & 3;
if (HaveReadBP() && g_Debugger->ReadBP32(Address) && MemoryBreakpoint())
{ {
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() void R4300iOp32::LWU()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if ((Address & 3) != 0) 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].UW[0] = _GPR[m_Opcode.rt].UW[0];
}
} }
void R4300iOp32::LL() void R4300iOp32::LL()
{ {
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset; 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; (*_LLBit) = 1;
} }
} }

View File

@ -7,6 +7,7 @@
#include <Project64-core\N64System\Recompiler\RecompilerCodeLog.h> #include <Project64-core\N64System\Recompiler\RecompilerCodeLog.h>
#include <Project64-core\N64System\Mips\OpcodeName.h> #include <Project64-core\N64System\Mips\OpcodeName.h>
#include <Project64-core\N64System\Mips\Disk.h> #include <Project64-core\N64System\Mips\Disk.h>
#include <Project64-core\Debugger.h>
#include <Project64-core\ExceptionHandler.h> #include <Project64-core\ExceptionHandler.h>
#include <Common\MemoryManagement.h> #include <Common\MemoryManagement.h>
#include <stdio.h> #include <stdio.h>
@ -266,27 +267,27 @@ void CMipsMemoryVM::FreeMemory()
CPifRam::Reset(); 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) if (m_TLB_ReadMap[VAddr >> 12] == -1)
{ {
return nullptr; return nullptr;
} }
uint32_t PAddr = m_TLB_ReadMap[VAddr >> 12] + VAddr; 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); 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)); 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)); 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]; return (uint8_t *)&m_Rom.GetRomAddress()[PAddr - 0x10000000];
} }
@ -329,6 +330,17 @@ bool CMipsMemoryVM::MemoryValue32(uint32_t VAddr, uint32_t & Value)
return true; 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) bool CMipsMemoryVM::UpdateMemoryValue8(uint32_t VAddr, uint8_t Value)
{ {
uint8_t * ptr = MemoryPtr(VAddr ^ 3, 1, false); 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) 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12];
if (MemoryPtr != (uint8_t*)-1) 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]; uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12];
if (BaseAddress == -1) if (BaseAddress == -1)
{ {
GenerateTLBReadException(VAddr, __FUNCTION__);
return false; return false;
} }
return LB_NonMemory(VAddr, Value); 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) 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12];
if (MemoryPtr != (uint8_t*)-1) 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]; uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12];
if (BaseAddress == -1) if (BaseAddress == -1)
{ {
GenerateTLBReadException(VAddr, __FUNCTION__);
return false; return false;
} }
return LH_NonMemory(VAddr, Value); 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) 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12];
if (MemoryPtr != (uint8_t *)-1) 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]; uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12];
if (BaseAddress == -1) if (BaseAddress == -1)
{ {
GenerateTLBReadException(VAddr, __FUNCTION__);
return false; return false;
} }
return LW_NonMemory(VAddr, Value); 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) 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryReadMap[VAddr >> 12];
if (MemoryPtr != (uint8_t *)-1) if (MemoryPtr != (uint8_t *)-1)
{ {
@ -427,8 +473,12 @@ bool CMipsMemoryVM::LD_Memory(uint32_t VAddr, uint64_t& Value)
return LD_NonMemory(VAddr, 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12];
if (MemoryPtr != (uint8_t *)-1) 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) if (m_TLB_WriteMap[VAddr >> 12] == -1)
{ {
GenerateTLBWriteException(VAddr, __FUNCTION__);
return false; return false;
} }
return SB_NonMemory(VAddr, Value); 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12];
if (MemoryPtr != (uint8_t *)-1) 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]; uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12];
if (BaseAddress == -1) if (BaseAddress == -1)
{ {
GenerateTLBWriteException(VAddr, __FUNCTION__);
return false; return false;
} }
return SH_NonMemory(VAddr, Value); 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12];
if (MemoryPtr != (uint8_t *)-1) 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]; uint32_t BaseAddress = m_TLB_ReadMap[VAddr >> 12];
if (BaseAddress == -1) if (BaseAddress == -1)
{ {
GenerateTLBWriteException(VAddr, __FUNCTION__);
return false; return false;
} }
return SW_NonMemory(VAddr, Value); 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]; uint8_t * MemoryPtr = (uint8_t*)m_MemoryWriteMap[VAddr >> 12];
if (MemoryPtr != (uint8_t *)-1) 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) if (m_TLB_WriteMap[VAddr >> 12] == -1)
{ {
GenerateTLBWriteException(VAddr, __FUNCTION__);
return false; return false;
} }
return SD_NonMemory(VAddr, Value); return SD_NonMemory(VAddr, Value);

View File

@ -73,11 +73,12 @@ public:
CSram & GetSram() { return m_CartridgeDomain2Address2Handler.Sram(); } CSram & GetSram() { return m_CartridgeDomain2Address2Handler.Sram(); }
CFlashRam & GetFlashRam() { return m_CartridgeDomain2Address2Handler.FlashRam(); } 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 MemoryValue8(uint32_t VAddr, uint8_t & Value);
bool MemoryValue16(uint32_t VAddr, uint16_t & Value); bool MemoryValue16(uint32_t VAddr, uint16_t & Value);
bool MemoryValue32(uint32_t VAddr, uint32_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 UpdateMemoryValue8(uint32_t VAddr, uint8_t Value);
bool UpdateMemoryValue16(uint32_t VAddr, uint16_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 LW_Memory(uint32_t VAddr, uint32_t & Value);
bool LD_Memory(uint32_t VAddr, uint64_t & Value); bool LD_Memory(uint32_t VAddr, uint64_t & Value);
bool SB_VAddr(uint32_t VAddr, uint8_t Value); bool SB_Memory(uint32_t VAddr, uint8_t Value);
bool SH_VAddr(uint32_t VAddr, uint16_t Value); bool SH_Memory(uint32_t VAddr, uint16_t Value);
bool SW_VAddr(uint32_t VAddr, uint32_t Value); bool SW_Memory(uint32_t VAddr, uint32_t Value);
bool SD_VAddr(uint32_t VAddr, uint64_t Value); bool SD_Memory(uint32_t VAddr, uint64_t Value);
int32_t MemoryFilter(uint32_t dwExptCode, void * lpExceptionPointer); int32_t MemoryFilter(uint32_t dwExptCode, void * lpExceptionPointer);