From 59db2c191a018a9d86fc905bae33008dab97ded6 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 10 May 2020 15:09:37 +0100 Subject: [PATCH] VFPv3: Implement VMOV (immediate) --- src/frontend/A32/decoder/vfp.inc | 2 +- .../A32/disassembler/disassembler_arm.cpp | 18 +++++++++++ .../A32/translate/impl/translate_arm.h | 1 + src/frontend/A32/translate/impl/vfp.cpp | 30 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/vfp.inc b/src/frontend/A32/decoder/vfp.inc index aca0c62e..c82c81b5 100644 --- a/src/frontend/A32/decoder/vfp.inc +++ b/src/frontend/A32/decoder/vfp.inc @@ -14,7 +14,7 @@ INST(vfp_VFMA, "VFMA", "cccc11101D10nnnndddd101zN INST(vfp_VFMS, "VFMS", "cccc11101D10nnnndddd101zN1M0mmmm") // VFPv4 // Other floating-point data-processing instructions -//INST(vfp_VMOV_imm, "VMOV (immediate)", "cccc11101D11vvvvdddd101z0000vvvv") // VFPv3 +INST(vfp_VMOV_imm, "VMOV (immediate)", "cccc11101D11vvvvdddd101z0000vvvv") // VFPv3 INST(vfp_VMOV_reg, "VMOV (reg)", "cccc11101D110000dddd101z01M0mmmm") // VFPv2 INST(vfp_VABS, "VABS", "cccc11101D110000dddd101z11M0mmmm") // VFPv2 INST(vfp_VNEG, "VNEG", "cccc11101D110001dddd101z01M0mmmm") // VFPv2 diff --git a/src/frontend/A32/disassembler/disassembler_arm.cpp b/src/frontend/A32/disassembler/disassembler_arm.cpp index 196bf3e4..b30d4c16 100644 --- a/src/frontend/A32/disassembler/disassembler_arm.cpp +++ b/src/frontend/A32/disassembler/disassembler_arm.cpp @@ -1232,6 +1232,24 @@ 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_VMOV_imm(Cond cond, bool D, Imm<4> imm4H, size_t Vd, bool sz, Imm<4> imm4L) { + const auto imm8 = concatenate(imm4H, imm4L); + + if (sz) { + const u64 sign = static_cast(imm8.Bit<7>()); + const u64 exp = (imm8.Bit<6>() ? 0x3FC : 0x400) | imm8.Bits<4, 5, u64>(); + const u64 fract = imm8.Bits<0, 3, u64>() << 48; + const u64 immediate = (sign << 63) | (exp << 52) | fract; + return fmt::format("vmov{}.f64 {}, #0x{:016x}", CondToString(cond), FPRegStr(sz, Vd, D), immediate); + } else { + const u32 sign = static_cast(imm8.Bit<7>()); + const u32 exp = (imm8.Bit<6>() ? 0x7C : 0x80) | imm8.Bits<4, 5>(); + const u32 fract = imm8.Bits<0, 3>() << 19; + const u32 immediate = (sign << 31) | (exp << 23) | fract; + return fmt::format("vmov{}.f32 {}, #0x{:08x}", CondToString(cond), FPRegStr(sz, Vd, D), immediate); + } + } + std::string vfp_VMOV_u32_f64(Cond cond, size_t Vd, Reg t, bool D){ return fmt::format("vmov{}.32 {}, {}", CondToString(cond), FPRegStr(true, Vd, D), t); } diff --git a/src/frontend/A32/translate/impl/translate_arm.h b/src/frontend/A32/translate/impl/translate_arm.h index 95a1d27b..f20807e5 100644 --- a/src/frontend/A32/translate/impl/translate_arm.h +++ b/src/frontend/A32/translate/impl/translate_arm.h @@ -377,6 +377,7 @@ struct ArmTranslatorVisitor final { bool vfp_VFMS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); // Floating-point move instructions + bool vfp_VMOV_imm(Cond cond, bool D, Imm<4> imm4H, size_t Vd, bool sz, Imm<4> imm4L); bool vfp_VMOV_u32_f64(Cond cond, size_t Vd, Reg t, bool D); bool vfp_VMOV_f64_u32(Cond cond, size_t Vn, Reg t, bool N); bool vfp_VMOV_u32_f32(Cond cond, size_t Vn, Reg t, bool N); diff --git a/src/frontend/A32/translate/impl/vfp.cpp b/src/frontend/A32/translate/impl/vfp.cpp index 7f6830c1..4bf6509a 100644 --- a/src/frontend/A32/translate/impl/vfp.cpp +++ b/src/frontend/A32/translate/impl/vfp.cpp @@ -482,6 +482,36 @@ bool ArmTranslatorVisitor::vfp_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, s return true; } +// VMOV.F64
, # +// VMOV.F32 , # +bool ArmTranslatorVisitor::vfp_VMOV_imm(Cond cond, bool D, Imm<4> imm4H, size_t Vd, bool sz, Imm<4> imm4L) { + if (!ConditionPassed(cond)) { + return true; + } + + if (ir.current_location.FPSCR().Stride() != 1 || ir.current_location.FPSCR().Len() != 1) { + return UndefinedInstruction(); + } + + const auto d = ToExtReg(sz, Vd, D); + const auto imm8 = concatenate(imm4H, imm4L); + + if (sz) { + const u64 sign = static_cast(imm8.Bit<7>()); + const u64 exp = (imm8.Bit<6>() ? 0x3FC : 0x400) | imm8.Bits<4, 5, u64>(); + const u64 fract = imm8.Bits<0, 3, u64>() << 48; + const u64 immediate = (sign << 63) | (exp << 52) | fract; + ir.SetExtendedRegister(d, ir.Imm64(immediate)); + } else { + const u32 sign = static_cast(imm8.Bit<7>()); + const u32 exp = (imm8.Bit<6>() ? 0x7C : 0x80) | imm8.Bits<4, 5>(); + const u32 fract = imm8.Bits<0, 3>() << 19; + const u32 immediate = (sign << 31) | (exp << 23) | fract; + ir.SetExtendedRegister(d, ir.Imm32(immediate)); + } + return true; +} + // VMOV.F64
, // VMOV.F32 , bool ArmTranslatorVisitor::vfp_VMOV_reg(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm) {