Skip to content

Commit

Permalink
Merge pull request #12740 from mitaclaw/breakpoint-before-fpu-exception
Browse files Browse the repository at this point in the history
Jit64/JitArm64: Check Breakpoints Before FPU Availability
  • Loading branch information
OatmealDome committed May 8, 2024
2 parents 2c91367 + 756ea81 commit 50386c4
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 57 deletions.
49 changes: 25 additions & 24 deletions Source/Core/Core/PowerPC/Jit64/Jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#endif

#include "Common/CommonTypes.h"
#include "Common/EnumUtils.h"
#include "Common/GekkoDisassembler.h"
#include "Common/IOFile.h"
#include "Common/Logging/Log.h"
Expand Down Expand Up @@ -1035,6 +1036,30 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
}
else
{
auto& cpu = m_system.GetCPU();
auto& power_pc = m_system.GetPowerPC();
if (m_enable_debugging && power_pc.GetBreakPoints().IsAddressBreakPoint(op.address) &&
!cpu.IsStepping())
{
gpr.Flush();
fpr.Flush();

MOV(32, PPCSTATE(pc), Imm32(op.address));
ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionP(PowerPC::CheckBreakPointsFromJIT, &power_pc);
ABI_PopRegistersAndAdjustStack({}, 0);
MOV(64, R(RSCRATCH), ImmPtr(cpu.GetStatePtr()));
CMP(32, MatR(RSCRATCH), Imm32(Common::ToUnderlying(CPU::State::Running)));
FixupBranch noBreakpoint = J_CC(CC_E);

Cleanup();
MOV(32, PPCSTATE(npc), Imm32(op.address));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher_exit, Jump::Near);

SetJumpTarget(noBreakpoint);
}

if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
{
// This instruction uses FPU - needs to add FP exception bailout
Expand All @@ -1061,30 +1086,6 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
js.firstFPInstructionFound = true;
}

auto& cpu = m_system.GetCPU();
auto& power_pc = m_system.GetPowerPC();
if (m_enable_debugging && power_pc.GetBreakPoints().IsAddressBreakPoint(op.address) &&
!cpu.IsStepping())
{
gpr.Flush();
fpr.Flush();

MOV(32, PPCSTATE(pc), Imm32(op.address));
ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionP(PowerPC::CheckBreakPointsFromJIT, &power_pc);
ABI_PopRegistersAndAdjustStack({}, 0);
MOV(64, R(RSCRATCH), ImmPtr(cpu.GetStatePtr()));
TEST(32, MatR(RSCRATCH), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);

Cleanup();
MOV(32, PPCSTATE(npc), Imm32(op.address));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher_exit, Jump::Near);

SetJumpTarget(noBreakpoint);
}

if (bJITRegisterCacheOff)
{
gpr.Flush();
Expand Down
9 changes: 5 additions & 4 deletions Source/Core/Core/PowerPC/Jit64/JitAsm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <climits>

#include "Common/CommonTypes.h"
#include "Common/EnumUtils.h"
#include "Common/JitRegister.h"
#include "Common/x64ABI.h"
#include "Common/x64Emitter.h"
Expand Down Expand Up @@ -105,8 +106,8 @@ void Jit64AsmRoutineManager::Generate()
if (enable_debugging)
{
MOV(64, R(RSCRATCH), ImmPtr(system.GetCPU().GetStatePtr()));
TEST(32, MatR(RSCRATCH), Imm32(0xFFFFFFFF));
dbg_exit = J_CC(CC_NZ, Jump::Near);
CMP(32, MatR(RSCRATCH), Imm32(Common::ToUnderlying(CPU::State::Running)));
dbg_exit = J_CC(CC_NE, Jump::Near);
}

SetJumpTarget(skipToRealDispatch);
Expand Down Expand Up @@ -236,8 +237,8 @@ void Jit64AsmRoutineManager::Generate()
// Check the state pointer to see if we are exiting
// Gets checked on at the end of every slice
MOV(64, R(RSCRATCH), ImmPtr(system.GetCPU().GetStatePtr()));
TEST(32, MatR(RSCRATCH), Imm32(0xFFFFFFFF));
J_CC(CC_Z, outerLoop);
CMP(32, MatR(RSCRATCH), Imm32(Common::ToUnderlying(CPU::State::Running)));
J_CC(CC_E, outerLoop);

// Landing pad for drec space
dispatcher_exit = GetCodePtr();
Expand Down
60 changes: 31 additions & 29 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "Common/Arm64Emitter.h"
#include "Common/CommonTypes.h"
#include "Common/EnumUtils.h"
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
#include "Common/MsgHandler.h"
Expand Down Expand Up @@ -1239,35 +1240,6 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
}
else
{
if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
{
// This instruction uses FPU - needs to add FP exception bailout
ARM64Reg WA = gpr.GetReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr));
FixupBranch b1 = TBNZ(WA, 13); // Test FP enabled bit

FixupBranch far_addr = B();
SwitchToFarCode();
SetJumpTarget(far_addr);

gpr.Flush(FlushMode::MaintainState, WA);
fpr.Flush(FlushMode::MaintainState, ARM64Reg::INVALID_REG);

LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
ORR(WA, WA, LogicalImm(EXCEPTION_FPU_UNAVAILABLE, GPRSize::B32));
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));

gpr.Unlock(WA);

WriteExceptionExit(js.compilerPC, false, true);

SwitchToNearCode();

SetJumpTarget(b1);

js.firstFPInstructionFound = true;
}

if (m_enable_debugging && !cpu.IsStepping() &&
m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(op.address))
{
Expand All @@ -1284,6 +1256,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)

LDR(IndexType::Unsigned, ARM64Reg::W0, ARM64Reg::X0,
MOVPage2R(ARM64Reg::X0, cpu.GetStatePtr()));
static_assert(Common::ToUnderlying(CPU::State::Running) == 0);
FixupBranch no_breakpoint = CBZ(ARM64Reg::W0);

Cleanup();
Expand All @@ -1298,6 +1271,35 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
SetJumpTarget(no_breakpoint);
}

if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
{
// This instruction uses FPU - needs to add FP exception bailout
ARM64Reg WA = gpr.GetReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr));
FixupBranch b1 = TBNZ(WA, 13); // Test FP enabled bit

FixupBranch far_addr = B();
SwitchToFarCode();
SetJumpTarget(far_addr);

gpr.Flush(FlushMode::MaintainState, WA);
fpr.Flush(FlushMode::MaintainState, ARM64Reg::INVALID_REG);

LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
ORR(WA, WA, LogicalImm(EXCEPTION_FPU_UNAVAILABLE, GPRSize::B32));
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));

gpr.Unlock(WA);

WriteExceptionExit(js.compilerPC, false, true);

SwitchToNearCode();

SetJumpTarget(b1);

js.firstFPInstructionFound = true;
}

if (bJITRegisterCacheOff)
{
FlushCarry();
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Common/Arm64Emitter.h"
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/EnumUtils.h"
#include "Common/FloatUtils.h"
#include "Common/JitRegister.h"
#include "Common/MathUtil.h"
Expand Down Expand Up @@ -88,6 +89,7 @@ void JitArm64::GenerateAsm()
{
LDR(IndexType::Unsigned, ARM64Reg::W8, ARM64Reg::X8,
MOVPage2R(ARM64Reg::X8, cpu.GetStatePtr()));
static_assert(Common::ToUnderlying(CPU::State::Running) == 0);
debug_exit = CBNZ(ARM64Reg::W8);
}

Expand Down Expand Up @@ -195,6 +197,7 @@ void JitArm64::GenerateAsm()
// Check the state pointer to see if we are exiting
// Gets checked on at the end of every slice
LDR(IndexType::Unsigned, ARM64Reg::W8, ARM64Reg::X8, MOVPage2R(ARM64Reg::X8, cpu.GetStatePtr()));
static_assert(Common::ToUnderlying(CPU::State::Running) == 0);
FixupBranch exit = CBNZ(ARM64Reg::W8);

SetJumpTarget(to_start_of_timing_slice);
Expand Down

0 comments on commit 50386c4

Please sign in to comment.