Merge pull request #10120 from Sintendo/jit64arithcxrefactor
Jit64: Merge arithcx into addx/subfx
This commit is contained in:
commit
1714dc64bb
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue