JitArm64: Implement memcheck for lfXX/stfXX with update

This commit is contained in:
JosJuice 2021-07-21 20:25:29 +02:00
parent 8c96e60cd1
commit 89301b1f91
1 changed files with 30 additions and 24 deletions

View File

@ -70,8 +70,6 @@ void JitArm64::lfXX(UGeckoInstruction inst)
break; break;
} }
FALLBACK_IF(jo.memcheck && update);
u32 imm_addr = 0; u32 imm_addr = 0;
bool is_immediate = false; bool is_immediate = false;
@ -156,7 +154,8 @@ void JitArm64::lfXX(UGeckoInstruction inst)
if (is_immediate) if (is_immediate)
MOVI2R(XA, imm_addr); MOVI2R(XA, imm_addr);
if (update) const bool early_update = !jo.memcheck;
if (update && early_update)
{ {
gpr.BindToRegister(a, false); gpr.BindToRegister(a, false);
MOV(gpr.R(a), addr_reg); MOV(gpr.R(a), addr_reg);
@ -164,7 +163,8 @@ void JitArm64::lfXX(UGeckoInstruction inst)
BitSet32 regs_in_use = gpr.GetCallerSavedUsed(); BitSet32 regs_in_use = gpr.GetCallerSavedUsed();
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed(); BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0; if (!update || early_update)
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0; fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0;
if (!jo.memcheck) if (!jo.memcheck)
fprs_in_use[DecodeReg(VD)] = 0; fprs_in_use[DecodeReg(VD)] = 0;
@ -181,6 +181,12 @@ void JitArm64::lfXX(UGeckoInstruction inst)
const ARM64Reg VD_again = fpr.RW(inst.FD, type, true); const ARM64Reg VD_again = fpr.RW(inst.FD, type, true);
ASSERT(VD == VD_again); ASSERT(VD == VD_again);
if (update && !early_update)
{
gpr.BindToRegister(a, false);
MOV(gpr.R(a), addr_reg);
}
gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30); gpr.Unlock(ARM64Reg::W0, ARM64Reg::W30);
fpr.Unlock(ARM64Reg::Q0); fpr.Unlock(ARM64Reg::Q0);
} }
@ -248,8 +254,6 @@ void JitArm64::stfXX(UGeckoInstruction inst)
break; break;
} }
FALLBACK_IF(jo.memcheck && update);
u32 imm_addr = 0; u32 imm_addr = 0;
bool is_immediate = false; bool is_immediate = false;
@ -340,26 +344,25 @@ void JitArm64::stfXX(UGeckoInstruction inst)
ARM64Reg XA = EncodeRegTo64(addr_reg); ARM64Reg XA = EncodeRegTo64(addr_reg);
if (is_immediate && !(jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(imm_addr))) bool addr_reg_set = !is_immediate;
{ const auto set_addr_reg_if_needed = [&] {
MOVI2R(XA, imm_addr); if (!addr_reg_set)
MOVI2R(XA, imm_addr);
};
if (update) const bool early_update = !jo.memcheck;
{ if (update && early_update)
gpr.BindToRegister(a, false);
MOV(gpr.R(a), addr_reg);
}
}
else if (!is_immediate && update)
{ {
gpr.BindToRegister(a, false); gpr.BindToRegister(a, false);
set_addr_reg_if_needed();
MOV(gpr.R(a), addr_reg); MOV(gpr.R(a), addr_reg);
} }
BitSet32 regs_in_use = gpr.GetCallerSavedUsed(); BitSet32 regs_in_use = gpr.GetCallerSavedUsed();
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed(); BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0; regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0; if (!update || early_update)
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0;
fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0; fprs_in_use[DecodeReg(ARM64Reg::Q0)] = 0;
if (is_immediate) if (is_immediate)
@ -384,28 +387,31 @@ void JitArm64::stfXX(UGeckoInstruction inst)
STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr)); STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr));
js.fifoBytesSinceCheck += accessSize >> 3; js.fifoBytesSinceCheck += accessSize >> 3;
if (update)
{
// Chance of this happening is fairly low, but support it
gpr.BindToRegister(a, false);
MOVI2R(gpr.R(a), imm_addr);
}
} }
else if (jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(imm_addr)) else if (jo.fastmem_arena && PowerPC::IsOptimizableRAMAddress(imm_addr))
{ {
set_addr_reg_if_needed();
EmitBackpatchRoutine(flags, true, false, V0, XA, BitSet32(0), BitSet32(0)); EmitBackpatchRoutine(flags, true, false, V0, XA, BitSet32(0), BitSet32(0));
} }
else else
{ {
set_addr_reg_if_needed();
EmitBackpatchRoutine(flags, false, false, V0, XA, regs_in_use, fprs_in_use); EmitBackpatchRoutine(flags, false, false, V0, XA, regs_in_use, fprs_in_use);
} }
} }
else else
{ {
set_addr_reg_if_needed();
EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, V0, XA, regs_in_use, fprs_in_use); EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, V0, XA, regs_in_use, fprs_in_use);
} }
if (update && !early_update)
{
gpr.BindToRegister(a, false);
set_addr_reg_if_needed();
MOV(gpr.R(a), addr_reg);
}
if (want_single && !have_single) if (want_single && !have_single)
fpr.Unlock(V0); fpr.Unlock(V0);