From d6606deda27ef52dd523846b86257e4a8190c641 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Sat, 13 Apr 2019 01:48:22 -0400
Subject: [PATCH] A64: Implement half-precision vector variants of FMLA/FMLS

---
 src/frontend/A64/decoder/a64.inc              |  4 +--
 .../A64/translate/impl/simd_three_same.cpp    | 30 +++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc
index e02bb2fa..ee133667 100644
--- a/src/frontend/A64/decoder/a64.inc
+++ b/src/frontend/A64/decoder/a64.inc
@@ -583,11 +583,11 @@ INST(INS_elt,                "INS (element)",                             "01101
 //INST(FCMGT_reg_3,            "FCMGT (register)",                          "0Q101110110mmmmm001001nnnnnddddd")
 //INST(FACGT_3,                "FACGT",                                     "0Q101110110mmmmm001011nnnnnddddd")
 //INST(FMAXNM_1,               "FMAXNM (vector)",                           "0Q001110010mmmmm000001nnnnnddddd")
-//INST(FMLA_vec_1,             "FMLA (vector)",                             "0Q001110010mmmmm000011nnnnnddddd")
+INST(FMLA_vec_1,             "FMLA (vector)",                             "0Q001110010mmmmm000011nnnnnddddd")
 //INST(FADD_1,                 "FADD (vector)",                             "0Q001110010mmmmm000101nnnnnddddd")
 //INST(FMAX_1,                 "FMAX (vector)",                             "0Q001110010mmmmm001101nnnnnddddd")
 //INST(FMINNM_1,               "FMINNM (vector)",                           "0Q001110110mmmmm000001nnnnnddddd")
-//INST(FMLS_vec_1,             "FMLS (vector)",                             "0Q001110110mmmmm000011nnnnnddddd")
+INST(FMLS_vec_1,             "FMLS (vector)",                             "0Q001110110mmmmm000011nnnnnddddd")
 //INST(FSUB_1,                 "FSUB (vector)",                             "0Q001110110mmmmm000101nnnnnddddd")
 //INST(FMIN_1,                 "FMIN (vector)",                             "0Q001110110mmmmm001101nnnnnddddd")
 //INST(FMAXNMP_vec_1,          "FMAXNMP (vector)",                          "0Q101110010mmmmm000001nnnnnddddd")
diff --git a/src/frontend/A64/translate/impl/simd_three_same.cpp b/src/frontend/A64/translate/impl/simd_three_same.cpp
index a4492165..a484dc17 100644
--- a/src/frontend/A64/translate/impl/simd_three_same.cpp
+++ b/src/frontend/A64/translate/impl/simd_three_same.cpp
@@ -680,10 +680,24 @@ bool TranslatorVisitor::FADD_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
     return true;
 }
 
+bool TranslatorVisitor::FMLA_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
+    const size_t datasize = Q ? 128 : 64;
+    const size_t esize = 16;
+
+    const IR::U128 operand1 = V(datasize, Vn);
+    const IR::U128 operand2 = V(datasize, Vm);
+    const IR::U128 operand3 = V(datasize, Vd);
+    const IR::U128 result = ir.FPVectorMulAdd(esize, operand3, operand1, operand2);
+
+    V(datasize, Vd, result);
+    return true;
+}
+
 bool TranslatorVisitor::FMLA_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
     if (sz && !Q) {
         return ReservedValue();
     }
+
     const size_t esize = sz ? 64 : 32;
     const size_t datasize = Q ? 128 : 64;
 
@@ -691,6 +705,20 @@ bool TranslatorVisitor::FMLA_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
     const IR::U128 operand2 = V(datasize, Vm);
     const IR::U128 operand3 = V(datasize, Vd);
     const IR::U128 result = ir.FPVectorMulAdd(esize, operand3, operand1, operand2);
+
+    V(datasize, Vd, result);
+    return true;
+}
+
+bool TranslatorVisitor::FMLS_vec_1(bool Q, Vec Vm, Vec Vn, Vec Vd) {
+    const size_t datasize = Q ? 128 : 64;
+    const size_t esize = 16;
+
+    const IR::U128 operand1 = V(datasize, Vn);
+    const IR::U128 operand2 = V(datasize, Vm);
+    const IR::U128 operand3 = V(datasize, Vd);
+    const IR::U128 result = ir.FPVectorMulAdd(esize, operand3, ir.FPVectorNeg(esize, operand1), operand2);
+
     V(datasize, Vd, result);
     return true;
 }
@@ -699,6 +727,7 @@ bool TranslatorVisitor::FMLS_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
     if (sz && !Q) {
         return ReservedValue();
     }
+
     const size_t esize = sz ? 64 : 32;
     const size_t datasize = Q ? 128 : 64;
 
@@ -706,6 +735,7 @@ bool TranslatorVisitor::FMLS_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
     const IR::U128 operand2 = V(datasize, Vm);
     const IR::U128 operand3 = V(datasize, Vd);
     const IR::U128 result = ir.FPVectorMulAdd(esize, operand3, ir.FPVectorNeg(esize, operand1), operand2);
+
     V(datasize, Vd, result);
     return true;
 }