From ada5c0b2faa0988dad3833a09d090f8154995a84 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 15 May 2018 10:42:13 -0400 Subject: [PATCH] A64: Implement SMLAL{2} --- src/frontend/A64/decoder/a64.inc | 2 +- .../translate/impl/simd_three_different.cpp | 30 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 34bab5e2..93fcae32 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -684,7 +684,7 @@ INST(ADDHN, "ADDHN, ADDHN2", "0Q001 INST(SABAL, "SABAL, SABAL2", "0Q001110zz1mmmmm010100nnnnnddddd") INST(SUBHN, "SUBHN, SUBHN2", "0Q001110zz1mmmmm011000nnnnnddddd") INST(SABDL, "SABDL, SABDL2", "0Q001110zz1mmmmm011100nnnnnddddd") -//INST(SMLAL_vec, "SMLAL, SMLAL2 (vector)", "0Q001110zz1mmmmm100000nnnnnddddd") +INST(SMLAL_vec, "SMLAL, SMLAL2 (vector)", "0Q001110zz1mmmmm100000nnnnnddddd") //INST(SMLSL_vec, "SMLSL, SMLSL2 (vector)", "0Q001110zz1mmmmm101000nnnnnddddd") INST(SMULL_vec, "SMULL, SMULL2 (vector)", "0Q001110zz1mmmmm110000nnnnnddddd") //INST(PMULL, "PMULL, PMULL2", "0Q001110zz1mmmmm111000nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_three_different.cpp b/src/frontend/A64/translate/impl/simd_three_different.cpp index 7ed9d85b..2fbe6f93 100644 --- a/src/frontend/A64/translate/impl/simd_three_different.cpp +++ b/src/frontend/A64/translate/impl/simd_three_different.cpp @@ -36,15 +36,28 @@ void AbsoluteDifferenceLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, V v.V(2 * datasize, Vd, result); } -void MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { +enum class MultiplyLongBehavior { + None, + Accumulate, +}; + +void MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, + MultiplyLongBehavior behavior) { const size_t esize = 8 << size.ZeroExtend(); + const size_t doubled_esize = 2 * esize; const size_t datasize = 64; + const size_t doubled_datasize = datasize * 2; const IR::U128 operand1 = v.ir.VectorSignExtend(esize, v.Vpart(datasize, Vn, Q)); const IR::U128 operand2 = v.ir.VectorSignExtend(esize, v.Vpart(datasize, Vm, Q)); - const IR::U128 product = v.ir.VectorMultiply(2 * esize, operand1, operand2); + IR::U128 result = v.ir.VectorMultiply(doubled_esize, operand1, operand2); - v.V(2 * datasize, Vd, product); + if (behavior == MultiplyLongBehavior::Accumulate) { + const IR::U128 addend = v.V(doubled_datasize, Vd); + result = v.ir.VectorAdd(doubled_esize, addend, result); + } + + v.V(doubled_datasize, Vd, result); } } // Anonymous namespace @@ -98,12 +111,21 @@ bool TranslatorVisitor::SADDW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return true; } +bool TranslatorVisitor::SMLAL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + if (size == 0b11) { + return ReservedValue(); + } + + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate); + return true; +} + bool TranslatorVisitor::SMULL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size == 0b11) { return ReservedValue(); } - MultiplyLong(*this, Q, size, Vm, Vn, Vd); + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None); return true; }