CPU/NewRec: Fix register corruption in swl/swr

This commit is contained in:
Stenzek
2024-03-31 13:17:05 +10:00
parent a3013efbca
commit 8ebda3cdc8
4 changed files with 75 additions and 64 deletions

View File

@ -1764,7 +1764,13 @@ void CPU::NewRec::AArch64Compiler::Compile_swx(CompileFlags cf, MemoryAccessSize
{
DebugAssert(size == MemoryAccessSize::Word && !sign);
// TODO: this can take over rt's value if it's no longer needed
// NOTE: can't trust T in cf because of the alloc
const WRegister addr = WRegister(AllocateTempHostReg(HR_CALLEE_SAVED));
const WRegister value = g_settings.gpu_pgxp_enable ? WRegister(AllocateTempHostReg(HR_CALLEE_SAVED)) : RWARG2;
if (g_settings.gpu_pgxp_enable)
MoveMIPSRegToReg(value, inst->r.rt);
FlushForLoadStore(address, true, use_fastmem);
// TODO: if address is constant, this can be simplified..
@ -1773,20 +1779,13 @@ void CPU::NewRec::AArch64Compiler::Compile_swx(CompileFlags cf, MemoryAccessSize
armAsm->and_(RWARG1, addr, armCheckLogicalConstant(~0x3u));
GenerateLoad(RWARG1, MemoryAccessSize::Word, false, use_fastmem, []() { return RWRET; });
// TODO: this can take over rt's value if it's no longer needed
// NOTE: can't trust T in cf because of the flush
const Reg rt = inst->r.rt;
const WRegister value = g_settings.gpu_pgxp_enable ? WRegister(AllocateTempHostReg(HR_CALLEE_SAVED)) : RWARG2;
MoveMIPSRegToReg(value, rt);
armAsm->and_(RWSCRATCH, addr, 3);
armAsm->lsl(RWSCRATCH, RWSCRATCH, 3); // *8
armAsm->and_(addr, addr, armCheckLogicalConstant(~0x3u));
// Don't need the original address anymore.
// Need to load down here for PGXP-off, because it's in a volatile reg that can get overwritten by flush.
if (!g_settings.gpu_pgxp_enable)
FreeHostReg(addr.GetCode());
else
armAsm->and_(addr, addr, armCheckLogicalConstant(~0x3u));
MoveMIPSRegToReg(value, inst->r.rt);
if (inst->op == InstructionOp::swl)
{
@ -1815,12 +1814,15 @@ void CPU::NewRec::AArch64Compiler::Compile_swx(CompileFlags cf, MemoryAccessSize
armAsm->orr(value, value, RWRET);
}
FreeHostReg(addr.GetCode());
GenerateStore(addr, value, MemoryAccessSize::Word, use_fastmem);
if (g_settings.gpu_pgxp_enable)
if (!g_settings.gpu_pgxp_enable)
{
GenerateStore(addr, value, MemoryAccessSize::Word, use_fastmem);
FreeHostReg(addr.GetCode());
}
else
{
GenerateStore(addr, value, MemoryAccessSize::Word, use_fastmem);
Flush(FLUSH_FOR_C_CALL);
armAsm->mov(RWARG3, value);
FreeHostReg(value.GetCode());