From ad96b2b18d9e5eef58f3a999ca819540ca4f6d02 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 19 Jun 2020 20:31:16 +0100 Subject: [PATCH] VFPv5: Implement VCVT{A,N,P,M} --- src/frontend/A32/decoder/vfp.inc | 2 +- .../A32/disassembler/disassembler_arm.cpp | 4 ++++ .../A32/translate/impl/translate_arm.h | 1 + src/frontend/A32/translate/impl/vfp.cpp | 22 +++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/vfp.inc b/src/frontend/A32/decoder/vfp.inc index 07ce7895..fcf95eb1 100644 --- a/src/frontend/A32/decoder/vfp.inc +++ b/src/frontend/A32/decoder/vfp.inc @@ -33,7 +33,7 @@ INST(vfp_VCVT_to_u32, "VCVT (to u32)", "cccc11101D111100dddd101zr INST(vfp_VCVT_to_s32, "VCVT (to s32)", "cccc11101D111101dddd101zr1M0mmmm") // VFPv2 //INST(vfp_VCVT_to_fixed, "VCVT (to fixed)", "cccc11101D11111Udddd101zx1i0vvvv") // VFPv3 INST(vfp_VRINT_rm, "VRINT{A,N,P,M}", "111111101D1110mmdddd101z01M0mmmm") // VFPv5 -//INST(vfp_VCVT_rm, "VCVT{A,N,P,M}", "111111101D1111mmdddd101zU1M0mmmm") // VFPv5 +INST(vfp_VCVT_rm, "VCVT{A,N,P,M}", "111111101D1111mmdddd101zU1M0mmmm") // VFPv5 // Floating-point move instructions INST(vfp_VMOV_u32_f64, "VMOV (core to f64)", "cccc11100000ddddtttt1011D0010000") // VFPv2 diff --git a/src/frontend/A32/disassembler/disassembler_arm.cpp b/src/frontend/A32/disassembler/disassembler_arm.cpp index 5b43ab17..00ef587e 100644 --- a/src/frontend/A32/disassembler/disassembler_arm.cpp +++ b/src/frontend/A32/disassembler/disassembler_arm.cpp @@ -1395,6 +1395,10 @@ public: return fmt::format("vrint{}.{} {}, {}", "anpm"[rm], sz ? "f64" : "f32", FPRegStr(sz, Vd, D), FPRegStr(sz, Vm, M)); } + std::string vfp_VCVT_rm(bool D, size_t rm, size_t Vd, bool sz, bool U, bool M, size_t Vm) { + return fmt::format("vcvt{}.{}.{} {}, {}", "anpm"[rm], U ? "u32" : "s32", sz ? "f64" : "f32", FPRegStr(false, Vd, D), FPRegStr(sz, Vm, M)); + } + std::string vfp_VMSR(Cond cond, Reg t) { return fmt::format("vmsr{} fpscr, {}", CondToString(cond), t); } diff --git a/src/frontend/A32/translate/impl/translate_arm.h b/src/frontend/A32/translate/impl/translate_arm.h index d1b093bd..4b8fbbab 100644 --- a/src/frontend/A32/translate/impl/translate_arm.h +++ b/src/frontend/A32/translate/impl/translate_arm.h @@ -421,6 +421,7 @@ struct ArmTranslatorVisitor final { bool vfp_VCVT_to_u32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm); bool vfp_VCVT_to_s32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm); bool vfp_VRINT_rm(bool D, size_t rm, size_t Vd, bool sz, bool M, size_t Vm); + bool vfp_VCVT_rm(bool D, size_t rm, size_t Vd, bool sz, bool U, bool M, size_t Vm); // Floating-point system register access bool vfp_VMSR(Cond cond, Reg t); diff --git a/src/frontend/A32/translate/impl/vfp.cpp b/src/frontend/A32/translate/impl/vfp.cpp index 340f3c1b..77341794 100644 --- a/src/frontend/A32/translate/impl/vfp.cpp +++ b/src/frontend/A32/translate/impl/vfp.cpp @@ -826,6 +826,28 @@ bool ArmTranslatorVisitor::vfp_VRINT_rm(bool D, size_t rm, size_t Vd, bool sz, b }); } +// VCVT{A,N,P,M}.F32 , +// VCVT{A,N,P,M}.F64 , +bool ArmTranslatorVisitor::vfp_VCVT_rm(bool D, size_t rm, size_t Vd, bool sz, bool U, bool M, size_t Vm) { + const std::array rm_lookup{ + FP::RoundingMode::ToNearest_TieAwayFromZero, + FP::RoundingMode::ToNearest_TieEven, + FP::RoundingMode::TowardsPlusInfinity, + FP::RoundingMode::TowardsMinusInfinity, + }; + const FP::RoundingMode rounding_mode = rm_lookup[rm]; + const bool unsigned_ = !U; + + const auto d = ToExtReg(false, Vd, D); + const auto m = ToExtReg(sz, Vm, M); + + return EmitVfpVectorOperation(sz, d, m, [this, rounding_mode, unsigned_](ExtReg d, ExtReg m) { + const auto reg_m = ir.GetExtendedRegister(m); + const auto result = unsigned_ ? ir.FPToFixedU32(reg_m, 0, rounding_mode) : ir.FPToFixedS32(reg_m, 0, rounding_mode); + ir.SetExtendedRegister(d, result); + }); +} + // VMSR FPSCR, bool ArmTranslatorVisitor::vfp_VMSR(Cond cond, Reg t) { if (t == Reg::PC) {