changeset 82bb3ee706b3 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=82bb3ee706b3
description:
        x86: revamp cmpxchg8b/cmpxchg16b implementation

        The previous implementation did a pair of nested RMW operations,
        which isn't compatible with the way that locked RMW operations are
        implemented in the cache models.  It was convenient though in that
        it didn't require any new micro-ops, and supported cmpxchg16b using
        64-bit memory ops.  It also worked in AtomicSimpleCPU where
        atomicity was guaranteed by the core and not by the memory system.
        It did not work with timing CPU models though.

        This new implementation defines new 'split' load and store micro-ops
        which allow a single memory operation to use a pair of registers as
        the source or destination, then uses a single ldsplit/stsplit RMW
        pair to implement cmpxchg.  This patch requires support for 128-bit
        memory accesses in the ISA (added via a separate patch) to support
        cmpxchg16b.

diffstat:

 src/arch/x86/insts/microldstop.cc                    |   18 +
 src/arch/x86/insts/microldstop.hh                    |   86 ++++++-
 src/arch/x86/isa/insts/general_purpose/semaphores.py |   10 +-
 src/arch/x86/isa/microops/ldstop.isa                 |  225 +++++++++++++++++-
 src/arch/x86/isa/operands.isa                        |    2 +
 5 files changed, 302 insertions(+), 39 deletions(-)

diffs (truncated from 554 to 300 lines):

diff -r 9512d2e25f14 -r 82bb3ee706b3 src/arch/x86/insts/microldstop.cc
--- a/src/arch/x86/insts/microldstop.cc Sat Feb 06 17:21:20 2016 -0800
+++ b/src/arch/x86/insts/microldstop.cc Sat Feb 06 17:21:20 2016 -0800
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2015 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -58,4 +59,21 @@
                 addressSize, false);
         return response.str();
     }
+
+    std::string LdStSplitOp::generateDisassembly(Addr pc,
+            const SymbolTable *symtab) const
+    {
+        std::stringstream response;
+
+        printMnemonic(response, instMnem, mnemonic);
+        int baseRegIdx = flags[IsLoad] ? 0 : 2;
+        response << "[";
+        printDestReg(response, baseRegIdx, dataSize);
+        response << ", ";
+        printDestReg(response, baseRegIdx+1, dataSize);
+        response << "], ";
+        printMem(response, segment, scale, index, base, disp,
+                addressSize, false);
+        return response.str();
+    }
 }
diff -r 9512d2e25f14 -r 82bb3ee706b3 src/arch/x86/insts/microldstop.hh
--- a/src/arch/x86/insts/microldstop.hh Sat Feb 06 17:21:20 2016 -0800
+++ b/src/arch/x86/insts/microldstop.hh Sat Feb 06 17:21:20 2016 -0800
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2015 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -49,9 +50,9 @@
 namespace X86ISA
 {
     /**
-     * Base class for load and store ops
+     * Base class for memory ops
      */
-    class LdStOp : public X86MicroopBase
+    class MemOp : public X86MicroopBase
     {
       protected:
         const uint8_t scale;
@@ -59,13 +60,43 @@
         const RegIndex base;
         const uint64_t disp;
         const uint8_t segment;
-        const RegIndex data;
         const uint8_t dataSize;
         const uint8_t addressSize;
         const Request::FlagsType memFlags;
         RegIndex foldOBit, foldABit;
 
         //Constructor
+        MemOp(ExtMachInst _machInst,
+                const char * mnem, const char * _instMnem,
+                uint64_t setFlags,
+                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
+                uint64_t _disp, InstRegIndex _segment,
+                uint8_t _dataSize, uint8_t _addressSize,
+                Request::FlagsType _memFlags,
+                OpClass __opClass) :
+        X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass),
+                scale(_scale), index(_index.idx), base(_base.idx),
+                disp(_disp), segment(_segment.idx),
+                dataSize(_dataSize), addressSize(_addressSize),
+                memFlags(_memFlags | _segment.idx)
+        {
+            assert(_segment.idx < NUM_SEGMENTREGS);
+            foldOBit =
+                (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
+            foldABit =
+                (addressSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
+        }
+    };
+
+    /**
+     * Base class for load and store ops using one register
+     */
+    class LdStOp : public MemOp
+    {
+      protected:
+        const RegIndex data;
+
+        //Constructor
         LdStOp(ExtMachInst _machInst,
                 const char * mnem, const char * _instMnem,
                 uint64_t setFlags,
@@ -75,17 +106,46 @@
                 uint8_t _dataSize, uint8_t _addressSize,
                 Request::FlagsType _memFlags,
                 OpClass __opClass) :
-        X86MicroopBase(_machInst, mnem, _instMnem, setFlags, __opClass),
-                scale(_scale), index(_index.idx), base(_base.idx),
-                disp(_disp), segment(_segment.idx),
-                data(_data.idx),
-                dataSize(_dataSize), addressSize(_addressSize),
-                memFlags(_memFlags | _segment.idx)
+        MemOp(_machInst, mnem, _instMnem, setFlags,
+                _scale, _index, _base, _disp, _segment,
+                _dataSize, _addressSize, _memFlags,
+                __opClass),
+                data(_data.idx)
         {
-            assert(_segment.idx < NUM_SEGMENTREGS);
-            foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
-            foldABit =
-                (addressSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
+        }
+
+        std::string generateDisassembly(Addr pc,
+            const SymbolTable *symtab) const;
+    };
+
+    /**
+     * Base class for load and store ops using two registers, we will
+     * call them split ops for this reason. These are mainly  used to
+     * implement cmpxchg8b and cmpxchg16b.
+     */
+    class LdStSplitOp : public MemOp
+    {
+      protected:
+        const RegIndex dataLow;
+        const RegIndex dataHi;
+
+        //Constructor
+        LdStSplitOp(ExtMachInst _machInst,
+                const char * mnem, const char * _instMnem,
+                uint64_t setFlags,
+                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
+                uint64_t _disp, InstRegIndex _segment,
+                InstRegIndex _dataLow, InstRegIndex _dataHi,
+                uint8_t _dataSize, uint8_t _addressSize,
+                Request::FlagsType _memFlags,
+                OpClass __opClass) :
+        MemOp(_machInst, mnem, _instMnem, setFlags,
+                _scale, _index, _base, _disp, _segment,
+                _dataSize, _addressSize, _memFlags,
+                __opClass),
+                dataLow(_dataLow.idx),
+                dataHi(_dataHi.idx)
+        {
         }
 
         std::string generateDisassembly(Addr pc,
diff -r 9512d2e25f14 -r 82bb3ee706b3 
src/arch/x86/isa/insts/general_purpose/semaphores.py
--- a/src/arch/x86/isa/insts/general_purpose/semaphores.py      Sat Feb 06 
17:21:20 2016 -0800
+++ b/src/arch/x86/isa/insts/general_purpose/semaphores.py      Sat Feb 06 
17:21:20 2016 -0800
@@ -1,4 +1,5 @@
 # Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2015 Advanced Micro Devices, Inc.
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -126,12 +127,14 @@
 
 '''
 
+# Despite the name, this microcode sequence implements both
+# cmpxchg8b and cmpxchg16b, depending on the dynamic value
+# of dataSize.
 cmpxchg8bCode = '''
 def macroop CMPXCHG8B_%(suffix)s {
     %(rdip)s
     lea t1, seg, %(sib)s, disp, dataSize=asz
-    ldst%(l)s t2, seg, [1, t0, t1], 0
-    ldst%(l)s t3, seg, [1, t0, t1], dsz
+    ldsplit%(l)s (t2, t3), seg, [1, t0, t1], disp=0
 
     sub t0, rax, t2, flags=(ZF,)
     br label("doneComparing"), flags=(nCZF,)
@@ -147,8 +150,7 @@
     mov rdx, rdx, t3, flags=(nCZF,)
 
     # Write to memory
-    st%(ul)s t3, seg, [1, t0, t1], dsz
-    st%(ul)s t2, seg, [1, t0, t1], 0
+    stsplit%(ul)s (t2, t3), seg, [1, t0, t1], disp=0
 };
 '''
 
diff -r 9512d2e25f14 -r 82bb3ee706b3 src/arch/x86/isa/microops/ldstop.isa
--- a/src/arch/x86/isa/microops/ldstop.isa      Sat Feb 06 17:21:20 2016 -0800
+++ b/src/arch/x86/isa/microops/ldstop.isa      Sat Feb 06 17:21:20 2016 -0800
@@ -1,4 +1,5 @@
 // Copyright (c) 2007-2008 The Hewlett-Packard Development Company
+// Copyright (c) 2015 Advanced Micro Devices, Inc.
 // All rights reserved.
 //
 // The license below extends only to copyright in the software and shall
@@ -98,7 +99,8 @@
         %(ea_code)s;
         DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
 
-        fault = readMemAtomic(xc, traceData, EA, Mem, dataSize, memFlags);
+        fault = readMemAtomic(xc, traceData, EA, Mem,
+                              %(memDataSize)s, memFlags);
 
         if (fault == NoFault) {
             %(code)s;
@@ -127,7 +129,8 @@
         %(ea_code)s;
         DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
 
-        fault = initiateMemRead(xc, traceData, EA, dataSize, memFlags);
+        fault = initiateMemRead(xc, traceData, EA,
+                                %(memDataSize)s, memFlags);
 
         return fault;
     }
@@ -143,7 +146,7 @@
         %(op_decl)s;
         %(op_rd)s;
 
-        getMem(pkt, Mem, dataSize, traceData);
+        getMem(pkt, Mem, %(memDataSize)s, traceData);
 
         %(code)s;
 
@@ -174,7 +177,7 @@
 
         if(fault == NoFault)
         {
-            fault = writeMemAtomic(xc, traceData, Mem, dataSize, EA,
+            fault = writeMemAtomic(xc, traceData, Mem, %(memDataSize)s, EA,
                     memFlags, NULL);
             if(fault == NoFault)
             {
@@ -202,7 +205,7 @@
 
         if(fault == NoFault)
         {
-            fault = writeMemTiming(xc, traceData, Mem, dataSize, EA,
+            fault = writeMemTiming(xc, traceData, Mem, %(memDataSize)s, EA,
                     memFlags, NULL);
         }
         return fault;
@@ -253,6 +256,28 @@
     };
 }};
 
+// LdStSplitOp is a load or store that uses a pair of regs as the
+// source or destination.  Used for cmpxchg{8,16}b.
+def template MicroLdStSplitOpDeclare {{
+    class %(class_name)s : public %(base_class)s
+    {
+      public:
+        %(class_name)s(ExtMachInst _machInst,
+                const char * instMnem, uint64_t setFlags,
+                uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
+                uint64_t _disp, InstRegIndex _segment,
+                InstRegIndex _dataLow, InstRegIndex _dataHi,
+                uint8_t _dataSize, uint8_t _addressSize,
+                Request::FlagsType _memFlags);
+
+        %(BasicExecDeclare)s
+
+        %(InitiateAccDeclare)s
+
+        %(CompleteAccDeclare)s
+    };
+}};
+
 def template MicroLdStOpConstructor {{
     %(class_name)s::%(class_name)s(
             ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
@@ -270,6 +295,23 @@
     }
 }};
 
+def template MicroLdStSplitOpConstructor {{
+    %(class_name)s::%(class_name)s(
+            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
+            uint8_t _scale, InstRegIndex _index, InstRegIndex _base,
+            uint64_t _disp, InstRegIndex _segment,
+            InstRegIndex _dataLow, InstRegIndex _dataHi,
+            uint8_t _dataSize, uint8_t _addressSize,
+            Request::FlagsType _memFlags) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
+                _scale, _index, _base,
+                _disp, _segment, _dataLow, _dataHi,
+                _dataSize, _addressSize, _memFlags, %(op_class)s)
+    {
+        %(constructor)s;
+    }
+}};
+
 let {{
     class LdStOp(X86Microop):
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to