From 98b1bddc641cb6854e290ab5342db8af654c7b97 Mon Sep 17 00:00:00 2001 From: zilmar Date: Thu, 7 Mar 2024 21:12:57 +1030 Subject: [PATCH] Core: Get COP1_D_ADD, COP1_D_SUB, COP1_D_DIV, COP1_D_ABS, COP1_D_SQRT --- .../Recompiler/x86/x86RecompilerOps.cpp | 212 ++++++++++++++---- 1 file changed, 166 insertions(+), 46 deletions(-) diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index 543f07b3f..ae162fa13 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -8297,20 +8297,46 @@ void CX86RecompilerOps::COP1_D_ADD() 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.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); - if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double)) + if (FpuExceptionInRecompiler()) { - m_Assembler.fadd(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + CompileInitFpuOperation(CRegInfo::RoundDefault); + if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.ft, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.fd, CRegInfo::FPU_Any)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + asmjit::x86::Gp TempReg = m_RegWorkingSet.FPRValuePointer(Reg1, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + TempReg = m_RegWorkingSet.FPRValuePointer(Reg2, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.PrepareFPTopToBe(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); + m_Assembler.fadd(asmjit::x86::qword_ptr(TempReg)); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + m_Assembler.mov(TempReg, (uint64_t)&m_TempValue64); + m_Assembler.fpuStoreQwordFromX86Reg(m_RegWorkingSet.StackTopPos(), TempReg, false); + CompileCheckFPUResult64(TempReg); + m_RegWorkingSet.SetFPTopAs(m_Opcode.fd); } else { - m_RegWorkingSet.UnMap_FPR(Reg2, true); - asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); - m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_D[Reg2], stdstr_f("_FPR_D[%d]", Reg2).c_str()); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double); - m_Assembler.fadd(asmjit::x86::qword_ptr(TempReg)); + CompileCop1Test(); + + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); + if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double)) + { + m_Assembler.fadd(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + } + else + { + m_RegWorkingSet.UnMap_FPR(Reg2, true); + asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); + m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_D[Reg2], stdstr_f("_FPR_D[%d]", Reg2).c_str()); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double); + m_Assembler.fadd(asmjit::x86::qword_ptr(TempReg)); + } } } @@ -8319,31 +8345,57 @@ void CX86RecompilerOps::COP1_D_SUB() 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(); - - if (m_Opcode.fd == m_Opcode.ft) + if (FpuExceptionInRecompiler()) { - 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_D[m_Opcode.ft], stdstr_f("_FPR_D[%d]", m_Opcode.ft).c_str()); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + CompileInitFpuOperation(CRegInfo::RoundDefault); + if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.ft, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.fd, CRegInfo::FPU_Any)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + asmjit::x86::Gp TempReg = m_RegWorkingSet.FPRValuePointer(Reg1, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + TempReg = m_RegWorkingSet.FPRValuePointer(Reg2, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.PrepareFPTopToBe(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); m_Assembler.fsub(asmjit::x86::qword_ptr(TempReg)); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + m_Assembler.mov(TempReg, (uint64_t)&m_TempValue64); + m_Assembler.fpuStoreQwordFromX86Reg(m_RegWorkingSet.StackTopPos(), TempReg, false); + CompileCheckFPUResult64(TempReg); + m_RegWorkingSet.SetFPTopAs(m_Opcode.fd); } else { - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); - if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double)) + CompileCop1Test(); + + if (m_Opcode.fd == m_Opcode.ft) { - m_Assembler.fsub(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + 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_D[m_Opcode.ft], stdstr_f("_FPR_D[%d]", m_Opcode.ft).c_str()); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + m_Assembler.fsub(asmjit::x86::qword_ptr(TempReg)); } else { - m_RegWorkingSet.UnMap_FPR(Reg2, true); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); + if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double)) + { + m_Assembler.fsub(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + } + else + { + m_RegWorkingSet.UnMap_FPR(Reg2, true); - asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); - m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_D[Reg2], stdstr_f("_FPR_D[%d]", Reg2).c_str()); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double); - m_Assembler.fsub(asmjit::x86::qword_ptr(TempReg)); + asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); + m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_D[Reg2], stdstr_f("_FPR_D[%d]", Reg2).c_str()); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double); + m_Assembler.fsub(asmjit::x86::qword_ptr(TempReg)); + } } } } @@ -8402,39 +8454,86 @@ void CX86RecompilerOps::COP1_D_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(); - - if (m_Opcode.fd == m_Opcode.ft) + if (FpuExceptionInRecompiler()) { - 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_D[m_Opcode.ft], stdstr_f("_FPR_D[%d]", m_Opcode.ft).c_str()); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + CompileInitFpuOperation(CRegInfo::RoundDefault); + if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.ft, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.fd, CRegInfo::FPU_Any)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + asmjit::x86::Gp TempReg = m_RegWorkingSet.FPRValuePointer(Reg1, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + TempReg = m_RegWorkingSet.FPRValuePointer(Reg2, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.PrepareFPTopToBe(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); m_Assembler.fdiv(asmjit::x86::qword_ptr(TempReg)); + m_RegWorkingSet.SetX86Protected(GetIndexFromX86Reg(TempReg), false); + m_Assembler.mov(TempReg, (uint64_t)&m_TempValue64); + m_Assembler.fpuStoreQwordFromX86Reg(m_RegWorkingSet.StackTopPos(), TempReg, false); + CompileCheckFPUResult64(TempReg); + m_RegWorkingSet.SetFPTopAs(m_Opcode.fd); } else { - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); - if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double)) + CompileCop1Test(); + + if (m_Opcode.fd == m_Opcode.ft) { - m_Assembler.fdiv(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + 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_D[m_Opcode.ft], stdstr_f("_FPR_D[%d]", m_Opcode.ft).c_str()); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + m_Assembler.fdiv(asmjit::x86::qword_ptr(TempReg)); } else { - m_RegWorkingSet.UnMap_FPR(Reg2, true); - asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); - m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_D[Reg2], stdstr_f("_FPR_D[%d]").c_str()); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double); - m_Assembler.fdiv(asmjit::x86::qword_ptr(TempReg)); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); + if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double)) + { + m_Assembler.fdiv(asmjit::x86::st0, m_RegWorkingSet.StackPosition(Reg2)); + } + else + { + m_RegWorkingSet.UnMap_FPR(Reg2, true); + asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); + m_Assembler.MoveVariableToX86reg(TempReg, (uint8_t *)&m_Reg.m_FPR_D[Reg2], stdstr_f("_FPR_D[%d]").c_str()); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double); + m_Assembler.fdiv(asmjit::x86::qword_ptr(TempReg)); + } } } } void CX86RecompilerOps::COP1_D_ABS() { - CompileCop1Test(); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); - m_Assembler.fabs(); + if (FpuExceptionInRecompiler()) + { + CompileInitFpuOperation(CRegInfo::RoundDefault); + if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.fd, CRegInfo::FPU_Any)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + asmjit::x86::Gp TempReg = m_RegWorkingSet.FPRValuePointer(m_Opcode.fs, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.PrepareFPTopToBe(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + m_Assembler.fabs(); + m_Assembler.mov(TempReg, (uint64_t)&m_TempValue64); + m_Assembler.fpuStoreQwordFromX86Reg(m_RegWorkingSet.StackTopPos(), TempReg, false); + CompileCheckFPUResult64(TempReg); + m_RegWorkingSet.SetFPTopAs(m_Opcode.fd); + } + else + { + CompileCop1Test(); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + m_Assembler.fabs(); + } } void CX86RecompilerOps::COP1_D_NEG() @@ -8446,9 +8545,30 @@ void CX86RecompilerOps::COP1_D_NEG() void CX86RecompilerOps::COP1_D_SQRT() { - CompileCop1Test(); - m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); - m_Assembler.fsqrt(); + if (FpuExceptionInRecompiler()) + { + CompileInitFpuOperation(CRegInfo::RoundDefault); + if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Any) || + m_RegWorkingSet.RegInStack(m_Opcode.fd, CRegInfo::FPU_Any)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + asmjit::x86::Gp TempReg = m_RegWorkingSet.FPRValuePointer(m_Opcode.fs, CRegInfo::FPU_Double); + CompileCheckFPUInput(TempReg, FpuOpSize_64bit); + m_RegWorkingSet.PrepareFPTopToBe(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + m_Assembler.fsqrt(); + m_Assembler.mov(TempReg, (uint64_t)&m_TempValue64); + m_Assembler.fpuStoreQwordFromX86Reg(m_RegWorkingSet.StackTopPos(), TempReg, false); + CompileCheckFPUResult64(TempReg); + m_RegWorkingSet.SetFPTopAs(m_Opcode.fd); + } + else + { + CompileCop1Test(); + m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); + m_Assembler.fsqrt(); + } } void CX86RecompilerOps::COP1_D_MOV()