Jit_Integer: divwux

This commit is contained in:
MerryMage 2018-10-15 21:01:02 +01:00
parent 2652d4dfdb
commit f945457915

View File

@ -1159,9 +1159,9 @@ void Jit64::divwux(UGeckoInstruction inst)
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
int a = inst.RA, b = inst.RB, d = inst.RD; int a = inst.RA, b = inst.RB, d = inst.RD;
if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) if (gpr.IsImm(a, b))
{ {
if (gpr.R(b).Imm32() == 0) if (gpr.Imm32(b) == 0)
{ {
gpr.SetImmediate32(d, 0); gpr.SetImmediate32(d, 0);
if (inst.OE) if (inst.OE)
@ -1169,14 +1169,14 @@ void Jit64::divwux(UGeckoInstruction inst)
} }
else else
{ {
gpr.SetImmediate32(d, gpr.R(a).Imm32() / gpr.R(b).Imm32()); gpr.SetImmediate32(d, gpr.Imm32(a) / gpr.Imm32(b));
if (inst.OE) if (inst.OE)
GenerateConstantOverflow(false); GenerateConstantOverflow(false);
} }
} }
else if (gpr.R(b).IsImm()) else if (gpr.IsImm(b))
{ {
u32 divisor = gpr.R(b).Imm32(); u32 divisor = gpr.Imm32(b);
if (divisor == 0) if (divisor == 0)
{ {
gpr.SetImmediate32(d, 0); gpr.SetImmediate32(d, 0);
@ -1191,12 +1191,14 @@ void Jit64::divwux(UGeckoInstruction inst)
if (divisor == (u32)(1 << shift)) if (divisor == (u32)(1 << shift))
{ {
gpr.Lock(a, b, d); RCOpArg Ra = gpr.Use(a, RCMode::Read);
gpr.BindToRegister(d, d == a, true); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
RegCache::Realize(Ra, Rd);
if (d != a) if (d != a)
MOV(32, gpr.R(d), gpr.R(a)); MOV(32, Rd, Ra);
if (shift) if (shift)
SHR(32, gpr.R(d), Imm8(shift)); SHR(32, Rd, Imm8(shift));
} }
else else
{ {
@ -1208,32 +1210,35 @@ void Jit64::divwux(UGeckoInstruction inst)
if (((u64)(magic + 1) * (max_quotient * divisor - 1)) >> (shift + 32) != max_quotient - 1) if (((u64)(magic + 1) * (max_quotient * divisor - 1)) >> (shift + 32) != max_quotient - 1)
{ {
// If failed, use slower round-down method // If failed, use slower round-down method
gpr.Lock(a, b, d); RCOpArg Ra = gpr.Use(a, RCMode::Read);
gpr.BindToRegister(d, d == a, true); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
RegCache::Realize(Ra, Rd);
MOV(32, R(RSCRATCH), Imm32(magic)); MOV(32, R(RSCRATCH), Imm32(magic));
if (d != a) if (d != a)
MOV(32, gpr.R(d), gpr.R(a)); MOV(32, Rd, Ra);
IMUL(64, gpr.RX(d), R(RSCRATCH)); IMUL(64, Rd, R(RSCRATCH));
ADD(64, gpr.R(d), R(RSCRATCH)); ADD(64, Rd, R(RSCRATCH));
SHR(64, gpr.R(d), Imm8(shift + 32)); SHR(64, Rd, Imm8(shift + 32));
} }
else else
{ {
// If success, use faster round-up method // If success, use faster round-up method
gpr.Lock(a, b, d); RCX64Reg Ra = gpr.Bind(a, RCMode::Read);
gpr.BindToRegister(a, true, false); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
gpr.BindToRegister(d, false, true); RegCache::Realize(Ra, Rd);
if (d == a) if (d == a)
{ {
MOV(32, R(RSCRATCH), Imm32(magic + 1)); MOV(32, R(RSCRATCH), Imm32(magic + 1));
IMUL(64, gpr.RX(d), R(RSCRATCH)); IMUL(64, Rd, R(RSCRATCH));
} }
else else
{ {
MOV(32, gpr.R(d), Imm32(magic + 1)); MOV(32, Rd, Imm32(magic + 1));
IMUL(64, gpr.RX(d), gpr.R(a)); IMUL(64, Rd, Ra);
} }
SHR(64, gpr.R(d), Imm8(shift + 32)); SHR(64, Rd, Imm8(shift + 32));
} }
} }
if (inst.OE) if (inst.OE)
@ -1242,24 +1247,27 @@ void Jit64::divwux(UGeckoInstruction inst)
} }
else else
{ {
gpr.Lock(a, b, d); RCOpArg Ra = gpr.Use(a, RCMode::Read);
RCX64Reg Rb = gpr.Bind(b, RCMode::Read);
RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
// no register choice (do we need to do this?) // no register choice (do we need to do this?)
gpr.FlushLockX(EAX, EDX); RCX64Reg eax = gpr.Scratch(EAX);
gpr.BindToRegister(d, (d == a || d == b), true); RCX64Reg edx = gpr.Scratch(EDX);
MOV(32, R(EAX), gpr.R(a)); RegCache::Realize(Ra, Rb, Rd, eax, edx);
XOR(32, R(EDX), R(EDX));
gpr.KillImmediate(b, true, false); MOV(32, eax, Ra);
CMP_or_TEST(32, gpr.R(b), Imm32(0)); XOR(32, edx, edx);
TEST(32, Rb, Rb);
FixupBranch not_div_by_zero = J_CC(CC_NZ); FixupBranch not_div_by_zero = J_CC(CC_NZ);
MOV(32, gpr.R(d), R(EDX)); MOV(32, Rd, edx);
if (inst.OE) if (inst.OE)
{ {
GenerateConstantOverflow(true); GenerateConstantOverflow(true);
} }
FixupBranch end = J(); FixupBranch end = J();
SetJumpTarget(not_div_by_zero); SetJumpTarget(not_div_by_zero);
DIV(32, gpr.R(b)); DIV(32, Rb);
MOV(32, gpr.R(d), R(EAX)); MOV(32, Rd, eax);
if (inst.OE) if (inst.OE)
{ {
GenerateConstantOverflow(false); GenerateConstantOverflow(false);
@ -1267,9 +1275,7 @@ void Jit64::divwux(UGeckoInstruction inst)
SetJumpTarget(end); SetJumpTarget(end);
} }
if (inst.Rc) if (inst.Rc)
ComputeRC(gpr.R(d)); ComputeRC(d);
gpr.UnlockAll();
gpr.UnlockAllX();
} }
void Jit64::divwx(UGeckoInstruction inst) void Jit64::divwx(UGeckoInstruction inst)