diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index 5801b527c1..5b5d4450a6 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -501,18 +501,18 @@ void Interpreter::divwx(UGeckoInstruction inst) { const s32 a = rGPR[inst.RA]; const s32 b = rGPR[inst.RB]; - const bool overflow = b == 0 || ((u32)a == 0x80000000 && b == -1); + const bool overflow = b == 0 || (static_cast(a) == 0x80000000 && b == -1); if (overflow) { - if (((u32)a & 0x80000000) && b == 0) + if (a < 0) rGPR[inst.RD] = UINT32_MAX; else rGPR[inst.RD] = 0; } else { - rGPR[inst.RD] = (u32)(a / b); + rGPR[inst.RD] = static_cast(a / b); } if (inst.OE) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index db14b184ac..4eb13c9344 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -1223,7 +1223,8 @@ void Jit64::divwx(UGeckoInstruction inst) s32 i = gpr.R(a).SImm32(), j = gpr.R(b).SImm32(); if (j == 0 || (i == (s32)0x80000000 && j == -1)) { - gpr.SetImmediate32(d, (i >> 31) ^ j); + const u32 result = i < 0 ? 0xFFFFFFFF : 0x00000000; + gpr.SetImmediate32(d, result); if (inst.OE) GenerateConstantOverflow(true); } @@ -1241,38 +1242,37 @@ void Jit64::divwx(UGeckoInstruction inst) gpr.FlushLockX(EAX, EDX); gpr.BindToRegister(d, (d == a || d == b), true); MOV(32, R(EAX), gpr.R(a)); - CDQ(); gpr.BindToRegister(b, true, false); + TEST(32, gpr.R(b), gpr.R(b)); - FixupBranch not_div_by_zero = J_CC(CC_NZ); - MOV(32, gpr.R(d), R(EDX)); - if (inst.OE) - { - GenerateConstantOverflow(true); - } - FixupBranch end1 = J(); - SetJumpTarget(not_div_by_zero); - CMP(32, gpr.R(b), R(EDX)); - FixupBranch not_div_by_neg_one = J_CC(CC_NZ); + const FixupBranch overflow = J_CC(CC_E); + + CMP(32, R(EAX), Imm32(0x80000000)); + const FixupBranch normal_path1 = J_CC(CC_NE); + + CMP(32, gpr.R(b), Imm32(0xFFFFFFFF)); + const FixupBranch normal_path2 = J_CC(CC_NE); + + SetJumpTarget(overflow); + SAR(32, R(EAX), Imm8(31)); MOV(32, gpr.R(d), R(EAX)); - NEG(32, gpr.R(d)); - FixupBranch no_overflow = J_CC(CC_NO); - XOR(32, gpr.R(d), gpr.R(d)); if (inst.OE) { GenerateConstantOverflow(true); } - FixupBranch end2 = J(); - SetJumpTarget(not_div_by_neg_one); + const FixupBranch done = J(); + + SetJumpTarget(normal_path1); + SetJumpTarget(normal_path2); + + CDQ(); IDIV(32, gpr.R(b)); MOV(32, gpr.R(d), R(EAX)); - SetJumpTarget(no_overflow); if (inst.OE) { GenerateConstantOverflow(false); } - SetJumpTarget(end1); - SetJumpTarget(end2); + SetJumpTarget(done); } if (inst.Rc) ComputeRC(gpr.R(d)); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index a620e4b9ad..c1fa56a4a1 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -1164,17 +1164,17 @@ void JitArm64::divwx(UGeckoInstruction inst) { s32 imm_a = gpr.GetImm(a); s32 imm_b = gpr.GetImm(b); - s32 imm_d; - if (imm_b == 0 || ((u32)imm_a == 0x80000000 && imm_b == -1)) + u32 imm_d; + if (imm_b == 0 || (static_cast(imm_a) == 0x80000000 && imm_b == -1)) { - if (((u32)imm_a & 0x80000000) && imm_b == 0) - imm_d = -1; + if (imm_a < 0) + imm_d = 0xFFFFFFFF; else imm_d = 0; } else { - imm_d = (u32)(imm_a / imm_b); + imm_d = static_cast(imm_a / imm_b); } gpr.SetImmediate(d, imm_d); @@ -1217,9 +1217,7 @@ void JitArm64::divwx(UGeckoInstruction inst) SetJumpTarget(slow1); SetJumpTarget(slow2); - CMP(RB, 0); - CCMP(RA, 0, 0, CC_EQ); - CSETM(RD, CC_LT); + ASR(RD, RA, 31); SetJumpTarget(done);