diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStorePaired.cpp index bae5af75ecc2..41d999631ba3 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStorePaired.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStorePaired.cpp @@ -69,7 +69,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst) } else { - // Stash PC in case asm_routine causes exception + // Stash PC in case asm routine needs to call into C++ MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); // We know what GQR is here, so we can load RSCRATCH2 and call into the store method directly // with just the scale bits. @@ -83,7 +83,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst) } else { - // Stash PC incase asm_routine causes exception + // Stash PC in case asm routine needs to call into C++ MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); // Some games (e.g. Dirt 2) incorrectly set the unused bits which breaks the lookup table code. // Hence, we need to mask out the unused bits. The layout of the GQR register is @@ -144,7 +144,7 @@ void Jit64::psq_lXX(UGeckoInstruction inst) } else { - // Stash PC in case asm_routine causes exception + // Stash PC in case asm routine needs to call into C++ MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); // Get the high part of the GQR register OpArg gqr = PPCSTATE_SPR(SPR_GQR0 + i); diff --git a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp index 04036e11ab05..6cebe3e5483a 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp +++ b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp @@ -384,8 +384,11 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress, SetJumpTarget(slow); } - // Helps external systems know which instruction triggered the read. - // Invalid for calls from Jit64AsmCommon routines + // PC is used by memory watchpoints (if enabled), profiling where to insert gather pipe + // interrupt checks, and printing accurate PC locations in debug logs. + // + // In the case of Jit64AsmCommon routines, we don't know the PC here, + // so the caller has to store the PC themselves. if (!(flags & SAFE_LOADSTORE_NO_UPDATE_PC)) { MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); @@ -553,8 +556,11 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces SetJumpTarget(slow); } - // PC is used by memory watchpoints (if enabled) or to print accurate PC locations in debug logs - // Invalid for calls from Jit64AsmCommon routines + // PC is used by memory watchpoints (if enabled), profiling where to insert gather pipe + // interrupt checks, and printing accurate PC locations in debug logs. + // + // In the case of Jit64AsmCommon routines, we don't know the PC here, + // so the caller has to store the PC themselves. if (!(flags & SAFE_LOADSTORE_NO_UPDATE_PC)) { MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp index 8e14e694c403..30d7080c8ed2 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp @@ -189,6 +189,17 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS, ABI_PushRegisters(gprs_to_push & ~gprs_to_push_early); m_float_emit.ABI_PushRegisters(fprs_to_push, ARM64Reg::X30); + // PC is used by memory watchpoints (if enabled), profiling where to insert gather pipe + // interrupt checks, and printing accurate PC locations in debug logs. + // + // In the case of JitAsm routines, we don't know the PC here, + // so the caller has to store the PC themselves. + if (!emitting_routine) + { + MOVI2R(ARM64Reg::W30, js.compilerPC); + STR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(pc)); + } + if (flags & BackPatchInfo::FLAG_STORE) { ARM64Reg src_reg = RS; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp index 9a747208420a..f60ca3cf2519 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStorePaired.cpp @@ -102,6 +102,11 @@ void JitArm64::psq_lXX(UGeckoInstruction inst) else { LDR(IndexType::Unsigned, scale_reg, PPC_REG, PPCSTATE_OFF_SPR(SPR_GQR0 + i)); + + // Stash PC in case asm routine needs to call into C++ + MOVI2R(ARM64Reg::W30, js.compilerPC); + STR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(pc)); + UBFM(type_reg, scale_reg, 16, 18); // Type UBFM(scale_reg, scale_reg, 24, 29); // Scale @@ -254,6 +259,11 @@ void JitArm64::psq_stXX(UGeckoInstruction inst) else { LDR(IndexType::Unsigned, scale_reg, PPC_REG, PPCSTATE_OFF_SPR(SPR_GQR0 + i)); + + // Stash PC in case asm routine needs to call into C++ + MOVI2R(ARM64Reg::W30, js.compilerPC); + STR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(pc)); + UBFM(type_reg, scale_reg, 0, 2); // Type UBFM(scale_reg, scale_reg, 8, 13); // Scale