From 590388b9ec52579c12b9535d868e2040a8a8804e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Apr 2019 17:37:45 -0400 Subject: [PATCH 1/6] fp/op/FPRoundInt: Add half-precision specialization of FPRoundInt --- src/common/fp/op/FPRoundInt.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/fp/op/FPRoundInt.cpp b/src/common/fp/op/FPRoundInt.cpp index f22c83d3..d2456394 100644 --- a/src/common/fp/op/FPRoundInt.cpp +++ b/src/common/fp/op/FPRoundInt.cpp @@ -31,11 +31,11 @@ u64 FPRoundInt(FPT op, FPCR fpcr, RoundingMode rounding, bool exact, FPSR& fpsr) } if (type == FPType::Infinity) { - return FPInfo::Infinity(sign); + return FPT(FPInfo::Infinity(sign)); } if (type == FPType::Zero) { - return FPInfo::Zero(sign); + return FPT(FPInfo::Zero(sign)); } // Reshift decimal point back to bit zero. @@ -79,7 +79,7 @@ u64 FPRoundInt(FPT op, FPCR fpcr, RoundingMode rounding, bool exact, FPSR& fpsr) const u64 abs_int_result = new_sign ? Safe::Negate(int_result) : static_cast(int_result); const FPT result = int_result == 0 - ? FPInfo::Zero(sign) + ? FPT(FPInfo::Zero(sign)) : FPRound(FPUnpacked{new_sign, normalized_point_position, abs_int_result}, fpcr, RoundingMode::TowardsZero, fpsr); if (error != ResidualError::Zero && exact) { @@ -89,6 +89,7 @@ u64 FPRoundInt(FPT op, FPCR fpcr, RoundingMode rounding, bool exact, FPSR& fpsr) return result; } +template u64 FPRoundInt(u16 op, FPCR fpcr, RoundingMode rounding, bool exact, FPSR& fpsr); template u64 FPRoundInt(u32 op, FPCR fpcr, RoundingMode rounding, bool exact, FPSR& fpsr); template u64 FPRoundInt(u64 op, FPCR fpcr, RoundingMode rounding, bool exact, FPSR& fpsr); From 8243705134f98a6cd74640ae39f0fe2fb4abaa2b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Apr 2019 17:40:56 -0400 Subject: [PATCH 2/6] frontend/ir_emitter: Add half-precision variant of FPRoundInt --- src/backend/x64/emit_x64_floating_point.cpp | 10 ++++++++-- src/frontend/ir/ir_emitter.cpp | 18 ++++++++++++++---- src/frontend/ir/ir_emitter.h | 2 +- src/frontend/ir/microinstruction.cpp | 1 + src/frontend/ir/opcodes.inc | 1 + 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/backend/x64/emit_x64_floating_point.cpp b/src/backend/x64/emit_x64_floating_point.cpp index 3fd10ced..2321b77b 100644 --- a/src/backend/x64/emit_x64_floating_point.cpp +++ b/src/backend/x64/emit_x64_floating_point.cpp @@ -843,7 +843,7 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz const bool exact = inst->GetArg(2).GetU1(); const auto round_imm = ConvertRoundingModeToX64Immediate(rounding_mode); - if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41) && round_imm && !exact) { + if (fsize != 16 && code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41) && round_imm && !exact) { if (fsize == 64) { FPTwoOp<64>(code, ctx, inst, [&](Xbyak::Xmm result) { code.roundsd(result, result, *round_imm); @@ -857,7 +857,9 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz return; } - using fsize_list = mp::list, mp::vlift>; + using fsize_list = mp::list, + mp::vlift, + mp::vlift>; using rounding_list = mp::list< std::integral_constant, std::integral_constant, @@ -897,6 +899,10 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz code.CallFunction(lut.at(std::make_tuple(fsize, rounding_mode, exact))); } +void EmitX64::EmitFPRoundInt16(EmitContext& ctx, IR::Inst* inst) { + EmitFPRound(code, ctx, inst, 16); +} + void EmitX64::EmitFPRoundInt32(EmitContext& ctx, IR::Inst* inst) { EmitFPRound(code, ctx, inst, 32); } diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 53df95b0..61c8bf1c 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -1950,11 +1950,21 @@ U32U64 IREmitter::FPRecipStepFused(const U32U64& a, const U32U64& b) { return Inst(Opcode::FPRecipStepFused64, a, b); } -U32U64 IREmitter::FPRoundInt(const U32U64& a, FP::RoundingMode rounding, bool exact) { - if (a.GetType() == Type::U32) { - return Inst(Opcode::FPRoundInt32, a, static_cast(rounding), Imm1(exact)); +U16U32U64 IREmitter::FPRoundInt(const U16U32U64& a, FP::RoundingMode rounding, bool exact) { + const u8 rounding_value = static_cast(rounding); + const IR::U1 exact_imm = Imm1(exact); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPRoundInt16, a, rounding_value, exact_imm); + case Type::U32: + return Inst(Opcode::FPRoundInt32, a, rounding_value, exact_imm); + case Type::U64: + return Inst(Opcode::FPRoundInt64, a, rounding_value, exact_imm); + default: + UNREACHABLE(); + return U16U32U64{}; } - return Inst(Opcode::FPRoundInt64, a, static_cast(rounding), Imm1(exact)); } U32U64 IREmitter::FPRSqrtEstimate(const U32U64& a) { diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 32fad5b7..09935cf6 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -308,7 +308,7 @@ public: U32U64 FPRecipEstimate(const U32U64& a); U16U32U64 FPRecipExponent(const U16U32U64& a); U32U64 FPRecipStepFused(const U32U64& a, const U32U64& b); - U32U64 FPRoundInt(const U32U64& a, FP::RoundingMode rounding, bool exact); + U16U32U64 FPRoundInt(const U16U32U64& a, FP::RoundingMode rounding, bool exact); U32U64 FPRSqrtEstimate(const U32U64& a); U32U64 FPRSqrtStepFused(const U32U64& a, const U32U64& b); U32U64 FPSqrt(const U32U64& a); diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index c087b514..958fd471 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -279,6 +279,7 @@ bool Inst::ReadsFromAndWritesToFPSRCumulativeExceptionBits() const { case Opcode::FPRecipExponent64: case Opcode::FPRecipStepFused32: case Opcode::FPRecipStepFused64: + case Opcode::FPRoundInt16: case Opcode::FPRoundInt32: case Opcode::FPRoundInt64: case Opcode::FPRSqrtEstimate32: diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index db3128e8..527aef5b 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -498,6 +498,7 @@ OPCODE(FPRecipExponent32, U32, U32 OPCODE(FPRecipExponent64, U64, U64 ) OPCODE(FPRecipStepFused32, U32, U32, U32 ) OPCODE(FPRecipStepFused64, U64, U64, U64 ) +OPCODE(FPRoundInt16, U16, U16, U8, U1 ) OPCODE(FPRoundInt32, U32, U32, U8, U1 ) OPCODE(FPRoundInt64, U64, U64, U8, U1 ) OPCODE(FPRSqrtEstimate32, U32, U32 ) From 722daae0d4f4137de0b667ce7bc8d336f84e8f4a Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Apr 2019 17:49:04 -0400 Subject: [PATCH 3/6] frontend/ir_emitter: Add half-precision variant of FPVectorRoundInt --- .../x64/emit_x64_vector_floating_point.cpp | 46 +++++++++++-------- src/frontend/ir/ir_emitter.cpp | 9 +++- src/frontend/ir/opcodes.inc | 1 + 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/backend/x64/emit_x64_vector_floating_point.cpp b/src/backend/x64/emit_x64_vector_floating_point.cpp index deb5ab1f..0bf4f619 100644 --- a/src/backend/x64/emit_x64_vector_floating_point.cpp +++ b/src/backend/x64/emit_x64_vector_floating_point.cpp @@ -1160,28 +1160,30 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { const auto rounding = static_cast(inst->GetArg(1).GetU8()); const bool exact = inst->GetArg(2).GetU1(); - if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) { - const u8 round_imm = [&]() -> u8 { - switch (rounding) { - case FP::RoundingMode::ToNearest_TieEven: - return 0b00; - case FP::RoundingMode::TowardsPlusInfinity: - return 0b10; - case FP::RoundingMode::TowardsMinusInfinity: - return 0b01; - case FP::RoundingMode::TowardsZero: - return 0b11; - default: - UNREACHABLE(); - } - return 0; - }(); + if constexpr (fsize != 16) { + if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) { + const u8 round_imm = [&]() -> u8 { + switch (rounding) { + case FP::RoundingMode::ToNearest_TieEven: + return 0b00; + case FP::RoundingMode::TowardsPlusInfinity: + return 0b10; + case FP::RoundingMode::TowardsMinusInfinity: + return 0b01; + case FP::RoundingMode::TowardsZero: + return 0b11; + default: + UNREACHABLE(); + } + return 0; + }(); - EmitTwoOpVectorOperation(code, ctx, inst, [&](const Xbyak::Xmm& result, const Xbyak::Xmm& xmm_a){ - FCODE(roundp)(result, xmm_a, round_imm); - }); + EmitTwoOpVectorOperation(code, ctx, inst, [&](const Xbyak::Xmm& result, const Xbyak::Xmm& xmm_a){ + FCODE(roundp)(result, xmm_a, round_imm); + }); - return; + return; + } } using rounding_list = mp::list< @@ -1218,6 +1220,10 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { EmitTwoOpFallback(code, ctx, inst, lut.at(std::make_tuple(rounding, exact))); } +void EmitX64::EmitFPVectorRoundInt16(EmitContext& ctx, IR::Inst* inst) { + EmitFPVectorRoundInt<16>(code, ctx, inst); +} + void EmitX64::EmitFPVectorRoundInt32(EmitContext& ctx, IR::Inst* inst) { EmitFPVectorRoundInt<32>(code, ctx, inst); } diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 61c8bf1c..27527f6c 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -2278,11 +2278,16 @@ U128 IREmitter::FPVectorRecipStepFused(size_t esize, const U128& a, const U128& } U128 IREmitter::FPVectorRoundInt(size_t esize, const U128& operand, FP::RoundingMode rounding, bool exact) { + const IR::U8 rounding_imm = Imm8(static_cast(rounding)); + const IR::U1 exact_imm = Imm1(exact); + switch (esize) { + case 16: + return Inst(Opcode::FPVectorRoundInt16, operand, rounding_imm, exact_imm); case 32: - return Inst(Opcode::FPVectorRoundInt32, operand, Imm8(static_cast(rounding)), Imm1(exact)); + return Inst(Opcode::FPVectorRoundInt32, operand, rounding_imm, exact_imm); case 64: - return Inst(Opcode::FPVectorRoundInt64, operand, Imm8(static_cast(rounding)), Imm1(exact)); + return Inst(Opcode::FPVectorRoundInt64, operand, rounding_imm, exact_imm); } UNREACHABLE(); return {}; diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 527aef5b..c7a4c227 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -574,6 +574,7 @@ OPCODE(FPVectorRecipEstimate32, U128, U128 OPCODE(FPVectorRecipEstimate64, U128, U128 ) OPCODE(FPVectorRecipStepFused32, U128, U128, U128 ) OPCODE(FPVectorRecipStepFused64, U128, U128, U128 ) +OPCODE(FPVectorRoundInt16, U128, U128, U8, U1 ) OPCODE(FPVectorRoundInt32, U128, U128, U8, U1 ) OPCODE(FPVectorRoundInt64, U128, U128, U8, U1 ) OPCODE(FPVectorRSqrtEstimate32, U128, U128 ) From 95a96b32c5c0c45120f457b356909631d17c430e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Apr 2019 17:51:12 -0400 Subject: [PATCH 4/6] frontend/microinstruction: Add FPVectorRoundInt types to ReadsFromAndWritesToFPSRCumulativeExceptionBits() All variants were previously missing from this. --- src/frontend/ir/microinstruction.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index 958fd471..a7c3386e 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -339,6 +339,9 @@ bool Inst::ReadsFromAndWritesToFPSRCumulativeExceptionBits() const { case Opcode::FPVectorRecipEstimate64: case Opcode::FPVectorRecipStepFused32: case Opcode::FPVectorRecipStepFused64: + case Opcode::FPVectorRoundInt16: + case Opcode::FPVectorRoundInt32: + case Opcode::FPVectorRoundInt64: case Opcode::FPVectorRSqrtEstimate32: case Opcode::FPVectorRSqrtEstimate64: case Opcode::FPVectorRSqrtStepFused32: From 7c5cc15f4e2d4a09c74681291edbd08afac5121b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Apr 2019 17:53:19 -0400 Subject: [PATCH 5/6] A64: Enable half-precision variants of floating-point FRINT* variants With all the backing machinery in place, we can remove the fallback check for half-precision. --- .../impl/floating_point_data_processing_one_register.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp b/src/frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp index 66b6d377..a2556966 100644 --- a/src/frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp +++ b/src/frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp @@ -149,12 +149,12 @@ bool TranslatorVisitor::FCVT_float(Imm<2> type, Imm<2> opc, Vec Vn, Vec Vd) { static bool FloatingPointRoundToIntegral(TranslatorVisitor& v, Imm<2> type, Vec Vn, Vec Vd, FP::RoundingMode rounding_mode, bool exact) { const auto datasize = FPGetDataSize(type); - if (!datasize || *datasize == 16) { + if (!datasize) { return v.UnallocatedEncoding(); } - const IR::U32U64 operand = v.V_scalar(*datasize, Vn); - const IR::U32U64 result = v.ir.FPRoundInt(operand, rounding_mode, exact); + const IR::U16U32U64 operand = v.V_scalar(*datasize, Vn); + const IR::U16U32U64 result = v.ir.FPRoundInt(operand, rounding_mode, exact); v.V_scalar(*datasize, Vd, result); return true; } From f8fb10289a0a991c6ae32b2727a6d7982a3e4909 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Apr 2019 18:01:43 -0400 Subject: [PATCH 6/6] A64: Enable half-precision vector FRINT* variants --- src/frontend/A64/decoder/a64.inc | 14 +++---- .../translate/impl/simd_two_register_misc.cpp | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 76f91273..062ef14c 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -621,9 +621,9 @@ INST(XTN, "XTN, XTN2", "0Q001 INST(SQXTN_2, "SQXTN, SQXTN2", "0Q001110zz100001010010nnnnnddddd") INST(FCVTN, "FCVTN, FCVTN2", "0Q0011100z100001011010nnnnnddddd") INST(FCVTL, "FCVTL, FCVTL2", "0Q0011100z100001011110nnnnnddddd") -//INST(FRINTN_1, "FRINTN (vector)", "0Q00111001111001100010nnnnnddddd") +INST(FRINTN_1, "FRINTN (vector)", "0Q00111001111001100010nnnnnddddd") INST(FRINTN_2, "FRINTN (vector)", "0Q0011100z100001100010nnnnnddddd") -//INST(FRINTM_1, "FRINTM (vector)", "0Q00111001111001100110nnnnnddddd") +INST(FRINTM_1, "FRINTM (vector)", "0Q00111001111001100110nnnnnddddd") INST(FRINTM_2, "FRINTM (vector)", "0Q0011100z100001100110nnnnnddddd") //INST(FCVTNS_3, "FCVTNS (vector)", "0Q00111001111001101010nnnnnddddd") INST(FCVTNS_4, "FCVTNS (vector)", "0Q0011100z100001101010nnnnnddddd") @@ -641,9 +641,9 @@ INST(FCMEQ_zero_4, "FCMEQ (zero)", "0Q001 INST(FCMLT_4, "FCMLT (zero)", "0Q0011101z100000111010nnnnnddddd") INST(FABS_1, "FABS (vector)", "0Q00111011111000111110nnnnnddddd") INST(FABS_2, "FABS (vector)", "0Q0011101z100000111110nnnnnddddd") -//INST(FRINTP_1, "FRINTP (vector)", "0Q00111011111001100010nnnnnddddd") +INST(FRINTP_1, "FRINTP (vector)", "0Q00111011111001100010nnnnnddddd") INST(FRINTP_2, "FRINTP (vector)", "0Q0011101z100001100010nnnnnddddd") -//INST(FRINTZ_1, "FRINTZ (vector)", "0Q00111011111001100110nnnnnddddd") +INST(FRINTZ_1, "FRINTZ (vector)", "0Q00111011111001100110nnnnnddddd") INST(FRINTZ_2, "FRINTZ (vector)", "0Q0011101z100001100110nnnnnddddd") //INST(FCVTPS_3, "FCVTPS (vector)", "0Q00111011111001101010nnnnnddddd") INST(FCVTPS_4, "FCVTPS (vector)", "0Q0011101z100001101010nnnnnddddd") @@ -665,9 +665,9 @@ INST(SQXTUN_2, "SQXTUN, SQXTUN2", "0Q101 INST(SHLL, "SHLL, SHLL2", "0Q101110zz100001001110nnnnnddddd") INST(UQXTN_2, "UQXTN, UQXTN2", "0Q101110zz100001010010nnnnnddddd") INST(FCVTXN_2, "FCVTXN, FCVTXN2", "0Q1011100z100001011010nnnnnddddd") -//INST(FRINTA_1, "FRINTA (vector)", "0Q10111001111001100010nnnnnddddd") +INST(FRINTA_1, "FRINTA (vector)", "0Q10111001111001100010nnnnnddddd") INST(FRINTA_2, "FRINTA (vector)", "0Q1011100z100001100010nnnnnddddd") -//INST(FRINTX_1, "FRINTX (vector)", "0Q10111001111001100110nnnnnddddd") +INST(FRINTX_1, "FRINTX (vector)", "0Q10111001111001100110nnnnnddddd") INST(FRINTX_2, "FRINTX (vector)", "0Q1011100z100001100110nnnnnddddd") //INST(FCVTNU_3, "FCVTNU (vector)", "0Q10111001111001101010nnnnnddddd") INST(FCVTNU_4, "FCVTNU (vector)", "0Q1011100z100001101010nnnnnddddd") @@ -681,7 +681,7 @@ INST(NOT, "NOT", "0Q101 INST(RBIT_asimd, "RBIT (vector)", "0Q10111001100000010110nnnnnddddd") INST(FNEG_1, "FNEG (vector)", "0Q10111011111000111110nnnnnddddd") INST(FNEG_2, "FNEG (vector)", "0Q1011101z100000111110nnnnnddddd") -//INST(FRINTI_1, "FRINTI (vector)", "0Q10111011111001100110nnnnnddddd") +INST(FRINTI_1, "FRINTI (vector)", "0Q10111011111001100110nnnnnddddd") INST(FRINTI_2, "FRINTI (vector)", "0Q1011101z100001100110nnnnnddddd") //INST(FCMGE_zero_3, "FCMGE (zero)", "0Q10111011111000110010nnnnnddddd") INST(FCMGE_zero_4, "FCMGE (zero)", "0Q1011101z100000110010nnnnnddddd") 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 92d9553f..ef0180f9 100644 --- a/src/frontend/A64/translate/impl/simd_two_register_misc.cpp +++ b/src/frontend/A64/translate/impl/simd_two_register_misc.cpp @@ -138,6 +138,17 @@ bool FloatRoundToIntegral(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd, return true; } +bool FloatRoundToIntegralHalfPrecision(TranslatorVisitor& v, bool Q, Vec Vn, Vec Vd, FP::RoundingMode rounding_mode, bool exact) { + const size_t datasize = Q ? 128 : 64; + const size_t esize = 16; + + const IR::U128 operand = v.V(datasize, Vn); + const IR::U128 result = v.ir.FPVectorRoundInt(esize, operand, rounding_mode, exact); + + v.V(datasize, Vd, result); + return true; +} + bool SaturatedNarrow(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec Vd, IR::U128 (IR::IREmitter::*fn)(size_t, const IR::U128&)) { if (size == 0b11) { return v.ReservedValue(); @@ -451,30 +462,58 @@ bool TranslatorVisitor::FCVTZU_int_4(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Unsigned, FP::RoundingMode::TowardsZero); } +bool TranslatorVisitor::FRINTN_1(bool Q, Vec Vn, Vec Vd) { + return FloatRoundToIntegralHalfPrecision(*this, Q, Vn, Vd, FP::RoundingMode::ToNearest_TieEven, false); +} + bool TranslatorVisitor::FRINTN_2(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatRoundToIntegral(*this, Q, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieEven, false); } +bool TranslatorVisitor::FRINTM_1(bool Q, Vec Vn, Vec Vd) { + return FloatRoundToIntegralHalfPrecision(*this, Q, Vn, Vd, FP::RoundingMode::TowardsMinusInfinity, false); +} + bool TranslatorVisitor::FRINTM_2(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatRoundToIntegral(*this, Q, sz, Vn, Vd, FP::RoundingMode::TowardsMinusInfinity, false); } +bool TranslatorVisitor::FRINTP_1(bool Q, Vec Vn, Vec Vd) { + return FloatRoundToIntegralHalfPrecision(*this, Q, Vn, Vd, FP::RoundingMode::TowardsPlusInfinity, false); +} + bool TranslatorVisitor::FRINTP_2(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatRoundToIntegral(*this, Q, sz, Vn, Vd, FP::RoundingMode::TowardsPlusInfinity, false); } +bool TranslatorVisitor::FRINTZ_1(bool Q, Vec Vn, Vec Vd) { + return FloatRoundToIntegralHalfPrecision(*this, Q, Vn, Vd, FP::RoundingMode::TowardsZero, false); +} + bool TranslatorVisitor::FRINTZ_2(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatRoundToIntegral(*this, Q, sz, Vn, Vd, FP::RoundingMode::TowardsZero, false); } +bool TranslatorVisitor::FRINTA_1(bool Q, Vec Vn, Vec Vd) { + return FloatRoundToIntegralHalfPrecision(*this, Q, Vn, Vd, FP::RoundingMode::ToNearest_TieAwayFromZero, false); +} + bool TranslatorVisitor::FRINTA_2(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatRoundToIntegral(*this, Q, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieAwayFromZero, false); } +bool TranslatorVisitor::FRINTX_1(bool Q, Vec Vn, Vec Vd) { + return FloatRoundToIntegralHalfPrecision(*this, Q, Vn, Vd, ir.current_location->FPCR().RMode(), true); +} + bool TranslatorVisitor::FRINTX_2(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatRoundToIntegral(*this, Q, sz, Vn, Vd, ir.current_location->FPCR().RMode(), true); } +bool TranslatorVisitor::FRINTI_1(bool Q, Vec Vn, Vec Vd) { + return FloatRoundToIntegralHalfPrecision(*this, Q, Vn, Vd, ir.current_location->FPCR().RMode(), false); +} + bool TranslatorVisitor::FRINTI_2(bool Q, bool sz, Vec Vn, Vec Vd) { return FloatRoundToIntegral(*this, Q, sz, Vn, Vd,ir.current_location->FPCR().RMode(), false); }