From f77721b84dfad9a1c44eeb82f8f1a5eca3466b71 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 13 Dec 2019 14:34:47 +1000 Subject: [PATCH] CPU/Recompiler: Fix "jalr t0, t0" and like instructions (mainly AArch64) --- src/core/cpu_recompiler_code_generator_aarch64.cpp | 9 +++++++-- src/core/cpu_recompiler_code_generator_x64.cpp | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/core/cpu_recompiler_code_generator_aarch64.cpp b/src/core/cpu_recompiler_code_generator_aarch64.cpp index 9ae6423bc..2d5575fb5 100644 --- a/src/core/cpu_recompiler_code_generator_aarch64.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch64.cpp @@ -1460,8 +1460,9 @@ static void EmitConditionalJump(Condition condition, bool invert, a64::MacroAsse void CodeGenerator::EmitBranch(Condition condition, Reg lr_reg, Value&& branch_target) { // ensure the lr register is flushed, since we want it's correct value after the branch + // we don't want to invalidate it yet because of "jalr r0, r0", branch_target could be the lr_reg. if (lr_reg != Reg::count && lr_reg != Reg::zero) - m_register_cache.FlushGuestRegister(lr_reg, true, true); + m_register_cache.FlushGuestRegister(lr_reg, false, true); // compute return address, which is also set as the new pc when the branch isn't taken Value new_pc; @@ -1508,7 +1509,7 @@ void CodeGenerator::EmitBranch(Condition condition, Reg lr_reg, Value&& branch_t Value far_code_addr = m_register_cache.AllocateScratch(RegSize_64); m_emit->Mov(GetHostReg64(far_code_addr), reinterpret_cast(GetCurrentFarCodePointer())); - m_emit->br(GetHostReg64(far_code_addr)); + m_emit->br(GetHostReg64(far_code_addr)); m_emit->Bind(&branch_target_okay); } @@ -1534,6 +1535,10 @@ void CodeGenerator::EmitBranch(Condition condition, Reg lr_reg, Value&& branch_t m_register_cache.WriteGuestRegister(Reg::pc, std::move(new_pc)); else m_register_cache.WriteGuestRegister(Reg::pc, std::move(branch_target)); + + // now invalidate lr becuase it was possibly written in the branch, and we don't need branch_target anymore + if (lr_reg != Reg::count && lr_reg != Reg::zero) + m_register_cache.InvalidateGuestRegister(lr_reg); } void CodeGenerator::EmitRaiseException(Exception excode, Condition condition /* = Condition::Always */) diff --git a/src/core/cpu_recompiler_code_generator_x64.cpp b/src/core/cpu_recompiler_code_generator_x64.cpp index 4c73d465a..b4709af8e 100644 --- a/src/core/cpu_recompiler_code_generator_x64.cpp +++ b/src/core/cpu_recompiler_code_generator_x64.cpp @@ -1862,8 +1862,9 @@ static void EmitConditionalJump(Condition condition, bool invert, Xbyak::CodeGen void CodeGenerator::EmitBranch(Condition condition, Reg lr_reg, Value&& branch_target) { // ensure the lr register is flushed, since we want it's correct value after the branch + // we don't want to invalidate it yet because of "jalr r0, r0", branch_target could be the lr_reg. if (lr_reg != Reg::count && lr_reg != Reg::zero) - m_register_cache.FlushGuestRegister(lr_reg, true, true); + m_register_cache.FlushGuestRegister(lr_reg, false, true); // compute return address, which is also set as the new pc when the branch isn't taken Value new_pc; @@ -1930,6 +1931,10 @@ void CodeGenerator::EmitBranch(Condition condition, Reg lr_reg, Value&& branch_t m_register_cache.WriteGuestRegister(Reg::pc, std::move(new_pc)); else m_register_cache.WriteGuestRegister(Reg::pc, std::move(branch_target)); + + // now invalidate lr becuase it was possibly written in the branch, and we don't need branch_target anymore + if (lr_reg != Reg::count && lr_reg != Reg::zero) + m_register_cache.InvalidateGuestRegister(lr_reg); } void CodeGenerator::EmitRaiseException(Exception excode, Condition condition /* = Condition::Always */)