Core: Get recompiler to handle DADDI/DADDIU

This commit is contained in:
zilmar 2022-10-10 11:53:30 +10:30
parent a8add093d1
commit fc247fd953
3 changed files with 89 additions and 22 deletions

View File

@ -2648,38 +2648,105 @@ void CX86RecompilerOps::LUI()
void CX86RecompilerOps::DADDI() void CX86RecompilerOps::DADDI()
{ {
if (m_Opcode.rs != 0) int64_t imm = (int64_t)((int16_t)m_Opcode.immediate);
{
UnMap_GPR(m_Opcode.rs, true);
}
if (m_Opcode.rt != 0) if (IsConst(m_Opcode.rs))
{ {
UnMap_GPR(m_Opcode.rt, true); int64_t rs = Is64Bit(m_Opcode.rs) ? GetMipsReg(m_Opcode.rs) : (int64_t)GetMipsRegLo_S(m_Opcode.rs);
int64_t sum = rs + imm;
if ((~(rs ^ imm) & (rs ^ sum)) & 0x8000000000000000)
{
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_ExceptionOverflow, true, nullptr);
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
}
else if(m_Opcode.rt != 0)
{
if (IsMapped(m_Opcode.rt))
{
UnMap_GPR(m_Opcode.rt, false);
}
m_RegWorkingSet.SetMipsReg(m_Opcode.rt, sum);
if (GetMipsRegLo_S(m_Opcode.rt) < 0 && GetMipsRegHi_S(m_Opcode.rt) == -1)
{
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_32_SIGN);
}
else if (GetMipsRegLo_S(m_Opcode.rt) >= 0 && GetMipsRegHi_S(m_Opcode.rt) == 0)
{
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_32_SIGN);
}
else
{
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_64);
}
}
} }
else
{
ProtectGPR(m_Opcode.rs);
CX86Ops::x86Reg RegLo = Map_TempReg(CX86Ops::x86_Unknown, m_Opcode.rs, false, false);
CX86Ops::x86Reg RegHi = Map_TempReg(CX86Ops::x86_Unknown, m_Opcode.rs, true, false);
m_RegWorkingSet.BeforeCallDirect(); m_Assembler.AddConstToX86Reg(RegLo, (uint32_t)imm, true);
m_Assembler.MoveConstToVariable(m_Opcode.Value, &R4300iOp::m_Opcode.Value, "R4300iOp::m_Opcode.Value"); m_Assembler.AdcConstToX86Reg(RegHi, (uint32_t)(imm >> 32));
m_Assembler.CallFunc((uint32_t)R4300iOp::DADDI, "R4300iOp::DADDI"); m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
m_RegWorkingSet.AfterCallDirect(); CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, ExitReason_ExceptionOverflow, false, &CX86Ops::JoLabel32);
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
if (m_Opcode.rt != 0)
{
UnProtectGPR(m_Opcode.rs);
Map_GPR_64bit(m_Opcode.rt, -1);
m_Assembler.MoveX86RegToX86Reg(RegLo, GetMipsRegMapLo(m_Opcode.rt));
m_Assembler.MoveX86RegToX86Reg(RegHi, GetMipsRegMapHi(m_Opcode.rt));
}
}
} }
void CX86RecompilerOps::DADDIU() void CX86RecompilerOps::DADDIU()
{ {
if (m_Opcode.rs != 0) if (m_Opcode.rt == 0)
{ {
UnMap_GPR(m_Opcode.rs, true); return;
} }
int64_t imm = (int64_t)((int16_t)m_Opcode.immediate);
if (m_Opcode.rs != 0) if (IsConst(m_Opcode.rs))
{ {
UnMap_GPR(m_Opcode.rt, true); int64_t rs = Is64Bit(m_Opcode.rs) ? GetMipsReg(m_Opcode.rs) : (int64_t)GetMipsRegLo_S(m_Opcode.rs);
if (IsMapped(m_Opcode.rt))
{
UnMap_GPR(m_Opcode.rt, false);
}
m_RegWorkingSet.SetMipsReg(m_Opcode.rt, rs + imm);
if (GetMipsRegLo_S(m_Opcode.rt) < 0 && GetMipsRegHi_S(m_Opcode.rt) == -1)
{
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_32_SIGN);
}
else if (GetMipsRegLo_S(m_Opcode.rt) >= 0 && GetMipsRegHi_S(m_Opcode.rt) == 0)
{
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_32_SIGN);
}
else
{
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_64);
}
} }
else
{
ProtectGPR(m_Opcode.rs);
CX86Ops::x86Reg RegLo = Map_TempReg(CX86Ops::x86_Unknown, m_Opcode.rs, false, false);
CX86Ops::x86Reg RegHi = Map_TempReg(CX86Ops::x86_Unknown, m_Opcode.rs, true, false);
m_RegWorkingSet.BeforeCallDirect(); m_Assembler.AddConstToX86Reg(RegLo, (uint32_t)imm, true);
m_Assembler.MoveConstToVariable(m_Opcode.Value, &R4300iOp::m_Opcode.Value, "R4300iOp::m_Opcode.Value"); m_Assembler.AdcConstToX86Reg(RegHi, (uint32_t)(imm >> 32));
m_Assembler.CallFunc((uint32_t)R4300iOp::DADDIU, "R4300iOp::DADDIU"); if (m_Opcode.rt != 0)
m_RegWorkingSet.AfterCallDirect(); {
UnProtectGPR(m_Opcode.rs);
Map_GPR_64bit(m_Opcode.rt, -1);
m_Assembler.MoveX86RegToX86Reg(RegLo, GetMipsRegMapLo(m_Opcode.rt));
m_Assembler.MoveX86RegToX86Reg(RegHi, GetMipsRegMapHi(m_Opcode.rt));
}
}
} }
void CX86RecompilerOps::CACHE() void CX86RecompilerOps::CACHE()

View File

@ -80,16 +80,16 @@ void CX86Ops::AddConstToVariable(uint32_t Const, void * Variable, const char * V
AddCode32(Const); AddCode32(Const);
} }
void CX86Ops::AddConstToX86Reg(x86Reg reg, uint32_t Const) void CX86Ops::AddConstToX86Reg(x86Reg reg, uint32_t Const, bool NeedCarry)
{ {
if (Const == 0) if (Const == 0)
{ {
} }
else if (Const == 1) else if (Const == 1 && !NeedCarry)
{ {
IncX86reg(reg); IncX86reg(reg);
} }
else if (Const == 0xFFFFFFFF) else if (Const == 0xFFFFFFFF && !NeedCarry)
{ {
DecX86reg(reg); DecX86reg(reg);
} }

View File

@ -70,7 +70,7 @@ public:
void AdcVariableToX86reg(x86Reg reg, void * Variable, const char * VariableName); void AdcVariableToX86reg(x86Reg reg, void * Variable, const char * VariableName);
void AdcX86RegToX86Reg(x86Reg Destination, x86Reg Source); void AdcX86RegToX86Reg(x86Reg Destination, x86Reg Source);
void AddConstToVariable(uint32_t Const, void * Variable, const char * VariableName); void AddConstToVariable(uint32_t Const, void * Variable, const char * VariableName);
void AddConstToX86Reg(x86Reg Reg, uint32_t Const); void AddConstToX86Reg(x86Reg Reg, uint32_t Const, bool NeedCarry = false);
void AddVariableToX86reg(x86Reg reg, void * Variable, const char * VariableName); void AddVariableToX86reg(x86Reg reg, void * Variable, const char * VariableName);
void AddX86regToVariable(x86Reg reg, void * Variable, const char * VariableName); void AddX86regToVariable(x86Reg reg, void * Variable, const char * VariableName);
void AddX86RegToX86Reg(x86Reg Destination, x86Reg Source); void AddX86RegToX86Reg(x86Reg Destination, x86Reg Source);