Core: Have CRegisters::DoTLBReadMiss set the target pipe line to jump, not directly modify the PC

This commit is contained in:
zilmar 2023-09-14 11:09:28 +09:30
parent fcd7257adc
commit 5da5dab3c5
6 changed files with 65 additions and 41 deletions

View File

@ -70,6 +70,7 @@ void CInterpreterCPU::ExecuteCPU()
if (!g_MMU->MemoryValue32(PROGRAM_COUNTER, Opcode.Value))
{
g_Reg->DoTLBReadMiss(PipelineStage == PIPELINE_STAGE_JUMP, PROGRAM_COUNTER);
PROGRAM_COUNTER = JumpToLocation;
PipelineStage = PIPELINE_STAGE_NORMAL;
continue;
}
@ -279,6 +280,7 @@ void CInterpreterCPU::ExecuteOps(int32_t Cycles)
else
{
g_Reg->DoTLBReadMiss(PipelineStage == PIPELINE_STAGE_JUMP, PROGRAM_COUNTER);
PROGRAM_COUNTER = JumpToLocation;
PipelineStage = PIPELINE_STAGE_NORMAL;
}
}

View File

@ -3057,8 +3057,6 @@ void R4300iOp::GenerateTLBReadException(uint64_t VAddr, const char * function)
g_Notify->DisplayError(stdstr_f("%s TLB: %X", function, (uint32_t)VAddr).c_str());
}
g_Reg->DoTLBReadMiss(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP, VAddr);
g_System->m_PipelineStage = PIPELINE_STAGE_JUMP;
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER);
}
void R4300iOp::GenerateTLBWriteException(uint64_t VAddr, const char * function)

View File

@ -614,11 +614,11 @@ void CRegisters::DoTLBReadMiss(bool DelaySlot, uint64_t BadVaddr)
}
if (g_TLB->AddressDefined((uint32_t)BadVaddr))
{
m_PROGRAM_COUNTER = 0x80000180;
m_System->m_JumpToLocation = 0x80000180;
}
else
{
m_PROGRAM_COUNTER = 0x80000000;
m_System->m_JumpToLocation = 0x80000000;
}
STATUS_REGISTER.ExceptionLevel = 1;
}
@ -628,8 +628,9 @@ void CRegisters::DoTLBReadMiss(bool DelaySlot, uint64_t BadVaddr)
{
g_Notify->DisplayError(stdstr_f("TLBMiss - EXL set\nBadVaddr = %X\nAddress defined: %s", (uint32_t)BadVaddr, g_TLB->AddressDefined((uint32_t)BadVaddr) ? "true" : "false").c_str());
}
m_PROGRAM_COUNTER = 0x80000180;
m_System->m_JumpToLocation = 0x80000180;
}
m_System->m_PipelineStage = PIPELINE_STAGE_JUMP;
}
void CRegisters::DoTLBWriteMiss(bool DelaySlot, uint64_t BadVaddr)

View File

@ -88,6 +88,8 @@ void CRecompiler::RecompilerMain_VirtualTable()
if (!m_MMU.ValidVaddr(PC))
{
m_Registers.DoTLBReadMiss(false, PC);
PC = g_System->m_JumpToLocation;
g_System->m_PipelineStage = PIPELINE_STAGE_NORMAL;
if (!m_MMU.ValidVaddr(PC))
{
g_Notify->DisplayError(stdstr_f("Failed to translate PC to a PAddr: %X\n\nEmulation stopped", PC).c_str());
@ -153,6 +155,8 @@ void CRecompiler::RecompilerMain_Lookup()
g_Notify->DisplayError(stdstr_f("Failed to translate PC to a PAddr: %X\n\nEmulation stopped", PROGRAM_COUNTER).c_str());
m_EndEmulation = true;
}
PROGRAM_COUNTER = g_System->m_JumpToLocation;
g_System->m_PipelineStage = PIPELINE_STAGE_NORMAL;
continue;
}
if (PhysicalAddr < g_System->RdramSize())
@ -211,6 +215,8 @@ void CRecompiler::RecompilerMain_Lookup_validate()
g_Notify->DisplayError(stdstr_f("Failed to translate PC to a PAddr: %X\n\nEmulation stopped", PC).c_str());
Done = true;
}
PROGRAM_COUNTER = g_System->m_JumpToLocation;
g_System->m_PipelineStage = PIPELINE_STAGE_NORMAL;
continue;
}
if (PhysicalAddr < g_System->RdramSize())

View File

@ -35,7 +35,7 @@ g_Notify->BreakPoint(__FILE__, __LINE__);
}
}*/
static void x86_compiler_Break_Point()
void CX86RecompilerOps::x86CompilerBreakPoint()
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
do
@ -51,6 +51,8 @@ static void x86_compiler_Break_Point()
if (!g_MMU->MemoryValue32(g_Reg->m_PROGRAM_COUNTER, OpcodeValue))
{
g_Reg->DoTLBReadMiss(false, g_Reg->m_PROGRAM_COUNTER);
g_Reg->m_PROGRAM_COUNTER = g_System->JumpToLocation();
g_System->m_PipelineStage = PIPELINE_STAGE_NORMAL;
continue;
}
continue;
@ -75,7 +77,7 @@ static void x86_compiler_Break_Point()
}
}
static void x86_Break_Point_DelaySlot()
void CX86RecompilerOps::x86BreakPointDelaySlot()
{
CInterpreterCPU::ExecuteOps(g_System->CountPerOp());
if (g_SyncSystem)
@ -85,7 +87,7 @@ static void x86_Break_Point_DelaySlot()
}
if (g_Debugger->ExecutionBP(g_Reg->m_PROGRAM_COUNTER))
{
x86_compiler_Break_Point();
x86CompilerBreakPoint();
}
if (g_System->PipelineStage() != PIPELINE_STAGE_NORMAL)
{
@ -102,7 +104,7 @@ static uint32_t memory_access_address;
static uint32_t memory_write_in_delayslot;
static uint32_t memory_breakpoint_found = 0;
static void x86MemoryBreakpoint()
void CX86RecompilerOps::x86MemoryBreakPoint()
{
memory_breakpoint_found = 1;
if (memory_write_in_delayslot)
@ -111,70 +113,70 @@ static void x86MemoryBreakpoint()
*g_NextTimer += g_System->CountPerOp();
CInterpreterCPU::ExecuteOps(g_System->CountPerOp());
}
x86_compiler_Break_Point();
x86CompilerBreakPoint();
}
static void x86TestReadBreakpoint8()
void CX86RecompilerOps::x86TestReadBreakPoint8()
{
if (g_Debugger->ReadBP8(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
static void x86TestReadBreakpoint16()
void CX86RecompilerOps::x86TestReadBreakPoint16()
{
if (g_Debugger->ReadBP16(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
static void x86TestReadBreakpoint32()
void CX86RecompilerOps::x86TestReadBreakPoint32()
{
if (g_Debugger->ReadBP32(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
static void x86TestReadBreakpoint64()
void CX86RecompilerOps::x86TestReadBreakPoint64()
{
if (g_Debugger->ReadBP64(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
static void x86TestWriteBreakpoint8()
void CX86RecompilerOps::x86TestWriteBreakPoint8()
{
if (g_Debugger->WriteBP8(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
static void x86TestWriteBreakpoint16()
void CX86RecompilerOps::x86TestWriteBreakPoint16()
{
if (g_Debugger->WriteBP16(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
static void x86TestWriteBreakpoint32()
void CX86RecompilerOps::x86TestWriteBreakPoint32()
{
if (g_Debugger->WriteBP32(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
static void x86TestWriteBreakpoint64()
void CX86RecompilerOps::x86TestWriteBreakPoint64()
{
if (g_Debugger->WriteBP64(memory_access_address))
{
x86MemoryBreakpoint();
x86MemoryBreakPoint();
}
}
@ -3215,7 +3217,7 @@ void CX86RecompilerOps::LWL()
m_Assembler.mov(OffsetReg, AddressReg);
m_Assembler.and_(OffsetReg, 3);
m_Assembler.and_(AddressReg, (uint32_t)~3);
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakpoint32, "x86TestReadBreakpoint32");
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakPoint32, "x86TestReadBreakpoint32");
CompileLoadMemoryValue(AddressReg, AddressReg, x86Reg_Unknown, 32, false);
m_RegWorkingSet.Map_GPR_32bit(m_Opcode.rt, true, m_Opcode.rt);
m_Assembler.AndVariableDispToX86Reg(m_RegWorkingSet.GetMipsRegMapLo(m_Opcode.rt), (void *)R4300iOp::LWL_MASK, "LWL_MASK", OffsetReg, CX86Ops::Multip_x4);
@ -3595,7 +3597,7 @@ void CX86RecompilerOps::LWR()
m_Assembler.mov(OffsetReg, AddressReg);
m_Assembler.and_(OffsetReg, 3);
m_Assembler.and_(AddressReg, (uint32_t)~3);
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakpoint32, "x86TestReadBreakpoint32");
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakPoint32, "x86TestReadBreakpoint32");
CompileLoadMemoryValue(AddressReg, AddressReg, x86Reg_Unknown, 32, false);
m_RegWorkingSet.Map_GPR_32bit(m_Opcode.rt, true, m_Opcode.rt);
m_Assembler.AndVariableDispToX86Reg(m_RegWorkingSet.GetMipsRegMapLo(m_Opcode.rt), (void *)R4300iOp::LWR_MASK, "LWR_MASK", OffsetReg, CX86Ops::Multip_x4);
@ -3719,7 +3721,7 @@ void CX86RecompilerOps::SWL()
}
PreWriteInstruction();
asmjit::x86::Gp shift = m_RegWorkingSet.Map_TempReg(asmjit::x86::ecx, -1, false, false), AddressReg = BaseOffsetAddress(false);
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakpoint32, "x86TestWriteBreakpoint32");
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakPoint32, "x86TestWriteBreakpoint32");
asmjit::x86::Gp TempReg2 = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false);
asmjit::x86::Gp OffsetReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false);
@ -3882,7 +3884,7 @@ void CX86RecompilerOps::SWR()
PreWriteInstruction();
asmjit::x86::Gp shift = m_RegWorkingSet.Map_TempReg(asmjit::x86::ecx, -1, false, false);
asmjit::x86::Gp AddressReg = BaseOffsetAddress(false);
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakpoint32, "x86TestWriteBreakpoint32");
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakPoint32, "x86TestWriteBreakpoint32");
asmjit::x86::Gp TempReg2 = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false);
asmjit::x86::Gp OffsetReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false);
asmjit::x86::Gp ValueReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false);
@ -8453,7 +8455,7 @@ void CX86RecompilerOps::FoundMemoryBreakpoint()
{
ClearCachedInstructionInfo();
m_Assembler.MoveConstToVariable(&memory_write_in_delayslot, "memory_write_in_delayslot", (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT) ? 1 : 0);
m_Assembler.CallFunc((uint32_t)x86MemoryBreakpoint, "x86MemoryBreakpoint");
m_Assembler.CallFunc((uint32_t)x86MemoryBreakPoint, "x86MemoryBreakPoint");
m_Assembler.MoveConstToVariable(&memory_breakpoint_found, "memory_breakpoint_found", 0);
ExitCodeBlock();
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
@ -9519,7 +9521,7 @@ void CX86RecompilerOps::CompileExecuteBP(void)
{
m_Assembler.CallThis((uint32_t)g_BaseSystem, AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem", 4);
}
m_Assembler.CallFunc((uint32_t)x86_compiler_Break_Point, "x86_compiler_Break_Point");
m_Assembler.CallFunc((uint32_t)x86CompilerBreakPoint, "x86CompilerBreakPoint");
ExitCodeBlock();
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
}
@ -9539,7 +9541,7 @@ void CX86RecompilerOps::CompileExecuteDelaySlotBP(void)
{
m_Assembler.CallThis((uint32_t)g_BaseSystem, AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem", 4);
}
m_Assembler.CallFunc((uint32_t)x86_Break_Point_DelaySlot, "x86_Break_Point_DelaySlot");
m_Assembler.CallFunc((uint32_t)x86BreakPointDelaySlot, "x86BreakPointDelaySlot");
ExitCodeBlock();
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
}
@ -9695,6 +9697,9 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
m_Assembler.push(asmjit::x86::edx);
m_Assembler.PushImm32(InDelaySlot ? "true" : "false", InDelaySlot);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoTLBReadMiss), "CRegisters::DoTLBReadMiss", 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_TLBWriteMiss:
@ -9832,22 +9837,22 @@ void CX86RecompilerOps::CompileLoadMemoryValue(asmjit::x86::Gp AddressReg, asmji
if (ValueSize == 8)
{
AddressReg = BaseOffsetAddress(false);
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakpoint8, "x86TestReadBreakpoint8");
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakPoint8, "x86TestReadBreakpoint8");
}
else if (ValueSize == 16)
{
AddressReg = BaseOffsetAddress(false);
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakpoint16, "x86TestReadBreakpoint16");
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakPoint16, "x86TestReadBreakpoint16");
}
else if (ValueSize == 32)
{
AddressReg = BaseOffsetAddress(true);
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakpoint32, "x86TestReadBreakpoint32");
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakPoint32, "x86TestReadBreakpoint32");
}
else if (ValueSize == 64)
{
AddressReg = BaseOffsetAddress(true);
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakpoint64, "x86TestReadBreakpoint64");
TestReadBreakpoint(AddressReg, (uint32_t)x86TestReadBreakPoint64, "x86TestReadBreakpoint64");
}
else
{
@ -10018,19 +10023,19 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, asmj
AddressReg = BaseOffsetAddress(ValueSize == 32);
if (ValueSize == 8)
{
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakpoint8, "x86TestWriteBreakpoint8");
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakPoint8, "x86TestWriteBreakpoint8");
}
else if (ValueSize == 16)
{
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakpoint16, "x86TestWriteBreakpoint16");
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakPoint16, "x86TestWriteBreakpoint16");
}
else if (ValueSize == 32)
{
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakpoint32, "x86TestWriteBreakpoint32");
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakPoint32, "x86TestWriteBreakpoint32");
}
else if (ValueSize == 64)
{
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakpoint64, "x86TestWriteBreakpoint64");
TestWriteBreakpoint(AddressReg, (uint32_t)x86TestWriteBreakPoint64, "x86TestWriteBreakpoint64");
}
else
{

View File

@ -286,6 +286,18 @@ private:
void CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo & ExitRegSet, ExitReason Reason, bool CompileNow, void (CX86Ops::*x86Jmp)(const char * LabelName, asmjit::Label & JumpLabel));
void ResetMemoryStack();
static void x86CompilerBreakPoint();
static void x86BreakPointDelaySlot();
static void x86MemoryBreakPoint();
static void x86TestReadBreakPoint8();
static void x86TestReadBreakPoint16();
static void x86TestReadBreakPoint32();
static void x86TestReadBreakPoint64();
static void x86TestWriteBreakPoint8();
static void x86TestWriteBreakPoint16();
static void x86TestWriteBreakPoint32();
static void x86TestWriteBreakPoint64();
EXIT_LIST m_ExitInfo;
CX86Ops m_Assembler;
PIPELINE_STAGE m_PipelineStage;