arch-arm: Add initial support for SVE contiguous loads/stores
authorGiacomo Gabrielli <giacomo.gabrielli@arm.com>
Wed, 8 Nov 2017 16:06:12 +0000 (16:06 +0000)
committerGiacomo Gabrielli <giacomo.gabrielli@arm.com>
Sat, 11 May 2019 12:49:15 +0000 (12:49 +0000)
Thanks to Pau Cabre and Adria Armejach Sanosa for their contribution
of bugfixes.

Change-Id: If8983cf85d95cddb187c90967a94ddfe2414bc46
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/13519
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>

src/arch/arm/SConscript
src/arch/arm/insts/sve_mem.cc [new file with mode: 0644]
src/arch/arm/insts/sve_mem.hh [new file with mode: 0644]
src/arch/arm/isa/formats/sve_2nd_level.isa
src/arch/arm/isa/includes.isa
src/arch/arm/isa/insts/insts.isa
src/arch/arm/isa/insts/sve_mem.isa [new file with mode: 0644]
src/arch/arm/isa/templates/sve.isa
src/arch/arm/isa/templates/sve_mem.isa [new file with mode: 0644]
src/arch/arm/isa/templates/templates.isa

index 58a13cd7212eadbbe445a9615c8af851ce6a9570..caea1c470550657b1a2f87d3127f73d961c61ab2 100644 (file)
@@ -61,6 +61,7 @@ if env['TARGET_ISA'] == 'arm':
     Source('insts/pseudo.cc')
     Source('insts/static_inst.cc')
     Source('insts/sve.cc')
+    Source('insts/sve_mem.cc')
     Source('insts/vfp.cc')
     Source('insts/fplib.cc')
     Source('insts/crypto.cc')
diff --git a/src/arch/arm/insts/sve_mem.cc b/src/arch/arm/insts/sve_mem.cc
new file mode 100644 (file)
index 0000000..0f24d89
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Giacomo Gabrielli
+ */
+
+#include "arch/arm/insts/sve_mem.hh"
+
+namespace ArmISA
+{
+
+std::string
+SveMemVecFillSpill::generateDisassembly(Addr pc,
+                                        const SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    printMnemonic(ss, "", false);
+    printVecReg(ss, dest, true);
+    ccprintf(ss, ", [");
+    printIntReg(ss, base);
+    if (imm != 0) {
+        ccprintf(ss, ", #%d, mul vl", imm);
+    }
+    ccprintf(ss, "]");
+    return ss.str();
+}
+
+std::string
+SveMemPredFillSpill::generateDisassembly(Addr pc,
+                                         const SymbolTable *symtab) const
+{
+    std::stringstream ss;
+    printMnemonic(ss, "", false);
+    printVecPredReg(ss, dest);
+    ccprintf(ss, ", [");
+    printIntReg(ss, base);
+    if (imm != 0) {
+        ccprintf(ss, ", #%d, mul vl", imm);
+    }
+    ccprintf(ss, "]");
+    return ss.str();
+}
+
+std::string
+SveContigMemSS::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+{
+    // TODO: add suffix to transfer register and scaling factor (LSL #<x>)
+    std::stringstream ss;
+    printMnemonic(ss, "", false);
+    ccprintf(ss, "{");
+    printVecReg(ss, dest, true);
+    ccprintf(ss, "}, ");
+    printVecPredReg(ss, gp);
+    ccprintf(ss, "/z, ");
+    ccprintf(ss, ", [");
+    printIntReg(ss, base);
+    ccprintf(ss, ", ");
+    printIntReg(ss, offset);
+    ccprintf(ss, "]");
+    return ss.str();
+}
+
+std::string
+SveContigMemSI::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+{
+    // TODO: add suffix to transfer register
+    std::stringstream ss;
+    printMnemonic(ss, "", false);
+    ccprintf(ss, "{");
+    printVecReg(ss, dest, true);
+    ccprintf(ss, "}, ");
+    printVecPredReg(ss, gp);
+    ccprintf(ss, "/z, ");
+    ccprintf(ss, ", [");
+    printIntReg(ss, base);
+    if (imm != 0) {
+        ccprintf(ss, ", #%d, mul vl", imm);
+    }
+    ccprintf(ss, "]");
+    return ss.str();
+}
+
+}  // namespace ArmISA
diff --git a/src/arch/arm/insts/sve_mem.hh b/src/arch/arm/insts/sve_mem.hh
new file mode 100644 (file)
index 0000000..de6b69c
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2017 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Giacomo Gabrielli
+ */
+
+#ifndef __ARCH_ARM_SVE_MEM_HH__
+#define __ARCH_ARM_SVE_MEM_HH__
+
+#include "arch/arm/insts/static_inst.hh"
+#include "arch/arm/tlb.hh"
+
+namespace ArmISA
+{
+
+class SveMemVecFillSpill : public ArmStaticInst
+{
+  protected:
+    IntRegIndex dest;
+    IntRegIndex base;
+    uint64_t imm;
+
+    /// True if the base register is SP (used for SP alignment checking).
+    bool baseIsSP;
+
+    unsigned memAccessFlags;
+
+    SveMemVecFillSpill(const char *mnem, ExtMachInst _machInst,
+                       OpClass __opClass, IntRegIndex _dest,
+                       IntRegIndex _base, uint64_t _imm)
+        : ArmStaticInst(mnem, _machInst, __opClass),
+          dest(_dest), base(_base), imm(_imm),
+          memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
+    {
+        baseIsSP = isSP(_base);
+    }
+
+    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
+class SveMemPredFillSpill : public ArmStaticInst
+{
+  protected:
+    IntRegIndex dest;
+    IntRegIndex base;
+    uint64_t imm;
+
+    /// True if the base register is SP (used for SP alignment checking).
+    bool baseIsSP;
+
+    unsigned memAccessFlags;
+
+    SveMemPredFillSpill(const char *mnem, ExtMachInst _machInst,
+                        OpClass __opClass, IntRegIndex _dest,
+                        IntRegIndex _base, uint64_t _imm)
+        : ArmStaticInst(mnem, _machInst, __opClass),
+          dest(_dest), base(_base), imm(_imm),
+          memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
+    {
+        baseIsSP = isSP(_base);
+    }
+
+    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
+class SveContigMemSS : public ArmStaticInst
+{
+  protected:
+    IntRegIndex dest;
+    IntRegIndex gp;
+    IntRegIndex base;
+    IntRegIndex offset;
+
+    /// True if the base register is SP (used for SP alignment checking).
+    bool baseIsSP;
+
+    unsigned memAccessFlags;
+
+    SveContigMemSS(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+                   IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
+                   IntRegIndex _offset)
+        : ArmStaticInst(mnem, _machInst, __opClass),
+          dest(_dest), gp(_gp), base(_base), offset(_offset),
+          memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
+    {
+        baseIsSP = isSP(_base);
+    }
+
+    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
+class SveContigMemSI : public ArmStaticInst
+{
+  protected:
+    IntRegIndex dest;
+    IntRegIndex gp;
+    IntRegIndex base;
+    uint64_t imm;
+
+    /// True if the base register is SP (used for SP alignment checking).
+    bool baseIsSP;
+
+    unsigned memAccessFlags;
+
+    SveContigMemSI(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+                   IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
+                   uint64_t _imm)
+        : ArmStaticInst(mnem, _machInst, __opClass),
+          dest(_dest), gp(_gp), base(_base), imm(_imm),
+          memAccessFlags(ArmISA::TLB::AllowUnaligned | ArmISA::TLB::MustBeOne)
+    {
+        baseIsSP = isSP(_base);
+    }
+
+    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
+}  // namespace ArmISA
+
+#endif  // __ARCH_ARM_SVE_MEM_HH__
index ff7e50ee5d98534356b5c98f715f4eb98be0e46e..e81ab3ed7b60af295732f5a3bd1e7a050013f448 100644 (file)
@@ -2896,12 +2896,152 @@ namespace Aarch64
     StaticInstPtr
     decodeSveMemGather32(ExtMachInst machInst)
     {
+        // TODO: for now only LDR and LD1R are implemented
+        if (bits(machInst, 22) && bits(machInst, 15)) {
+            IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+            IntRegIndex rn = makeSP(
+                (IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+            uint64_t imm = bits(machInst, 21, 16);
+            IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
+            uint8_t dtype = (bits(machInst, 24, 23) << 2) |
+                            bits(machInst, 14, 13);
+            return decodeSveContigLoadSIInsts<SveLoadAndRepl>(
+                    dtype, machInst, zt, pg, rn, imm, false, true);
+        } else if (bits(machInst, 24, 22) == 0x6 &&
+                   bits(machInst, 15, 13) == 0x0 &&
+                   bits(machInst, 4) == 0x0) {
+            IntRegIndex pt = (IntRegIndex) (uint8_t) bits(machInst, 3, 0);
+            IntRegIndex rn = makeSP(
+                (IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+            uint64_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
+                                   bits(machInst, 12, 10));
+            return new SveLdrPred(machInst, pt, rn, imm);
+        } else if (bits(machInst, 24, 22) == 0x6 &&
+                   bits(machInst, 15, 13) == 0x2) {
+            IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+            IntRegIndex rn = makeSP(
+                (IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+            uint64_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
+                                   bits(machInst, 12, 10));
+            return new SveLdrVec(machInst, zt, rn, imm);
+        }
         return new Unknown64(machInst);
     }  // decodeSveMemGather32
 
+    StaticInstPtr
+    decodeSveLoadBcastQuadSS(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveLoadBcastQuadSS
+
+    StaticInstPtr
+    decodeSveLoadBcastQuadSI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveLoadBcastQuadSI
+
+    StaticInstPtr
+    decodeSveContigLoadSS(ExtMachInst machInst)
+    {
+        IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+        IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+        IntRegIndex rm = makeSP(
+            (IntRegIndex) (uint8_t) bits(machInst, 20, 16));
+        IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
+
+        if (rm == 0x1f) {
+            return new Unknown64(machInst);
+        }
+
+        return decodeSveContigLoadSSInsts<SveContigLoadSS>(
+            bits(machInst, 24, 21), machInst, zt, pg, rn, rm, false);
+    }  // decodeSveContigLoadSS
+
+    StaticInstPtr
+    decodeSveContigFFLoadSS(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveContigFFLoadSS
+
+    StaticInstPtr
+    decodeSveContigLoadSI(ExtMachInst machInst)
+    {
+        IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+        IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+        uint64_t imm = sext<4>(bits(machInst, 19, 16));
+        IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
+
+        return decodeSveContigLoadSIInsts<SveContigLoadSI>(
+            bits(machInst, 24, 21), machInst, zt, pg, rn, imm, false);
+    }  // decodeSveContigLoadSI
+
+    StaticInstPtr
+    decodeSveContigNFLoadSI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveContigNFLoadSI
+
+    StaticInstPtr
+    decodeSveContigNTLoadSS(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveContigNTLoadSS
+
+    StaticInstPtr
+    decodeSveLoadStructsSS(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveLoadStructsSS
+
+    StaticInstPtr
+    decodeSveContigNTLoadSI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveContigNTLoadSI
+
+    StaticInstPtr
+    decodeSveLoadStructsSI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveLoadStructsSI
+
     StaticInstPtr
     decodeSveMemContigLoad(ExtMachInst machInst)
     {
+        switch (bits(machInst, 15, 13)) {
+          case 0x0:
+            return decodeSveLoadBcastQuadSS(machInst);
+          case 0x1:
+            if (bits(machInst, 20) == 0x0) {
+                return decodeSveLoadBcastQuadSI(machInst);
+            }
+            break;
+          case 0x2:
+            return decodeSveContigLoadSS(machInst);
+          case 0x3:
+            return decodeSveContigFFLoadSS(machInst);
+          case 0x5:
+            if (bits(machInst, 20) == 0x0) {
+                return decodeSveContigLoadSI(machInst);
+            } else {
+                return decodeSveContigNFLoadSI(machInst);
+            }
+          case 0x6:
+            if (bits(machInst, 22, 21) == 0x0) {
+                return decodeSveContigNTLoadSS(machInst);
+            } else {
+                return decodeSveLoadStructsSS(machInst);
+            }
+          case 0x7:
+            if (bits(machInst, 20) == 0) {
+                if (bits(machInst, 22, 21) == 0x0) {
+                    return decodeSveContigNTLoadSI(machInst);
+                } else {
+                return decodeSveLoadStructsSI(machInst);
+                }
+            }
+            break;
+        }
         return new Unknown64(machInst);
     }  // decodeSveMemContigLoad
 
@@ -2911,9 +3051,185 @@ namespace Aarch64
         return new Unknown64(machInst);
     }  // decodeSveMemGather64
 
+    StaticInstPtr
+    decodeSveContigStoreSS(ExtMachInst machInst)
+    {
+        IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+        IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+        IntRegIndex rm = makeSP(
+            (IntRegIndex) (uint8_t) bits(machInst, 20, 16));
+        IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
+
+        if (rm == 0x1f) {
+            return new Unknown64(machInst);
+        }
+
+        return decodeSveContigStoreSSInsts<SveContigStoreSS>(
+            bits(machInst, 24, 21), machInst, zt, pg, rn, rm);
+    }  // decodeSveContigStoreSS
+
+    StaticInstPtr
+    decodeSveContigStoreSI(ExtMachInst machInst)
+    {
+        IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+        IntRegIndex rn = makeSP((IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+        int8_t imm = sext<4>(bits(machInst, 19, 16));
+        IntRegIndex pg = (IntRegIndex) (uint8_t) bits(machInst, 12, 10);
+
+        return decodeSveContigStoreSIInsts<SveContigStoreSI>(
+            bits(machInst, 24, 21), machInst, zt, pg, rn, imm);
+    }  // decodeSveContigStoreSI
+
+    StaticInstPtr
+    decodeSveContigNTStoreSS(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveContigNTStoreSS
+
+    StaticInstPtr
+    decodeSveScatterStore64SV32U(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore64SV32U
+
+    StaticInstPtr
+    decodeSveScatterStore64SV64U(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore64SV64U
+
+    StaticInstPtr
+    decodeSveContigNTStoreSI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveContigNTStoreSI
+
+    StaticInstPtr
+    decodeSveScatterStore64VI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore64VI
+
+    StaticInstPtr
+    decodeSveScatterStore32SV32S(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore32SV32S
+
+    StaticInstPtr
+    decodeSveStoreStructsSS(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveStoreStructsSS
+
+    StaticInstPtr
+    decodeSveStoreStructsSI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveStoreStructsSI
+
+    StaticInstPtr
+    decodeSveScatterStore32SV32U(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore32SV32U
+
+    StaticInstPtr
+    decodeSveScatterStore32VI(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore32VI
+
+    StaticInstPtr
+    decodeSveScatterStore64SV32S(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore64SV32S
+
+    StaticInstPtr
+    decodeSveScatterStore64SV64S(ExtMachInst machInst)
+    {
+        return new Unknown64(machInst);
+    }  // decodeSveScatterStore64SV64S
+
     StaticInstPtr
     decodeSveMemStore(ExtMachInst machInst)
     {
+        switch (bits(machInst, 15, 13)) {
+          case 0x0:
+            if (bits(machInst, 24, 22) == 0x6 && bits(machInst, 4) == 0x0) {
+                IntRegIndex pt = (IntRegIndex) (uint8_t) bits(machInst, 3, 0);
+                IntRegIndex rn = makeSP(
+                    (IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+                int16_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
+                                      bits(machInst, 12, 10));
+                return new SveStrPred(machInst, pt, rn, imm);
+            }
+            break;
+          case 0x2:
+            if (bits(machInst, 24, 22) == 0x6) {
+                IntRegIndex zt = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
+                IntRegIndex rn = makeSP(
+                    (IntRegIndex) (uint8_t) bits(machInst, 9, 5));
+                int16_t imm = sext<9>((bits(machInst, 21, 16) << 3) |
+                                      bits(machInst, 12, 10));
+                return new SveStrVec(machInst, zt, rn, imm);
+            } else {
+                return decodeSveContigStoreSS(machInst);
+            }
+            break;
+          case 0x3:
+            if (bits(machInst, 22, 21) == 0x0) {
+                return decodeSveContigNTStoreSS(machInst);
+            } else {
+                return decodeSveStoreStructsSS(machInst);
+            }
+          case 0x4:
+          case 0x6:
+            switch (bits(machInst, 22, 21)) {
+              case 0x0:
+                return decodeSveScatterStore64SV32U(machInst);
+              case 0x1:
+                if (bits(machInst, 24, 23) != 0x0) {
+                    return decodeSveScatterStore64SV32S(machInst);
+                }
+                break;
+              case 0x2:
+                if (bits(machInst, 24, 23) != 0x3) {
+                    return decodeSveScatterStore32SV32U(machInst);
+                }
+                break;
+              case 0x3:
+                return decodeSveScatterStore32SV32S(machInst);
+            }
+            break;
+          case 0x5:
+            switch (bits(machInst, 22, 21)) {
+              case 0x0:
+                return decodeSveScatterStore64SV64U(machInst);
+              case 0x1:
+                if (bits(machInst, 24, 23) != 0x0) {
+                    return decodeSveScatterStore64SV64S(machInst);
+                }
+                break;
+              case 0x2:
+                return decodeSveScatterStore64VI(machInst);
+              case 0x3:
+                if (bits(machInst, 24, 23) != 0x3) {
+                    return decodeSveScatterStore64VI(machInst);
+                }
+                break;
+            }
+            break;
+          case 0x7:
+            if (bits(machInst, 20) == 0x0) {
+                return decodeSveContigStoreSI(machInst);
+            } else if (bits(machInst, 22, 21) == 0x0) {
+                return decodeSveContigNTStoreSI(machInst);
+            } else {
+                return decodeSveStoreStructsSI(machInst);
+            }
+        }
         return new Unknown64(machInst);
     }  // decodeSveMemStore
 
index b89a6743209ba3ead047b7b83120d1c557e40533..9aef8c651b7e285b902ab2da4bfbb1006098fe7d 100644 (file)
@@ -65,6 +65,7 @@ output header {{
 #include "arch/arm/insts/pseudo.hh"
 #include "arch/arm/insts/static_inst.hh"
 #include "arch/arm/insts/sve.hh"
+#include "arch/arm/insts/sve_mem.hh"
 #include "arch/arm/insts/vfp.hh"
 #include "arch/arm/isa_traits.hh"
 #include "mem/packet.hh"
index 623657efc210c3ed7ade899a0a9b8d129523f245..a1b35efc4415791119bcaa53bdcdb5fcec28eb0d 100644 (file)
@@ -99,6 +99,7 @@ split decoder;
 
 //SVE
 ##include "sve.isa"
+##include "sve_mem.isa"
 
 //m5 Pseudo-ops
 ##include "m5ops.isa"
diff --git a/src/arch/arm/isa/insts/sve_mem.isa b/src/arch/arm/isa/insts/sve_mem.isa
new file mode 100644 (file)
index 0000000..f4ca4c3
--- /dev/null
@@ -0,0 +1,453 @@
+// Copyright (c) 2017 ARM Limited
+// All rights reserved
+//
+// The license below extends only to copyright in the software and shall
+// not be construed as granting a license to any other intellectual
+// property including but not limited to intellectual property relating
+// to a hardware implementation of the functionality of the software
+// licensed hereunder.  You may use the software subject to the license
+// terms below provided that you ensure that this notice is replicated
+// unmodified and in its entirety in all distributions of the software,
+// modified or unmodified, in source code or in binary form.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Giacomo Gabrielli
+
+// @file Definition of SVE memory access instructions.
+
+output header {{
+
+    // Decodes SVE contiguous load instructions, scalar plus scalar form.
+    template <template <typename T1, typename T2> class Base>
+    StaticInstPtr
+    decodeSveContigLoadSSInsts(uint8_t dtype, ExtMachInst machInst,
+                               IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
+                               IntRegIndex rm, bool firstFaulting)
+    {
+        const char* mn = firstFaulting ? "ldff1" : "ld1";
+        switch (dtype) {
+          case 0x0:
+            return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x1:
+            return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x2:
+            return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x3:
+            return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x4:
+            return new Base<int64_t, int32_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x5:
+            return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x6:
+            return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x7:
+            return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x8:
+            return new Base<int64_t, int16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x9:
+            return new Base<int32_t, int16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xa:
+            return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xb:
+            return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xc:
+            return new Base<int64_t, int8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xd:
+            return new Base<int32_t, int8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xe:
+            return new Base<int16_t, int8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xf:
+            return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, rm);
+        }
+        return new Unknown64(machInst);
+    }
+
+    // Decodes SVE contiguous load instructions, scalar plus immediate form.
+    template <template <typename T1, typename T2> class Base>
+    StaticInstPtr
+    decodeSveContigLoadSIInsts(uint8_t dtype, ExtMachInst machInst,
+                               IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
+                               uint64_t imm, bool firstFaulting,
+                               bool replicate = false)
+    {
+        assert(!(replicate && firstFaulting));
+
+        const char* mn = replicate ? "ld1r" :
+                                     (firstFaulting ? "ldff1" : "ld1");
+        switch (dtype) {
+          case 0x0:
+            return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x1:
+            return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x2:
+            return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x3:
+            return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x4:
+            return new Base<int64_t, int32_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x5:
+            return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x6:
+            return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x7:
+            return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x8:
+            return new Base<int64_t, int16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x9:
+            return new Base<int32_t, int16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xa:
+            return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xb:
+            return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xc:
+            return new Base<int64_t, int8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xd:
+            return new Base<int32_t, int8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xe:
+            return new Base<int16_t, int8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xf:
+            return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, imm);
+        }
+        return new Unknown64(machInst);
+    }
+
+    // Decodes SVE contiguous store instructions, scalar plus scalar form.
+    template <template <typename T1, typename T2> class Base>
+    StaticInstPtr
+    decodeSveContigStoreSSInsts(uint8_t dtype, ExtMachInst machInst,
+                                IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
+                                IntRegIndex rm)
+    {
+        const char* mn = "st1";
+        switch (dtype) {
+          case 0x0:
+            return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x1:
+            return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x2:
+            return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x3:
+            return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x5:
+            return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x6:
+            return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0x7:
+            return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xa:
+            return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xb:
+            return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, rm);
+          case 0xf:
+            return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, rm);
+        }
+        return new Unknown64(machInst);
+    }
+
+    // Decodes SVE contiguous store instructions, scalar plus immediate form.
+    template <template <typename T1, typename T2> class Base>
+    StaticInstPtr
+    decodeSveContigStoreSIInsts(uint8_t dtype, ExtMachInst machInst,
+                                IntRegIndex zt, IntRegIndex pg, IntRegIndex rn,
+                                int8_t imm)
+    {
+        const char* mn = "st1";
+        switch (dtype) {
+          case 0x0:
+            return new Base<uint8_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x1:
+            return new Base<uint16_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x2:
+            return new Base<uint32_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x3:
+            return new Base<uint64_t, uint8_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x5:
+            return new Base<uint16_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x6:
+            return new Base<uint32_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0x7:
+            return new Base<uint64_t, uint16_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xa:
+            return new Base<uint32_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xb:
+            return new Base<uint64_t, uint32_t>(mn, machInst, zt, pg, rn, imm);
+          case 0xf:
+            return new Base<uint64_t, uint64_t>(mn, machInst, zt, pg, rn, imm);
+        }
+        return new Unknown64(machInst);
+    }
+
+    // NOTE: SVE load-and-replicate instructions are decoded with
+    // decodeSveContigLoadSIInsts(...).
+
+}};
+
+let {{
+
+    header_output = ''
+    exec_output = ''
+    decoders = { 'Generic': {} }
+
+    SPAlignmentCheckCode = '''
+        if (this->baseIsSP && bits(XBase, 3, 0) &&
+            SPAlignmentCheckEnabled(xc->tcBase())) {
+            return std::make_shared<SPAlignmentFault>();
+        }
+    '''
+
+    def emitSveMemFillSpill(isPred):
+        global header_output, exec_output, decoders
+        eaCode = SPAlignmentCheckCode + '''
+        int memAccessSize = %(memacc_size)s;
+        EA = XBase + ((int64_t) imm * %(memacc_size)s)''' % {
+            'memacc_size': 'eCount / 8' if isPred else 'eCount'}
+        if isPred:
+            loadMemAccCode = '''
+            int index = 0;
+            uint8_t byte;
+            for (int i = 0; i < eCount / 8; i++) {
+                byte = memDataView[i];
+                for (int j = 0; j < 8; j++, index++) {
+                    PDest_x[index] = (byte >> j) & 1;
+                }
+            }
+            '''
+            storeMemAccCode = '''
+            int index = 0;
+            uint8_t byte;
+            for (int i = 0; i < eCount / 8; i++) {
+                byte = 0;
+                for (int j = 0; j < 8; j++, index++) {
+                    byte |= PDest_x[index] << j;
+                }
+                memDataView[i] = byte;
+            }
+            '''
+            storeWrEnableCode = '''
+            auto wrEn = std::vector<bool>(eCount / 8, true);
+            '''
+        else:
+            loadMemAccCode = '''
+            for (int i = 0; i < eCount; i++) {
+                AA64FpDest_x[i] = memDataView[i];
+            }
+            '''
+            storeMemAccCode = '''
+            for (int i = 0; i < eCount; i++) {
+                memDataView[i] = AA64FpDest_x[i];
+            }
+            '''
+            storeWrEnableCode = '''
+            auto wrEn = std::vector<bool>(sizeof(MemElemType) * eCount, true);
+            '''
+        loadIop = InstObjParams('ldr',
+            'SveLdrPred' if isPred else 'SveLdrVec',
+            'SveMemPredFillSpill' if isPred else 'SveMemVecFillSpill',
+            {'tpl_header': '',
+             'tpl_args': '',
+             'memacc_code': loadMemAccCode,
+             'ea_code' : sveEnabledCheckCode + eaCode,
+             'fa_code' : ''},
+            ['IsMemRef', 'IsLoad'])
+        storeIop = InstObjParams('str',
+            'SveStrPred' if isPred else 'SveStrVec',
+            'SveMemPredFillSpill' if isPred else 'SveMemVecFillSpill',
+            {'tpl_header': '',
+             'tpl_args': '',
+             'wren_code': storeWrEnableCode,
+             'memacc_code': storeMemAccCode,
+             'ea_code' : sveEnabledCheckCode + eaCode,
+             'fa_code' : ''},
+            ['IsMemRef', 'IsStore'])
+        header_output += SveMemFillSpillOpDeclare.subst(loadIop)
+        header_output += SveMemFillSpillOpDeclare.subst(storeIop)
+        exec_output += (
+            SveContigLoadExecute.subst(loadIop) +
+            SveContigLoadInitiateAcc.subst(loadIop) +
+            SveContigLoadCompleteAcc.subst(loadIop) +
+            SveContigStoreExecute.subst(storeIop) +
+            SveContigStoreInitiateAcc.subst(storeIop) +
+            SveContigStoreCompleteAcc.subst(storeIop))
+
+    loadTplArgs = (
+        ('uint8_t', 'uint8_t'),
+        ('uint16_t', 'uint8_t'),
+        ('uint32_t', 'uint8_t'),
+        ('uint64_t', 'uint8_t'),
+        ('int64_t', 'int32_t'),
+        ('uint16_t', 'uint16_t'),
+        ('uint32_t', 'uint16_t'),
+        ('uint64_t', 'uint16_t'),
+        ('int64_t', 'int16_t'),
+        ('int32_t', 'int16_t'),
+        ('uint32_t', 'uint32_t'),
+        ('uint64_t', 'uint32_t'),
+        ('int64_t', 'int8_t'),
+        ('int32_t', 'int8_t'),
+        ('int16_t', 'int8_t'),
+        ('uint64_t', 'uint64_t'),
+    )
+
+    storeTplArgs = (
+        ('uint8_t', 'uint8_t'),
+        ('uint16_t', 'uint8_t'),
+        ('uint32_t', 'uint8_t'),
+        ('uint64_t', 'uint8_t'),
+        ('uint16_t', 'uint16_t'),
+        ('uint32_t', 'uint16_t'),
+        ('uint64_t', 'uint16_t'),
+        ('uint32_t', 'uint32_t'),
+        ('uint64_t', 'uint32_t'),
+        ('uint64_t', 'uint64_t'),
+    )
+
+    # Generates definitions for SVE contiguous loads
+    def emitSveContigMemInsts(offsetIsImm):
+        global header_output, exec_output, decoders
+        tplHeader = 'template <class RegElemType, class MemElemType>'
+        tplArgs = '<RegElemType, MemElemType>'
+        eaCode = SPAlignmentCheckCode + '''
+        int memAccessSize = eCount * sizeof(MemElemType);
+        EA = XBase + '''
+        if offsetIsImm:
+            eaCode += '((int64_t) this->imm * eCount * sizeof(MemElemType))'
+        else:
+            eaCode += '(XOffset * sizeof(MemElemType));'
+        loadMemAccCode = '''
+        for (int i = 0; i < eCount; i++) {
+            if (GpOp_x[i]) {
+                AA64FpDest_x[i] = memDataView[i];
+            } else {
+                AA64FpDest_x[i] = 0;
+            }
+        }
+        '''
+        storeMemAccCode = '''
+        for (int i = 0; i < eCount; i++) {
+            if (GpOp_x[i]) {
+                memDataView[i] = AA64FpDest_x[i];
+            } else {
+                memDataView[i] = 0;
+                for (int j = 0; j < sizeof(MemElemType); j++) {
+                    wrEn[sizeof(MemElemType) * i + j] = false;
+                }
+            }
+        }
+        '''
+        storeWrEnableCode = '''
+        auto wrEn = std::vector<bool>(sizeof(MemElemType) * eCount, true);
+        '''
+        loadIop = InstObjParams('ld1',
+            'SveContigLoadSI' if offsetIsImm else 'SveContigLoadSS',
+            'SveContigMemSI' if offsetIsImm else 'SveContigMemSS',
+            {'tpl_header': tplHeader,
+             'tpl_args': tplArgs,
+             'memacc_code': loadMemAccCode,
+             'ea_code' : sveEnabledCheckCode + eaCode,
+             'fa_code' : ''},
+            ['IsMemRef', 'IsLoad'])
+        storeIop = InstObjParams('st1',
+            'SveContigStoreSI' if offsetIsImm else 'SveContigStoreSS',
+            'SveContigMemSI' if offsetIsImm else 'SveContigMemSS',
+            {'tpl_header': tplHeader,
+             'tpl_args': tplArgs,
+             'wren_code': storeWrEnableCode,
+             'memacc_code': storeMemAccCode,
+             'ea_code' : sveEnabledCheckCode + eaCode,
+             'fa_code' : ''},
+            ['IsMemRef', 'IsStore'])
+        if offsetIsImm:
+            header_output += SveContigMemSIOpDeclare.subst(loadIop)
+            header_output += SveContigMemSIOpDeclare.subst(storeIop)
+        else:
+            header_output += SveContigMemSSOpDeclare.subst(loadIop)
+            header_output += SveContigMemSSOpDeclare.subst(storeIop)
+        exec_output += (
+            SveContigLoadExecute.subst(loadIop) +
+            SveContigLoadInitiateAcc.subst(loadIop) +
+            SveContigLoadCompleteAcc.subst(loadIop) +
+            SveContigStoreExecute.subst(storeIop) +
+            SveContigStoreInitiateAcc.subst(storeIop) +
+            SveContigStoreCompleteAcc.subst(storeIop))
+        for args in loadTplArgs:
+            substDict = {'tpl_args': '<%s>' % ', '.join(args),
+                         'class_name': 'SveContigLoadSI' if offsetIsImm
+                                       else 'SveContigLoadSS'}
+            exec_output += SveContigMemExecDeclare.subst(substDict)
+        for args in storeTplArgs:
+            substDict = {'tpl_args': '<%s>' % ', '.join(args),
+                         'class_name': 'SveContigStoreSI' if offsetIsImm
+                                       else 'SveContigStoreSS'}
+            exec_output += SveContigMemExecDeclare.subst(substDict)
+
+    # Generates definitions for SVE load-and-replicate instructions
+    def emitSveLoadAndRepl():
+        global header_output, exec_output, decoders
+        tplHeader = 'template <class RegElemType, class MemElemType>'
+        tplArgs = '<RegElemType, MemElemType>'
+        eaCode = SPAlignmentCheckCode + '''
+        EA = XBase + imm * sizeof(MemElemType);'''
+        memAccCode = '''
+        for (int i = 0; i < eCount; i++) {
+            if (GpOp_x[i]) {
+                AA64FpDest_x[i] = memData;
+            } else {
+                AA64FpDest_x[i] = 0;
+            }
+        }
+        '''
+        iop = InstObjParams('ld1r',
+            'SveLoadAndRepl',
+            'SveContigMemSI',
+            {'tpl_header': tplHeader,
+             'tpl_args': tplArgs,
+             'memacc_code': memAccCode,
+             'ea_code' : sveEnabledCheckCode + eaCode,
+             'fa_code' : ''},
+            ['IsMemRef', 'IsLoad'])
+        header_output += SveContigMemSIOpDeclare.subst(iop)
+        exec_output += (
+            SveLoadAndReplExecute.subst(iop) +
+            SveLoadAndReplInitiateAcc.subst(iop) +
+            SveLoadAndReplCompleteAcc.subst(iop))
+        for args in loadTplArgs:
+            substDict = {'tpl_args': '<%s>' % ', '.join(args),
+                         'class_name': 'SveLoadAndRepl'}
+            exec_output += SveContigMemExecDeclare.subst(substDict)
+
+    # LD1[S]{B,H,W,D} (scalar plus immediate)
+    emitSveContigMemInsts(True)
+    # LD1[S]{B,H,W,D} (scalar plus scalar)
+    emitSveContigMemInsts(False)
+
+    # LD1R[S]{B,H,W,D}
+    emitSveLoadAndRepl()
+
+    # LDR (predicate), STR (predicate)
+    emitSveMemFillSpill(True)
+    # LDR (vector), STR (vector)
+    emitSveMemFillSpill(False)
+
+}};
index d7682c4472d743aee2576a60de214260112cc8da..6520a0c7107e701bf0537484df0fe4351205312e 100644 (file)
@@ -38,7 +38,7 @@
 let {{
     sveEnabledCheckCode = '''
         if (FullSystem) {
-            fault = checkSveEnabled(xc->tcBase(), Cpsr, Cpacr64);
+            fault = this->checkSveEnabled(xc->tcBase(), Cpsr, Cpacr64);
             if (fault != NoFault) {
                 return fault;
             }
diff --git a/src/arch/arm/isa/templates/sve_mem.isa b/src/arch/arm/isa/templates/sve_mem.isa
new file mode 100644 (file)
index 0000000..8471e44
--- /dev/null
@@ -0,0 +1,386 @@
+// Copyright (c) 2017 ARM Limited
+// All rights reserved
+//
+// The license below extends only to copyright in the software and shall
+// not be construed as granting a license to any other intellectual
+// property including but not limited to intellectual property relating
+// to a hardware implementation of the functionality of the software
+// licensed hereunder.  You may use the software subject to the license
+// terms below provided that you ensure that this notice is replicated
+// unmodified and in its entirety in all distributions of the software,
+// modified or unmodified, in source code or in binary form.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Giacomo Gabrielli
+
+def template SveMemFillSpillOpDeclare {{
+    class %(class_name)s : public %(base_class)s
+    {
+      protected:
+        typedef uint8_t TPElem;
+        typedef uint8_t RegElemType;
+        typedef uint8_t MemElemType;
+
+      public:
+        %(class_name)s(ExtMachInst machInst,
+            IntRegIndex _dest, IntRegIndex _base, uint64_t _imm)
+            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+                _dest, _base, _imm)
+        {
+            %(constructor)s;
+        }
+
+        Fault execute(ExecContext *, Trace::InstRecord *) const;
+        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
+        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
+
+        virtual void
+        annotateFault(ArmFault *fault) {
+            %(fa_code)s
+        }
+    };
+}};
+
+def template SveContigMemSSOpDeclare {{
+    %(tpl_header)s
+    class %(class_name)s : public %(base_class)s
+    {
+      protected:
+        typedef RegElemType TPElem;
+
+      public:
+        %(class_name)s(const char* mnem, ExtMachInst machInst,
+            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
+            IntRegIndex _offset)
+            : %(base_class)s(mnem, machInst, %(op_class)s,
+                _dest, _gp, _base, _offset)
+        {
+            %(constructor)s;
+        }
+
+        Fault execute(ExecContext *, Trace::InstRecord *) const;
+        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
+        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
+
+        virtual void
+        annotateFault(ArmFault *fault) {
+            %(fa_code)s
+        }
+    };
+}};
+
+def template SveContigMemSIOpDeclare {{
+    %(tpl_header)s
+    class %(class_name)s : public %(base_class)s
+    {
+      protected:
+        typedef RegElemType TPElem;
+
+      public:
+        %(class_name)s(const char* mnem, ExtMachInst machInst,
+            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
+            uint64_t _imm)
+            : %(base_class)s(mnem, machInst, %(op_class)s,
+                _dest, _gp, _base, _imm)
+        {
+            %(constructor)s;
+        }
+
+        Fault execute(ExecContext *, Trace::InstRecord *) const;
+        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
+        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
+
+        virtual void
+        annotateFault(ArmFault *fault) {
+            %(fa_code)s
+        }
+    };
+}};
+
+def template SveContigMemExecDeclare {{
+    template
+    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *,
+        Trace::InstRecord *) const;
+
+    template
+    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *,
+        Trace::InstRecord *) const;
+
+    template
+    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr,
+        ExecContext *, Trace::InstRecord *) const;
+}};
+
+def template SveContigLoadExecute {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
+        Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
+            xc->tcBase());
+
+        %(op_decl)s;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        TheISA::VecRegContainer memData;
+        auto memDataView = memData.as<MemElemType>();
+
+        if (fault == NoFault) {
+            fault = xc->readMem(EA, memData.raw_ptr<uint8_t>(), memAccessSize,
+                this->memAccessFlags);
+            %(memacc_code)s;
+        }
+
+        if (fault == NoFault) {
+            %(op_wb)s;
+        }
+
+        return fault;
+    }
+}};
+
+def template SveContigLoadInitiateAcc {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
+        Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
+            xc->tcBase());
+
+        %(op_src_decl)s;
+        %(op_rd)s;
+
+        %(ea_code)s;
+
+        if (fault == NoFault) {
+            fault = xc->initiateMemRead(EA, memAccessSize,
+                this->memAccessFlags);
+        }
+
+        return fault;
+    }
+}};
+
+def template SveContigLoadCompleteAcc {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
+        ExecContext *xc, Trace::InstRecord *traceData) const
+    {
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
+            xc->tcBase());
+
+        %(op_decl)s;
+        %(op_rd)s;
+
+        TheISA::VecRegContainer memData;
+        auto memDataView = memData.as<MemElemType>();
+
+        memcpy(memData.raw_ptr<uint8_t>(), pkt->getPtr<uint8_t>(),
+            pkt->getSize());
+
+        if (fault == NoFault) {
+            %(memacc_code)s;
+        }
+
+        if (fault == NoFault) {
+            %(op_wb)s;
+        }
+
+        return fault;
+    }
+}};
+
+def template SveContigStoreExecute {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
+        Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
+            xc->tcBase());
+
+        %(op_decl)s;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        TheISA::VecRegContainer memData;
+        auto memDataView = memData.as<MemElemType>();
+
+        %(wren_code)s;
+
+        if (fault == NoFault) {
+            %(memacc_code)s;
+        }
+
+        if (fault == NoFault) {
+            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
+                this->memAccessFlags, NULL, wrEn);
+        }
+
+        if (fault == NoFault) {
+            %(op_wb)s;
+        }
+
+        return fault;
+    }
+}};
+
+def template SveContigStoreInitiateAcc {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
+        Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
+            xc->tcBase());
+
+        %(op_decl)s;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        TheISA::VecRegContainer memData;
+        auto memDataView = memData.as<MemElemType>();
+
+        %(wren_code)s;
+
+        if (fault == NoFault) {
+            %(memacc_code)s;
+        }
+
+        if (fault == NoFault) {
+            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
+                this->memAccessFlags, NULL, wrEn);
+        }
+
+        return fault;
+    }
+}};
+
+def template SveContigStoreCompleteAcc {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
+        ExecContext *xc, Trace::InstRecord *traceData) const
+    {
+        return NoFault;
+    }
+}};
+
+def template SveLoadAndReplExecute {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
+        Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
+            xc->tcBase());
+
+        %(op_decl)s;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        MemElemType memData;
+
+        if (fault == NoFault) {
+            fault = readMemAtomic(xc, traceData, EA, memData,
+                this->memAccessFlags);
+            %(memacc_code)s;
+        }
+
+        if (fault == NoFault) {
+            %(op_wb)s;
+        }
+
+        return fault;
+    }
+}};
+
+def template SveLoadAndReplInitiateAcc {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
+        Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+
+        %(op_src_decl)s;
+        %(op_rd)s;
+
+        %(ea_code)s;
+
+        MemElemType memData;
+
+        if (fault == NoFault) {
+            fault = initiateMemRead(xc, traceData, EA, memData,
+                this->memAccessFlags);
+        }
+
+        return fault;
+    }
+}};
+
+def template SveLoadAndReplCompleteAcc {{
+    %(tpl_header)s
+    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
+        ExecContext *xc, Trace::InstRecord *traceData) const
+    {
+        Fault fault = NoFault;
+        bool aarch64 M5_VAR_USED = true;
+        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
+            xc->tcBase());
+
+        %(op_decl)s;
+        %(op_rd)s;
+
+        MemElemType memData;
+        getMem(pkt, memData, traceData);
+
+        if (fault == NoFault) {
+            %(memacc_code)s;
+        }
+
+        if (fault == NoFault) {
+            %(op_wb)s;
+        }
+
+        return fault;
+    }
+}};
+
index c0647b81fd1211072811889d4a07da3e8a559418..0207599a294cb1de100b8527c911433cebe48ead 100644 (file)
@@ -83,3 +83,4 @@
 
 //Templates for SVE instructions
 ##include "sve.isa"
+##include "sve_mem.isa"