Core: Handle more with LW and invalid addresses

This commit is contained in:
zilmar 2022-10-10 20:25:16 +10:30
parent 082ec9c22e
commit 801a3e29fc
3 changed files with 65 additions and 8 deletions

View File

@ -17,7 +17,8 @@ enum ExitReason
ExitReason_TLBWriteMiss, ExitReason_TLBWriteMiss,
ExitReason_ResetRecompCode, ExitReason_ResetRecompCode,
ExitReason_ExceptionOverflow, ExitReason_ExceptionOverflow,
ExitReason_AddressErrorExceptionRead, ExitReason_AddressErrorExceptionRead32,
ExitReason_AddressErrorExceptionRead64,
}; };
struct CExitInfo struct CExitInfo

View File

@ -20,6 +20,7 @@
#include <stdio.h> #include <stdio.h>
uint32_t CX86RecompilerOps::m_TempValue32 = 0; uint32_t CX86RecompilerOps::m_TempValue32 = 0;
uint64_t CX86RecompilerOps::m_TempValue64 = 0;
uint32_t CX86RecompilerOps::m_BranchCompare = 0; uint32_t CX86RecompilerOps::m_BranchCompare = 0;
/*int TestValue = 0; /*int TestValue = 0;
@ -3163,8 +3164,7 @@ void CX86RecompilerOps::LW(bool ResultSigned, bool bRecordLLBit)
else else
{ {
PreReadInstruction(); PreReadInstruction();
Map_GPR_32bit(m_Opcode.rt, ResultSigned, m_Opcode.base == m_Opcode.rt ? m_Opcode.rt : -1); CompileLoadMemoryValue(CX86Ops::x86_Unknown, CX86Ops::x86_Unknown, CX86Ops::x86_Unknown, 32, false);
CompileLoadMemoryValue(CX86Ops::x86_Unknown, GetMipsRegMapLo(m_Opcode.rt), CX86Ops::x86_Unknown, 32, false);
if (bRecordLLBit) if (bRecordLLBit)
{ {
m_Assembler.MoveConstToVariable(1, _LLBit, "LLBit"); m_Assembler.MoveConstToVariable(1, _LLBit, "LLBit");
@ -9615,7 +9615,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoOverflowException), "CRegisters::DoOverflowException", 12); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoOverflowException), "CRegisters::DoOverflowException", 12);
ExitCodeBlock(); ExitCodeBlock();
break; break;
case ExitReason_AddressErrorExceptionRead: case ExitReason_AddressErrorExceptionRead32:
m_Assembler.PushImm32("1", 1); m_Assembler.PushImm32("1", 1);
m_Assembler.MoveVariableToX86reg(&m_TempValue32, "TempValue32", CX86Ops::x86_EDX); m_Assembler.MoveVariableToX86reg(&m_TempValue32, "TempValue32", CX86Ops::x86_EDX);
m_Assembler.MoveX86RegToX86Reg(CX86Ops::x86_EDX, CX86Ops::x86_EAX); m_Assembler.MoveX86RegToX86Reg(CX86Ops::x86_EDX, CX86Ops::x86_EAX);
@ -9626,6 +9626,16 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoAddressError), "CRegisters::DoAddressError", 12); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoAddressError), "CRegisters::DoAddressError", 12);
ExitCodeBlock(); ExitCodeBlock();
break; break;
case ExitReason_AddressErrorExceptionRead64:
m_Assembler.PushImm32("1", 1);
m_Assembler.MoveVariableToX86reg(&m_TempValue64, "TempValue64", CX86Ops::x86_EDX);
m_Assembler.MoveVariableToX86reg(&m_TempValue64 + 4, "TempValue64+4", CX86Ops::x86_EAX);
m_Assembler.Push(CX86Ops::x86_EAX);
m_Assembler.Push(CX86Ops::x86_EDX);
m_Assembler.PushImm32(InDelaySlot ? "true" : "false", InDelaySlot);
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoAddressError), "CRegisters::DoAddressError", 12);
ExitCodeBlock();
break;
default: default:
WriteTrace(TraceRecompiler, TraceError, "How did you want to exit on reason (%d) ???", reason); WriteTrace(TraceRecompiler, TraceError, "How did you want to exit on reason (%d) ???", reason);
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
@ -9663,6 +9673,37 @@ CX86Ops::x86Reg CX86RecompilerOps::BaseOffsetAddress(bool UseBaseRegister)
AddressReg = Map_TempReg(CX86Ops::x86_Unknown, m_Opcode.base, false, false); AddressReg = Map_TempReg(CX86Ops::x86_Unknown, m_Opcode.base, false, false);
m_Assembler.AddConstToX86Reg(AddressReg, (int16_t)m_Opcode.immediate); m_Assembler.AddConstToX86Reg(AddressReg, (int16_t)m_Opcode.immediate);
} }
if (!b32BitCore() && ((IsKnown(m_Opcode.base) && Is64Bit(m_Opcode.base)) || IsUnknown(m_Opcode.base)))
{
m_Assembler.MoveX86regToVariable(AddressReg, &m_TempValue64, "TempValue64");
CX86Ops::x86Reg AddressRegHi = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
m_Assembler.MoveX86RegToX86Reg(AddressReg, AddressRegHi);
m_Assembler.ShiftRightSignImmed(AddressRegHi, 31);
if (IsConst(m_Opcode.base))
{
m_Assembler.MoveConstToVariable(GetMipsRegHi(m_Opcode.base), &m_TempValue64 + 4, "TempValue64 + 4");
m_Assembler.CompConstToX86reg(AddressRegHi, GetMipsRegHi(m_Opcode.base));
}
else if (IsMapped(m_Opcode.base))
{
m_Assembler.MoveX86regToVariable(GetMipsRegMapHi(m_Opcode.base), &m_TempValue64 + 4, "TempValue64 + 4");
m_Assembler.CompX86RegToX86Reg(AddressRegHi, GetMipsRegMapHi(m_Opcode.base));
}
else
{
CX86Ops::x86Reg AddressMemoryHi = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
m_Assembler.MoveVariableToX86reg(&_GPR[m_Opcode.base].W[1], CRegName::GPR_Hi[m_Opcode.base], AddressMemoryHi);
m_Assembler.MoveX86regToVariable(AddressMemoryHi, &m_TempValue64 + 4, "TempValue64 + 4");
m_Assembler.CompX86RegToX86Reg(AddressRegHi, AddressMemoryHi);
m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(AddressMemoryHi), false);
}
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_AddressErrorExceptionRead64, false, &CX86Ops::JneLabel32);
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(AddressRegHi), false);
}
return AddressReg; return AddressReg;
} }
@ -9697,16 +9738,24 @@ void CX86RecompilerOps::CompileLoadMemoryValue(CX86Ops::x86Reg AddressReg, CX86O
} }
} }
CX86Ops::x86Reg TempReg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
if (ValueSize == 16) if (ValueSize == 16)
{ {
m_Assembler.TestConstToX86Reg(1, AddressReg);
m_Assembler.MoveX86regToVariable(AddressReg, &m_TempValue32, "TempValue32"); m_Assembler.MoveX86regToVariable(AddressReg, &m_TempValue32, "TempValue32");
m_Assembler.TestConstToX86Reg(1, AddressReg);
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp()); m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_AddressErrorExceptionRead, false, &CX86Ops::JneLabel32); CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_AddressErrorExceptionRead32, false, &CX86Ops::JneLabel32);
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
}
else if (ValueSize == 32)
{
m_Assembler.MoveX86regToVariable(AddressReg, &m_TempValue32, "TempValue32");
m_Assembler.TestConstToX86Reg(3, AddressReg);
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_AddressErrorExceptionRead32, false, &CX86Ops::JneLabel32);
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp()); m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
} }
CX86Ops::x86Reg TempReg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
m_Assembler.MoveX86RegToX86Reg(AddressReg, TempReg); m_Assembler.MoveX86RegToX86Reg(AddressReg, TempReg);
m_Assembler.ShiftRightUnsignImmed(TempReg, 12); m_Assembler.ShiftRightUnsignImmed(TempReg, 12);
m_Assembler.MoveVariableDispToX86Reg(g_MMU->m_MemoryReadMap, "MMU->m_MemoryReadMap", TempReg, TempReg, 4); m_Assembler.MoveVariableDispToX86Reg(g_MMU->m_MemoryReadMap, "MMU->m_MemoryReadMap", TempReg, TempReg, 4);
@ -9791,7 +9840,7 @@ void CX86RecompilerOps::CompileLoadMemoryValue(CX86Ops::x86Reg AddressReg, CX86O
m_Assembler.XorConstToX86Reg(AddressReg, 2); m_Assembler.XorConstToX86Reg(AddressReg, 2);
if (ValueReg == CX86Ops::x86_Unknown) if (ValueReg == CX86Ops::x86_Unknown)
{ {
Map_GPR_32bit(m_Opcode.rt, true, m_Opcode.base == m_Opcode.rt ? m_Opcode.rt : -1); Map_GPR_32bit(m_Opcode.rt, SignExtend, -1);
ValueReg = GetMipsRegMapLo(m_Opcode.rt); ValueReg = GetMipsRegMapLo(m_Opcode.rt);
} }
@ -9806,6 +9855,12 @@ void CX86RecompilerOps::CompileLoadMemoryValue(CX86Ops::x86Reg AddressReg, CX86O
} }
else if (ValueSize == 32) else if (ValueSize == 32)
{ {
if (ValueReg == CX86Ops::x86_Unknown)
{
Map_GPR_32bit(m_Opcode.rt, true, -1);
ValueReg = GetMipsRegMapLo(m_Opcode.rt);
}
if (ValueReg != CX86Ops::x86_Unknown) if (ValueReg != CX86Ops::x86_Unknown)
{ {
m_Assembler.MoveX86regPointerToX86reg(AddressReg, TempReg, ValueReg); m_Assembler.MoveX86regPointerToX86reg(AddressReg, TempReg, ValueReg);

View File

@ -454,6 +454,7 @@ private:
CRegInfo m_RegBeforeDelay; CRegInfo m_RegBeforeDelay;
bool m_EffectDelaySlot; bool m_EffectDelaySlot;
static uint32_t m_TempValue32; static uint32_t m_TempValue32;
static uint64_t m_TempValue64;
static uint32_t m_BranchCompare; static uint32_t m_BranchCompare;
}; };