diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index e46ccf9ee4..3caadf9918 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -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(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);