From 2d1aca25e6971f4aaa0b05159984badb7033bc5e Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 15 May 2018 10:20:03 -0400
Subject: [PATCH] A64: Implement SMULL{2}

---
 src/frontend/A64/decoder/a64.inc              |  2 +-
 .../translate/impl/simd_three_different.cpp   | 20 +++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc
index 72a725b2..34bab5e2 100644
--- a/src/frontend/A64/decoder/a64.inc
+++ b/src/frontend/A64/decoder/a64.inc
@@ -686,7 +686,7 @@ INST(SUBHN,                  "SUBHN, SUBHN2",                             "0Q001
 INST(SABDL,                  "SABDL, SABDL2",                             "0Q001110zz1mmmmm011100nnnnnddddd")
 //INST(SMLAL_vec,              "SMLAL, SMLAL2 (vector)",                    "0Q001110zz1mmmmm100000nnnnnddddd")
 //INST(SMLSL_vec,              "SMLSL, SMLSL2 (vector)",                    "0Q001110zz1mmmmm101000nnnnnddddd")
-//INST(SMULL_vec,              "SMULL, SMULL2 (vector)",                    "0Q001110zz1mmmmm110000nnnnnddddd")
+INST(SMULL_vec,              "SMULL, SMULL2 (vector)",                    "0Q001110zz1mmmmm110000nnnnnddddd")
 //INST(PMULL,                  "PMULL, PMULL2",                             "0Q001110zz1mmmmm111000nnnnnddddd")
 INST(UADDL,                  "UADDL, UADDL2",                             "0Q101110zz1mmmmm000000nnnnnddddd")
 INST(UADDW,                  "UADDW, UADDW2",                             "0Q101110zz1mmmmm000100nnnnnddddd")
diff --git a/src/frontend/A64/translate/impl/simd_three_different.cpp b/src/frontend/A64/translate/impl/simd_three_different.cpp
index b08be1cc..7ed9d85b 100644
--- a/src/frontend/A64/translate/impl/simd_three_different.cpp
+++ b/src/frontend/A64/translate/impl/simd_three_different.cpp
@@ -35,6 +35,17 @@ 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) {
+    const size_t esize = 8 << size.ZeroExtend();
+    const size_t datasize = 64;
+
+    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);
+
+    v.V(2 * datasize, Vd, product);
+}
 } // Anonymous namespace
 
 bool TranslatorVisitor::SABAL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -87,6 +98,15 @@ bool TranslatorVisitor::SADDW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
     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);
+    return true;
+}
+
 bool TranslatorVisitor::SSUBW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
     if (size == 0b11) {
         return ReservedValue();