JIT: fix memcheck on float load/store, plus some corner cases

This commit is contained in:
Fiora
2014-09-06 12:54:24 -07:00
parent b3c1cec197
commit 32a67ef264

View File

@ -27,13 +27,18 @@ void Jit64::lfXXX(UGeckoInstruction inst)
int a = inst.RA; int a = inst.RA;
int b = inst.RB; int b = inst.RB;
FALLBACK_IF(!indexed && !a); FALLBACK_IF((!indexed && !a) || (update && a == d));
if (update) if (update)
gpr.BindToRegister(a, true, true); gpr.BindToRegister(a, true, true);
s32 offset = 0; s32 offset = 0;
OpArg addr = gpr.R(a); OpArg addr = gpr.R(a);
if (update && js.memcheck)
{
addr = R(RSCRATCH2);
MOV(32, addr, gpr.R(a));
}
if (indexed) if (indexed)
{ {
if (update) if (update)
@ -58,10 +63,13 @@ void Jit64::lfXXX(UGeckoInstruction inst)
if (update) if (update)
ADD(32, addr, Imm32((s32)(s16)inst.SIMM_16)); ADD(32, addr, Imm32((s32)(s16)inst.SIMM_16));
else else
offset = (s32)(s16)inst.SIMM_16; offset = (s16)inst.SIMM_16;
} }
SafeLoadToReg(RSCRATCH, addr, single ? 32 : 64, offset, CallerSavedRegistersInUse(), false); u32 registersInUse = CallerSavedRegistersInUse();
if (update && js.memcheck)
registersInUse |= (1 << RSCRATCH2);
SafeLoadToReg(RSCRATCH, addr, single ? 32 : 64, offset, registersInUse, false);
fpr.Lock(d); fpr.Lock(d);
fpr.BindToRegister(d, js.memcheck || !single); fpr.BindToRegister(d, js.memcheck || !single);
@ -75,6 +83,8 @@ void Jit64::lfXXX(UGeckoInstruction inst)
MOVQ_xmm(XMM0, R(RSCRATCH)); MOVQ_xmm(XMM0, R(RSCRATCH));
MOVSD(fpr.RX(d), R(XMM0)); MOVSD(fpr.RX(d), R(XMM0));
} }
if (update && js.memcheck)
MOV(32, gpr.R(a), addr);
MEMCHECK_END MEMCHECK_END
fpr.UnlockAll(); fpr.UnlockAll();
gpr.UnlockAll(); gpr.UnlockAll();
@ -93,9 +103,10 @@ void Jit64::stfXXX(UGeckoInstruction inst)
int a = inst.RA; int a = inst.RA;
int b = inst.RB; int b = inst.RB;
FALLBACK_IF(!indexed && !a); FALLBACK_IF((!indexed && !a) || (update && (a == s || a == b)));
s32 offset = 0; s32 offset = 0;
s32 imm = (s16)inst.SIMM_16;
if (indexed) if (indexed)
{ {
if (update) if (update)
@ -121,11 +132,11 @@ void Jit64::stfXXX(UGeckoInstruction inst)
if (update) if (update)
{ {
gpr.BindToRegister(a, true, true); gpr.BindToRegister(a, true, true);
ADD(32, gpr.R(a), Imm32((s32)(s16)inst.SIMM_16)); ADD(32, gpr.R(a), Imm32(imm));
} }
else else
{ {
offset = (s32)(s16)inst.SIMM_16; offset = imm;
} }
MOV(32, R(RSCRATCH2), gpr.R(a)); MOV(32, R(RSCRATCH2), gpr.R(a));
} }
@ -145,6 +156,13 @@ void Jit64::stfXXX(UGeckoInstruction inst)
MOV(64, R(RSCRATCH), fpr.R(s)); MOV(64, R(RSCRATCH), fpr.R(s));
SafeWriteRegToReg(RSCRATCH, RSCRATCH2, 64, offset, CallerSavedRegistersInUse()); SafeWriteRegToReg(RSCRATCH, RSCRATCH2, 64, offset, CallerSavedRegistersInUse());
} }
if (js.memcheck && update)
{
// revert the address change if an exception occurred
MEMCHECK_START(true)
SUB(32, gpr.R(a), indexed ? gpr.R(b) : Imm32(imm));
MEMCHECK_END
}
gpr.UnlockAll(); gpr.UnlockAll();
gpr.UnlockAllX(); gpr.UnlockAllX();
} }