block_of_code: Extract flag loading into a function

LoadRequiredFlagsForCondFromRax
This commit is contained in:
Merry 2022-08-05 21:43:37 +01:00
parent d7bd5bb7a7
commit a38966a874
4 changed files with 72 additions and 72 deletions

View file

@ -393,6 +393,44 @@ void BlockOfCode::LookupBlock() {
cb.LookupBlock->EmitCall(*this); 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<size_t>(cond));
break;
}
}
Xbyak::Address BlockOfCode::MConst(const Xbyak::AddressFrame& frame, u64 lower, u64 upper) { Xbyak::Address BlockOfCode::MConst(const Xbyak::AddressFrame& frame, u64 lower, u64 upper) {
return constant_pool.GetConstant(frame, lower, upper); return constant_pool.GetConstant(frame, lower, upper);
} }

View file

@ -21,6 +21,7 @@
#include "dynarmic/backend/x64/jitstate_info.h" #include "dynarmic/backend/x64/jitstate_info.h"
#include "dynarmic/common/cast_util.h" #include "dynarmic/common/cast_util.h"
#include "dynarmic/interface/halt_reason.h" #include "dynarmic/interface/halt_reason.h"
#include "dynarmic/ir/cond.h"
namespace Dynarmic::Backend::X64 { namespace Dynarmic::Backend::X64 {
@ -74,6 +75,9 @@ public:
/// @note this clobbers ABI caller-save registers /// @note this clobbers ABI caller-save registers
void LookupBlock(); 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 /// Code emitter: Calls the function
template<typename FunctionPointer> template<typename FunctionPointer>
void CallFunction(FunctionPointer fn) { void CallFunction(FunctionPointer fn) {

View file

@ -244,70 +244,49 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) {
code.mov(eax, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]); code.mov(eax, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]);
// sahf restores SF, ZF, CF code.LoadRequiredFlagsForCondFromRax(cond);
// add al, 0x7F restores OF
switch (cond) { switch (cond) {
case IR::Cond::EQ: // z case IR::Cond::EQ:
code.sahf();
code.jz(pass); code.jz(pass);
break; break;
case IR::Cond::NE: //! z case IR::Cond::NE:
code.sahf();
code.jnz(pass); code.jnz(pass);
break; break;
case IR::Cond::CS: // c case IR::Cond::CS:
code.sahf();
code.jc(pass); code.jc(pass);
break; break;
case IR::Cond::CC: //! c case IR::Cond::CC:
code.sahf();
code.jnc(pass); code.jnc(pass);
break; break;
case IR::Cond::MI: // n case IR::Cond::MI:
code.sahf();
code.js(pass); code.js(pass);
break; break;
case IR::Cond::PL: //! n case IR::Cond::PL:
code.sahf();
code.jns(pass); code.jns(pass);
break; break;
case IR::Cond::VS: // v case IR::Cond::VS:
code.cmp(al, 0x81);
code.jo(pass); code.jo(pass);
break; break;
case IR::Cond::VC: //! v case IR::Cond::VC:
code.cmp(al, 0x81);
code.jno(pass); code.jno(pass);
break; break;
case IR::Cond::HI: // c & !z case IR::Cond::HI:
code.sahf();
code.cmc();
code.ja(pass); code.ja(pass);
break; break;
case IR::Cond::LS: //! c | z case IR::Cond::LS:
code.sahf();
code.cmc();
code.jna(pass); code.jna(pass);
break; break;
case IR::Cond::GE: // n == v case IR::Cond::GE:
code.cmp(al, 0x81);
code.sahf();
code.jge(pass); code.jge(pass);
break; break;
case IR::Cond::LT: // n != v case IR::Cond::LT:
code.cmp(al, 0x81);
code.sahf();
code.jl(pass); code.jl(pass);
break; break;
case IR::Cond::GT: // !z & (n == v) case IR::Cond::GT:
code.cmp(al, 0x81);
code.sahf();
code.jg(pass); code.jg(pass);
break; break;
case IR::Cond::LE: // z | (n != v) case IR::Cond::LE:
code.cmp(al, 0x81);
code.sahf();
code.jle(pass); code.jle(pass);
break; break;
default: default:

View file

@ -143,70 +143,49 @@ static void EmitConditionalSelect(BlockOfCode& code, EmitContext& ctx, IR::Inst*
code.mov(nzcv, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]); code.mov(nzcv, dword[r15 + code.GetJitStateInfo().offsetof_cpsr_nzcv]);
// sahf restores SF, ZF, CF code.LoadRequiredFlagsForCondFromRax(args[0].GetImmediateCond());
// add al, 0x7F restores OF
switch (args[0].GetImmediateCond()) { switch (args[0].GetImmediateCond()) {
case IR::Cond::EQ: // z case IR::Cond::EQ:
code.sahf();
code.cmovz(else_, then_); code.cmovz(else_, then_);
break; break;
case IR::Cond::NE: //! z case IR::Cond::NE:
code.sahf();
code.cmovnz(else_, then_); code.cmovnz(else_, then_);
break; break;
case IR::Cond::CS: // c case IR::Cond::CS:
code.sahf();
code.cmovc(else_, then_); code.cmovc(else_, then_);
break; break;
case IR::Cond::CC: //! c case IR::Cond::CC:
code.sahf();
code.cmovnc(else_, then_); code.cmovnc(else_, then_);
break; break;
case IR::Cond::MI: // n case IR::Cond::MI:
code.sahf();
code.cmovs(else_, then_); code.cmovs(else_, then_);
break; break;
case IR::Cond::PL: //! n case IR::Cond::PL:
code.sahf();
code.cmovns(else_, then_); code.cmovns(else_, then_);
break; break;
case IR::Cond::VS: // v case IR::Cond::VS:
code.cmp(nzcv.cvt8(), 0x81);
code.cmovo(else_, then_); code.cmovo(else_, then_);
break; break;
case IR::Cond::VC: //! v case IR::Cond::VC:
code.cmp(nzcv.cvt8(), 0x81);
code.cmovno(else_, then_); code.cmovno(else_, then_);
break; break;
case IR::Cond::HI: // c & !z case IR::Cond::HI:
code.sahf();
code.cmc();
code.cmova(else_, then_); code.cmova(else_, then_);
break; break;
case IR::Cond::LS: //! c | z case IR::Cond::LS:
code.sahf();
code.cmc();
code.cmovna(else_, then_); code.cmovna(else_, then_);
break; break;
case IR::Cond::GE: // n == v case IR::Cond::GE:
code.cmp(nzcv.cvt8(), 0x81);
code.sahf();
code.cmovge(else_, then_); code.cmovge(else_, then_);
break; break;
case IR::Cond::LT: // n != v case IR::Cond::LT:
code.cmp(nzcv.cvt8(), 0x81);
code.sahf();
code.cmovl(else_, then_); code.cmovl(else_, then_);
break; break;
case IR::Cond::GT: // !z & (n == v) case IR::Cond::GT:
code.cmp(nzcv.cvt8(), 0x81);
code.sahf();
code.cmovg(else_, then_); code.cmovg(else_, then_);
break; break;
case IR::Cond::LE: // z | (n != v) case IR::Cond::LE:
code.cmp(nzcv.cvt8(), 0x81);
code.sahf();
code.cmovle(else_, then_); code.cmovle(else_, then_);
break; break;
case IR::Cond::AL: case IR::Cond::AL: