From 2ef2d4778d438534926e58cb1f9489f85f128195 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 16 Apr 2022 13:22:36 +0200 Subject: [PATCH 1/2] JitArm64: Always lock Q0 in psq_stXX Q0 is used as a scratch register by EmitBackpatchRoutine. Fixes a vertex explosion in Spider-Man 2 that was uncovered by 20b2300. --- .../Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp index 13197303bd..4fa015dcd4 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp @@ -151,8 +151,9 @@ void JitArm64::psq_stXX(UGeckoInstruction inst) const int i = indexed ? inst.Ix : inst.I; const int w = indexed ? inst.Wx : inst.W; + fpr.Lock(ARM64Reg::Q0); if (!js.assumeNoPairedQuantize) - fpr.Lock(ARM64Reg::Q0, ARM64Reg::Q1); + fpr.Lock(ARM64Reg::Q1); const bool have_single = fpr.IsSingle(inst.RS); @@ -259,9 +260,10 @@ void JitArm64::psq_stXX(UGeckoInstruction inst) fpr.Unlock(VS); gpr.Unlock(ARM64Reg::W0, ARM64Reg::W1, ARM64Reg::W30); + fpr.Unlock(ARM64Reg::Q0); if (!js.assumeNoPairedQuantize) { gpr.Unlock(ARM64Reg::W2); - fpr.Unlock(ARM64Reg::Q0, ARM64Reg::Q1); + fpr.Unlock(ARM64Reg::Q1); } } From 14f9ffeb02dc0d9dcc6204cc1063d4f5fdbdde23 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 23 Apr 2022 11:37:52 +0200 Subject: [PATCH 2/2] JitArm64: Add documentation comment for EmitBackpatchRoutine --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 3ef1955e37..e979e3a0cc 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -215,10 +215,29 @@ protected: // Dump a memory range of code void DumpCode(const u8* start, const u8* end); - // Backpatching routines + // This is the core routine for accessing emulated memory, with support for + // many different kinds of loads and stores as well as fastmem backpatching. + // + // Registers used: + // addr scratch + // Store: X1 X0 + // Load: X0 + // Zero 256: X0 X30 + // Store float: X1 Q0 + // Load float: X0 + // + // If fastmem && !do_farcode, the addr argument can be any register. + // Otherwise it must be the register listed in the table above. + // + // Additional scratch registers are used in the following situations: + // fastmem && do_farcode && emitting_routine: X2 + // fastmem && do_farcode && emitting_routine && (flags & BackPatchInfo::FLAG_STORE): X0 + // fastmem && do_farcode && emitting_routine && !(flags & BackPatchInfo::FLAG_STORE): X3 + // !fastmem || do_farcode: X30 (plus lots more unless you set gprs_to_push and fprs_to_push) void EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, Arm64Gen::ARM64Reg RS, Arm64Gen::ARM64Reg addr, BitSet32 gprs_to_push = BitSet32(0), BitSet32 fprs_to_push = BitSet32(0), bool emitting_routine = false); + // Loadstore routines void SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 offset, bool update); void SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s32 offset, bool update);