From bebe7235aeffdc311d5e5acbf845d579d503d482 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 25 Apr 2018 16:07:58 -0400 Subject: [PATCH] A64: Implement UZP1 and UZP2 --- src/frontend/A64/decoder/a64.inc | 4 +- .../A64/translate/impl/simd_permute.cpp | 50 +++++++++++++++++-- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 19b4e123..e2f18c44 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -514,10 +514,10 @@ INST(SLI_1, "SLI", "01111 //INST(TBX, "TBX", "0Q001110000mmmmm0LL100nnnnnddddd") // Data Processing - FP and SIMD - SIMD Permute -//INST(UZP1, "UZP1", "0Q001110zz0mmmmm000110nnnnnddddd") +INST(UZP1, "UZP1", "0Q001110zz0mmmmm000110nnnnnddddd") INST(TRN1, "TRN1", "0Q001110zz0mmmmm001010nnnnnddddd") INST(ZIP1, "ZIP1", "0Q001110zz0mmmmm001110nnnnnddddd") -//INST(UZP2, "UZP2", "0Q001110zz0mmmmm010110nnnnnddddd") +INST(UZP2, "UZP2", "0Q001110zz0mmmmm010110nnnnnddddd") INST(TRN2, "TRN2", "0Q001110zz0mmmmm011010nnnnnddddd") INST(ZIP2, "ZIP2", "0Q001110zz0mmmmm011110nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_permute.cpp b/src/frontend/A64/translate/impl/simd_permute.cpp index 5fe34298..e190c602 100644 --- a/src/frontend/A64/translate/impl/simd_permute.cpp +++ b/src/frontend/A64/translate/impl/simd_permute.cpp @@ -8,14 +8,14 @@ #include "frontend/A64/translate/impl/impl.h" namespace Dynarmic::A64 { - +namespace { enum class Transposition { TRN1, TRN2, }; -static void VectorTranspose(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, - Transposition type) { +void VectorTranspose(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, + Transposition type) { const size_t datasize = Q ? 128 : 64; const u8 esize = static_cast(8 << size.ZeroExtend()); @@ -63,6 +63,32 @@ static void VectorTranspose(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, V v.V(datasize, Vd, result); } +enum class UnzipType { + Even, + Odd, +}; + +void VectorUnzip(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, UnzipType type) { + const size_t datasize = Q ? 128 : 64; + const size_t esize = 8 << size.ZeroExtend(); + + const IR::U128 n = v.V(datasize, Vn); + const IR::U128 m = v.V(datasize, Vm); + IR::U128 result = [&] { + if (type == UnzipType::Even) { + return v.ir.VectorDeinterleaveEven(esize, n, m); + } + return v.ir.VectorDeinterleaveOdd(esize, n, m); + }(); + + if (datasize == 64) { + result = v.ir.VectorShuffleWords(result, 0b11011000); + } + + v.V(datasize, Vd, result); +} +} // Anonymous namespace + bool TranslatorVisitor::TRN1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (!Q && size == 0b11) { return ReservedValue(); @@ -81,6 +107,24 @@ bool TranslatorVisitor::TRN2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return true; } +bool TranslatorVisitor::UZP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + if (size == 0b11 && !Q) { + return ReservedValue(); + } + + VectorUnzip(*this, Q, size, Vm, Vn, Vd, UnzipType::Even); + return true; +} + +bool TranslatorVisitor::UZP2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + if (size == 0b11 && !Q) { + return ReservedValue(); + } + + VectorUnzip(*this, Q, size, Vm, Vn, Vd, UnzipType::Odd); + return true; +} + bool TranslatorVisitor::ZIP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size == 0b11 && !Q) { return ReservedValue();