From a38966a874b9a7a7a08aac31a6c84853041efb6e Mon Sep 17 00:00:00 2001 From: Merry Date: Fri, 5 Aug 2022 21:43:37 +0100 Subject: [PATCH] block_of_code: Extract flag loading into a function LoadRequiredFlagsForCondFromRax --- src/dynarmic/backend/x64/block_of_code.cpp | 38 ++++++++++++++ src/dynarmic/backend/x64/block_of_code.h | 4 ++ src/dynarmic/backend/x64/emit_x64.cpp | 51 ++++++------------- .../backend/x64/emit_x64_data_processing.cpp | 51 ++++++------------- 4 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/backend/x64/block_of_code.cpp index fc0dc555..6e42231b 100644 --- a/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/backend/x64/block_of_code.cpp @@ -393,6 +393,44 @@ void BlockOfCode::LookupBlock() { cb.LookupBlock->EmitCall(*this); } +void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) { + // sahf restores SF, ZF, CF + // add al, 0x7F restores OF + + switch (cond) { + case IR::Cond::EQ: // z + case IR::Cond::NE: // !z + case IR::Cond::CS: // c + case IR::Cond::CC: // !c + case IR::Cond::MI: // n + case IR::Cond::PL: // !n + sahf(); + break; + case IR::Cond::VS: // v + case IR::Cond::VC: // !v + cmp(al, 0x81); + break; + case IR::Cond::HI: // c & !z + case IR::Cond::LS: // !c | z + sahf(); + cmc(); + break; + case IR::Cond::GE: // n == v + case IR::Cond::LT: // n != v + case IR::Cond::GT: // !z & (n == v) + case IR::Cond::LE: // z | (n != v) + cmp(al, 0x81); + sahf(); + break; + case IR::Cond::AL: + case IR::Cond::NV: + break; + default: + ASSERT_MSG(false, "Unknown cond {}", static_cast(cond)); + break; + } +} + Xbyak::Address BlockOfCode::MConst(const Xbyak::AddressFrame& frame, u64 lower, u64 upper) { return constant_pool.GetConstant(frame, lower, upper); } diff --git a/src/dynarmic/backend/x64/block_of_code.h b/src/dynarmic/backend/x64/block_of_code.h index e7c1a68b..73ab9cf2 100644 --- a/src/dynarmic/backend/x64/block_of_code.h +++ b/src/dynarmic/backend/x64/block_of_code.h @@ -21,6 +21,7 @@ #include "dynarmic/backend/x64/jitstate_info.h" #include "dynarmic/common/cast_util.h" #include "dynarmic/interface/halt_reason.h" +#include "dynarmic/ir/cond.h" namespace Dynarmic::Backend::X64 { @@ -74,6 +75,9 @@ public: /// @note this clobbers ABI caller-save registers void LookupBlock(); + /// Code emitter: Load required flags for conditional cond from rax into host rflags + void LoadRequiredFlagsForCondFromRax(IR::Cond cond); + /// Code emitter: Calls the function template void CallFunction(FunctionPointer fn) { diff --git a/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/backend/x64/emit_x64.cpp index 89f2f0a0..c3a7c80b 100644 --- a/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/backend/x64/emit_x64.cpp @@ -244,70 +244,49 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) { code.mov(eax, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]); - // sahf restores SF, ZF, CF - // add al, 0x7F restores OF + code.LoadRequiredFlagsForCondFromRax(cond); switch (cond) { - case IR::Cond::EQ: // z - code.sahf(); + case IR::Cond::EQ: code.jz(pass); break; - case IR::Cond::NE: //! z - code.sahf(); + case IR::Cond::NE: code.jnz(pass); break; - case IR::Cond::CS: // c - code.sahf(); + case IR::Cond::CS: code.jc(pass); break; - case IR::Cond::CC: //! c - code.sahf(); + case IR::Cond::CC: code.jnc(pass); break; - case IR::Cond::MI: // n - code.sahf(); + case IR::Cond::MI: code.js(pass); break; - case IR::Cond::PL: //! n - code.sahf(); + case IR::Cond::PL: code.jns(pass); break; - case IR::Cond::VS: // v - code.cmp(al, 0x81); + case IR::Cond::VS: code.jo(pass); break; - case IR::Cond::VC: //! v - code.cmp(al, 0x81); + case IR::Cond::VC: code.jno(pass); break; - case IR::Cond::HI: // c & !z - code.sahf(); - code.cmc(); + case IR::Cond::HI: code.ja(pass); break; - case IR::Cond::LS: //! c | z - code.sahf(); - code.cmc(); + case IR::Cond::LS: code.jna(pass); break; - case IR::Cond::GE: // n == v - code.cmp(al, 0x81); - code.sahf(); + case IR::Cond::GE: code.jge(pass); break; - case IR::Cond::LT: // n != v - code.cmp(al, 0x81); - code.sahf(); + case IR::Cond::LT: code.jl(pass); break; - case IR::Cond::GT: // !z & (n == v) - code.cmp(al, 0x81); - code.sahf(); + case IR::Cond::GT: code.jg(pass); break; - case IR::Cond::LE: // z | (n != v) - code.cmp(al, 0x81); - code.sahf(); + case IR::Cond::LE: code.jle(pass); break; default: diff --git a/src/dynarmic/backend/x64/emit_x64_data_processing.cpp b/src/dynarmic/backend/x64/emit_x64_data_processing.cpp index eead879a..feabe5e5 100644 --- a/src/dynarmic/backend/x64/emit_x64_data_processing.cpp +++ b/src/dynarmic/backend/x64/emit_x64_data_processing.cpp @@ -143,70 +143,49 @@ static void EmitConditionalSelect(BlockOfCode& code, EmitContext& ctx, IR::Inst* code.mov(nzcv, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]); - // sahf restores SF, ZF, CF - // add al, 0x7F restores OF + code.LoadRequiredFlagsForCondFromRax(args[0].GetImmediateCond()); switch (args[0].GetImmediateCond()) { - case IR::Cond::EQ: // z - code.sahf(); + case IR::Cond::EQ: code.cmovz(else_, then_); break; - case IR::Cond::NE: //! z - code.sahf(); + case IR::Cond::NE: code.cmovnz(else_, then_); break; - case IR::Cond::CS: // c - code.sahf(); + case IR::Cond::CS: code.cmovc(else_, then_); break; - case IR::Cond::CC: //! c - code.sahf(); + case IR::Cond::CC: code.cmovnc(else_, then_); break; - case IR::Cond::MI: // n - code.sahf(); + case IR::Cond::MI: code.cmovs(else_, then_); break; - case IR::Cond::PL: //! n - code.sahf(); + case IR::Cond::PL: code.cmovns(else_, then_); break; - case IR::Cond::VS: // v - code.cmp(nzcv.cvt8(), 0x81); + case IR::Cond::VS: code.cmovo(else_, then_); break; - case IR::Cond::VC: //! v - code.cmp(nzcv.cvt8(), 0x81); + case IR::Cond::VC: code.cmovno(else_, then_); break; - case IR::Cond::HI: // c & !z - code.sahf(); - code.cmc(); + case IR::Cond::HI: code.cmova(else_, then_); break; - case IR::Cond::LS: //! c | z - code.sahf(); - code.cmc(); + case IR::Cond::LS: code.cmovna(else_, then_); break; - case IR::Cond::GE: // n == v - code.cmp(nzcv.cvt8(), 0x81); - code.sahf(); + case IR::Cond::GE: code.cmovge(else_, then_); break; - case IR::Cond::LT: // n != v - code.cmp(nzcv.cvt8(), 0x81); - code.sahf(); + case IR::Cond::LT: code.cmovl(else_, then_); break; - case IR::Cond::GT: // !z & (n == v) - code.cmp(nzcv.cvt8(), 0x81); - code.sahf(); + case IR::Cond::GT: code.cmovg(else_, then_); break; - case IR::Cond::LE: // z | (n != v) - code.cmp(nzcv.cvt8(), 0x81); - code.sahf(); + case IR::Cond::LE: code.cmovle(else_, then_); break; case IR::Cond::AL: