From 082ec9c22eab4991da3f2a8674154fe1f61ff6a6 Mon Sep 17 00:00:00 2001 From: zilmar Date: Mon, 10 Oct 2022 17:17:56 +1030 Subject: [PATCH] Core: Handle unaligned LH --- .../N64System/Recompiler/ExitInfo.h | 1 + .../Recompiler/x86/x86RecompilerOps.cpp | 29 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Source/Project64-core/N64System/Recompiler/ExitInfo.h b/Source/Project64-core/N64System/Recompiler/ExitInfo.h index 7481cd939..752bf4b2a 100644 --- a/Source/Project64-core/N64System/Recompiler/ExitInfo.h +++ b/Source/Project64-core/N64System/Recompiler/ExitInfo.h @@ -17,6 +17,7 @@ enum ExitReason ExitReason_TLBWriteMiss, ExitReason_ResetRecompCode, ExitReason_ExceptionOverflow, + ExitReason_AddressErrorExceptionRead, }; struct CExitInfo diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index b71583683..9bb69be31 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -3076,8 +3076,7 @@ void CX86RecompilerOps::LH() return; } PreReadInstruction(); - Map_GPR_32bit(m_Opcode.rt, true, m_Opcode.base == m_Opcode.rt ? m_Opcode.rt : -1); - CompileLoadMemoryValue(CX86Ops::x86_Unknown, GetMipsRegMapLo(m_Opcode.rt), CX86Ops::x86_Unknown, 16, true); + CompileLoadMemoryValue(CX86Ops::x86_Unknown, CX86Ops::x86_Unknown, CX86Ops::x86_Unknown, 16, true); } void CX86RecompilerOps::LWL() @@ -9616,6 +9615,17 @@ 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: + m_Assembler.PushImm32("1", 1); + m_Assembler.MoveVariableToX86reg(&m_TempValue32, "TempValue32", CX86Ops::x86_EDX); + m_Assembler.MoveX86RegToX86Reg(CX86Ops::x86_EDX, CX86Ops::x86_EAX); + m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EAX, 31); + 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__); @@ -9687,6 +9697,15 @@ void CX86RecompilerOps::CompileLoadMemoryValue(CX86Ops::x86Reg AddressReg, CX86O } } + if (ValueSize == 16) + { + m_Assembler.TestConstToX86Reg(1, AddressReg); + m_Assembler.MoveX86regToVariable(AddressReg, &m_TempValue32, "TempValue32"); + m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp()); + CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_AddressErrorExceptionRead, 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); @@ -9772,9 +9791,11 @@ void CX86RecompilerOps::CompileLoadMemoryValue(CX86Ops::x86Reg AddressReg, CX86O m_Assembler.XorConstToX86Reg(AddressReg, 2); if (ValueReg == CX86Ops::x86_Unknown) { - g_Notify->BreakPoint(__FILE__, __LINE__); + Map_GPR_32bit(m_Opcode.rt, true, m_Opcode.base == m_Opcode.rt ? m_Opcode.rt : -1); + ValueReg = GetMipsRegMapLo(m_Opcode.rt); } - else if (SignExtend) + + if (SignExtend) { m_Assembler.MoveSxHalfX86regPointerToX86reg(AddressReg, TempReg, ValueReg); }