JitArm64: Use ScopedARM64Reg

This commit is contained in:
Sintendo 2024-06-23 23:17:25 +02:00
parent c0a0746d65
commit cb29a29866
1 changed files with 62 additions and 67 deletions

View File

@ -222,12 +222,11 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
if (js.op->canEndBlock)
{
// also flush the program counter
ARM64Reg WA = gpr.GetReg();
auto WA = gpr.GetScopedReg();
MOVI2R(WA, js.compilerPC);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(pc));
ADD(WA, WA, 4);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
gpr.Unlock(WA);
}
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
@ -243,24 +242,23 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
{
if (js.isLastInstruction)
{
ARM64Reg WA = gpr.GetReg();
auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
WriteExceptionExit(WA);
gpr.Unlock(WA);
}
else
{
// only exit if ppcstate.npc was changed
ARM64Reg WA = gpr.GetReg();
auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(npc));
ARM64Reg WB = gpr.GetReg();
MOVI2R(WB, js.compilerPC + 4);
CMP(WB, WA);
gpr.Unlock(WB);
{
auto WB = gpr.GetScopedReg();
MOVI2R(WB, js.compilerPC + 4);
CMP(WB, WA);
}
FixupBranch c = B(CC_EQ);
WriteExceptionExit(WA);
SetJumpTarget(c);
gpr.Unlock(WA);
}
}
else if (ShouldHandleFPExceptionForInstruction(js.op))
@ -359,11 +357,12 @@ void JitArm64::IntializeSpeculativeConstants()
SwitchToNearCode();
}
ARM64Reg tmp = gpr.GetReg();
ARM64Reg value = gpr.R(i);
MOVI2R(tmp, compile_time_value);
CMP(value, tmp);
gpr.Unlock(tmp);
{
auto tmp = gpr.GetScopedReg();
ARM64Reg value = gpr.R(i);
MOVI2R(tmp, compile_time_value);
CMP(value, tmp);
}
FixupBranch no_fail = B(CCFlags::CC_EQ);
B(fail);
@ -402,16 +401,15 @@ void JitArm64::MSRUpdated(u32 msr)
}
else
{
ARM64Reg WA = gpr.GetReg();
auto WA = gpr.GetScopedReg();
MOVI2R(WA, feature_flags);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(feature_flags));
gpr.Unlock(WA);
}
}
void JitArm64::MSRUpdated(ARM64Reg msr)
{
ARM64Reg WA = gpr.GetReg();
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
// Update mem_ptr
@ -432,8 +430,6 @@ void JitArm64::MSRUpdated(ARM64Reg msr)
if (other_feature_flags != 0)
ORR(WA, WA, LogicalImm(other_feature_flags, GPRSize::B32));
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,
@ -631,35 +627,37 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return, ARM64Reg exit_address_a
// function has been called!
gpr.Lock(ARM64Reg::W30);
}
// Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack
ARM64Reg after_reg = ARM64Reg::INVALID_REG;
ARM64Reg reg_to_push;
const u64 feature_flags = m_ppc_state.feature_flags;
if (exit_address_after_return_reg == ARM64Reg::INVALID_REG)
const u8* host_address_after_return;
{
after_reg = gpr.GetReg();
reg_to_push = EncodeRegTo64(after_reg);
MOVI2R(reg_to_push, feature_flags << 32 | exit_address_after_return);
// Push {ARM_PC (64-bit); PPC_PC (32-bit); feature_flags (32-bit)} on the stack
Arm64RegCache::ScopedARM64Reg after_reg;
ARM64Reg reg_to_push;
const u64 feature_flags = m_ppc_state.feature_flags;
if (exit_address_after_return_reg == ARM64Reg::INVALID_REG)
{
after_reg = gpr.GetScopedReg();
reg_to_push = EncodeRegTo64(after_reg);
MOVI2R(reg_to_push, feature_flags << 32 | exit_address_after_return);
}
else if (feature_flags == 0)
{
reg_to_push = EncodeRegTo64(exit_address_after_return_reg);
}
else
{
after_reg = gpr.GetScopedReg();
reg_to_push = EncodeRegTo64(after_reg);
ORRI2R(reg_to_push, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32,
reg_to_push);
}
auto code_reg = gpr.GetScopedReg();
constexpr s32 adr_offset = sizeof(u32) * 3;
host_address_after_return = GetCodePtr() + adr_offset;
ADR(EncodeRegTo64(code_reg), adr_offset);
STP(IndexType::Pre, EncodeRegTo64(code_reg), reg_to_push, ARM64Reg::SP, -16);
}
else if (feature_flags == 0)
{
reg_to_push = EncodeRegTo64(exit_address_after_return_reg);
}
else
{
after_reg = gpr.GetReg();
reg_to_push = EncodeRegTo64(after_reg);
ORRI2R(reg_to_push, EncodeRegTo64(exit_address_after_return_reg), feature_flags << 32,
reg_to_push);
}
ARM64Reg code_reg = gpr.GetReg();
constexpr s32 adr_offset = sizeof(u32) * 3;
const u8* host_address_after_return = GetCodePtr() + adr_offset;
ADR(EncodeRegTo64(code_reg), adr_offset);
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();
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)
{
ARM64Reg WA = gpr.GetReg();
auto WA = gpr.GetScopedReg();
WriteConditionalExceptionExit(exception, WA, Arm64Gen::ARM64Reg::INVALID_REG,
increment_sp_on_exit);
gpr.Unlock(WA);
}
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.
if (jo.optimizeGatherPipe && gatherPipeIntCheck)
{
ARM64Reg WA = gpr.GetReg();
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
@ -1209,8 +1206,6 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
SwitchToNearCode();
SetJumpTarget(no_ext_exception);
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.
// If any non-branch instruction starts setting that too, this will need to be changed.
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 =
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,
gpr_caller_save, fpr.GetCallerSavedUsed());
gpr.Unlock(bw_reg_a, bw_reg_b);
}
}
else
@ -1267,23 +1261,24 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
{
FixupBranch b1;
// 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
{
auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(msr));
b1 = TBNZ(WA, 13); // Test FP enabled bit
FixupBranch far_addr = B();
SwitchToFarCode();
SetJumpTarget(far_addr);
FixupBranch far_addr = B();
SwitchToFarCode();
SetJumpTarget(far_addr);
gpr.Flush(FlushMode::MaintainState, WA);
fpr.Flush(FlushMode::MaintainState, ARM64Reg::INVALID_REG);
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);
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));
}
WriteExceptionExit(js.compilerPC, false, true);