From 09bf273bc829bcd7307b9e81d216523f4869effa Mon Sep 17 00:00:00 2001 From: MerryMage Date: Wed, 19 Sep 2018 20:09:59 +0100 Subject: [PATCH] A64: Implement SCVTF, UCVTF (vector, fixed-point), scalar variant --- src/frontend/A64/decoder/a64.inc | 4 +- .../impl/simd_scalar_shift_by_immediate.cpp | 49 +++++++++++++++---- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 6f6e1e07..1a7b8d8f 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -473,7 +473,7 @@ INST(SHL_1, "SHL", "01011 //INST(SQSHL_imm_1, "SQSHL (immediate)", "010111110IIIIiii011101nnnnnddddd") //INST(SQSHRN_1, "SQSHRN, SQSHRN2", "010111110IIIIiii100101nnnnnddddd") //INST(SQRSHRN_1, "SQRSHRN, SQRSHRN2", "010111110IIIIiii100111nnnnnddddd") -//INST(SCVTF_fix_1, "SCVTF (vector, fixed-point)", "010111110IIIIiii111001nnnnnddddd") +INST(SCVTF_fix_1, "SCVTF (vector, fixed-point)", "010111110IIIIiii111001nnnnnddddd") INST(FCVTZS_fix_1, "FCVTZS (vector, fixed-point)", "010111110IIIIiii111111nnnnnddddd") INST(USHR_1, "USHR", "011111110IIIIiii000001nnnnnddddd") INST(USRA_1, "USRA", "011111110IIIIiii000101nnnnnddddd") @@ -487,7 +487,7 @@ INST(SLI_1, "SLI", "01111 //INST(SQRSHRUN_1, "SQRSHRUN, SQRSHRUN2", "011111110IIIIiii100011nnnnnddddd") //INST(UQSHRN_1, "UQSHRN, UQSHRN2", "011111110IIIIiii100101nnnnnddddd") //INST(UQRSHRN_1, "UQRSHRN, UQRSHRN2", "011111110IIIIiii100111nnnnnddddd") -//INST(UCVTF_fix_1, "UCVTF (vector, fixed-point)", "011111110IIIIiii111001nnnnnddddd") +INST(UCVTF_fix_1, "UCVTF (vector, fixed-point)", "011111110IIIIiii111001nnnnnddddd") INST(FCVTZU_fix_1, "FCVTZU (vector, fixed-point)", "011111110IIIIiii111111nnnnnddddd") // Data Processing - FP and SIMD - SIMD Scalar x indexed element diff --git a/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp b/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp index 867b2601..a379d140 100644 --- a/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp +++ b/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp @@ -4,6 +4,7 @@ * General Public License version 2 or any later version. */ +#include "common/fp/rounding_mode.h" #include "frontend/A64/translate/impl/impl.h" namespace Dynarmic::A64 { @@ -18,6 +19,11 @@ enum class Signedness { Unsigned, }; +enum class FloatConversionDirection { + FixedToFloat, + FloatToFixed, +}; + bool ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, ShiftExtraBehavior behavior, Signedness signedness) { if (!immh.Bit<3>()) { @@ -121,7 +127,7 @@ bool ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec return true; } -bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness sign) { +bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness sign, FloatConversionDirection direction, FP::RoundingMode rounding_mode) { const u32 immh_value = immh.ZeroExtend(); if ((immh_value & 0b1110) == 0b0000) { @@ -139,15 +145,32 @@ bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Ve const IR::U32U64 operand = v.V_scalar(esize, Vn); const IR::U32U64 result = [&]() -> IR::U32U64 { - if (esize == 64) { + switch (direction) { + case FloatConversionDirection::FloatToFixed: + if (esize == 64) { + return sign == Signedness::Signed + ? v.ir.FPToFixedS64(operand, fbits, rounding_mode) + : v.ir.FPToFixedU64(operand, fbits, rounding_mode); + } + return sign == Signedness::Signed - ? v.ir.FPToFixedS64(operand, fbits, FP::RoundingMode::TowardsZero) - : v.ir.FPToFixedU64(operand, fbits, FP::RoundingMode::TowardsZero); + ? v.ir.FPToFixedS32(operand, fbits, rounding_mode) + : v.ir.FPToFixedU32(operand, fbits, rounding_mode); + + case FloatConversionDirection::FixedToFloat: + if (esize == 64) { + return sign == Signedness::Signed + ? v.ir.FPSignedFixedToDouble(operand, fbits, rounding_mode) + : v.ir.FPUnsignedFixedToDouble(operand, fbits, rounding_mode); + } + + return sign == Signedness::Signed + ? v.ir.FPSignedFixedToSingle(operand, fbits, rounding_mode) + : v.ir.FPUnsignedFixedToSingle(operand, fbits, rounding_mode); } - return sign == Signedness::Signed - ? v.ir.FPToFixedS32(operand, fbits, FP::RoundingMode::TowardsZero) - : v.ir.FPToFixedU32(operand, fbits, FP::RoundingMode::TowardsZero); + UNREACHABLE(); + return {}; }(); v.V_scalar(esize, Vd, result); @@ -156,11 +179,19 @@ bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Ve } // Anonymous namespace bool TranslatorVisitor::FCVTZS_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { - return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Signed); + return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero); } bool TranslatorVisitor::FCVTZU_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { - return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Unsigned); + return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero); +} + +bool TranslatorVisitor::SCVTF_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { + return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode()); +} + +bool TranslatorVisitor::UCVTF_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { + return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode()); } bool TranslatorVisitor::SLI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {