From fac9224d5ea83e6a5b369c4a2e98ac3a01637c56 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 23 Mar 2019 12:32:01 -0400 Subject: [PATCH] A64: Handle half-precision floating point in FCVTN Now that we have IR instructions for performing conversions with half-precision floating point, we can also handle half-precision values within FCVTN. --- .../translate/impl/simd_two_register_misc.cpp | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/frontend/A64/translate/impl/simd_two_register_misc.cpp b/src/frontend/A64/translate/impl/simd_two_register_misc.cpp index 5aa47e49..d8f3160d 100644 --- a/src/frontend/A64/translate/impl/simd_two_register_misc.cpp +++ b/src/frontend/A64/translate/impl/simd_two_register_misc.cpp @@ -362,22 +362,27 @@ bool TranslatorVisitor::FCVTL(bool Q, bool sz, Vec Vn, Vec Vd) { } bool TranslatorVisitor::FCVTN(bool Q, bool sz, Vec Vn, Vec Vd) { - // Half-precision not handled directly. - if (!sz) { - return InterpretThisInstruction(); - } + const size_t datasize = 64; + const size_t esize = sz ? 32 : 16; + const size_t num_elements = datasize / esize; const IR::U128 operand = V(128, Vn); const auto rounding_mode = ir.current_location->FPCR().RMode(); IR::U128 result = ir.ZeroVector(); - for (size_t i = 0; i < 2; i++) { - const IR::U32 element = ir.FPDoubleToSingle(ir.VectorGetElement(64, operand, i), rounding_mode); + for (size_t i = 0; i < num_elements; i++) { + IR::U16U32U64 element = ir.VectorGetElement(2 * esize, operand, i); - result = ir.VectorSetElement(32, result, i, element); + if (esize == 16) { + element = ir.FPSingleToHalf(element, rounding_mode); + } else if (esize == 32) { + element = ir.FPDoubleToSingle(element, rounding_mode); + } + + result = ir.VectorSetElement(esize, result, i, element); } - Vpart(64, Vd, Q, result); + Vpart(datasize, Vd, Q, result); return true; }