ARM: Implement the strex instructions.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:10 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:10 +0000 (12:58 -0500)
src/arch/arm/insts/mem.hh
src/arch/arm/isa/insts/ldr.isa
src/arch/arm/isa/insts/macromem.isa
src/arch/arm/isa/insts/mem.isa
src/arch/arm/isa/insts/str.isa
src/arch/arm/isa/operands.isa
src/arch/arm/isa/templates/mem.isa

index d5b5d35194c615c2e47724190c0154cf4260287a..ae3437120b93554d4e95c2a45b70384689e25c1d 100644 (file)
@@ -142,6 +142,27 @@ class MemoryImm : public Memory
     }
 };
 
+class MemoryExImm : public MemoryImm
+{
+  protected:
+    IntRegIndex result;
+
+    MemoryExImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+                IntRegIndex _result, IntRegIndex _dest, IntRegIndex _base,
+                bool _add, int32_t _imm)
+        : MemoryImm(mnem, _machInst, __opClass, _dest, _base, _add, _imm),
+                    result(_result)
+    {}
+
+    void
+    printDest(std::ostream &os) const
+    {
+        printReg(os, result);
+        os << ", ";
+        MemoryImm::printDest(os);
+    }
+};
+
 // The address is a base register plus an immediate.
 class MemoryDImm : public MemoryImm
 {
@@ -164,6 +185,27 @@ class MemoryDImm : public MemoryImm
     }
 };
 
+class MemoryExDImm : public MemoryDImm
+{
+  protected:
+    IntRegIndex result;
+
+    MemoryExDImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+                 IntRegIndex _result, IntRegIndex _dest, IntRegIndex _dest2,
+                 IntRegIndex _base, bool _add, int32_t _imm)
+        : MemoryDImm(mnem, _machInst, __opClass, _dest, _dest2,
+                     _base, _add, _imm), result(_result)
+    {}
+
+    void
+    printDest(std::ostream &os) const
+    {
+        printReg(os, result);
+        os << ", ";
+        MemoryDImm::printDest(os);
+    }
+};
+
 // The address is a shifted register plus an immediate
 class MemoryReg : public Memory
 {
@@ -265,6 +307,14 @@ class MemoryOffset : public Base
         : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
     {}
 
+    MemoryOffset(const char *mnem, ExtMachInst _machInst,
+                 OpClass __opClass, IntRegIndex _result,
+                 IntRegIndex _dest, IntRegIndex _dest2,
+                 IntRegIndex _base, bool _add, int32_t _imm)
+        : Base(mnem, _machInst, __opClass, _result,
+                _dest, _dest2, _base, _add, _imm)
+    {}
+
     MemoryOffset(const char *mnem, ExtMachInst _machInst,
                  OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
                  IntRegIndex _base, bool _add,
@@ -307,6 +357,14 @@ class MemoryPreIndex : public Base
         : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
     {}
 
+    MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
+                   OpClass __opClass, IntRegIndex _result,
+                   IntRegIndex _dest, IntRegIndex _dest2,
+                   IntRegIndex _base, bool _add, int32_t _imm)
+        : Base(mnem, _machInst, __opClass, _result,
+                _dest, _dest2, _base, _add, _imm)
+    {}
+
     MemoryPreIndex(const char *mnem, ExtMachInst _machInst,
                    OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
                    IntRegIndex _base, bool _add,
@@ -349,6 +407,14 @@ class MemoryPostIndex : public Base
         : Base(mnem, _machInst, __opClass, _dest, _dest2, _base, _add, _imm)
     {}
 
+    MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
+                    OpClass __opClass, IntRegIndex _result,
+                    IntRegIndex _dest, IntRegIndex _dest2,
+                    IntRegIndex _base, bool _add, int32_t _imm)
+        : Base(mnem, _machInst, __opClass, _result,
+                _dest, _dest2, _base, _add, _imm)
+    {}
+
     MemoryPostIndex(const char *mnem, ExtMachInst _machInst,
                     OpClass __opClass, IntRegIndex _dest, IntRegIndex _dest2,
                     IntRegIndex _base, bool _add,
index c170da68821de7f54c1ac5282dd304288b0c5894..ce87d7a9ebfc96792655ad4dcf33d923150305d6 100644 (file)
@@ -66,8 +66,8 @@ let {{
         (newHeader,
          newDecoder,
          newExec) = loadStoreBase(name, Name, imm,
-                                  eaCode, accCode,
-                                  memFlags, instFlags, double,
+                                  eaCode, accCode, "",
+                                  memFlags, instFlags, double, False,
                                   base, execTemplateBase = 'Load')
 
         header_output += newHeader
index f393c74f0c2530757cf0f0773b8f90a9dab87205..781cbca7a3f43175ba076bc25d9a34cc9307482a 100644 (file)
@@ -87,6 +87,7 @@ let {{
     microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
                                    'MicroMemOp',
                                    {'memacc_code': microStrUopCode,
+                                    'postacc_code': "",
                                     'ea_code': 'EA = Rb + (up ? imm : -imm);',
                                     'predicate_test': predicateTest},
                                    ['IsMicroop'])
@@ -95,6 +96,7 @@ let {{
     microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
                                      'MicroMemOp',
                                      {'memacc_code': microStrFpUopCode,
+                                      'postacc_code': "",
                                       'ea_code': 'EA = Rb + (up ? imm : -imm);',
                                       'predicate_test': predicateTest},
                                      ['IsMicroop'])
index db3665a54542348ef4d2b2bf9d8877948fb03ea9..e17235c817fa28fdd989f37200811d3f4d1260ff 100644 (file)
@@ -39,7 +39,7 @@
 
 let {{
     def loadStoreBaseWork(name, Name, imm, swp, rfe, codeBlobs, memFlags,
-                          instFlags, double, base = 'Memory',
+                          instFlags, double, strex, base = 'Memory',
                           execTemplateBase = ''):
         # Make sure flags are in lists (convert to lists if not).
         memFlags = makeList(memFlags)
@@ -70,6 +70,12 @@ let {{
             if double:
                 declareTemplate = LoadStoreDImmDeclare
                 constructTemplate = LoadStoreDImmConstructor
+                if strex:
+                    declareTemplate = StoreExDImmDeclare
+                    constructTemplate = StoreExDImmConstructor
+            elif strex:
+                declareTemplate = StoreExImmDeclare
+                constructTemplate = StoreExImmConstructor
             else:
                 declareTemplate = LoadStoreImmDeclare
                 constructTemplate = LoadStoreImmConstructor
@@ -88,14 +94,15 @@ let {{
                 + initiateAccTemplate.subst(iop)
                 + completeAccTemplate.subst(iop))
 
-    def loadStoreBase(name, Name, imm, eaCode, accCode, memFlags,
-                      instFlags, double, base = 'Memory',
+    def loadStoreBase(name, Name, imm, eaCode, accCode, postAccCode,
+                      memFlags, instFlags, double, strex, base = 'Memory',
                       execTemplateBase = ''):
         codeBlobs = { "ea_code": eaCode,
                       "memacc_code": accCode,
+                      "postacc_code": postAccCode,
                       "predicate_test": predicateTest }
         return loadStoreBaseWork(name, Name, imm, False, False, codeBlobs,
-                                 memFlags, instFlags, double, base,
+                                 memFlags, instFlags, double, strex, base,
                                  execTemplateBase)
 
     def RfeBase(name, Name, eaCode, accCode, memFlags, instFlags):
@@ -103,7 +110,8 @@ let {{
                       "memacc_code": accCode,
                       "predicate_test": predicateTest }
         return loadStoreBaseWork(name, Name, False, False, True, codeBlobs,
-                                 memFlags, instFlags, False, 'RfeOp', 'Load')
+                                 memFlags, instFlags, False, False,
+                                 'RfeOp', 'Load')
 
     def SwapBase(name, Name, eaCode, preAccCode, postAccCode, memFlags,
                  instFlags):
@@ -112,7 +120,8 @@ let {{
                       "postacc_code": postAccCode,
                       "predicate_test": predicateTest }
         return loadStoreBaseWork(name, Name, False, True, False, codeBlobs,
-                                 memFlags, instFlags, False, 'Swap', 'Swap')
+                                 memFlags, instFlags, False, False,
+                                 'Swap', 'Swap')
 
     def memClassName(base, post, add, writeback, \
                      size=4, sign=False, user=False):
index 0c92b20df39eef83f40301be1b874b17da381c29..f9002a6f77a60e7a8ff5c886618490e571362aa5 100644 (file)
@@ -61,23 +61,24 @@ let {{
         return memClassName("STORE_REGD", post, add, writeback,
                             4, False, False)
 
-    def emitStore(name, Name, imm, eaCode, accCode, \
-                  memFlags, instFlags, base, double=False):
+    def emitStore(name, Name, imm, eaCode, accCode, postAccCode, \
+                  memFlags, instFlags, base, double=False, strex=False,
+                  execTemplateBase = 'Store'):
         global header_output, decoder_output, exec_output
 
         (newHeader,
          newDecoder,
          newExec) = loadStoreBase(name, Name, imm,
-                                  eaCode, accCode,
-                                  memFlags, instFlags, double,
-                                  base, execTemplateBase = 'Store')
+                                  eaCode, accCode, postAccCode,
+                                  memFlags, instFlags, double, strex,
+                                  base, execTemplateBase = execTemplateBase)
 
         header_output += newHeader
         decoder_output += newDecoder
         exec_output += newExec
 
     def buildImmStore(mnem, post, add, writeback, \
-                      size=4, sign=False, user=False):
+                      size=4, sign=False, user=False, strex=False):
         name = mnem
         Name = storeImmClassName(post, add, writeback, \
                                  size, sign, user)
@@ -97,15 +98,26 @@ let {{
             { "suffix" : buildMemSuffix(sign, size) }
         if writeback:
             accCode += "Base = Base %s;\n" % offset
-        base = buildMemBase("MemoryImm", post, writeback)
 
-        emitStore(name, Name, True, eaCode, accCode, \
-                ["ArmISA::TLB::MustBeOne", \
-                 "ArmISA::TLB::AllowUnaligned", \
-                 "%d" % (size - 1)], [], base)
+        memFlags = ["ArmISA::TLB::MustBeOne", "%d" % (size - 1)]
+        if strex:
+            memFlags.append("Request::LLSC")
+            Name = "%s_%s" % (mnem.upper(), Name)
+            base = buildMemBase("MemoryExImm", post, writeback)
+            postAccCode = "Result = !writeResult;"
+            execTemplateBase = 'StoreEx'
+        else:
+            memFlags.append("ArmISA::TLB::AllowUnaligned")
+            base = buildMemBase("MemoryImm", post, writeback)
+            postAccCode = ""
+            execTemplateBase = 'Store'
+
+        emitStore(name, Name, True, eaCode, accCode, postAccCode, \
+                  memFlags, [], base, strex=strex,
+                  execTemplateBase = execTemplateBase)
 
     def buildRegStore(mnem, post, add, writeback, \
-                      size=4, sign=False, user=False):
+                      size=4, sign=False, user=False, strex=False):
         name = mnem
         Name = storeRegClassName(post, add, writeback,
                                  size, sign, user)
@@ -128,12 +140,12 @@ let {{
             accCode += "Base = Base %s;\n" % offset
         base = buildMemBase("MemoryReg", post, writeback)
 
-        emitStore(name, Name, False, eaCode, accCode, \
+        emitStore(name, Name, False, eaCode, accCode, "",\
                 ["ArmISA::TLB::MustBeOne", \
                  "ArmISA::TLB::AllowUnaligned", \
                  "%d" % (size - 1)], [], base)
 
-    def buildDoubleImmStore(mnem, post, add, writeback):
+    def buildDoubleImmStore(mnem, post, add, writeback, strex=False):
         name = mnem
         Name = storeDoubleImmClassName(post, add, writeback)
 
@@ -155,11 +167,20 @@ let {{
         '''
         if writeback:
             accCode += "Base = Base %s;\n" % offset
-        base = buildMemBase("MemoryDImm", post, writeback)
 
-        emitStore(name, Name, True, eaCode, accCode, \
-                ["ArmISA::TLB::MustBeOne",
-                 "ArmISA::TLB::AlignWord"], [], base, double=True)
+        memFlags = ["ArmISA::TLB::MustBeOne",
+                    "ArmISA::TLB::AlignWord"]
+        if strex:
+            memFlags.append("Request::LLSC")
+            Name = "%s_%s" % (mnem.upper(), Name)
+            base = buildMemBase("MemoryExDImm", post, writeback)
+            postAccCode = "Result = !writeResult;"
+        else:
+            base = buildMemBase("MemoryDImm", post, writeback)
+            postAccCode = ""
+
+        emitStore(name, Name, True, eaCode, accCode, postAccCode, \
+                  memFlags, [], base, double=True, strex=strex)
 
     def buildDoubleRegStore(mnem, post, add, writeback):
         name = mnem
@@ -186,9 +207,11 @@ let {{
             accCode += "Base = Base %s;\n" % offset
         base = buildMemBase("MemoryDReg", post, writeback)
 
-        emitStore(name, Name, False, eaCode, accCode, \
-                ["ArmISA::TLB::MustBeOne", \
-                 "ArmISA::TLB::AlignWord"], [], base, double=True)
+        memFlags = ["ArmISA::TLB::MustBeOne",
+                    "ArmISA::TLB::AlignWord"]
+
+        emitStore(name, Name, False, eaCode, accCode, "", \
+                  memFlags, [], base, double=True)
 
     def buildStores(mnem, size=4, sign=False, user=False):
         buildImmStore(mnem, True, True, True, size, sign, user)
@@ -226,4 +249,9 @@ let {{
     buildStores("strht", size=2, user=True)
 
     buildDoubleStores("strd")
+
+    buildImmStore("strex", False, True, False, size=4, strex=True)
+    buildImmStore("strexh", False, True, False, size=2, strex=True)
+    buildImmStore("strexb", False, True, False, size=1, strex=True)
+    buildDoubleImmStore("strexd", False, True, False, strex=True)
 }};
index a8b0b197a1af38fba5eafbf15edd0eb0ec0370a3..3fda93668cd4d804aa1aa8c913ba00e74143a33a 100644 (file)
@@ -91,6 +91,8 @@ def operands {{
     #Abstracted integer reg operands
     'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
              maybePCRead, maybePCWrite),
+    'Result': ('IntReg', 'uw', 'result', 'IsInteger', 2,
+               maybePCRead, maybePCWrite),
     'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 2,
               maybePCRead, maybePCWrite),
     'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
index e44fe41db9cc36c07004d2022e36e1cd721e50aa..7c93cd4eee03d8e2ed731d265cb63e8324271e0e 100644 (file)
@@ -190,6 +190,77 @@ def template StoreExecute {{
     }
 }};
 
+def template StoreExExecute {{
+    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+                                  Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+
+        %(op_decl)s;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        if (%(predicate_test)s)
+        {
+            if (fault == NoFault) {
+                %(memacc_code)s;
+            }
+
+            uint64_t writeResult;
+
+            if (fault == NoFault) {
+                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+                                  memAccessFlags, &writeResult);
+                if (traceData) { traceData->setData(Mem); }
+            }
+
+            if (fault == NoFault) {
+                %(postacc_code)s;
+            }
+
+            if (fault == NoFault) {
+                %(op_wb)s;
+            }
+        }
+
+        return fault;
+    }
+}};
+
+def template StoreExInitiateAcc {{
+    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+                                      Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+
+        %(op_decl)s;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        if (%(predicate_test)s)
+        {
+            if (fault == NoFault) {
+                %(memacc_code)s;
+            }
+
+            if (fault == NoFault) {
+                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+                                  memAccessFlags, NULL);
+                if (traceData) { traceData->setData(Mem); }
+            }
+
+            // Need to write back any potential address register update
+            if (fault == NoFault) {
+                %(op_wb)s;
+            }
+        }
+
+        return fault;
+    }
+}};
+
 def template StoreInitiateAcc {{
     Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
                                       Trace::InstRecord *traceData) const
@@ -294,6 +365,30 @@ def template StoreCompleteAcc {{
     }
 }};
 
+def template StoreExCompleteAcc {{
+    Fault %(class_name)s::completeAcc(PacketPtr pkt,
+                                      %(CPU_exec_context)s *xc,
+                                      Trace::InstRecord *traceData) const
+    {
+        Fault fault = NoFault;
+
+        %(op_decl)s;
+        %(op_rd)s;
+
+        if (%(predicate_test)s)
+        {
+            uint64_t writeResult = pkt->req->getExtraData();
+            %(postacc_code)s;
+
+            if (fault == NoFault) {
+                %(op_wb)s;
+            }
+        }
+
+        return fault;
+    }
+}};
+
 def template RfeDeclare {{
     /**
      * Static instruction class for "%(mnemonic)s".
@@ -355,6 +450,27 @@ def template LoadStoreDImmDeclare {{
     };
 }};
 
+def template StoreExDImmDeclare {{
+    /**
+     * Static instruction class for "%(mnemonic)s".
+     */
+    class %(class_name)s : public %(base_class)s
+    {
+      public:
+
+        /// Constructor.
+        %(class_name)s(ExtMachInst machInst,
+                uint32_t _result, uint32_t _dest, uint32_t _dest2,
+                uint32_t _base, bool _add, int32_t _imm);
+
+        %(BasicExecDeclare)s
+
+        %(InitiateAccDeclare)s
+
+        %(CompleteAccDeclare)s
+    };
+}};
+
 def template LoadStoreImmDeclare {{
     /**
      * Static instruction class for "%(mnemonic)s".
@@ -375,6 +491,27 @@ def template LoadStoreImmDeclare {{
     };
 }};
 
+def template StoreExImmDeclare {{
+    /**
+     * Static instruction class for "%(mnemonic)s".
+     */
+    class %(class_name)s : public %(base_class)s
+    {
+      public:
+
+        /// Constructor.
+        %(class_name)s(ExtMachInst machInst,
+                uint32_t _result, uint32_t _dest, uint32_t _base,
+                bool _add, int32_t _imm);
+
+        %(BasicExecDeclare)s
+
+        %(InitiateAccDeclare)s
+
+        %(CompleteAccDeclare)s
+    };
+}};
+
 def template LoadStoreDRegDeclare {{
     /**
      * Static instruction class for "%(mnemonic)s".
@@ -460,6 +597,19 @@ def template LoadStoreDImmConstructor {{
     }
 }};
 
+def template StoreExDImmConstructor {{
+    inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
+            uint32_t _result, uint32_t _dest, uint32_t _dest2,
+            uint32_t _base, bool _add, int32_t _imm)
+         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+                 (IntRegIndex)_result,
+                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
+                 (IntRegIndex)_base, _add, _imm)
+    {
+        %(constructor)s;
+    }
+}};
+
 def template LoadStoreImmConstructor {{
     inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
             uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
@@ -470,6 +620,18 @@ def template LoadStoreImmConstructor {{
     }
 }};
 
+def template StoreExImmConstructor {{
+    inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
+            uint32_t _result, uint32_t _dest, uint32_t _base,
+            bool _add, int32_t _imm)
+         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+                 (IntRegIndex)_result, (IntRegIndex)_dest,
+                 (IntRegIndex)_base, _add, _imm)
+    {
+        %(constructor)s;
+    }
+}};
+
 def template LoadStoreDRegConstructor {{
     inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
             uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,