From 809dfe9c54ab77590f6e133d0c757bcb012e36c8 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 21 Jun 2020 14:03:39 +0100 Subject: [PATCH] A32: Implement ASIMD VCVT (between floating-point and integer) --- src/frontend/A32/decoder/asimd.inc | 2 +- .../translate/impl/asimd_two_regs_misc.cpp | 22 +++++++++++++++++++ .../A32/translate/impl/translate_arm.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/asimd.inc b/src/frontend/A32/decoder/asimd.inc index 42254b37..e3344810 100644 --- a/src/frontend/A32/decoder/asimd.inc +++ b/src/frontend/A32/decoder/asimd.inc @@ -108,7 +108,7 @@ INST(asimd_VMOVN, "VMOVN", "111100111D11zz10dddd001 //INST(asimd_VCVT_half, "VCVT (half-precision)", "111100111-11--10----011x00-0----") // ASIMD INST(asimd_VRECPE, "VRECPE", "111100111D11zz11dddd010F0QM0mmmm") // ASIMD INST(asimd_VRSQRTE, "VRSQRTE", "111100111D11zz11dddd010F1QM0mmmm") // ASIMD -//INST(asimd_VCVT_integer, "VCVT (integer)", "111100111-11--11----011xxx-0----") // ASIMD +INST(asimd_VCVT_integer, "VCVT (integer)", "111100111D11zz11dddd011oUQM0mmmm") // ASIMD // Miscellaneous INST(asimd_VEXT, "VEXT", "111100101D11nnnnddddiiiiNQM0mmmm") // ASIMD diff --git a/src/frontend/A32/translate/impl/asimd_two_regs_misc.cpp b/src/frontend/A32/translate/impl/asimd_two_regs_misc.cpp index 284b38b6..3e1ab2f5 100644 --- a/src/frontend/A32/translate/impl/asimd_two_regs_misc.cpp +++ b/src/frontend/A32/translate/impl/asimd_two_regs_misc.cpp @@ -558,4 +558,26 @@ bool ArmTranslatorVisitor::asimd_VRSQRTE(bool D, size_t sz, size_t Vd, bool F, b return true; } +bool ArmTranslatorVisitor::asimd_VCVT_integer(bool D, size_t sz, size_t Vd, bool op, bool U, bool Q, bool M, size_t Vm) { + if (Q && (Common::Bit<0>(Vd) || Common::Bit<0>(Vm))) { + return UndefinedInstruction(); + } + + if (sz != 0b10) { + return UndefinedInstruction(); + } + + const size_t esize = 8U << sz; + const auto d = ToVector(Q, Vd, D); + const auto m = ToVector(Q, Vm, M); + const auto reg_m = ir.GetVector(m); + const auto result = op ? (U ? ir.FPVectorToUnsignedFixed(esize, reg_m, 0, FP::RoundingMode::TowardsZero, false) + : ir.FPVectorToSignedFixed(esize, reg_m, 0, FP::RoundingMode::TowardsZero, false)) + : (U ? ir.FPVectorFromUnsignedFixed(esize, reg_m, 0, FP::RoundingMode::ToNearest_TieEven, false) + : ir.FPVectorFromSignedFixed(esize, reg_m, 0, FP::RoundingMode::ToNearest_TieEven, false)); + + ir.SetVector(d, result); + return true; +} + } // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_arm.h b/src/frontend/A32/translate/impl/translate_arm.h index 670c26fe..c6b433e0 100644 --- a/src/frontend/A32/translate/impl/translate_arm.h +++ b/src/frontend/A32/translate/impl/translate_arm.h @@ -533,6 +533,7 @@ struct ArmTranslatorVisitor final { bool asimd_VMOVN(bool D, size_t sz, size_t Vd, bool M, size_t Vm); bool asimd_VRECPE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm); bool asimd_VRSQRTE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm); + bool asimd_VCVT_integer(bool D, size_t sz, size_t Vd, bool op, bool U, bool Q, bool M, size_t Vm); // Advanced SIMD miscellaneous bool asimd_VEXT(bool D, size_t Vn, size_t Vd, Imm<4> imm4, bool N, bool Q, bool M, size_t Vm);