From 19da68568e02e78c308afa0347eb9138ec23030c Mon Sep 17 00:00:00 2001 From: MerryMage Date: Wed, 17 Jan 2018 00:34:33 +0000 Subject: [PATCH] A64/translate/branch: bug: Read-after-write error in BLR --- src/backend_x64/a64_emit_x64.cpp | 16 ++++++++++++---- src/frontend/A64/translate/impl/branch.cpp | 5 ++++- src/frontend/ir/basic_block.cpp | 4 ++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index 0106c66e..dc569d8a 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -347,10 +347,18 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::PopRSBHint, IR::LocationDescriptor i } void A64EmitX64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) { - Xbyak::Label pass = EmitCond(terminal.if_); - EmitTerminal(terminal.else_, initial_location); - code->L(pass); - EmitTerminal(terminal.then_, initial_location); + switch (terminal.if_) { + case IR::Cond::AL: + case IR::Cond::NV: + EmitTerminal(terminal.then_, initial_location); + break; + default: + Xbyak::Label pass = EmitCond(terminal.if_); + EmitTerminal(terminal.else_, initial_location); + code->L(pass); + EmitTerminal(terminal.then_, initial_location); + break; + } } void A64EmitX64::EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) { diff --git a/src/frontend/A64/translate/impl/branch.cpp b/src/frontend/A64/translate/impl/branch.cpp index 8592d9fe..0b549be2 100644 --- a/src/frontend/A64/translate/impl/branch.cpp +++ b/src/frontend/A64/translate/impl/branch.cpp @@ -39,10 +39,11 @@ bool TranslatorVisitor::BL(Imm<26> imm26) { } bool TranslatorVisitor::BLR(Reg Rn) { + auto target = X(64, Rn); + X(64, Reg::R30, ir.Imm64(ir.PC() + 4)); ir.PushRSB(ir.current_location.AdvancePC(4)); - auto target = X(64, Rn); ir.SetPC(target); ir.SetTerm(IR::Term::ReturnToDispatch{}); return false; @@ -50,6 +51,7 @@ bool TranslatorVisitor::BLR(Reg Rn) { bool TranslatorVisitor::BR(Reg Rn) { auto target = X(64, Rn); + ir.SetPC(target); ir.SetTerm(IR::Term::ReturnToDispatch{}); return false; @@ -57,6 +59,7 @@ bool TranslatorVisitor::BR(Reg Rn) { bool TranslatorVisitor::RET(Reg Rn) { auto target = X(64, Rn); + ir.SetPC(target); ir.SetTerm(IR::Term::PopRSBHint{}); return false; diff --git a/src/frontend/ir/basic_block.cpp b/src/frontend/ir/basic_block.cpp index c0a608b5..9d89021a 100644 --- a/src/frontend/ir/basic_block.cpp +++ b/src/frontend/ir/basic_block.cpp @@ -129,7 +129,7 @@ static std::string TerminalToString(const Terminal& terminal_variant) { } case 6: { auto terminal = boost::get(terminal_variant); - return fmt::format("If{{{}, {}, {}}}", A32::CondToString(terminal.if_), TerminalToString(terminal.then_), TerminalToString(terminal.else_)); + return fmt::format("If{{{}, {}, {}}}", A64::CondToString(terminal.if_), TerminalToString(terminal.then_), TerminalToString(terminal.else_)); } case 7: { auto terminal = boost::get(terminal_variant); @@ -149,7 +149,7 @@ std::string DumpBlock(const IR::Block& block) { ret += fmt::format("Block: location={}\n", block.Location()); ret += fmt::format("cycles={}", block.CycleCount()); - ret += fmt::format(", entry_cond={}", A32::CondToString(block.GetCondition(), true)); + ret += fmt::format(", entry_cond={}", A64::CondToString(block.GetCondition())); if (block.GetCondition() != Cond::AL) { ret += fmt::format(", cond_fail={}", block.ConditionFailedLocation()); }