Merge pull request #12143 from JosJuice/jitarm64-loadstore-pc

JitArm64: Write PC when calling MMU.cpp
This commit is contained in:
Mai 2023-11-28 21:29:37 +01:00 committed by GitHub
commit b53ecd73fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 7 deletions

View File

@ -69,7 +69,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst)
} }
else 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)); 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 // We know what GQR is here, so we can load RSCRATCH2 and call into the store method directly
// with just the scale bits. // with just the scale bits.
@ -83,7 +83,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst)
} }
else 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)); MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
// Some games (e.g. Dirt 2) incorrectly set the unused bits which breaks the lookup table code. // 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 // 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 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)); MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
// Get the high part of the GQR register // Get the high part of the GQR register
OpArg gqr = PPCSTATE_SPR(SPR_GQR0 + i); OpArg gqr = PPCSTATE_SPR(SPR_GQR0 + i);

View File

@ -385,8 +385,11 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
SetJumpTarget(slow); SetJumpTarget(slow);
} }
// Helps external systems know which instruction triggered the read. // PC is used by memory watchpoints (if enabled), profiling where to insert gather pipe
// Invalid for calls from Jit64AsmCommon routines // 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)) if (!(flags & SAFE_LOADSTORE_NO_UPDATE_PC))
{ {
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
@ -555,8 +558,11 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
SetJumpTarget(slow); SetJumpTarget(slow);
} }
// PC is used by memory watchpoints (if enabled) or to print accurate PC locations in debug logs // PC is used by memory watchpoints (if enabled), profiling where to insert gather pipe
// Invalid for calls from Jit64AsmCommon routines // 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)) if (!(flags & SAFE_LOADSTORE_NO_UPDATE_PC))
{ {
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));

View File

@ -189,6 +189,17 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
ABI_PushRegisters(gprs_to_push & ~gprs_to_push_early); ABI_PushRegisters(gprs_to_push & ~gprs_to_push_early);
m_float_emit.ABI_PushRegisters(fprs_to_push, ARM64Reg::X30); 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) if (flags & BackPatchInfo::FLAG_STORE)
{ {
ARM64Reg src_reg = RS; ARM64Reg src_reg = RS;

View File

@ -102,6 +102,11 @@ void JitArm64::psq_lXX(UGeckoInstruction inst)
else else
{ {
LDR(IndexType::Unsigned, scale_reg, PPC_REG, PPCSTATE_OFF_SPR(SPR_GQR0 + i)); 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(type_reg, scale_reg, 16, 18); // Type
UBFM(scale_reg, scale_reg, 24, 29); // Scale UBFM(scale_reg, scale_reg, 24, 29); // Scale
@ -254,6 +259,11 @@ void JitArm64::psq_stXX(UGeckoInstruction inst)
else else
{ {
LDR(IndexType::Unsigned, scale_reg, PPC_REG, PPCSTATE_OFF_SPR(SPR_GQR0 + i)); 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(type_reg, scale_reg, 0, 2); // Type
UBFM(scale_reg, scale_reg, 8, 13); // Scale UBFM(scale_reg, scale_reg, 8, 13); // Scale