Core: Have CRegisters::DoAddressError to not directly modify program counter

This commit is contained in:
zilmar 2023-09-14 11:37:21 +09:30
parent 2d09178449
commit a5a4873e84
5 changed files with 21 additions and 14 deletions

View File

@ -134,6 +134,8 @@ void CInterpreterCPU::ExecuteCPU()
if ((PROGRAM_COUNTER & 0x3) != 0)
{
GenerateAddressErrorException((int32_t)JumpToLocation, true);
PROGRAM_COUNTER = JumpToLocation;
PipelineStage = PIPELINE_STAGE_NORMAL;
}
else if (CheckTimer)
{

View File

@ -3045,9 +3045,7 @@ bool R4300iOp::MemoryBreakpoint()
void R4300iOp::GenerateAddressErrorException(uint64_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);
g_Reg->DoAddressError(VAddr, FromRead);
}
void R4300iOp::GenerateTLBReadException(uint64_t VAddr, const char * function)

View File

@ -528,7 +528,7 @@ void CRegisters::CheckInterrupts()
}
}
void CRegisters::DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead)
void CRegisters::DoAddressError(uint64_t BadVaddr, bool FromRead)
{
if (BreakOnAddressError())
{
@ -549,7 +549,7 @@ void CRegisters::DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead
XCONTEXT_REGISTER.BadVPN2 = BadVaddr >> 13;
XCONTEXT_REGISTER.R = BadVaddr >> 61;
if (DelaySlot)
if (m_System->m_PipelineStage == PIPELINE_STAGE_JUMP)
{
CAUSE_REGISTER.BranchDelay = 1;
EPC_REGISTER = (int32_t)(m_PROGRAM_COUNTER - 4);
@ -560,7 +560,8 @@ void CRegisters::DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead
EPC_REGISTER = (int32_t)m_PROGRAM_COUNTER;
}
STATUS_REGISTER.ExceptionLevel = 1;
m_PROGRAM_COUNTER = 0x80000180;
m_System->m_JumpToLocation = 0x80000180;
m_System->m_PipelineStage = PIPELINE_STAGE_JUMP;
}
void CRegisters::FixFpuLocations()

View File

@ -450,7 +450,7 @@ public:
CRegisters(CN64System * System, CSystemEvents * SystemEvents);
void CheckInterrupts();
void DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead);
void DoAddressError(uint64_t BadVaddr, bool FromRead);
bool DoIntrException();
void DoTLBReadMiss(bool DelaySlot, uint64_t BadVaddr);
void DoTLBWriteMiss(bool DelaySlot, uint64_t BadVaddr);

View File

@ -9659,7 +9659,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
ExitCodeBlock();
break;
case ExitReason_DoSysCall:
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.push(0);
m_Assembler.PushImm32("EXC_SYSCALL", EXC_SYSCALL);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12);
@ -9669,7 +9669,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
ExitCodeBlock();
break;
case ExitReason_Break:
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.push(0);
m_Assembler.PushImm32("EXC_BREAK", EXC_BREAK);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12);
@ -9679,7 +9679,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
ExitCodeBlock();
break;
case ExitReason_COP1Unuseable:
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.push(1);
m_Assembler.PushImm32("EXC_CPU", EXC_CPU);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12);
@ -9707,7 +9707,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
ExitCodeBlock();
break;
case ExitReason_ExceptionOverflow:
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.push(0);
m_Assembler.PushImm32("EXC_OV", EXC_OV);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12);
@ -9717,28 +9717,34 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
ExitCodeBlock();
break;
case ExitReason_AddressErrorExceptionRead32:
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.push(1);
m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &m_TempValue32, "TempValue32");
m_Assembler.mov(asmjit::x86::eax, asmjit::x86::edx);
m_Assembler.sar(asmjit::x86::eax, 31);
m_Assembler.push(asmjit::x86::eax);
m_Assembler.push(asmjit::x86::edx);
m_Assembler.PushImm32(InDelaySlot ? "true" : "false", InDelaySlot);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoAddressError), "CRegisters::DoAddressError", 12);
m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &g_System->m_JumpToLocation, "System->m_JumpToLocation");
m_Assembler.MoveX86regToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", asmjit::x86::edx);
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
ExitCodeBlock();
break;
case ExitReason_AddressErrorExceptionRead64:
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.push(1);
m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &m_TempValue64, "TempValue64");
m_Assembler.MoveVariableToX86reg(asmjit::x86::eax, &m_TempValue64 + 4, "TempValue64+4");
m_Assembler.push(asmjit::x86::eax);
m_Assembler.push(asmjit::x86::edx);
m_Assembler.PushImm32(InDelaySlot ? "true" : "false", InDelaySlot);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoAddressError), "CRegisters::DoAddressError", 12);
m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &g_System->m_JumpToLocation, "System->m_JumpToLocation");
m_Assembler.MoveX86regToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", asmjit::x86::edx);
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
ExitCodeBlock();
break;
case ExitReason_IllegalInstruction:
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL);
m_Assembler.push(0);
m_Assembler.PushImm32("EXC_II", EXC_II);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12);