diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index a9c0785e72..857bf5a91d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -265,6 +265,7 @@ protected: void ComputeCarry(Arm64Gen::ARM64Reg reg); // reg must contain 0 or 1 void ComputeCarry(bool carry); void ComputeCarry(); + void LoadCarry(); void FlushCarry(); void reg_imm(u32 d, u32 a, u32 value, u32 (*do_op)(u32, u32), diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index bbff6503db..49c2406c8c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -75,6 +75,35 @@ void JitArm64::ComputeCarry() FlushCarry(); } +void JitArm64::LoadCarry() +{ + switch (js.carryFlag) + { + case CarryFlag::InPPCState: + { + ARM64Reg WA = gpr.GetReg(); + LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + CMP(WA, 1); + gpr.Unlock(WA); + break; + } + case CarryFlag::InHostCarry: + { + break; + } + case CarryFlag::ConstantTrue: + { + CMP(ARM64Reg::WZR, ARM64Reg::WZR); + break; + } + case CarryFlag::ConstantFalse: + { + CMN(ARM64Reg::WZR, ARM64Reg::WZR); + break; + } + } +} + void JitArm64::FlushCarry() { switch (js.carryFlag) @@ -995,45 +1024,17 @@ void JitArm64::subfex(UGeckoInstruction inst) { gpr.BindToRegister(d, d == a || d == b); - switch (js.carryFlag) - { - case CarryFlag::InPPCState: - { - // upload the carry state - ARM64Reg WA = gpr.GetReg(); - LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - CMP(WA, 1); - gpr.Unlock(WA); - [[fallthrough]]; - } - case CarryFlag::InHostCarry: - { - CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), gpr.R(b), gpr.R(a)); - ComputeCarry(); - break; - } - case CarryFlag::ConstantTrue: + if (js.carryFlag == CarryFlag::ConstantTrue) { CARRY_IF_NEEDED(SUB, SUBS, gpr.R(d), gpr.R(b), gpr.R(a)); - ComputeCarry(); - break; } - case CarryFlag::ConstantFalse: + else { - ARM64Reg WA = gpr.GetReg(); - - if (gpr.IsImm(a)) - MOVI2R(WA, u32(~gpr.GetImm(a))); - else - MVN(WA, gpr.R(a)); - - CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), WA, gpr.R(b)); - - gpr.Unlock(WA); - ComputeCarry(); - break; - } + LoadCarry(); + CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), gpr.R(b), gpr.R(a)); } + + ComputeCarry(); } if (inst.Rc) @@ -1211,60 +1212,17 @@ void JitArm64::addex(UGeckoInstruction inst) { gpr.BindToRegister(d, d == a || d == b); - if (js.carryFlag == CarryFlag::ConstantTrue && !gpr.IsImm(a) && !gpr.IsImm(b)) - { - CMP(ARM64Reg::WZR, ARM64Reg::WZR); - js.carryFlag = CarryFlag::InHostCarry; - } - - switch (js.carryFlag) - { - case CarryFlag::InPPCState: - { - // upload the carry state - ARM64Reg WA = gpr.GetReg(); - LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - CMP(WA, 1); - gpr.Unlock(WA); - [[fallthrough]]; - } - case CarryFlag::InHostCarry: - { - CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), gpr.R(b)); - ComputeCarry(); - break; - } - case CarryFlag::ConstantTrue: - { - if (!gpr.IsImm(b)) - std::swap(a, b); - ASSERT(gpr.IsImm(b)); - - ARM64Reg WA = gpr.GetReg(); - const u32 imm = gpr.GetImm(b) + 1; - if (imm == 0) - { - if (d != a) - MOV(gpr.R(d), gpr.R(a)); - - ComputeCarry(true); - } - else - { - CARRY_IF_NEEDED(ADDI2R, ADDSI2R, gpr.R(d), gpr.R(a), imm, WA); - ComputeCarry(); - } - gpr.Unlock(WA); - - break; - } - case CarryFlag::ConstantFalse: + if (js.carryFlag == CarryFlag::ConstantFalse) { CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), gpr.R(b)); - ComputeCarry(); - break; } + else + { + LoadCarry(); + CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), gpr.R(b)); } + + ComputeCarry(); } if (inst.Rc)