Skip to content

Commit

Permalink
Core: Handle more with LW and invalid addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
project64 committed Oct 10, 2022
1 parent 082ec9c commit 801a3e2
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
3 changes: 2 additions & 1 deletion Source/Project64-core/N64System/Recompiler/ExitInfo.h
Expand Up @@ -17,7 +17,8 @@ enum ExitReason
ExitReason_TLBWriteMiss,
ExitReason_ResetRecompCode,
ExitReason_ExceptionOverflow,
ExitReason_AddressErrorExceptionRead,
ExitReason_AddressErrorExceptionRead32,
ExitReason_AddressErrorExceptionRead64,
};

struct CExitInfo
Expand Down
Expand Up @@ -20,6 +20,7 @@
#include <stdio.h>

uint32_t CX86RecompilerOps::m_TempValue32 = 0;
uint64_t CX86RecompilerOps::m_TempValue64 = 0;
uint32_t CX86RecompilerOps::m_BranchCompare = 0;

/*int TestValue = 0;
Expand Down Expand Up @@ -3163,8 +3164,7 @@ void CX86RecompilerOps::LW(bool ResultSigned, bool bRecordLLBit)
else
{
PreReadInstruction();
Map_GPR_32bit(m_Opcode.rt, ResultSigned, m_Opcode.base == m_Opcode.rt ? m_Opcode.rt : -1);
CompileLoadMemoryValue(CX86Ops::x86_Unknown, GetMipsRegMapLo(m_Opcode.rt), CX86Ops::x86_Unknown, 32, false);
CompileLoadMemoryValue(CX86Ops::x86_Unknown, CX86Ops::x86_Unknown, CX86Ops::x86_Unknown, 32, false);
if (bRecordLLBit)
{
m_Assembler.MoveConstToVariable(1, _LLBit, "LLBit");
Expand Down Expand Up @@ -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);
ExitCodeBlock();
break;
case ExitReason_AddressErrorExceptionRead:
case ExitReason_AddressErrorExceptionRead32:
m_Assembler.PushImm32("1", 1);
m_Assembler.MoveVariableToX86reg(&m_TempValue32, "TempValue32", CX86Ops::x86_EDX);
m_Assembler.MoveX86RegToX86Reg(CX86Ops::x86_EDX, CX86Ops::x86_EAX);
Expand All @@ -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);
ExitCodeBlock();
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:
WriteTrace(TraceRecompiler, TraceError, "How did you want to exit on reason (%d) ???", reason);
g_Notify->BreakPoint(__FILE__, __LINE__);
Expand Down Expand Up @@ -9663,6 +9673,37 @@ CX86Ops::x86Reg CX86RecompilerOps::BaseOffsetAddress(bool UseBaseRegister)
AddressReg = Map_TempReg(CX86Ops::x86_Unknown, m_Opcode.base, false, false);
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;
}

Expand Down Expand Up @@ -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)
{
m_Assembler.TestConstToX86Reg(1, AddressReg);
m_Assembler.MoveX86regToVariable(AddressReg, &m_TempValue32, "TempValue32");
m_Assembler.TestConstToX86Reg(1, 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());
}
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_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());
}

CX86Ops::x86Reg TempReg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
m_Assembler.MoveX86RegToX86Reg(AddressReg, TempReg);
m_Assembler.ShiftRightUnsignImmed(TempReg, 12);
m_Assembler.MoveVariableDispToX86Reg(g_MMU->m_MemoryReadMap, "MMU->m_MemoryReadMap", TempReg, TempReg, 4);
Expand Down Expand Up @@ -9791,7 +9840,7 @@ void CX86RecompilerOps::CompileLoadMemoryValue(CX86Ops::x86Reg AddressReg, CX86O
m_Assembler.XorConstToX86Reg(AddressReg, 2);
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);
}

Expand All @@ -9806,6 +9855,12 @@ void CX86RecompilerOps::CompileLoadMemoryValue(CX86Ops::x86Reg AddressReg, CX86O
}
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)
{
m_Assembler.MoveX86regPointerToX86reg(AddressReg, TempReg, ValueReg);
Expand Down
Expand Up @@ -454,6 +454,7 @@ class CX86RecompilerOps :
CRegInfo m_RegBeforeDelay;
bool m_EffectDelaySlot;
static uint32_t m_TempValue32;
static uint64_t m_TempValue64;
static uint32_t m_BranchCompare;
};

Expand Down

0 comments on commit 801a3e2

Please sign in to comment.