Correct divide by zero HI/LO values a bit.

Interpreter is now correct, but it's probably not all that important to
get right in jit.
This commit is contained in:
Unknown W. Brackets 2016-05-14 18:38:54 -07:00
parent 4ac773e8b4
commit a05ae2a0a6
5 changed files with 25 additions and 19 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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();