Merge pull request #10120 from Sintendo/jit64arithcxrefactor

Jit64: Merge arithcx into addx/subfx
This commit is contained in:
JMC47 2021-12-20 14:20:49 -05:00 committed by GitHub
commit 1714dc64bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 61 deletions

View File

@ -151,7 +151,6 @@ public:
void DynaRunTable63(UGeckoInstruction inst); void DynaRunTable63(UGeckoInstruction inst);
void addx(UGeckoInstruction inst); void addx(UGeckoInstruction inst);
void arithcx(UGeckoInstruction inst);
void mulli(UGeckoInstruction inst); void mulli(UGeckoInstruction inst);
void mulhwXx(UGeckoInstruction inst); void mulhwXx(UGeckoInstruction inst);
void mullwx(UGeckoInstruction inst); void mullwx(UGeckoInstruction inst);

View File

@ -151,8 +151,8 @@ constexpr std::array<GekkoOPTemplate, 13> s_table19{{
constexpr std::array<GekkoOPTemplate, 107> s_table31{{ constexpr std::array<GekkoOPTemplate, 107> s_table31{{
{266, &Jit64::addx}, // addx {266, &Jit64::addx}, // addx
{778, &Jit64::addx}, // addox {778, &Jit64::addx}, // addox
{10, &Jit64::arithcx}, // addcx {10, &Jit64::addx}, // addcx
{522, &Jit64::arithcx}, // addcox {522, &Jit64::addx}, // addcox
{138, &Jit64::arithXex}, // addex {138, &Jit64::arithXex}, // addex
{650, &Jit64::arithXex}, // addeox {650, &Jit64::arithXex}, // addeox
{234, &Jit64::arithXex}, // addmex {234, &Jit64::arithXex}, // addmex
@ -171,8 +171,8 @@ constexpr std::array<GekkoOPTemplate, 107> s_table31{{
{616, &Jit64::negx}, // negox {616, &Jit64::negx}, // negox
{40, &Jit64::subfx}, // subfx {40, &Jit64::subfx}, // subfx
{552, &Jit64::subfx}, // subfox {552, &Jit64::subfx}, // subfox
{8, &Jit64::arithcx}, // subfcx {8, &Jit64::subfx}, // subfcx
{520, &Jit64::arithcx}, // subfcox {520, &Jit64::subfx}, // subfcox
{136, &Jit64::arithXex}, // subfex {136, &Jit64::arithXex}, // subfex
{648, &Jit64::arithXex}, // subfeox {648, &Jit64::arithXex}, // subfeox
{232, &Jit64::arithXex}, // subfmex {232, &Jit64::arithXex}, // subfmex

View File

@ -941,10 +941,13 @@ void Jit64::subfx(UGeckoInstruction inst)
INSTRUCTION_START INSTRUCTION_START
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
int a = inst.RA, b = inst.RB, d = inst.RD; int a = inst.RA, b = inst.RB, d = inst.RD;
const bool carry = !(inst.SUBOP10 & (1 << 5));
if (a == b) if (a == b)
{ {
gpr.SetImmediate32(d, 0); gpr.SetImmediate32(d, 0);
if (carry)
FinalizeCarry(true);
if (inst.OE) if (inst.OE)
GenerateConstantOverflow(false); GenerateConstantOverflow(false);
} }
@ -952,6 +955,8 @@ void Jit64::subfx(UGeckoInstruction inst)
{ {
s32 i = gpr.SImm32(b), j = gpr.SImm32(a); s32 i = gpr.SImm32(b), j = gpr.SImm32(a);
gpr.SetImmediate32(d, i - j); gpr.SetImmediate32(d, i - j);
if (carry)
FinalizeCarry(j == 0 || Interpreter::Helper_Carry((u32)i, 0u - (u32)j));
if (inst.OE) if (inst.OE)
GenerateConstantOverflow((s64)i - (s64)j); GenerateConstantOverflow((s64)i - (s64)j);
} }
@ -966,16 +971,20 @@ void Jit64::subfx(UGeckoInstruction inst)
{ {
if (d != b) if (d != b)
MOV(32, Rd, Rb); MOV(32, Rd, Rb);
if (carry)
FinalizeCarry(true);
if (inst.OE) if (inst.OE)
GenerateConstantOverflow(false); GenerateConstantOverflow(false);
} }
else if (d == b) else if (d == b)
{ {
SUB(32, Rd, Imm32(j)); SUB(32, Rd, Imm32(j));
if (carry)
FinalizeCarry(CC_NC);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
else if (Rb.IsSimpleReg() && !inst.OE) else if (Rb.IsSimpleReg() && !carry && !inst.OE)
{ {
LEA(32, Rd, MDisp(Rb.GetSimpleReg(), -j)); LEA(32, Rd, MDisp(Rb.GetSimpleReg(), -j));
} }
@ -983,6 +992,8 @@ void Jit64::subfx(UGeckoInstruction inst)
{ {
MOV(32, Rd, Rb); MOV(32, Rd, Rb);
SUB(32, Rd, Imm32(j)); SUB(32, Rd, Imm32(j));
if (carry)
FinalizeCarry(CC_NC);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
@ -996,6 +1007,8 @@ void Jit64::subfx(UGeckoInstruction inst)
if (d != a) if (d != a)
MOV(32, Rd, Ra); MOV(32, Rd, Ra);
NEG(32, Rd); NEG(32, Rd);
if (carry)
FinalizeCarry(CC_NC);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
@ -1006,21 +1019,21 @@ void Jit64::subfx(UGeckoInstruction inst)
RCX64Reg Rd = gpr.Bind(d, RCMode::Write); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
RegCache::Realize(Ra, Rb, Rd); RegCache::Realize(Ra, Rb, Rd);
if (d == b) if (d == a && d != b)
{
SUB(32, Rd, Ra);
}
else if (d == a)
{ {
// special case, because sub isn't reversible
MOV(32, R(RSCRATCH), Ra); MOV(32, R(RSCRATCH), Ra);
MOV(32, Rd, Rb); MOV(32, Rd, Rb);
SUB(32, Rd, R(RSCRATCH)); SUB(32, Rd, R(RSCRATCH));
} }
else else
{ {
MOV(32, Rd, Rb); if (d != b)
MOV(32, Rd, Rb);
SUB(32, Rd, Ra); SUB(32, Rd, Ra);
} }
if (carry)
FinalizeCarry(CC_NC);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
@ -1665,19 +1678,21 @@ void Jit64::addx(UGeckoInstruction inst)
INSTRUCTION_START INSTRUCTION_START
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
int a = inst.RA, b = inst.RB, d = inst.RD; int a = inst.RA, b = inst.RB, d = inst.RD;
bool carry = !(inst.SUBOP10 & (1 << 8));
if (gpr.IsImm(a, b)) if (gpr.IsImm(a, b))
{ {
s32 i = gpr.SImm32(a), j = gpr.SImm32(b); const s32 i = gpr.SImm32(a), j = gpr.SImm32(b);
gpr.SetImmediate32(d, i + j); gpr.SetImmediate32(d, i + j);
if (carry)
FinalizeCarry(Interpreter::Helper_Carry(i, j));
if (inst.OE) if (inst.OE)
GenerateConstantOverflow((s64)i + (s64)j); GenerateConstantOverflow((s64)i + (s64)j);
} }
else if (gpr.IsImm(a) || gpr.IsImm(b)) else if (gpr.IsImm(a) || gpr.IsImm(b))
{ {
auto [i, j] = gpr.IsImm(a) ? std::pair(a, b) : std::pair(b, a); const auto [i, j] = gpr.IsImm(a) ? std::pair(a, b) : std::pair(b, a);
const s32 imm = gpr.SImm32(i);
s32 imm = gpr.SImm32(i);
RCOpArg Rj = gpr.Use(j, RCMode::Read); RCOpArg Rj = gpr.Use(j, RCMode::Read);
RCX64Reg Rd = gpr.Bind(d, RCMode::Write); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
RegCache::Realize(Rj, Rd); RegCache::Realize(Rj, Rd);
@ -1686,16 +1701,20 @@ void Jit64::addx(UGeckoInstruction inst)
{ {
if (d != j) if (d != j)
MOV(32, Rd, Rj); MOV(32, Rd, Rj);
if (carry)
FinalizeCarry(false);
if (inst.OE) if (inst.OE)
GenerateConstantOverflow(false); GenerateConstantOverflow(false);
} }
else if (d == j) else if (d == j)
{ {
ADD(32, Rd, Imm32(imm)); ADD(32, Rd, Imm32(imm));
if (carry)
FinalizeCarry(CC_C);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
else if (Rj.IsSimpleReg() && !inst.OE) else if (Rj.IsSimpleReg() && !carry && !inst.OE)
{ {
LEA(32, Rd, MDisp(Rj.GetSimpleReg(), imm)); LEA(32, Rd, MDisp(Rj.GetSimpleReg(), imm));
} }
@ -1703,6 +1722,8 @@ void Jit64::addx(UGeckoInstruction inst)
{ {
MOV(32, Rd, Rj); MOV(32, Rd, Rj);
ADD(32, Rd, Imm32(imm)); ADD(32, Rd, Imm32(imm));
if (carry)
FinalizeCarry(CC_C);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
@ -1710,6 +1731,8 @@ void Jit64::addx(UGeckoInstruction inst)
{ {
MOV(32, Rd, Imm32(imm)); MOV(32, Rd, Imm32(imm));
ADD(32, Rd, Rj); ADD(32, Rd, Rj);
if (carry)
FinalizeCarry(CC_C);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
@ -1726,7 +1749,7 @@ void Jit64::addx(UGeckoInstruction inst)
RCOpArg& Rnotd = (d == a) ? Rb : Ra; RCOpArg& Rnotd = (d == a) ? Rb : Ra;
ADD(32, Rd, Rnotd); ADD(32, Rd, Rnotd);
} }
else if (Ra.IsSimpleReg() && Rb.IsSimpleReg() && !inst.OE) else if (Ra.IsSimpleReg() && Rb.IsSimpleReg() && !carry && !inst.OE)
{ {
LEA(32, Rd, MRegSum(Ra.GetSimpleReg(), Rb.GetSimpleReg())); LEA(32, Rd, MRegSum(Ra.GetSimpleReg(), Rb.GetSimpleReg()));
} }
@ -1735,6 +1758,8 @@ void Jit64::addx(UGeckoInstruction inst)
MOV(32, Rd, Ra); MOV(32, Rd, Ra);
ADD(32, Rd, Rb); ADD(32, Rd, Rb);
} }
if (carry)
FinalizeCarry(CC_C);
if (inst.OE) if (inst.OE)
GenerateOverflow(); GenerateOverflow();
} }
@ -1815,49 +1840,6 @@ void Jit64::arithXex(UGeckoInstruction inst)
ComputeRC(d); ComputeRC(d);
} }
void Jit64::arithcx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITIntegerOff);
bool add = !!(inst.SUBOP10 & 2); // add or sub
int a = inst.RA, b = inst.RB, d = inst.RD;
{
RCOpArg Ra = gpr.Use(a, RCMode::Read);
RCOpArg Rb = gpr.Use(b, RCMode::Read);
RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
RegCache::Realize(Ra, Rb, Rd);
if (d == a && d != b)
{
if (add)
{
ADD(32, Rd, Rb);
}
else
{
// special case, because sub isn't reversible
MOV(32, R(RSCRATCH), Ra);
MOV(32, Rd, Rb);
SUB(32, Rd, R(RSCRATCH));
}
}
else
{
if (d != b)
MOV(32, Rd, Rb);
if (add)
ADD(32, Rd, Ra);
else
SUB(32, Rd, Ra);
}
}
FinalizeCarryOverflow(inst.OE, !add);
if (inst.Rc)
ComputeRC(d);
}
void Jit64::rlwinmx(UGeckoInstruction inst) void Jit64::rlwinmx(UGeckoInstruction inst)
{ {
INSTRUCTION_START INSTRUCTION_START