diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5b4949d8..e8d2fdf0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,6 +77,7 @@ add_library(dynarmic frontend/A64/translate/impl/exception_generating.cpp frontend/A64/translate/impl/floating_point_compare.cpp frontend/A64/translate/impl/floating_point_conversion_integer.cpp + frontend/A64/translate/impl/floating_point_conditional_compare.cpp frontend/A64/translate/impl/floating_point_conditional_select.cpp frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index f7646460..c3b76900 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -912,7 +912,7 @@ INST(FCMPE_float, "FCMPE", "00011 INST(FMOV_float_imm, "FMOV (scalar, immediate)", "00011110yy1iiiiiiii10000000ddddd") // Data Processing - FP and SIMD - Floating point conditional compare -//INST(FCCMP_float, "FCCMP", "00011110yy1mmmmmcccc01nnnnn0ffff") +INST(FCCMP_float, "FCCMP", "00011110yy1mmmmmcccc01nnnnn0ffff") //INST(FCCMPE_float, "FCCMPE", "00011110yy1mmmmmcccc01nnnnn1ffff") // Data Processing - FP and SIMD - Floating point data processing two register diff --git a/src/frontend/A64/translate/impl/floating_point_conditional_compare.cpp b/src/frontend/A64/translate/impl/floating_point_conditional_compare.cpp new file mode 100644 index 00000000..dbe710ed --- /dev/null +++ b/src/frontend/A64/translate/impl/floating_point_conditional_compare.cpp @@ -0,0 +1,41 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include + +#include "frontend/A64/translate/impl/impl.h" + +namespace Dynarmic::A64 { + +static boost::optional GetDataSize(Imm<2> type) { + switch (type.ZeroExtend()) { + case 0b00: + return 32; + case 0b01: + return 64; + case 0b11: + return 16; + } + return boost::none; +} + +bool TranslatorVisitor::FCCMP_float(Imm<2> type, Vec Vm, Cond cond, Vec Vn, Imm<4> nzcv) { + const auto datasize = GetDataSize(type); + if (!datasize || *datasize == 16) { + return UnallocatedEncoding(); + } + const u32 flags = nzcv.ZeroExtend() << 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, false, 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