arch-arm: Add support for the SVE INSR (scalar) instruction

Change-Id: I0e2fb57cf6c0d452722c92bd60f291d9d33c758b
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 e8e6fa9..d16c47e 100644
--- a/src/arch/arm/insts/sve.cc
+++ b/src/arch/arm/insts/sve.cc
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -690,6 +690,18 @@
 }
 
 std::string
+SveUnarySca2VecUnpredOp::generateDisassembly(Addr pc,
+        const SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    printMnemonic(ss, "", false);
+    printVecReg(ss, dest, true);
+    ccprintf(ss, ", ");
+    printIntReg(ss, op1);
+    return ss.str();
+}
+
+std::string
 sveDisasmPredCountImm(uint8_t imm)
 {
     switch (imm) {
diff --git a/src/arch/arm/insts/sve.hh b/src/arch/arm/insts/sve.hh
index 2417211..3344e8c 100644
--- a/src/arch/arm/insts/sve.hh
+++ b/src/arch/arm/insts/sve.hh
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -729,6 +729,20 @@
     std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
 };
 
+/// Unary unpredicated scalar to vector instruction
+class SveUnarySca2VecUnpredOp : public ArmStaticInst {
+  protected:
+    IntRegIndex dest, op1;
+
+    SveUnarySca2VecUnpredOp(const char* mnem, ExtMachInst _machInst,
+            OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1) :
+        ArmStaticInst(mnem, _machInst, __opClass),
+        dest(_dest), op1(_op1)
+    {}
+
+    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
 /// Returns the symbolic name associated with pattern `imm` for PTRUE(S)
 /// instructions.
 std::string sveDisasmPredCountImm(uint8_t imm);
diff --git a/src/arch/arm/isa/formats/sve_2nd_level.isa b/src/arch/arm/isa/formats/sve_2nd_level.isa
index c994f5c..2276cd6 100644
--- a/src/arch/arm/isa/formats/sve_2nd_level.isa
+++ b/src/arch/arm/isa/formats/sve_2nd_level.isa
@@ -1003,8 +1003,10 @@
             IntRegIndex zd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
             return decodeSveUnaryUnpredU<SveDupScalar>(size, machInst, zd, rn);
         } else if (bits(machInst, 20, 16) == 0x4 && b12_10 == 0x6) {
-            // INSR (scalar)
-            return new Unknown64(machInst);
+            uint8_t size = bits(machInst, 23, 22);
+            IntRegIndex zdn = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+            IntRegIndex rm = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
+            return decodeSveUnaryUnpredU<SveInsr>(size, machInst, zdn, rm);
         } else if (bits(machInst, 20, 16) == 0x14 && b12_10 == 0x6) {
             // INSR (SIMD&FP scalar)
             return new Unknown64(machInst);
diff --git a/src/arch/arm/isa/insts/sve.isa b/src/arch/arm/isa/insts/sve.isa
index d71ab23..0182da3 100644
--- a/src/arch/arm/isa/insts/sve.isa
+++ b/src/arch/arm/isa/insts/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
@@ -2612,6 +2612,33 @@
             substDict = {'targs': type, 'class_name': 'Sve' + Name}
             exec_output += SveOpExecDeclare.subst(substDict)
 
+    # Generate definition for shift & insert instructions
+    def sveShiftAndInsertInst(name, Name, opClass, types,
+            srcType = SrcRegType.Scalar, decoder = 'Generic'):
+        assert srcType in (SrcRegType.Vector, SrcRegType.Scalar)
+        global header_output, exec_output, decoders
+        code = sveEnabledCheckCode + '''
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
+                xc->tcBase());'''
+        if srcType == SrcRegType.Scalar:
+            code += '''
+            auto& srcElem1 = XOp1;'''
+        else:
+            code += '''
+            auto& srcElem1 = AA64FpOp1;'''
+        code += '''
+        for (int i = eCount - 1; i > 0; --i) {
+            AA64FpDest_x[i] = AA64FpDestMerge_x[i-1];
+        }
+        AA64FpDest_x[0] = srcElem1;'''
+        iop = InstObjParams(name, 'Sve' + Name, 'SveUnarySca2VecUnpredOp',
+                {'code': code, 'op_class': opClass}, [])
+        header_output += SveUnaryUnpredOpDeclare.subst(iop)
+        exec_output += SveOpExecute.subst(iop)
+        for type in types:
+            substDict = {'targs': type, 'class_name': 'Sve' + Name}
+            exec_output += SveOpExecDeclare.subst(substDict)
+
     fpTypes = ('uint16_t', 'uint32_t', 'uint64_t')
     signedTypes = ('int8_t', 'int16_t', 'int32_t', 'int64_t')
     unsignedTypes = ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t')
@@ -3385,6 +3412,9 @@
     sveIndex(IndexFormat.RegImm)
     # INDEX (scalars)
     sveIndex(IndexFormat.RegReg)
+    # INSR (scalar)
+    sveShiftAndInsertInst('insr', 'Insr', 'SimdAluOp', unsignedTypes,
+            srcType = SrcRegType.Scalar)
     # LASTA (scalar)
     lastaCode = '''
         last++;