From 8f0f1cfd66eb85be94010a92217862c5d0b4416b Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 21 Jun 2020 16:27:33 +0100 Subject: [PATCH] A32: Implement ASIMD VST{1,2,3,4} (single n-element structure from one lane) --- src/frontend/A32/decoder/asimd.inc | 2 +- .../impl/asimd_load_store_structures.cpp | 63 ++++++++++++++++++- .../A32/translate/impl/translate_arm.h | 1 + 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/asimd.inc b/src/frontend/A32/decoder/asimd.inc index ab06ed9f..7f38100b 100644 --- a/src/frontend/A32/decoder/asimd.inc +++ b/src/frontend/A32/decoder/asimd.inc @@ -127,5 +127,5 @@ INST(arm_UDF, "UNALLOCATED", "111101000--0--------11- INST(arm_UDF, "UNALLOCATED", "111101001-00--------11----------") // v8 INST(v8_VLD_all_lanes, "VLD{1-4} (all lanes)", "111101001D10nnnndddd11nnzzTammmm") // v8 INST(arm_UDF, "UNALLOCATED", "111101001-10--------1110---1----") // v8 -//INST(v8_VST_single, "VST{1-4} (single)", "111101001D00nnnnddddzzNNaaaammmm") // v8 +INST(v8_VST_single, "VST{1-4} (single)", "111101001D00nnnnddddzzNNaaaammmm") // v8 INST(v8_VLD_single, "VLD{1-4} (single)", "111101001D10nnnnddddzzNNaaaammmm") // v8 diff --git a/src/frontend/A32/translate/impl/asimd_load_store_structures.cpp b/src/frontend/A32/translate/impl/asimd_load_store_structures.cpp index cf0ed9d0..80b0847f 100644 --- a/src/frontend/A32/translate/impl/asimd_load_store_structures.cpp +++ b/src/frontend/A32/translate/impl/asimd_load_store_structures.cpp @@ -235,6 +235,68 @@ bool ArmTranslatorVisitor::v8_VLD_all_lanes(bool D, Reg n, size_t Vd, size_t nn, return true; } +bool ArmTranslatorVisitor::v8_VST_single(bool D, Reg n, size_t Vd, size_t sz, size_t nn, size_t index_align, Reg m) { + const size_t nelem = nn + 1; + + ASSERT_MSG(sz != 0b11, "Decode Error"); + + if (nelem == 1 && Common::Bit(sz, index_align)) { + return UndefinedInstruction(); + } + + const size_t ebytes = 1 << sz; + const size_t index = Common::Bits(sz + 1, 3, index_align); + const size_t inc = (sz != 0 && Common::Bit(sz, index_align)) ? 2 : 1; + const size_t a = Common::Bits(0, sz ? sz - 1 : 0, index_align); + + if (nelem == 1 && inc == 2) { + return UndefinedInstruction(); + } + if (nelem == 1 && (a != 0b00 && a != 0b11)) { + return UndefinedInstruction(); + } + if (nelem == 2 && Common::Bit<1>(a)) { + return UndefinedInstruction(); + } + if (nelem == 3 && a != 0b00) { + return UndefinedInstruction(); + } + if (nelem == 4 && a == 0b11) { + return UndefinedInstruction(); + } + + // TODO: alignment + + const ExtReg d = ToExtRegD(Vd, D); + const size_t d_last = RegNumber(d) + inc * (nelem - 1); + if (n == Reg::R15 || d_last + 1 > 32) { + return UnpredictableInstruction(); + } + + const bool wback = m != Reg::R15; + const bool register_index = m != Reg::R15 && m != Reg::R13; + + auto address = ir.GetRegister(n); + for (size_t i = 0; i < nelem; i++) { + const ExtReg ext_reg = d + i * inc; + const auto element = ir.VectorGetElement(ebytes * 8, ir.GetVector(ext_reg), index); + + ir.WriteMemory(ebytes * 8, address, element); + + address = ir.Add(address, ir.Imm32(static_cast(ebytes))); + } + + if (wback) { + if (register_index) { + ir.SetRegister(n, ir.Add(ir.GetRegister(n), ir.GetRegister(m))); + } else { + ir.SetRegister(n, ir.Add(ir.GetRegister(n), ir.Imm32(static_cast(nelem * ebytes)))); + } + } + + return true; +} + bool ArmTranslatorVisitor::v8_VLD_single(bool D, Reg n, size_t Vd, size_t sz, size_t nn, size_t index_align, Reg m) { const size_t nelem = nn + 1; @@ -297,5 +359,4 @@ bool ArmTranslatorVisitor::v8_VLD_single(bool D, Reg n, size_t Vd, size_t sz, si 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 5dfa8738..6b194689 100644 --- a/src/frontend/A32/translate/impl/translate_arm.h +++ b/src/frontend/A32/translate/impl/translate_arm.h @@ -545,6 +545,7 @@ struct ArmTranslatorVisitor final { bool v8_VST_multiple(bool D, Reg n, size_t Vd, Imm<4> type, size_t sz, size_t align, Reg m); bool v8_VLD_multiple(bool D, Reg n, size_t Vd, Imm<4> type, size_t sz, size_t align, Reg m); bool v8_VLD_all_lanes(bool D, Reg n, size_t Vd, size_t nn, size_t sz, bool T, bool a, Reg m); + bool v8_VST_single(bool D, Reg n, size_t Vd, size_t sz, size_t nn, size_t index_align, Reg m); bool v8_VLD_single(bool D, Reg n, size_t Vd, size_t sz, size_t nn, size_t index_align, Reg m); };