arch-arm: Add support for the SVE CLAST[A|B] (vectors) instructions

Change-Id: I5ce54832ac19054b0cacc4887eac8707d1f46cbd
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
diff --git a/src/arch/arm/insts/sve.cc b/src/arch/arm/insts/sve.cc
index d16c47e..6074ce0 100644
--- a/src/arch/arm/insts/sve.cc
+++ b/src/arch/arm/insts/sve.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited
+ * Copyright (c) 2017-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -547,17 +547,23 @@
 }
 
 std::string
-SveScalarSelectOp::generateDisassembly(Addr pc,
+SveSelectOp::generateDisassembly(Addr pc,
         const SymbolTable *symtab) const
 {
     std::stringstream ss;
     printMnemonic(ss, "", false);
-    printIntReg(ss, dest, scalar_width);
+    if (scalar)
+        printIntReg(ss, dest, scalar_width);
+    else
+        printVecReg(ss, dest, true);
     ccprintf(ss, ", ");
     printPredReg(ss, gp);
     if (conditional) {
         ccprintf(ss, ", ");
-        printIntReg(ss, dest, scalar_width);
+        if (scalar)
+            printIntReg(ss, dest, scalar_width);
+        else
+            printVecReg(ss, dest, true);
     }
     ccprintf(ss, ", ");
     printVecReg(ss, op1, true);
diff --git a/src/arch/arm/insts/sve.hh b/src/arch/arm/insts/sve.hh
index 3344e8c..9062b4f 100644
--- a/src/arch/arm/insts/sve.hh
+++ b/src/arch/arm/insts/sve.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited
+ * Copyright (c) 2017-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -569,20 +569,22 @@
 };
 
 /// Scalar element select SVE instruction.
-class SveScalarSelectOp : public ArmStaticInst {
+class SveSelectOp : public ArmStaticInst {
   protected:
     IntRegIndex dest;
     IntRegIndex op1;
     IntRegIndex gp;
     bool conditional;
+    bool scalar;
     size_t scalar_width;
 
-    SveScalarSelectOp(const char* mnem, ExtMachInst _machInst,
+    SveSelectOp(const char* mnem, ExtMachInst _machInst,
                       OpClass __opClass, IntRegIndex _dest,
                       IntRegIndex _op1, IntRegIndex _gp,
-                      bool _conditional) :
+                      bool _conditional, bool _scalar) :
         ArmStaticInst(mnem, _machInst, __opClass),
-        dest(_dest), op1(_op1), gp(_gp), conditional(_conditional)
+        dest(_dest), op1(_op1), gp(_gp), conditional(_conditional),
+        scalar(_scalar)
     {}
     std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
 };
diff --git a/src/arch/arm/isa/formats/sve_2nd_level.isa b/src/arch/arm/isa/formats/sve_2nd_level.isa
index 2276cd6..8ba83d9 100644
--- a/src/arch/arm/isa/formats/sve_2nd_level.isa
+++ b/src/arch/arm/isa/formats/sve_2nd_level.isa
@@ -1185,7 +1185,6 @@
             break;
           case 0xC:
             if (!b13) {
-                // sve_int_perm_splice
                 uint8_t size = bits(machInst, 23, 22);
                 IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10);
                 IntRegIndex zdn = (IntRegIndex)(uint8_t) bits(machInst, 4, 0);
@@ -1219,12 +1218,25 @@
             break;
           case 0x4:
             if (!b13) {
-                // sve_int_perm_clast_zz
+                uint8_t AB = bits(machInst, 16);
+                uint8_t size = bits(machInst, 23, 22);
+                IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10);
+                IntRegIndex zm = (IntRegIndex)(uint8_t) bits(machInst, 9, 5);
+                IntRegIndex zdn = (IntRegIndex)(uint8_t) bits(machInst, 4, 0);
+                if (!AB) {
+                    return decodeSveUnaryPredU<SveClastav>(size,
+                            machInst, zdn, zm, pg);
+                } else {
+                    return decodeSveUnaryPredU<SveClastbv>(size,
+                            machInst, zdn, zm, pg);
+                }
             }
             break;
           case 0x5:
             if (!b13) {
                 // sve_int_perm_clast_vz
+                // uint8_t AB = bits(machInst, 16);
+                // uint8_t size = bits(machInst, 23, 22);
             }
             break;
           case 0x8:
@@ -1245,7 +1257,6 @@
             break;
         }
         if (bits(machInst, 20, 18) == 0x1 && !b13) {
-            // sve_int_perm_rev
             unsigned size = (unsigned) bits(machInst, 23, 22);
             IntRegIndex pg = (IntRegIndex)(uint8_t) bits(machInst, 12, 10);
             IntRegIndex zn = (IntRegIndex)(uint8_t) bits(machInst, 9, 5);
diff --git a/src/arch/arm/isa/insts/sve.isa b/src/arch/arm/isa/insts/sve.isa
index 0182da3..a782af5 100644
--- a/src/arch/arm/isa/insts/sve.isa
+++ b/src/arch/arm/isa/insts/sve.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 ARM Limited
+// Copyright (c) 2017-2018 ARM Limited
 // All rights reserved
 //
 // The license below extends only to copyright in the software and shall
@@ -2267,7 +2267,7 @@
 
     # Generate definitions for scalar select instructions
     def sveSelectInst(name, Name, opClass, types, op, isCond,
-            decoder = 'Generic'):
+            destType = DestType.Scalar, decoder = 'Generic'):
         global header_output, exec_output, decoders
         code = sveEnabledCheckCode + '''
         unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
@@ -2278,13 +2278,34 @@
                 break;
             }
         }
-        Element destElem;
-        %(op)s
-        XDest = destElem;'''%{'op': op}
-        iop = InstObjParams(name, 'Sve' + Name, 'SveScalarSelectOp',
+        '''
+        if isCond:
+            code += '''
+        if (last >= 0) {'''
+        code += '''
+            Element destElem;
+            %(op)s'''%{'op': op}
+        if destType == DestType.Vector:
+            code += '''
+            for (unsigned i = 0; i < eCount; ++i)
+                AA64FpDest_x[i] = destElem;'''
+        elif destType == DestType.Scalar:
+            code += '''
+            XDest = destElem;'''
+        if isCond:
+            code += '''
+        }'''
+            if destType == DestType.Scalar:
+                code += ''' else {
+            XDest = (Element) XDest;
+        }'''
+        iop = InstObjParams(name, 'Sve' + Name, 'SveSelectOp',
                             {'code': code, 'op_class': opClass,
-                             'isCond': 'true' if isCond else 'false'}, [])
-        header_output += SveScalarSelectOpDeclare.subst(iop)
+                             'isCond': 'true' if isCond else 'false',
+                             'isScalar': 'true' if destType == DestType.Scalar
+                             else 'false'},
+                            [])
+        header_output += SveSelectOpDeclare.subst(iop)
         exec_output += SveOpExecute.subst(iop)
         for type in types:
             substDict = {'targs' : type,
@@ -2812,25 +2833,23 @@
             isFlagSetting = True, whenBrk = Break.Before)
     # CLASTA (scalar)
     clastaCode = '''
-        if (last < 0) {
-            destElem = XDest;
-        } else {
-            last++;
-            if (last >= eCount)
-                last = 0;
-            destElem = AA64FpOp1_x[last];
-        }'''
+        last++;
+        if (last >= eCount)
+            last = 0;
+        destElem = AA64FpOp1_x[last];'''
     sveSelectInst('clasta', 'Clasta', 'SimdAluOp', unsignedTypes, clastaCode,
-            isCond = True)
+            isCond = True, destType = DestType.Scalar)
+    # CLASTA (vector)
+    sveSelectInst('clasta', 'Clastav', 'SimdAluOp', unsignedTypes, clastaCode,
+            isCond = True, destType = DestType.Vector)
     # CLASTB (scalar)
     clastbCode = '''
-        if (last < 0) {
-            destElem = XDest;
-        } else {
-            destElem = AA64FpOp1_x[last];
-        }'''
+        destElem = AA64FpOp1_x[last];'''
     sveSelectInst('clastb', 'Clastb', 'SimdAluOp', unsignedTypes, clastbCode,
-            isCond = True)
+            isCond = True, destType = DestType.Scalar)
+    # CLASTB (vector)
+    sveSelectInst('clastb', 'Clastbv', 'SimdAluOp', unsignedTypes, clastbCode,
+            isCond = True, destType = DestType.Vector)
     # CLS
     clsCode = '''
         destElem = 0;
diff --git a/src/arch/arm/isa/templates/sve.isa b/src/arch/arm/isa/templates/sve.isa
index 6626b70..27fcf7e 100644
--- a/src/arch/arm/isa/templates/sve.isa
+++ b/src/arch/arm/isa/templates/sve.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 ARM Limited
+// Copyright (c) 2018 ARM Limited
 // All rights reserved
 //
 // The license below extends only to copyright in the software and shall
@@ -719,7 +719,7 @@
 };
 }};
 
-def template SveScalarSelectOpDeclare {{
+def template SveSelectOpDeclare {{
 template <class _Element>
 class %(class_name)s : public %(base_class)s
 {
@@ -730,7 +730,7 @@
     %(class_name)s(ExtMachInst machInst, IntRegIndex _dest,
             IntRegIndex _op1, IntRegIndex _gp)
         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest,
-                _op1, _gp, %(isCond)s)
+                _op1, _gp, %(isCond)s, %(isScalar)s)
     {
         %(constructor)s;
         scalar_width = (sizeof(Element) == 8) ? 64 : 32;