JitArm64: Use ScopedARM64Reg

This commit is contained in:
Sintendo 2024-06-23 23:17:25 +02:00
parent c0a0746d65
commit cb29a29866

View File

@ -222,12 +222,11 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
if (js.op->canEndBlock) if (js.op->canEndBlock)
{ {
// also flush the program counter // also flush the program counter
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
MOVI2R(WA, js.compilerPC); MOVI2R(WA, js.compilerPC);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(pc)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(pc));
ADD(WA, WA, 4); ADD(WA, WA, 4);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
gpr.Unlock(WA);
} }
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst); Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
@ -243,24 +242,23 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
{ {
if (js.isLastInstruction) if (js.isLastInstruction)
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
WriteExceptionExit(WA); WriteExceptionExit(WA);
gpr.Unlock(WA);
} }
else else
{ {
// only exit if ppcstate.npc was changed // only exit if ppcstate.npc was changed
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
ARM64Reg WB = gpr.GetReg(); {
auto WB = gpr.GetScopedReg();
MOVI2R(WB, js.compilerPC + 4); MOVI2R(WB, js.compilerPC + 4);
CMP(WB, WA); CMP(WB, WA);
gpr.Unlock(WB); }
FixupBranch c = B(CC_EQ); FixupBranch c = B(CC_EQ);
WriteExceptionExit(WA); WriteExceptionExit(WA);
SetJumpTarget(c); SetJumpTarget(c);
gpr.Unlock(WA);
} }
} }
else if (ShouldHandleFPExceptionForInstruction(js.op)) else if (ShouldHandleFPExceptionForInstruction(js.op))
@ -359,11 +357,12 @@ void JitArm64::IntializeSpeculativeConstants()
SwitchToNearCode(); SwitchToNearCode();
} }
ARM64Reg tmp = gpr.GetReg(); {
auto tmp = gpr.GetScopedReg();
ARM64Reg value = gpr.R(i); ARM64Reg value = gpr.R(i);
MOVI2R(tmp, compile_time_value); MOVI2R(tmp, compile_time_value);
CMP(value, tmp); CMP(value, tmp);
gpr.Unlock(tmp); }
FixupBranch no_fail = B(CCFlags::CC_EQ); FixupBranch no_fail = B(CCFlags::CC_EQ);
B(fail); B(fail);
@ -402,16 +401,15 @@ void JitArm64::MSRUpdated(u32 msr)
} }
else else
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
MOVI2R(WA, feature_flags); MOVI2R(WA, feature_flags);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags));
gpr.Unlock(WA);
} }
} }
void JitArm64::MSRUpdated(ARM64Reg msr) void JitArm64::MSRUpdated(ARM64Reg msr)
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
// Update mem_ptr // Update mem_ptr
@ -432,8 +430,6 @@ void JitArm64::MSRUpdated(ARM64Reg msr)
if (other_feature_flags != 0) if (other_feature_flags != 0)
ORR(WA, WA, LogicalImm(other_feature_flags, GPRSize::B32)); ORR(WA, WA, LogicalImm(other_feature_flags, GPRSize::B32));
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags));
gpr.Unlock(WA);
} }
void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return, void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return,
@ -631,13 +627,16 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return, ARM64Reg exit_address_a
// function has been called! // function has been called!
gpr.Lock(ARM64Reg::W30); gpr.Lock(ARM64Reg::W30);
} }
const u8* host_address_after_return;
{
// Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack // Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack
ARM64Reg after_reg = ARM64Reg::INVALID_REG; Arm64RegCache::ScopedARM64Reg after_reg;
ARM64Reg reg_to_push; ARM64Reg reg_to_push;
const u64 feature_flags = m_ppc_state.feature_flags; const u64 feature_flags = m_ppc_state.feature_flags;
if (exit_address_after_return_reg == ARM64Reg::INVALID_REG) if (exit_address_after_return_reg == ARM64Reg::INVALID_REG)
{ {
after_reg = gpr.GetReg(); after_reg = gpr.GetScopedReg();
reg_to_push = EncodeRegTo64(after_reg); reg_to_push = EncodeRegTo64(after_reg);
MOVI2R(reg_to_push, feature_flags << 32 | exit_address_after_return); MOVI2R(reg_to_push, feature_flags << 32 | exit_address_after_return);
} }
@ -647,19 +646,18 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return, ARM64Reg exit_address_a
} }
else else
{ {
after_reg = gpr.GetReg(); after_reg = gpr.GetScopedReg();
reg_to_push = EncodeRegTo64(after_reg); reg_to_push = EncodeRegTo64(after_reg);
ORRI2R(reg_to_push, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32, ORRI2R(reg_to_push, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32,
reg_to_push); reg_to_push);
} }
ARM64Reg code_reg = gpr.GetReg();
auto code_reg = gpr.GetScopedReg();
constexpr s32 adr_offset = sizeof(u32) * 3; constexpr s32 adr_offset = sizeof(u32) * 3;
const u8* host_address_after_return = GetCodePtr() + adr_offset; host_address_after_return = GetCodePtr() + adr_offset;
ADR(EncodeRegTo64(code_reg), adr_offset); ADR(EncodeRegTo64(code_reg), adr_offset);
STP(IndexType::Pre, EncodeRegTo64(code_reg), reg_to_push, ARM64Reg::SP, -16); STP(IndexType::Pre, EncodeRegTo64(code_reg), reg_to_push, ARM64Reg::SP, -16);
gpr.Unlock(code_reg); }
if (after_reg != ARM64Reg::INVALID_REG)
gpr.Unlock(after_reg);
FixupBranch skip_exit = BL(); FixupBranch skip_exit = BL();
DEBUG_ASSERT(GetCodePtr() == host_address_after_return || HasWriteFailed()); DEBUG_ASSERT(GetCodePtr() == host_address_after_return || HasWriteFailed());
@ -792,10 +790,9 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always
void JitArm64::WriteConditionalExceptionExit(int exception, u64 increment_sp_on_exit) void JitArm64::WriteConditionalExceptionExit(int exception, u64 increment_sp_on_exit)
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
WriteConditionalExceptionExit(exception, WA, Arm64Gen::ARM64Reg::INVALID_REG, WriteConditionalExceptionExit(exception, WA, Arm64Gen::ARM64Reg::INVALID_REG,
increment_sp_on_exit); increment_sp_on_exit);
gpr.Unlock(WA);
} }
void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_gpr, ARM64Reg temp_fpr, void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_gpr, ARM64Reg temp_fpr,
@ -1183,7 +1180,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
// asynchronous. // asynchronous.
if (jo.optimizeGatherPipe && gatherPipeIntCheck) if (jo.optimizeGatherPipe && gatherPipeIntCheck)
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
@ -1209,8 +1206,6 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
SwitchToNearCode(); SwitchToNearCode();
SetJumpTarget(no_ext_exception); SetJumpTarget(no_ext_exception);
SetJumpTarget(exit); SetJumpTarget(exit);
gpr.Unlock(WA);
} }
} }
@ -1224,12 +1219,11 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
// The only thing that currently sets op.skip is the BLR following optimization. // The only thing that currently sets op.skip is the BLR following optimization.
// If any non-branch instruction starts setting that too, this will need to be changed. // If any non-branch instruction starts setting that too, this will need to be changed.
ASSERT(op.inst.hex == 0x4e800020); ASSERT(op.inst.hex == 0x4e800020);
const ARM64Reg bw_reg_a = gpr.GetReg(), bw_reg_b = gpr.GetReg(); const auto bw_reg_a = gpr.GetScopedReg(), bw_reg_b = gpr.GetScopedReg();
const BitSet32 gpr_caller_save = const BitSet32 gpr_caller_save =
gpr.GetCallerSavedUsed() & ~BitSet32{DecodeReg(bw_reg_a), DecodeReg(bw_reg_b)}; gpr.GetCallerSavedUsed() & ~BitSet32{DecodeReg(bw_reg_a), DecodeReg(bw_reg_b)};
WriteBranchWatch<true>(op.address, op.branchTo, op.inst, bw_reg_a, bw_reg_b, WriteBranchWatch<true>(op.address, op.branchTo, op.inst, bw_reg_a, bw_reg_b,
gpr_caller_save, fpr.GetCallerSavedUsed()); gpr_caller_save, fpr.GetCallerSavedUsed());
gpr.Unlock(bw_reg_a, bw_reg_b);
} }
} }
else else
@ -1267,10 +1261,12 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound) if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
{ {
FixupBranch b1;
// This instruction uses FPU - needs to add FP exception bailout // This instruction uses FPU - needs to add FP exception bailout
ARM64Reg WA = gpr.GetReg(); {
auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr));
FixupBranch b1 = TBNZ(WA, 13); // Test FP enabled bit b1 = TBNZ(WA, 13); // Test FP enabled bit
FixupBranch far_addr = B(); FixupBranch far_addr = B();
SwitchToFarCode(); SwitchToFarCode();
@ -1282,8 +1278,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
ORR(WA, WA, LogicalImm(EXCEPTION_FPU_UNAVAILABLE, GPRSize::B32)); ORR(WA, WA, LogicalImm(EXCEPTION_FPU_UNAVAILABLE, GPRSize::B32));
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
}
gpr.Unlock(WA);
WriteExceptionExit(js.compilerPC, false, true); WriteExceptionExit(js.compilerPC, false, true);