diff --git a/Core/MIPS/ARM/ArmCompALU.cpp b/Core/MIPS/ARM/ArmCompALU.cpp index 6232044290..3601833ac5 100644 --- a/Core/MIPS/ARM/ArmCompALU.cpp +++ b/Core/MIPS/ARM/ArmCompALU.cpp @@ -760,9 +760,9 @@ namespace MIPSComp if (gpr.IsImm(rt) && (gpr.GetImm(rt) & (gpr.GetImm(rt) - 1)) == 0) { u32 denominator = gpr.GetImm(rt); if (denominator == 0) { - // TODO: Is this correct? - gpr.SetImm(MIPS_REG_LO, 0); - gpr.SetImm(MIPS_REG_HI, 0); + gpr.MapDirtyIn(MIPS_REG_HI, rs); + gpr.SetImm(MIPS_REG_LO, -1); + MOV(gpr.R(MIPS_REG_HI), gpr.R(rs)); } else { gpr.MapDirtyDirtyIn(MIPS_REG_LO, MIPS_REG_HI, rs); // Remainder is just an AND, neat. diff --git a/Core/MIPS/ARM64/Arm64CompALU.cpp b/Core/MIPS/ARM64/Arm64CompALU.cpp index 4a87760410..2e24a26f77 100644 --- a/Core/MIPS/ARM64/Arm64CompALU.cpp +++ b/Core/MIPS/ARM64/Arm64CompALU.cpp @@ -636,8 +636,8 @@ void Arm64Jit::Comp_MulDivType(MIPSOpcode op) { if (gpr.IsImm(rt) && (gpr.GetImm(rt) & (gpr.GetImm(rt) - 1)) == 0) { u32 denominator = gpr.GetImm(rt); if (denominator == 0) { - // TODO: Is this correct? - gpr.SetImm(MIPS_REG_LO, 0); + // TODO: This isn't exactly right. + gpr.SetImm(MIPS_REG_LO, -1); } else { gpr.MapDirtyIn(MIPS_REG_LO, rs); // Remainder is just an AND, neat. diff --git a/Core/MIPS/IR/IRCompALU.cpp b/Core/MIPS/IR/IRCompALU.cpp index 54a2d3b5ea..15d5f6cbb8 100644 --- a/Core/MIPS/IR/IRCompALU.cpp +++ b/Core/MIPS/IR/IRCompALU.cpp @@ -294,6 +294,7 @@ void IRFrontend::Comp_Allegrex2(MIPSOpcode op) { CONDITIONAL_DISABLE; MIPSGPReg rt = _RT; MIPSGPReg rd = _RD; + // Don't change $zr. if (rd == 0) return; diff --git a/Core/MIPS/MIPSInt.cpp b/Core/MIPS/MIPSInt.cpp index 0f067549b7..fe9373e9f5 100644 --- a/Core/MIPS/MIPSInt.cpp +++ b/Core/MIPS/MIPSInt.cpp @@ -660,11 +660,13 @@ namespace MIPSInt s32 b = (s32)R(rt); if (a == (s32)0x80000000 && b == -1) { LO = 0x80000000; + HI = -1; } else if (b != 0) { LO = (u32)(a / b); HI = (u32)(a % b); } else { - LO = HI = 0; // Not sure what the right thing to do is? + LO = a < 0 ? 1 : -1; + HI = a; } } break; @@ -672,12 +674,12 @@ namespace MIPSInt { u32 a = R(rs); u32 b = R(rt); - if (b != 0) - { + if (b != 0) { LO = (a/b); HI = (a%b); } else { - LO = HI = 0; + LO = a <= 0xFFFF ? 0xFFFF : -1; + HI = a; } } break; diff --git a/Core/MIPS/x86/CompALU.cpp b/Core/MIPS/x86/CompALU.cpp index e45622d048..f47010d4ee 100644 --- a/Core/MIPS/x86/CompALU.cpp +++ b/Core/MIPS/x86/CompALU.cpp @@ -1002,6 +1002,9 @@ namespace MIPSComp // For CMP. gpr.KillImmediate(rs, true, false); gpr.KillImmediate(rt, true, false); + + MOV(32, R(EAX), gpr.R(rs)); + CMP(32, gpr.R(rt), Imm32(0)); FixupBranch divZero = J_CC(CC_E); @@ -1010,14 +1013,13 @@ namespace MIPSComp FixupBranch notOverflow = J_CC(CC_NE); CMP(32, gpr.R(rt), Imm32((u32) -1)); FixupBranch notOverflow2 = J_CC(CC_NE); - // TODO: Should HI be set to anything? MOV(32, gpr.R(MIPS_REG_LO), Imm32(0x80000000)); + MOV(32, gpr.R(MIPS_REG_HI), Imm32(-1)); FixupBranch skip2 = J(); SetJumpTarget(notOverflow); SetJumpTarget(notOverflow2); - MOV(32, R(EAX), gpr.R(rs)); CDQ(); IDIV(32, gpr.R(rt)); MOV(32, gpr.R(MIPS_REG_HI), R(EDX)); @@ -1025,9 +1027,9 @@ namespace MIPSComp FixupBranch skip = J(); SetJumpTarget(divZero); - // TODO: Is this the right way to handle a divide by zero? - MOV(32, gpr.R(MIPS_REG_HI), Imm32(0)); - MOV(32, gpr.R(MIPS_REG_LO), Imm32(0)); + // TODO: This isn't exactly right. + MOV(32, gpr.R(MIPS_REG_HI), R(EAX)); + MOV(32, gpr.R(MIPS_REG_LO), Imm32(-1)); SetJumpTarget(skip); SetJumpTarget(skip2); @@ -1041,20 +1043,21 @@ namespace MIPSComp gpr.KillImmediate(MIPS_REG_HI, false, true); gpr.KillImmediate(MIPS_REG_LO, false, true); gpr.KillImmediate(rt, true, false); - CMP(32, gpr.R(rt), Imm32(0)); - FixupBranch divZero = J_CC(CC_E); MOV(32, R(EAX), gpr.R(rs)); MOV(32, R(EDX), Imm32(0)); + + CMP(32, gpr.R(rt), Imm32(0)); + FixupBranch divZero = J_CC(CC_E); + DIV(32, gpr.R(rt)); MOV(32, gpr.R(MIPS_REG_HI), R(EDX)); MOV(32, gpr.R(MIPS_REG_LO), R(EAX)); FixupBranch skip = J(); SetJumpTarget(divZero); - // TODO: Is this the right way to handle a divide by zero? - MOV(32, gpr.R(MIPS_REG_HI), Imm32(0)); - MOV(32, gpr.R(MIPS_REG_LO), Imm32(0)); + MOV(32, gpr.R(MIPS_REG_HI), R(EAX)); + MOV(32, gpr.R(MIPS_REG_LO), Imm32(-1)); SetJumpTarget(skip); gpr.UnlockAllX();