floating_point_{conditional}_compare: Deduplicate code

Deduplicates the implementation code of instructions by extracting the
code to a common function.
This commit is contained in:
Lioncash 2018-07-29 00:45:26 -04:00 committed by MerryMage
parent f9c6d5e1a0
commit f83cd2da9a
2 changed files with 30 additions and 47 deletions

View file

@ -9,8 +9,8 @@
#include "frontend/A64/translate/impl/impl.h" #include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
namespace {
static boost::optional<size_t> GetDataSize(Imm<2> type) { boost::optional<size_t> GetDataSize(Imm<2> type) {
switch (type.ZeroExtend()) { switch (type.ZeroExtend()) {
case 0b00: case 0b00:
return 32; return 32;
@ -23,42 +23,32 @@ static boost::optional<size_t> GetDataSize(Imm<2> type) {
return boost::none; return boost::none;
} }
bool TranslatorVisitor::FCMP_float(Imm<2> type, Vec Vm, Vec Vn, bool cmp_with_zero) { bool FPCompare(TranslatorVisitor& v, Imm<2> type, Vec Vm, Vec Vn, bool exc_on_qnan, bool cmp_with_zero) {
auto datasize = GetDataSize(type); const auto datasize = GetDataSize(type);
if (!datasize) { if (!datasize) {
return UnallocatedEncoding(); return v.UnallocatedEncoding();
} }
const IR::U32U64 operand1 = V_scalar(*datasize, Vn); const IR::U32U64 operand1 = v.V_scalar(*datasize, Vn);
IR::U32U64 operand2; IR::U32U64 operand2;
if (cmp_with_zero) { if (cmp_with_zero) {
operand2 = I(*datasize, 0); operand2 = v.I(*datasize, 0);
} else { } else {
operand2 = V_scalar(*datasize, Vm); operand2 = v.V_scalar(*datasize, Vm);
} }
auto nzcv = ir.FPCompare(operand1, operand2, false, true); const auto nzcv = v.ir.FPCompare(operand1, operand2, exc_on_qnan, true);
ir.SetNZCV(nzcv); v.ir.SetNZCV(nzcv);
return true; return true;
} }
} // Anonymous namespace
bool TranslatorVisitor::FCMP_float(Imm<2> type, Vec Vm, Vec Vn, bool cmp_with_zero) {
return FPCompare(*this, type, Vm, Vn, false, cmp_with_zero);
}
bool TranslatorVisitor::FCMPE_float(Imm<2> type, Vec Vm, Vec Vn, bool cmp_with_zero) { bool TranslatorVisitor::FCMPE_float(Imm<2> type, Vec Vm, Vec Vn, bool cmp_with_zero) {
auto datasize = GetDataSize(type); return FPCompare(*this, type, Vm, Vn, true, cmp_with_zero);
if (!datasize) {
return UnallocatedEncoding();
}
const IR::U32U64 operand1 = V_scalar(*datasize, Vn);
IR::U32U64 operand2;
if (cmp_with_zero) {
operand2 = I(*datasize, 0);
} else {
operand2 = V_scalar(*datasize, Vm);
}
auto nzcv = ir.FPCompare(operand1, operand2, true, true);
ir.SetNZCV(nzcv);
return true;
} }
} // namespace Dynarmic::A64 } // namespace Dynarmic::A64

View file

@ -9,7 +9,7 @@
#include "frontend/A64/translate/impl/impl.h" #include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
namespace {
static boost::optional<size_t> GetDataSize(Imm<2> type) { static boost::optional<size_t> GetDataSize(Imm<2> type) {
switch (type.ZeroExtend()) { switch (type.ZeroExtend()) {
case 0b00: case 0b00:
@ -22,36 +22,29 @@ static boost::optional<size_t> GetDataSize(Imm<2> type) {
return boost::none; return boost::none;
} }
bool TranslatorVisitor::FCCMP_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv) { bool FPCompare(TranslatorVisitor& v, Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv, bool exc_on_qnan) {
const auto datasize = GetDataSize(type); const auto datasize = GetDataSize(type);
if (!datasize || *datasize == 16) { if (!datasize || *datasize == 16) {
return UnallocatedEncoding(); return v.UnallocatedEncoding();
} }
const u32 flags = nzcv.ZeroExtend<u32>() << 28; const u32 flags = nzcv.ZeroExtend<u32>() << 28;
const IR::U32U64 operand1 = V_scalar(*datasize, Vn); const IR::U32U64 operand1 = v.V_scalar(*datasize, Vn);
const IR::U32U64 operand2 = V_scalar(*datasize, Vm); const IR::U32U64 operand2 = v.V_scalar(*datasize, Vm);
const IR::NZCV then_flags = ir.FPCompare(operand1, operand2, false, true); const IR::NZCV then_flags = v.ir.FPCompare(operand1, operand2, exc_on_qnan, true);
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags)); const IR::NZCV else_flags = v.ir.NZCVFromPackedFlags(v.ir.Imm32(flags));
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags)); v.ir.SetNZCV(v.ir.ConditionalSelect(cond, then_flags, else_flags));
return true; return true;
} }
} // Anonymous namespace
bool TranslatorVisitor::FCCMP_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv) {
return FPCompare(*this, type, Vm, cond, Vn, nzcv, false);
}
bool TranslatorVisitor::FCCMPE_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv) { bool TranslatorVisitor::FCCMPE_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv) {
const auto datasize = GetDataSize(type); return FPCompare(*this, type, Vm, cond, Vn, nzcv, true);
if (!datasize || *datasize == 16) {
return UnallocatedEncoding();
}
const u32 flags = nzcv.ZeroExtend<u32>() << 28;
const IR::U32U64 operand1 = V_scalar(*datasize, Vn);
const IR::U32U64 operand2 = V_scalar(*datasize, Vm);
const IR::NZCV then_flags = ir.FPCompare(operand1, operand2, true, true);
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags));
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags));
return true;
} }
} // namespace Dynarmic::A64 } // namespace Dynarmic::A64