block_of_code: Extract flag loading into a function
LoadRequiredFlagsForCondFromRax
This commit is contained in:
parent
d7bd5bb7a7
commit
a38966a874
4 changed files with 72 additions and 72 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue