From d14a639a6247ad6821259cc27a634c9eebe91190 Mon Sep 17 00:00:00 2001 From: zilmar Date: Thu, 21 Dec 2023 14:11:29 +1030 Subject: [PATCH] Core: Implement COP1_S_DIV with fpu exceptions --- .../Recompiler/x86/x86RecompilerOps.cpp | 73 +++++++++++++------ 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index 8b3a82b20..190dd7848 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -7768,40 +7768,65 @@ void CX86RecompilerOps::COP1_S_MUL() void CX86RecompilerOps::COP1_S_DIV() { - uint32_t Reg1 = m_Opcode.ft == m_Opcode.fd ? m_Opcode.ft : m_Opcode.fs; - uint32_t Reg2 = m_Opcode.ft == m_Opcode.fd ? m_Opcode.fs : m_Opcode.ft; - - CompileCop1Test(); - m_RegWorkingSet.FixRoundModel(CRegInfo::RoundDefault); - - if (m_Opcode.fd == m_Opcode.ft) + if (FpuExceptionInRecompiler()) { - m_RegWorkingSet.UnMap_FPR(m_Opcode.fd, true); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Float); - - asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); - m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_S[m_Opcode.ft], stdstr_f("m_FPR_S[%d]", m_Opcode.ft).c_str()); - m_Assembler.fdiv(asmjit::x86::dword_ptr(TempReg)); - } - else - { - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Float); - if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Float)) + CompileInitFpuOperation(CRegInfo::RoundDefault); + if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Float)) { - m_Assembler.fdiv(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + g_Notify->BreakPoint(__FILE__, __LINE__); + return; } else { - m_RegWorkingSet.UnMap_FPR(Reg2, true); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Float); + asmjit::x86::Gp TempReg = m_RegWorkingSet.FPRValuePointer(m_Opcode.fs, CRegInfo::FPU_Float); + CompileCheckFPUInput32(TempReg); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + TempReg = m_RegWorkingSet.FPRValuePointer(m_Opcode.ft, CRegInfo::FPU_Float); + CompileCheckFPUInput32(TempReg); + m_RegWorkingSet.PrepareFPTopToBe(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Float); + m_Assembler.fdiv(asmjit::x86::dword_ptr(TempReg)); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + } + CompileCheckFPUResult32(m_Opcode.fd); + m_RegWorkingSet.SetFPTopAs(m_Opcode.fd); + } + else + { + uint32_t Reg1 = m_Opcode.ft == m_Opcode.fd ? m_Opcode.ft : m_Opcode.fs; + uint32_t Reg2 = m_Opcode.ft == m_Opcode.fd ? m_Opcode.fs : m_Opcode.ft; + + CompileCop1Test(); + m_RegWorkingSet.FixRoundModel(CRegInfo::RoundDefault); + + if (m_Opcode.fd == m_Opcode.ft) + { + m_RegWorkingSet.UnMap_FPR(m_Opcode.fd, true); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Float); asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); - m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_S[Reg2], stdstr_f("m_FPR_S[%d]", Reg2).c_str()); + m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_S[m_Opcode.ft], stdstr_f("m_FPR_S[%d]", m_Opcode.ft).c_str()); m_Assembler.fdiv(asmjit::x86::dword_ptr(TempReg)); } - } + else + { + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Float); + if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Float)) + { + m_Assembler.fdiv(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + } + else + { + m_RegWorkingSet.UnMap_FPR(Reg2, true); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Float); - m_RegWorkingSet.UnMap_FPR(m_Opcode.fd, true); + asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); + m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_S[Reg2], stdstr_f("m_FPR_S[%d]", Reg2).c_str()); + m_Assembler.fdiv(asmjit::x86::dword_ptr(TempReg)); + } + } + + m_RegWorkingSet.UnMap_FPR(m_Opcode.fd, true); + } } void CX86RecompilerOps::COP1_S_ABS()