Core: Get COP1_D_ADD, COP1_D_SUB, COP1_D_DIV, COP1_D_ABS, COP1_D_SQRT

This commit is contained in:
zilmar 2024-03-07 21:12:57 +10:30
parent 97ec1f533b
commit 98b1bddc64
1 changed files with 166 additions and 46 deletions

View File

@ -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 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; uint32_t Reg2 = m_Opcode.ft == m_Opcode.fd ? m_Opcode.fs : m_Opcode.ft;
CompileCop1Test(); if (FpuExceptionInRecompiler())
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)); 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 else
{ {
m_RegWorkingSet.UnMap_FPR(Reg2, true); CompileCop1Test();
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, Reg1, CRegInfo::FPU_Double);
m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double); if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double))
m_Assembler.fadd(asmjit::x86::qword_ptr(TempReg)); {
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 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; uint32_t Reg2 = m_Opcode.ft == m_Opcode.fd ? m_Opcode.fs : m_Opcode.ft;
CompileCop1Test(); if (FpuExceptionInRecompiler())
if (m_Opcode.fd == m_Opcode.ft)
{ {
m_RegWorkingSet.UnMap_FPR(m_Opcode.fd, true); CompileInitFpuOperation(CRegInfo::RoundDefault);
asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Any) ||
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.RegInStack(m_Opcode.ft, CRegInfo::FPU_Any) ||
m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); 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_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 else
{ {
m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); CompileCop1Test();
if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double))
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 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); 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_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_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fd, CRegInfo::FPU_Double);
m_Assembler.fsub(asmjit::x86::qword_ptr(TempReg)); 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 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; uint32_t Reg2 = m_Opcode.ft == m_Opcode.fd ? m_Opcode.fs : m_Opcode.ft;
CompileCop1Test(); if (FpuExceptionInRecompiler())
if (m_Opcode.fd == m_Opcode.ft)
{ {
m_RegWorkingSet.UnMap_FPR(m_Opcode.fd, true); CompileInitFpuOperation(CRegInfo::RoundDefault);
asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); if (m_RegWorkingSet.RegInStack(m_Opcode.fs, CRegInfo::FPU_Any) ||
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.RegInStack(m_Opcode.ft, CRegInfo::FPU_Any) ||
m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); 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_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 else
{ {
m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double); CompileCop1Test();
if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double))
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 else
{ {
m_RegWorkingSet.UnMap_FPR(Reg2, true); m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, Reg1, CRegInfo::FPU_Double);
asmjit::x86::Gp TempReg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, false); if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double))
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::st0, m_RegWorkingSet.StackPosition(Reg2));
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));
}
} }
} }
} }
void CX86RecompilerOps::COP1_D_ABS() void CX86RecompilerOps::COP1_D_ABS()
{ {
CompileCop1Test(); if (FpuExceptionInRecompiler())
m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); {
m_Assembler.fabs(); 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() void CX86RecompilerOps::COP1_D_NEG()
@ -8446,9 +8545,30 @@ void CX86RecompilerOps::COP1_D_NEG()
void CX86RecompilerOps::COP1_D_SQRT() void CX86RecompilerOps::COP1_D_SQRT()
{ {
CompileCop1Test(); if (FpuExceptionInRecompiler())
m_RegWorkingSet.Load_FPR_ToTop(m_Opcode.fd, m_Opcode.fs, CRegInfo::FPU_Double); {
m_Assembler.fsqrt(); 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() void CX86RecompilerOps::COP1_D_MOV()