diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 2e5b4949db..359a2b53cc 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -151,7 +151,6 @@ public: void DynaRunTable63(UGeckoInstruction inst); void addx(UGeckoInstruction inst); - void arithcx(UGeckoInstruction inst); void mulli(UGeckoInstruction inst); void mulhwXx(UGeckoInstruction inst); void mullwx(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp index e201518a07..482303f70d 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp @@ -151,8 +151,8 @@ constexpr std::array s_table19{{ constexpr std::array s_table31{{ {266, &Jit64::addx}, // addx {778, &Jit64::addx}, // addox - {10, &Jit64::arithcx}, // addcx - {522, &Jit64::arithcx}, // addcox + {10, &Jit64::addx}, // addcx + {522, &Jit64::addx}, // addcox {138, &Jit64::arithXex}, // addex {650, &Jit64::arithXex}, // addeox {234, &Jit64::arithXex}, // addmex @@ -171,8 +171,8 @@ constexpr std::array s_table31{{ {616, &Jit64::negx}, // negox {40, &Jit64::subfx}, // subfx {552, &Jit64::subfx}, // subfox - {8, &Jit64::arithcx}, // subfcx - {520, &Jit64::arithcx}, // subfcox + {8, &Jit64::subfx}, // subfcx + {520, &Jit64::subfx}, // subfcox {136, &Jit64::arithXex}, // subfex {648, &Jit64::arithXex}, // subfeox {232, &Jit64::arithXex}, // subfmex diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 7c1b073148..c870682cf8 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -941,10 +941,13 @@ void Jit64::subfx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITIntegerOff); int a = inst.RA, b = inst.RB, d = inst.RD; + const bool carry = !(inst.SUBOP10 & (1 << 5)); if (a == b) { gpr.SetImmediate32(d, 0); + if (carry) + FinalizeCarry(true); if (inst.OE) GenerateConstantOverflow(false); } @@ -952,6 +955,8 @@ void Jit64::subfx(UGeckoInstruction inst) { s32 i = gpr.SImm32(b), j = gpr.SImm32(a); gpr.SetImmediate32(d, i - j); + if (carry) + FinalizeCarry(j == 0 || Interpreter::Helper_Carry((u32)i, 0u - (u32)j)); if (inst.OE) GenerateConstantOverflow((s64)i - (s64)j); } @@ -966,16 +971,20 @@ void Jit64::subfx(UGeckoInstruction inst) { if (d != b) MOV(32, Rd, Rb); + if (carry) + FinalizeCarry(true); if (inst.OE) GenerateConstantOverflow(false); } else if (d == b) { SUB(32, Rd, Imm32(j)); + if (carry) + FinalizeCarry(CC_NC); if (inst.OE) GenerateOverflow(); } - else if (Rb.IsSimpleReg() && !inst.OE) + else if (Rb.IsSimpleReg() && !carry && !inst.OE) { LEA(32, Rd, MDisp(Rb.GetSimpleReg(), -j)); } @@ -983,6 +992,8 @@ void Jit64::subfx(UGeckoInstruction inst) { MOV(32, Rd, Rb); SUB(32, Rd, Imm32(j)); + if (carry) + FinalizeCarry(CC_NC); if (inst.OE) GenerateOverflow(); } @@ -996,6 +1007,8 @@ void Jit64::subfx(UGeckoInstruction inst) if (d != a) MOV(32, Rd, Ra); NEG(32, Rd); + if (carry) + FinalizeCarry(CC_NC); if (inst.OE) GenerateOverflow(); } @@ -1006,21 +1019,21 @@ void Jit64::subfx(UGeckoInstruction inst) RCX64Reg Rd = gpr.Bind(d, RCMode::Write); RegCache::Realize(Ra, Rb, Rd); - if (d == b) - { - SUB(32, Rd, Ra); - } - else if (d == a) + if (d == a && d != b) { + // special case, because sub isn't reversible MOV(32, R(RSCRATCH), Ra); MOV(32, Rd, Rb); SUB(32, Rd, R(RSCRATCH)); } else { - MOV(32, Rd, Rb); + if (d != b) + MOV(32, Rd, Rb); SUB(32, Rd, Ra); } + if (carry) + FinalizeCarry(CC_NC); if (inst.OE) GenerateOverflow(); } @@ -1665,19 +1678,21 @@ void Jit64::addx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITIntegerOff); int a = inst.RA, b = inst.RB, d = inst.RD; + bool carry = !(inst.SUBOP10 & (1 << 8)); 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); + if (carry) + FinalizeCarry(Interpreter::Helper_Carry(i, j)); if (inst.OE) GenerateConstantOverflow((s64)i + (s64)j); } else if (gpr.IsImm(a) || gpr.IsImm(b)) { - auto [i, j] = gpr.IsImm(a) ? std::pair(a, b) : std::pair(b, a); - - s32 imm = gpr.SImm32(i); + const auto [i, j] = gpr.IsImm(a) ? std::pair(a, b) : std::pair(b, a); + const s32 imm = gpr.SImm32(i); RCOpArg Rj = gpr.Use(j, RCMode::Read); RCX64Reg Rd = gpr.Bind(d, RCMode::Write); RegCache::Realize(Rj, Rd); @@ -1686,16 +1701,20 @@ void Jit64::addx(UGeckoInstruction inst) { if (d != j) MOV(32, Rd, Rj); + if (carry) + FinalizeCarry(false); if (inst.OE) GenerateConstantOverflow(false); } else if (d == j) { ADD(32, Rd, Imm32(imm)); + if (carry) + FinalizeCarry(CC_C); if (inst.OE) GenerateOverflow(); } - else if (Rj.IsSimpleReg() && !inst.OE) + else if (Rj.IsSimpleReg() && !carry && !inst.OE) { LEA(32, Rd, MDisp(Rj.GetSimpleReg(), imm)); } @@ -1703,6 +1722,8 @@ void Jit64::addx(UGeckoInstruction inst) { MOV(32, Rd, Rj); ADD(32, Rd, Imm32(imm)); + if (carry) + FinalizeCarry(CC_C); if (inst.OE) GenerateOverflow(); } @@ -1710,6 +1731,8 @@ void Jit64::addx(UGeckoInstruction inst) { MOV(32, Rd, Imm32(imm)); ADD(32, Rd, Rj); + if (carry) + FinalizeCarry(CC_C); if (inst.OE) GenerateOverflow(); } @@ -1726,7 +1749,7 @@ void Jit64::addx(UGeckoInstruction inst) RCOpArg& Rnotd = (d == a) ? Rb : Ra; 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())); } @@ -1735,6 +1758,8 @@ void Jit64::addx(UGeckoInstruction inst) MOV(32, Rd, Ra); ADD(32, Rd, Rb); } + if (carry) + FinalizeCarry(CC_C); if (inst.OE) GenerateOverflow(); } @@ -1815,49 +1840,6 @@ void Jit64::arithXex(UGeckoInstruction inst) 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) { INSTRUCTION_START