Core: get COP1_D_CMP to work in recompiler
This commit is contained in:
parent
9272ac05f6
commit
0cf4c7dc11
|
@ -8587,85 +8587,172 @@ void CX86RecompilerOps::COP1_D_CVT_L()
|
|||
|
||||
void CX86RecompilerOps::COP1_D_CMP()
|
||||
{
|
||||
uint32_t Reg1 = m_Opcode.fs;
|
||||
uint32_t Reg2 = m_Opcode.ft;
|
||||
uint32_t cmp = 0;
|
||||
if (FpuExceptionInRecompiler())
|
||||
{
|
||||
CompileInitFpuOperation(CRegBase::RoundUnknown);
|
||||
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;
|
||||
}
|
||||
if (m_RegWorkingSet.IsFPStatusRegMapped())
|
||||
{
|
||||
m_Assembler.and_(m_RegWorkingSet.Map_FPStatusReg(), (uint32_t)~FPCSR_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.AndConstToVariable(&m_Reg.m_FPCR[31], "_FPCR[31]", (uint32_t)~FPCSR_C);
|
||||
}
|
||||
m_RegWorkingSet.Map_TempReg(asmjit::x86::eax, 0, false, false);
|
||||
asmjit::x86::Gp StatusReg = m_RegWorkingSet.Map_FPStatusReg();
|
||||
asmjit::x86::Gp TempRegValue = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, -1, false, true);
|
||||
asmjit::x86::Gp FsPtr = m_RegWorkingSet.FPRValuePointer(m_Opcode.fs, CRegInfo::FPU_Double);
|
||||
asmjit::x86::Gp FtPtr = m_RegWorkingSet.FPRValuePointer(m_Opcode.ft, CRegInfo::FPU_UnsignedDoubleWord);
|
||||
|
||||
if ((m_Opcode.funct & 4) == 0)
|
||||
{
|
||||
Reg1 = m_RegWorkingSet.RegInStack(m_Opcode.ft, CRegInfo::FPU_Double) ? m_Opcode.ft : m_Opcode.fs;
|
||||
Reg2 = m_RegWorkingSet.RegInStack(m_Opcode.ft, CRegInfo::FPU_Double) ? m_Opcode.fs : m_Opcode.ft;
|
||||
}
|
||||
|
||||
CompileCop1Test();
|
||||
if ((m_Opcode.funct & 7) == 0)
|
||||
{
|
||||
CX86RecompilerOps::UnknownOpcode();
|
||||
}
|
||||
if ((m_Opcode.funct & 2) != 0)
|
||||
{
|
||||
cmp |= 0x4000;
|
||||
}
|
||||
if ((m_Opcode.funct & 4) != 0)
|
||||
{
|
||||
cmp |= 0x0100;
|
||||
}
|
||||
|
||||
m_RegWorkingSet.Load_FPR_ToTop(Reg1, Reg1, CRegInfo::FPU_Double);
|
||||
m_RegWorkingSet.Map_TempReg(asmjit::x86::eax, 0, false, false);
|
||||
if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double))
|
||||
{
|
||||
m_Assembler.fcom(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(Reg1, Reg1, CRegInfo::FPU_Double);
|
||||
m_Assembler.fcom(asmjit::x86::qword_ptr(TempReg));
|
||||
}
|
||||
if (m_RegWorkingSet.IsFPStatusRegMapped())
|
||||
{
|
||||
m_Assembler.and_(m_RegWorkingSet.Map_FPStatusReg(), (uint32_t)~FPCSR_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.AndConstToVariable(&m_Reg.m_FPCR[31], "_FPCR[31]", (uint32_t)~FPCSR_C);
|
||||
}
|
||||
m_Assembler.fnstsw(asmjit::x86::ax);
|
||||
asmjit::x86::Gp Reg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, 0, false, true);
|
||||
m_Assembler.test(asmjit::x86::eax, cmp);
|
||||
m_Assembler.setnz(Reg);
|
||||
if (cmp != 0)
|
||||
{
|
||||
m_Assembler.test(asmjit::x86::eax, cmp);
|
||||
m_Assembler.setnz(Reg);
|
||||
m_Assembler.fpuLoadQwordFromX86Reg(m_RegWorkingSet.StackTopPos(), FtPtr);
|
||||
m_Assembler.fpuLoadQwordFromX86Reg(m_RegWorkingSet.StackTopPos(), FsPtr);
|
||||
m_Assembler.fucompp();
|
||||
m_Assembler.fstsw(asmjit::x86::ax);
|
||||
m_Assembler.sahf();
|
||||
asmjit::Label NotNanLabel = m_Assembler.newLabel();
|
||||
m_Assembler.JnpLabel("NotNan", NotNanLabel);
|
||||
|
||||
//is Nan
|
||||
asmjit::Label NotQuietNanLabel;
|
||||
if ((m_Opcode.funct & 8) == 0)
|
||||
{
|
||||
//check QuietNan
|
||||
NotQuietNanLabel = m_Assembler.newLabel();
|
||||
asmjit::Label FsIsQuietNan = m_Assembler.newLabel();
|
||||
m_Assembler.mov(TempRegValue, asmjit::x86::dword_ptr(FsPtr));
|
||||
m_Assembler.cmp(TempRegValue, 0x7FC00000);
|
||||
m_Assembler.JgeLabel("FsIsQuietNan", FsIsQuietNan);
|
||||
m_Assembler.mov(TempRegValue, asmjit::x86::dword_ptr(FtPtr));
|
||||
m_Assembler.cmp(TempRegValue, 0x7FC00000);
|
||||
m_Assembler.JlLabel("FsIsQuietNan", NotQuietNanLabel);
|
||||
m_Assembler.bind(FsIsQuietNan);
|
||||
}
|
||||
m_Assembler.or_(StatusReg, (uint32_t)FPCSR_CV);
|
||||
m_Assembler.test(StatusReg, FPCSR_EV);
|
||||
CRegInfo ExitRegSet = m_RegWorkingSet;
|
||||
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_ExceptionFloatingPoint, false, &CX86Ops::JnzLabel);
|
||||
m_Assembler.or_(StatusReg, (uint32_t)FPCSR_FV);
|
||||
if ((m_Opcode.funct & 8) == 0)
|
||||
{
|
||||
m_Assembler.bind(NotQuietNanLabel);
|
||||
}
|
||||
if ((m_Opcode.funct & 1) != 0)
|
||||
{
|
||||
asmjit::x86::Gp _86RegReg2 = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, 0, false, true);
|
||||
m_Assembler.and_(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.CompConstToX86reg(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.setz(_86RegReg2);
|
||||
|
||||
m_Assembler.or_(Reg, _86RegReg2);
|
||||
m_Assembler.or_(StatusReg, (uint32_t)FPCSR_C);
|
||||
}
|
||||
uint32_t cmp = 0;
|
||||
if ((m_Opcode.funct & 2) != 0)
|
||||
{
|
||||
cmp |= 0x4000;
|
||||
}
|
||||
if ((m_Opcode.funct & 4) != 0)
|
||||
{
|
||||
cmp |= 0x0100;
|
||||
}
|
||||
asmjit::Label IsNanSkipCompare = m_Assembler.newLabel();
|
||||
if (cmp != 0)
|
||||
{
|
||||
m_Assembler.JmpLabel("IsNanSkipCompare", IsNanSkipCompare);
|
||||
}
|
||||
m_Assembler.bind(NotNanLabel);
|
||||
if (cmp != 0)
|
||||
{
|
||||
m_Assembler.xor_(TempRegValue, TempRegValue);
|
||||
m_Assembler.test(asmjit::x86::eax, cmp);
|
||||
m_Assembler.setnz(TempRegValue);
|
||||
m_Assembler.shl(TempRegValue, 23);
|
||||
m_Assembler.or_(StatusReg, TempRegValue);
|
||||
m_Assembler.bind(IsNanSkipCompare);
|
||||
}
|
||||
}
|
||||
else if ((m_Opcode.funct & 1) != 0)
|
||||
{
|
||||
m_Assembler.and_(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.CompConstToX86reg(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.setz(Reg);
|
||||
}
|
||||
m_Assembler.shl(Reg, 23);
|
||||
if (m_RegWorkingSet.IsFPStatusRegMapped())
|
||||
{
|
||||
m_Assembler.or_(m_RegWorkingSet.Map_FPStatusReg(), Reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.OrX86RegToVariable(&m_Reg.m_FPCR[31], "_FPCR[31]", Reg);
|
||||
uint32_t Reg1 = m_Opcode.fs;
|
||||
uint32_t Reg2 = m_Opcode.ft;
|
||||
uint32_t cmp = 0;
|
||||
|
||||
if ((m_Opcode.funct & 4) == 0)
|
||||
{
|
||||
Reg1 = m_RegWorkingSet.RegInStack(m_Opcode.ft, CRegInfo::FPU_Double) ? m_Opcode.ft : m_Opcode.fs;
|
||||
Reg2 = m_RegWorkingSet.RegInStack(m_Opcode.ft, CRegInfo::FPU_Double) ? m_Opcode.fs : m_Opcode.ft;
|
||||
}
|
||||
|
||||
CompileCop1Test();
|
||||
if ((m_Opcode.funct & 7) == 0)
|
||||
{
|
||||
CX86RecompilerOps::UnknownOpcode();
|
||||
}
|
||||
if ((m_Opcode.funct & 2) != 0)
|
||||
{
|
||||
cmp |= 0x4000;
|
||||
}
|
||||
if ((m_Opcode.funct & 4) != 0)
|
||||
{
|
||||
cmp |= 0x0100;
|
||||
}
|
||||
|
||||
m_RegWorkingSet.Load_FPR_ToTop(Reg1, Reg1, CRegInfo::FPU_Double);
|
||||
m_RegWorkingSet.Map_TempReg(asmjit::x86::eax, 0, false, false);
|
||||
if (m_RegWorkingSet.RegInStack(Reg2, CRegInfo::FPU_Double))
|
||||
{
|
||||
m_Assembler.fcom(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(Reg1, Reg1, CRegInfo::FPU_Double);
|
||||
m_Assembler.fcom(asmjit::x86::qword_ptr(TempReg));
|
||||
}
|
||||
if (m_RegWorkingSet.IsFPStatusRegMapped())
|
||||
{
|
||||
m_Assembler.and_(m_RegWorkingSet.Map_FPStatusReg(), (uint32_t)~FPCSR_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.AndConstToVariable(&m_Reg.m_FPCR[31], "_FPCR[31]", (uint32_t)~FPCSR_C);
|
||||
}
|
||||
m_Assembler.fnstsw(asmjit::x86::ax);
|
||||
asmjit::x86::Gp Reg = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, 0, false, true);
|
||||
m_Assembler.test(asmjit::x86::eax, cmp);
|
||||
m_Assembler.setnz(Reg);
|
||||
if (cmp != 0)
|
||||
{
|
||||
m_Assembler.test(asmjit::x86::eax, cmp);
|
||||
m_Assembler.setnz(Reg);
|
||||
|
||||
if ((m_Opcode.funct & 1) != 0)
|
||||
{
|
||||
asmjit::x86::Gp _86RegReg2 = m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, 0, false, true);
|
||||
m_Assembler.and_(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.CompConstToX86reg(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.setz(_86RegReg2);
|
||||
|
||||
m_Assembler.or_(Reg, _86RegReg2);
|
||||
}
|
||||
}
|
||||
else if ((m_Opcode.funct & 1) != 0)
|
||||
{
|
||||
m_Assembler.and_(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.CompConstToX86reg(asmjit::x86::eax, 0x4300);
|
||||
m_Assembler.setz(Reg);
|
||||
}
|
||||
m_Assembler.shl(Reg, 23);
|
||||
if (m_RegWorkingSet.IsFPStatusRegMapped())
|
||||
{
|
||||
m_Assembler.or_(m_RegWorkingSet.Map_FPStatusReg(), Reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.OrX86RegToVariable(&m_Reg.m_FPCR[31], "_FPCR[31]", Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue