diff --git a/src/frontend/A32/decoder/vfp.inc b/src/frontend/A32/decoder/vfp.inc index 58c42308..a043cb0f 100644 --- a/src/frontend/A32/decoder/vfp.inc +++ b/src/frontend/A32/decoder/vfp.inc @@ -12,7 +12,7 @@ INST(vfp_VFNMS, "VFNMS", "cccc11101D01nnnndddd101zN INST(vfp_VFNMA, "VFNMA", "cccc11101D01nnnndddd101zN1M0mmmm") // VFPv4 INST(vfp_VFMA, "VFMA", "cccc11101D10nnnndddd101zN0M0mmmm") // VFPv4 INST(vfp_VFMS, "VFMS", "cccc11101D10nnnndddd101zN1M0mmmm") // VFPv4 -//INST(vfp_VSEL, "VSEL", "111111100Dccnnnndddd101zN0M0mmmm") // VFPv5 +INST(vfp_VSEL, "VSEL", "111111100Dccnnnndddd101zN0M0mmmm") // VFPv5 INST(vfp_VMAXNM, "VMAXNNM", "111111101D00nnnndddd101zN0M0mmmm") // VFPv5 INST(vfp_VMINNM, "VMINNM", "111111101D00nnnndddd101zN1M0mmmm") // VFPv5 diff --git a/src/frontend/A32/disassembler/disassembler_arm.cpp b/src/frontend/A32/disassembler/disassembler_arm.cpp index 92c8d22c..606c3145 100644 --- a/src/frontend/A32/disassembler/disassembler_arm.cpp +++ b/src/frontend/A32/disassembler/disassembler_arm.cpp @@ -1274,6 +1274,11 @@ public: return fmt::format("vfma{}.{} {}, {}, {}", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D), FPRegStr(sz, Vn, N), FPRegStr(sz, Vm, M)); } + std::string vfp_VSEL(bool D, Imm<2> cc, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) { + const Cond cond = concatenate(cc, Imm<1>{cc.Bit<0>() != cc.Bit<1>()}, Imm<1>{0}).ZeroExtend(); + return fmt::format("vsel{}.{} {}, {}, {}", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D), FPRegStr(sz, Vn, N), FPRegStr(sz, Vm, M)); + } + std::string vfp_VMAXNM(bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) { return fmt::format("vmaxnm.{} {}, {}, {}", sz ? "f64" : "f32", FPRegStr(sz, Vd, D), FPRegStr(sz, Vn, N), FPRegStr(sz, Vm, M)); } diff --git a/src/frontend/A32/translate/impl/translate_arm.h b/src/frontend/A32/translate/impl/translate_arm.h index 64b25499..9fd6642d 100644 --- a/src/frontend/A32/translate/impl/translate_arm.h +++ b/src/frontend/A32/translate/impl/translate_arm.h @@ -392,6 +392,7 @@ struct ArmTranslatorVisitor final { bool vfp_VFNMA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); bool vfp_VFMA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); bool vfp_VFMS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); + bool vfp_VSEL(bool D, Imm<2> cc, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); bool vfp_VMAXNM(bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); bool vfp_VMINNM(bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); diff --git a/src/frontend/A32/translate/impl/vfp.cpp b/src/frontend/A32/translate/impl/vfp.cpp index 1d188d3e..6558656e 100644 --- a/src/frontend/A32/translate/impl/vfp.cpp +++ b/src/frontend/A32/translate/impl/vfp.cpp @@ -336,6 +336,23 @@ bool ArmTranslatorVisitor::vfp_VFMS(Cond cond, bool D, size_t Vn, size_t Vd, boo }); } +// VSEL.F64
, , +// VSEL.F32 , , +bool ArmTranslatorVisitor::vfp_VSEL(bool D, Imm<2> cc, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) { + const Cond cond = concatenate(cc, Imm<1>{cc.Bit<0>() != cc.Bit<1>()}, Imm<1>{0}).ZeroExtend(); + + const auto d = ToExtReg(sz, Vd, D); + const auto n = ToExtReg(sz, Vn, N); + const auto m = ToExtReg(sz, Vm, M); + + return EmitVfpVectorOperation(sz, d, n, m, [this, cond](ExtReg d, ExtReg n, ExtReg m) { + const auto reg_n = ir.GetExtendedRegister(n); + const auto reg_m = ir.GetExtendedRegister(m); + const auto result = ir.ConditionalSelect(cond, reg_n, reg_m); + ir.SetExtendedRegister(d, result); + }); +} + // VMAXNM.F64
, , // VMAXNM.F32 , , bool ArmTranslatorVisitor::vfp_VMAXNM(bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {