ARM: Implement the swp and swpb instructions.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:05 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:05 +0000 (12:58 -0500)
src/arch/arm/insts/mem.cc
src/arch/arm/insts/mem.hh
src/arch/arm/isa/insts/insts.isa
src/arch/arm/isa/insts/mem.isa
src/arch/arm/isa/insts/swap.isa [new file with mode: 0644]
src/arch/arm/isa/templates/mem.isa

index ea98771e0ccb3c955b7f59423a633e72f133b6e3..6cbe08ac8de4d03675ad8d54e08b42c4ced3e299 100644 (file)
 #include "arch/arm/insts/mem.hh"
 #include "base/loader/symtab.hh"
 
+using namespace std;
+
 namespace ArmISA
 {
 
+string
+Swap::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+{
+    stringstream ss;
+    printMnemonic(ss);
+    printReg(ss, dest);
+    ss << ", ";
+    printReg(ss, op1);
+    ss << ", [";
+    printReg(ss, base);
+    ss << "]";
+    return ss.str();
+}
+
 void
 Memory::printInst(std::ostream &os, AddrMode addrMode) const
 {
index e58005883b005c451a3b6373da44899c6f0c1a8b..6ed99ba5bbe527dcf7b7136d5d947784dd532597 100644 (file)
 namespace ArmISA
 {
 
+class Swap : public PredOp
+{
+  protected:
+    IntRegIndex dest;
+    IntRegIndex op1;
+    IntRegIndex base;
+
+    Swap(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+         IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _base)
+        : PredOp(mnem, _machInst, __opClass),
+          dest(_dest), op1(_op1), base(_base)
+    {}
+
+    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+};
+
 class Memory : public PredOp
 {
   public:
index 04dc867c752a0d21d04295f3fa1ea056efbc4b3a..82bace31bde40b22ffd3a660c7e59f30bd4030d7 100644 (file)
@@ -52,6 +52,9 @@
 //Stores of a single item
 ##include "str.isa"
 
+//Swaps
+##include "swap.isa"
+
 //Load/store multiple
 ##include "macromem.isa"
 
index 1bd70e54b34b8df952f6c212d4c6be07fa9f2fa6..21687b225d218cadd9467706095612485f548f33 100644 (file)
 // Authors: Gabe Black
 
 let {{
-    def loadStoreBase(name, Name, imm, eaCode, accCode, memFlags,
-                      instFlags, base = 'Memory', execTemplateBase = ''):
+    def loadStoreBaseWork(name, Name, imm, swp, codeBlobs, memFlags,
+                          instFlags, base = 'Memory', execTemplateBase = ''):
         # Make sure flags are in lists (convert to lists if not).
         memFlags = makeList(memFlags)
         instFlags = makeList(instFlags)
 
+        eaCode = codeBlobs["ea_code"]
+
         # This shouldn't be part of the eaCode, but until the exec templates
         # are converted over it's the easiest place to put it.
         eaCode += '\n    unsigned memAccessFlags = '
@@ -52,17 +54,18 @@ let {{
         else:
             eaCode += '0;'
 
-        iop = InstObjParams(name, Name, base,
-                            {'ea_code': eaCode,
-                             'memacc_code': accCode,
-                             'predicate_test': predicateTest},
-                            instFlags)
+        codeBlobs["ea_code"] = eaCode
+
+        iop = InstObjParams(name, Name, base, codeBlobs, instFlags)
 
         fullExecTemplate = eval(execTemplateBase + 'Execute')
         initiateAccTemplate = eval(execTemplateBase + 'InitiateAcc')
         completeAccTemplate = eval(execTemplateBase + 'CompleteAcc')
 
-        if imm:
+        if swp:
+            declareTemplate = SwapDeclare
+            constructTemplate = SwapConstructor
+        elif imm:
             declareTemplate = LoadStoreImmDeclare
             constructTemplate = LoadStoreImmConstructor
         else:
@@ -76,6 +79,23 @@ let {{
                 + initiateAccTemplate.subst(iop)
                 + completeAccTemplate.subst(iop))
 
+    def loadStoreBase(name, Name, imm, eaCode, accCode, memFlags,
+                      instFlags, base = 'Memory', execTemplateBase = ''):
+        codeBlobs = { "ea_code": eaCode,
+                      "memacc_code": accCode,
+                      "predicate_test": predicateTest }
+        return loadStoreBaseWork(name, Name, imm, False, codeBlobs, memFlags,
+                                 instFlags, base, execTemplateBase)
+
+    def SwapBase(name, Name, eaCode, preAccCode, postAccCode, memFlags,
+                 instFlags):
+        codeBlobs = { "ea_code": eaCode,
+                      "preacc_code": preAccCode,
+                      "postacc_code": postAccCode,
+                      "predicate_test": predicateTest }
+        return loadStoreBaseWork(name, Name, False, True, codeBlobs, memFlags,
+                                 instFlags, 'Swap', 'Swap')
+
     def memClassName(base, post, add, writeback, \
                      size=4, sign=False, user=False):
         Name = base
diff --git a/src/arch/arm/isa/insts/swap.isa b/src/arch/arm/isa/insts/swap.isa
new file mode 100644 (file)
index 0000000..6cbca6d
--- /dev/null
@@ -0,0 +1,61 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2010 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: Gabe Black
+
+let {{
+
+    header_output = decoder_output = exec_output = ""
+
+    (newHeader,
+     newDecoder,
+     newExec) = SwapBase("swp", "Swp", "EA = Base;",
+                         "Mem = Op1;", "Dest = memData;",
+                         ["Request::MEM_SWAP"], [])
+    header_output += newHeader
+    decoder_output += newDecoder
+    exec_output += newExec
+
+    (newHeader,
+     newDecoder,
+     newExec) = SwapBase("swpb", "Swpb", "EA = Base;",
+                         "Mem.ub = Op1.ub;", "Dest.ub = (uint8_t)memData;",
+                         ["Request::MEM_SWAP"], [])
+    header_output += newHeader
+    decoder_output += newDecoder
+    exec_output += newExec
+}};
index b424072bcad7effa425cb49db83f8e82802415f1..e0147066606c267048069eac7df386da0751b799 100644 (file)
 // Authors: Stephen Hines
 
 
+def template SwapExecute {{
+    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+                                  Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+
+        %(op_decl)s;
+        uint64_t memData = 0;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        if (%(predicate_test)s)
+        {
+            %(preacc_code)s;
+
+            if (fault == NoFault) {
+                fault = xc->write((uint%(mem_acc_size)d_t&)Mem,
+                        EA, memAccessFlags, &memData);
+            }
+
+            if (fault == NoFault) {
+                %(postacc_code)s;
+            }
+
+            if (fault == NoFault) {
+                %(op_wb)s;
+            }
+        }
+
+        return fault;
+    }
+}};
+
+def template SwapInitiateAcc {{
+    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+                                      Trace::InstRecord *traceData) const
+    {
+        Addr EA;
+        Fault fault = NoFault;
+
+        %(op_decl)s;
+        uint64_t memData = 0;
+        %(op_rd)s;
+        %(ea_code)s;
+
+        if (%(predicate_test)s)
+        {
+            %(preacc_code)s;
+
+            if (fault == NoFault) {
+                fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+                                  memAccessFlags, &memData);
+            }
+
+            if (fault == NoFault) {
+                %(op_wb)s;
+            }
+        }
+
+        return fault;
+    }
+}};
+
+def template SwapCompleteAcc {{
+    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)
+        {
+            // ARM instructions will not have a pkt if the predicate is false
+            uint64_t memData = pkt->get<typeof(Mem)>();
+
+            %(postacc_code)s;
+
+            if (fault == NoFault) {
+                %(op_wb)s;
+            }
+        }
+
+        return fault;
+    }
+}};
+
 def template LoadExecute {{
     Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
                                   Trace::InstRecord *traceData) const
@@ -204,6 +294,26 @@ def template StoreCompleteAcc {{
     }
 }};
 
+def template SwapDeclare {{
+    /**
+     * Static instruction class for "%(mnemonic)s".
+     */
+    class %(class_name)s : public %(base_class)s
+    {
+      public:
+
+        /// Constructor.
+        %(class_name)s(ExtMachInst machInst,
+                uint32_t _dest, uint32_t _op1, uint32_t _base);
+
+        %(BasicExecDeclare)s
+
+        %(InitiateAccDeclare)s
+
+        %(CompleteAccDeclare)s
+    };
+}};
+
 def template LoadStoreImmDeclare {{
     /**
      * Static instruction class for "%(mnemonic)s".
@@ -254,6 +364,16 @@ def template CompleteAccDeclare {{
     Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
 }};
 
+def template SwapConstructor {{
+    inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
+            uint32_t _dest, uint32_t _op1, uint32_t _base)
+         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+                 (IntRegIndex)_dest, (IntRegIndex)_op1, (IntRegIndex)_base)
+    {
+        %(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)