Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/56492 )

Change subject: arch-x86: Move load/store microops into python.
......................................................................

arch-x86: Move load/store microops into python.

Change-Id: I0fd3d1193b42c90b5ae74c2fe52ef5a95aa9636e
---
M src/arch/x86/isa/microops/ldstop.isa
M src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
A src/arch/x86/ucasmlib/arch/x86/microops/ldstop.py
3 files changed, 425 insertions(+), 379 deletions(-)



diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa
index 99a381a..2e15b71 100644
--- a/src/arch/x86/isa/microops/ldstop.isa
+++ b/src/arch/x86/isa/microops/ldstop.isa
@@ -217,10 +217,6 @@
     %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
             Trace::InstRecord *traceData) const
     {
-        %(op_decl)s;
-        %(op_rd)s;
-        %(complete_code)s;
-        %(op_wb)s;
         return NoFault;
     }
 }};
@@ -293,153 +289,6 @@
 }};

 let {{
-    class LdStOp(X86Microop):
-        def __init__(self, data, segment, addr, disp,
- dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
-                uncacheable):
-            self.data = data
-            [self.scale, self.index, self.base] = addr
-            self.disp = disp
-            self.segment = segment
-            self.dataSize = dataSize
-            self.addressSize = addressSize
-            self.memFlags = baseFlags
-            if atCPL0:
-                self.memFlags += " | CPL0FlagBit"
-            self.instFlags = ""
-            if prefetch:
-                self.memFlags += " | Request::PREFETCH"
-                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
-            if nonSpec:
- self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
-            if uncacheable:
-                self.instFlags += " | Request::UNCACHEABLE"
-            self.memFlags += \
- " | ((log2i(%s) & AddrSizeFlagMask) << AddrSizeFlagShift)" % \
-                addressSize
-
-        def getAllocator(self, microFlags):
-            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
-                    %(flags)s, %(dataSize)s, %(addressSize)s, %(memFlags)s,
-                    %(data)s, %(scale)s, %(index)s, %(base)s,
-                    %(disp)s, %(segment)s)''' % {
-                "class_name" : self.className,
-                "flags" : self.microFlagsText(microFlags) + self.instFlags,
-                "scale" : self.scale, "index" : self.index,
-                "base" : self.base,
-                "disp" : self.disp,
-                "segment" : self.segment, "data" : self.data,
- "dataSize" : self.dataSize, "addressSize" : self.addressSize,
-                "memFlags" : self.memFlags}
-            return allocator
-
-    class BigLdStOp(X86Microop):
-        def __init__(self, data, segment, addr, disp,
- dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
-                uncacheable):
-            self.data = data
-            [self.scale, self.index, self.base] = addr
-            self.disp = disp
-            self.segment = segment
-            self.dataSize = dataSize
-            self.addressSize = addressSize
-            self.memFlags = baseFlags
-            if atCPL0:
-                self.memFlags += " | CPL0FlagBit"
-            self.instFlags = ""
-            if prefetch:
-                self.memFlags += " | Request::PREFETCH"
-                self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
-            if nonSpec:
- self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
-            if uncacheable:
-                self.instFlags += " | Request::UNCACHEABLE"
-            self.memFlags += \
- " | ((log2i(%s) & AddrSizeFlagMask) << AddrSizeFlagShift)" % \
-                addressSize
-
-        def getAllocator(self, microFlags):
-            allocString = '''
-                (%(dataSize)s >= 4) ?
-                    (StaticInstPtr)(new %(class_name)sBig(machInst,
-                        macrocodeBlock, %(flags)s, %(dataSize)s,
-                        %(addressSize)s, %(memFlags)s, %(data)s, %(scale)s,
-                        %(index)s, %(base)s, %(disp)s, %(segment)s)) :
-                    (StaticInstPtr)(new %(class_name)s(machInst,
-                        macrocodeBlock, %(flags)s, %(dataSize)s,
-                        %(addressSize)s, %(memFlags)s, %(data)s, %(scale)s,
-                        %(index)s, %(base)s, %(disp)s, %(segment)s))
-            '''
-            allocator = allocString % {
-                "class_name" : self.className,
-                "flags" : self.microFlagsText(microFlags) + self.instFlags,
-                "scale" : self.scale, "index" : self.index,
-                "base" : self.base,
-                "disp" : self.disp,
-                "segment" : self.segment, "data" : self.data,
- "dataSize" : self.dataSize, "addressSize" : self.addressSize,
-                "memFlags" : self.memFlags}
-            return allocator
-
-    class LdStSplitOp(LdStOp):
-        def __init__(self, data, segment, addr, disp,
- dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
-                uncacheable):
-            super().__init__(0, segment, addr, disp,
- dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
-                uncacheable)
-            (self.dataLow, self.dataHi) = data
-
-        def getAllocator(self, microFlags):
-            allocString = '''(StaticInstPtr)(new %(class_name)s(machInst,
-                        macrocodeBlock, %(flags)s, %(dataLow)s, %(dataHi)s,
-                        %(scale)s, %(index)s, %(base)s, %(disp)s, %(segment)s,
-                        %(dataSize)s, %(addressSize)s, %(memFlags)s))
-            '''
-            allocator = allocString % {
-                "class_name" : self.className,
-                "flags" : self.microFlagsText(microFlags) + self.instFlags,
-                "scale" : self.scale, "index" : self.index,
-                "base" : self.base,
-                "disp" : self.disp,
-                "segment" : self.segment,
-                "dataLow" : self.dataLow, "dataHi" : self.dataHi,
- "dataSize" : self.dataSize, "addressSize" : self.addressSize,
-                "memFlags" : self.memFlags}
-            return allocator
-
-    class MemNoDataOp(X86Microop):
-        def __init__(self, segment, addr, disp=0,
-                dataSize="env.dataSize", addressSize="env.addressSize",
-                baseFlags="0"):
-            [self.scale, self.index, self.base] = addr
-            self.disp = disp
-            self.segment = segment
-            self.dataSize = dataSize
-            self.addressSize = addressSize
-            self.instFlags = ""
-            self.memFlags = baseFlags + \
- " | ((log2i(%s) & AddrSizeFlagMask) << AddrSizeFlagShift)" % \
-                addressSize
-
-        def getAllocator(self, microFlags):
-            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
-                    %(flags)s, %(dataSize)s, %(addressSize)s, %(memFlags)s,
-                    %(scale)s, %(index)s, %(base)s, %(disp)s,
-                    %(segment)s)''' % {
-                "class_name" : self.className,
-                "flags" : self.microFlagsText(microFlags) + self.instFlags,
-                "scale" : self.scale, "index" : self.index,
-                "base" : self.base,
-                "disp" : self.disp,
-                "segment" : self.segment,
- "dataSize" : self.dataSize, "addressSize" : self.addressSize,
-                "memFlags" : self.memFlags}
-            return allocator
-
-}};
-
-let {{

     # Make these empty strings so that concatenating onto
     # them will always work.
@@ -452,29 +301,20 @@

     calculateEA = 'EA = SegBase + ' + segmentEAExpr

-    def defineMicroLoadOp(mnemonic, code, bigCode='',
-                          mem_flags="0", big=True, nonSpec=False,
-                          is_float=False):
-        global header_output
-        global decoder_output
-        global exec_output
-        global microopClasses
-        Name = mnemonic
-        name = mnemonic.lower()
-
-        if is_float:
+    for cls in microopClasses.loadops:
+        if cls.is_float:
             base = 'X86ISA::LdStFpOp'
         else:
             base = 'X86ISA::LdStOp'

         # Build up the all register version of this micro op
-        iops = [InstObjParams(name, Name, base,
-                              { "code": code,
+        iops = [InstObjParams(cls.mnemonic, cls.className, base,
+                              { "code": cls.code,
                                 "ea_code": calculateEA,
                                 "memDataSize": "dataSize" })]
-        if big:
-            iops += [InstObjParams(name, Name + "Big", base,
-                                   { "code": bigCode,
+        if cls.big:
+ iops += [InstObjParams(cls.mnemonic, cls.className + "Big", base,
+                                   { "code": cls.bigCode,
                                      "ea_code": calculateEA,
                                      "memDataSize": "dataSize" })]
         for iop in iops:
@@ -483,78 +323,13 @@
             exec_output += MicroLoadInitiateAcc.subst(iop)
             exec_output += MicroLoadCompleteAcc.subst(iop)

-        base = LdStOp
-        if big:
-            base = BigLdStOp
-        class LoadOp(base):
-            def __init__(self, data, segment, addr, disp = 0,
-                    dataSize="env.dataSize",
-                    addressSize="env.addressSize",
-                    atCPL0=False, prefetch=False, nonSpec=nonSpec,
-                    uncacheable=False):
-                super().__init__(data, segment, addr,
-                        disp, dataSize, addressSize, mem_flags,
-                        atCPL0, prefetch, nonSpec, uncacheable)
-                self.className = Name
-                self.mnemonic = name
+    for cls in microopClasses.splitloadops:
+        code = '''
+            DataLow = Mem_u2qw[0];
+            DataHi = Mem_u2qw[1];
+        '''

-        microopClasses[name] = LoadOp
-
-    defineMicroLoadOp('Ld', 'Data = merge(Data, data, Mem, dataSize);',
-                            'Data = Mem & mask(dataSize * 8);')
-    defineMicroLoadOp('Ldst', 'Data = merge(Data, data, Mem, dataSize);',
-                              'Data = Mem & mask(dataSize * 8);',
-                      'Request::READ_MODIFY_WRITE')
-    defineMicroLoadOp('Ldstl', 'Data = merge(Data, data, Mem, dataSize);',
-                               'Data = Mem & mask(dataSize * 8);',
-                      'Request::READ_MODIFY_WRITE | Request::LOCKED_RMW',
-                      nonSpec=True)
-
-    defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big=False,
-            is_float=True)
-
-    defineMicroLoadOp('Ldfp87', code='''
-        switch (dataSize)
-        {
-          case 4:
-            FpData_df = *(float *)&Mem;
-            break;
-          case 8:
-            FpData_df = *(double *)&Mem;
-            break;
-          default:
-            panic("Unhandled data size in LdFp87.\\n");
-        }
-    ''', big=False, is_float=True)
-
-    # Load integer from memory into x87 top-of-stack register.
-    # Used to implement fild instruction.
-    defineMicroLoadOp('Ldifp87', code='''
-        switch (dataSize)
-        {
-          case 2:
-            FpData_df = (int64_t)sext<16>(Mem);
-            break;
-          case 4:
-            FpData_df = (int64_t)sext<32>(Mem);
-            break;
-          case 8:
-            FpData_df = (int64_t)Mem;
-            break;
-          default:
-            panic("Unhandled data size in LdIFp87.\\n");
-        }
-    ''', big=False, is_float=True)
-
- def defineMicroLoadSplitOp(mnemonic, code, mem_flags="0", nonSpec=False):
-        global header_output
-        global decoder_output
-        global exec_output
-        global microopClasses
-        Name = mnemonic
-        name = mnemonic.lower()
-
-        iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
+ iop = InstObjParams(cls.mnemonic, cls.className, 'X86ISA::LdStSplitOp',
                             { "code": code,
                               "ea_code": calculateEA,
                               "memDataSize": "2 * dataSize" })
@@ -565,52 +340,17 @@
         exec_output += MicroLoadInitiateAcc.subst(iop)
         exec_output += MicroLoadCompleteAcc.subst(iop)

-        class LoadOp(LdStSplitOp):
-            def __init__(self, data, segment, addr, disp = 0,
-                    dataSize="env.dataSize",
-                    addressSize="env.addressSize",
-                    atCPL0=False, prefetch=False, nonSpec=nonSpec,
-                    uncacheable=False):
-                super().__init__(data, segment, addr,
-                        disp, dataSize, addressSize, mem_flags,
-                        atCPL0, prefetch, nonSpec, uncacheable)
-                self.className = Name
-                self.mnemonic = name
-
-        microopClasses[name] = LoadOp
-
-    code = '''
-        DataLow = Mem_u2qw[0];
-        DataHi = Mem_u2qw[1];
-    '''
-
-    defineMicroLoadSplitOp('LdSplit', code,
-                           'Request::READ_MODIFY_WRITE')
-
-    defineMicroLoadSplitOp('LdSplitl', code,
- 'Request::READ_MODIFY_WRITE | Request::LOCKED_RMW',
-                           nonSpec=True)
-
-    def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0",
-                           is_float=False, has_data=True):
-        global header_output
-        global decoder_output
-        global exec_output
-        global microopClasses
-        Name = mnemonic
-        name = mnemonic.lower()
-
-        if not has_data:
+    for cls in microopClasses.storeops:
+        if not cls.has_data:
             base = 'X86ISA::MemNoDataOp'
-        elif is_float:
+        elif cls.is_float:
             base = 'X86ISA::LdStFpOp'
         else:
             base = 'X86ISA::LdStOp'

         # Build up the all register version of this micro op
-        iop = InstObjParams(name, Name, base,
-                            { "code": code,
-                              "complete_code": completeCode,
+        iop = InstObjParams(cls.mnemonic, cls.className, base,
+                            { "code": cls.code,
                               "ea_code": calculateEA,
                               "memDataSize": "dataSize" })
         header_output += MicroLdStOpDeclare.subst(iop)
@@ -618,70 +358,14 @@
         exec_output += MicroStoreInitiateAcc.subst(iop)
         exec_output += MicroStoreCompleteAcc.subst(iop)

+    for cls in microopClasses.splitstoreops:
+        code = '''
+            Mem_u2qw[0] = DataLow;
+            Mem_u2qw[1] = DataHi;
+        '''

-        if has_data:
-            class StoreOp(LdStOp):
-                def __init__(self, data, segment, addr, disp=0,
- dataSize="env.dataSize", addressSize="env.addressSize",
-                        atCPL0=False, nonSpec=False, uncacheable=False):
-                    super().__init__(data, segment, addr, disp,
- dataSize, addressSize, mem_flags, atCPL0, False,
-                            nonSpec, uncacheable)
-                    self.className = Name
-                    self.mnemonic = name
-        else:
-            class StoreOp(MemNoDataOp):
-                def __init__(self, segment, addr, disp=0,
-                        dataSize="env.dataSize",
-                        addressSize="env.addressSize"):
-                    super().__init__(segment, addr, disp,
-                            dataSize, addressSize, mem_flags)
-                    self.className = Name
-                    self.mnemonic = name
-
-        microopClasses[name] = StoreOp
-
-    defineMicroStoreOp('St', 'Mem = PData;')
-    defineMicroStoreOp('Stis', 'Mem = PData;')
- defineMicroStoreOp('Stul', 'Mem = PData;', mem_flags="Request::LOCKED_RMW")
-
-    defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;', is_float=True)
-
-    defineMicroStoreOp('Stfp87', code='''
-        switch (dataSize)
-        {
-          case 4: {
-            float single(FpData_df);
-            Mem = *(uint32_t *)&single;
-          } break;
-          case 8:
-            Mem = *(uint64_t *)&FpData_df;
-            break;
-          default:
-            panic("Unhandled data size in StFp87.\\n");
-        }
-    ''', is_float=True)
-
-    defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS",
-                       has_data=False)
-    defineMicroStoreOp('Clflushopt', 'Mem = 0;',
-                       mem_flags="Request::CLEAN | Request::INVALIDATE" +
-                       " | Request::DST_POC", has_data=False)
-    defineMicroStoreOp('Clwb', 'Mem = 0;', has_data=False,
-                       mem_flags="Request::CLEAN | Request::DST_POC")
-
-    def defineMicroStoreSplitOp(mnemonic, code,
-                                completeCode="", mem_flags="0"):
-        global header_output
-        global decoder_output
-        global exec_output
-        global microopClasses
-        Name = mnemonic
-        name = mnemonic.lower()
-
-        iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp',
+ iop = InstObjParams(cls.mnemonic, cls.className, 'X86ISA::LdStSplitOp',
                             { "code": code,
-                              "complete_code": completeCode,
                               "ea_code": calculateEA,
                               "memDataSize": "2 * dataSize" })

@@ -691,29 +375,6 @@
         exec_output += MicroStoreInitiateAcc.subst(iop)
         exec_output += MicroStoreCompleteAcc.subst(iop)

-        class StoreOp(LdStSplitOp):
-            def __init__(self, data, segment, addr, disp = 0,
-                    dataSize="env.dataSize",
-                    addressSize="env.addressSize",
-                    atCPL0=False, nonSpec=False, uncacheable=False):
-                super().__init__(data, segment, addr, disp,
-                        dataSize, addressSize, mem_flags, atCPL0, False,
-                        nonSpec, uncacheable)
-                self.className = Name
-                self.mnemonic = name
-
-        microopClasses[name] = StoreOp
-
-    code = '''
-        Mem_u2qw[0] = DataLow;
-        Mem_u2qw[1] = DataHi;
-    '''
-
-    defineMicroStoreSplitOp('StSplit', code);
-
-    defineMicroStoreSplitOp('StSplitul', code,
-                            mem_flags='Request::LOCKED_RMW')
-
     iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
{ "code": "Data = merge(Data, data, EA, dataSize);",
                           "ea_code": "EA = " + segmentEAExpr,
@@ -721,17 +382,6 @@
     header_output += MicroLeaDeclare.subst(iop)
     exec_output += MicroLeaExecute.subst(iop)

-    class LeaOp(LdStOp):
-        def __init__(self, data, segment, addr, disp = 0,
-                dataSize="env.dataSize", addressSize="env.addressSize"):
-            super().__init__(data, segment, addr, disp,
-                    dataSize, addressSize, "0",
-                    False, False, False, False)
-            self.className = "Lea"
-            self.mnemonic = "lea"
-
-    microopClasses["lea"] = LeaOp
-

     iop = InstObjParams("tia", "Tia", 'X86ISA::MemNoDataOp',
                         { "code": "xc->demapPage(EA, 0);",
@@ -739,9 +389,4 @@
                           "memDataSize": "dataSize" })
     header_output += MicroLeaDeclare.subst(iop)
     exec_output += MicroLeaExecute.subst(iop)
-
-    class TiaOp(MemNoDataOp):
-        className = "Tia"
-        mnemonic = "tia"
-    microopClasses["tia"] = TiaOp
 }};
diff --git a/src/arch/x86/ucasmlib/arch/x86/microops/__init__.py b/src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
index 90f0c9e..3afee2a 100644
--- a/src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
+++ b/src/arch/x86/ucasmlib/arch/x86/microops/__init__.py
@@ -50,3 +50,11 @@
 # Add the load immediate microops.
 from . import limmop
 microops.update(limmop.microops)
+
+# Add the load/store microops.
+from . import ldstop
+microops.update(ldstop.microops)
+microops.loadops = ldstop.loadops
+microops.splitloadops = ldstop.splitloadops
+microops.storeops = ldstop.storeops
+microops.splitstoreops = ldstop.splitstoreops
diff --git a/src/arch/x86/ucasmlib/arch/x86/microops/ldstop.py b/src/arch/x86/ucasmlib/arch/x86/microops/ldstop.py
new file mode 100644
index 0000000..c2a5828
--- /dev/null
+++ b/src/arch/x86/ucasmlib/arch/x86/microops/ldstop.py
@@ -0,0 +1,384 @@
+# Copyright 2007-2008 The Hewlett-Packard Development Company
+# Copyright 2015 Advanced Micro Devices, Inc.
+#
+# 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.
+#
+# Copyright (c) 2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# 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.
+
+from .base import X86Microop
+
+microops = {}
+
+class LdStOp(X86Microop):
+    def __init__(self, data, segment, addr, disp,
+            dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+            uncacheable):
+        self.data = data
+        [self.scale, self.index, self.base] = addr
+        self.disp = disp
+        self.segment = segment
+        self.dataSize = dataSize
+        self.addressSize = addressSize
+        self.memFlags = baseFlags
+        if atCPL0:
+            self.memFlags += " | CPL0FlagBit"
+        self.instFlags = ""
+        if prefetch:
+            self.memFlags += " | Request::PREFETCH"
+            self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
+        if nonSpec:
+            self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
+        if uncacheable:
+            self.instFlags += " | Request::UNCACHEABLE"
+        self.memFlags += \
+            " | ((log2i(%s) & AddrSizeFlagMask) << AddrSizeFlagShift)" % \
+            addressSize
+
+    def getAllocator(self, microFlags):
+        allocator = '''new %(class_name)s(machInst, macrocodeBlock,
+                %(flags)s, %(dataSize)s, %(addressSize)s, %(memFlags)s,
+                %(data)s, %(scale)s, %(index)s, %(base)s,
+                %(disp)s, %(segment)s)''' % {
+            "class_name" : self.className,
+            "flags" : self.microFlagsText(microFlags) + self.instFlags,
+            "scale" : self.scale, "index" : self.index,
+            "base" : self.base,
+            "disp" : self.disp,
+            "segment" : self.segment, "data" : self.data,
+            "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+            "memFlags" : self.memFlags}
+        return allocator
+
+class BigLdStOp(X86Microop):
+    def __init__(self, data, segment, addr, disp,
+            dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+            uncacheable):
+        self.data = data
+        [self.scale, self.index, self.base] = addr
+        self.disp = disp
+        self.segment = segment
+        self.dataSize = dataSize
+        self.addressSize = addressSize
+        self.memFlags = baseFlags
+        if atCPL0:
+            self.memFlags += " | CPL0FlagBit"
+        self.instFlags = ""
+        if prefetch:
+            self.memFlags += " | Request::PREFETCH"
+            self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
+        if nonSpec:
+            self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
+        if uncacheable:
+            self.instFlags += " | Request::UNCACHEABLE"
+        self.memFlags += \
+            " | ((log2i(%s) & AddrSizeFlagMask) << AddrSizeFlagShift)" % \
+            addressSize
+
+    def getAllocator(self, microFlags):
+        allocString = '''
+            (%(dataSize)s >= 4) ?
+                (StaticInstPtr)(new %(class_name)sBig(machInst,
+                    macrocodeBlock, %(flags)s, %(dataSize)s,
+                    %(addressSize)s, %(memFlags)s, %(data)s, %(scale)s,
+                    %(index)s, %(base)s, %(disp)s, %(segment)s)) :
+                (StaticInstPtr)(new %(class_name)s(machInst,
+                    macrocodeBlock, %(flags)s, %(dataSize)s,
+                    %(addressSize)s, %(memFlags)s, %(data)s, %(scale)s,
+                    %(index)s, %(base)s, %(disp)s, %(segment)s))
+        '''
+        allocator = allocString % {
+            "class_name" : self.className,
+            "flags" : self.microFlagsText(microFlags) + self.instFlags,
+            "scale" : self.scale, "index" : self.index,
+            "base" : self.base,
+            "disp" : self.disp,
+            "segment" : self.segment, "data" : self.data,
+            "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+            "memFlags" : self.memFlags}
+        return allocator
+
+class LdStSplitOp(LdStOp):
+    def __init__(self, data, segment, addr, disp,
+            dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+            uncacheable):
+        super().__init__(0, segment, addr, disp,
+            dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+            uncacheable)
+        (self.dataLow, self.dataHi) = data
+
+    def getAllocator(self, microFlags):
+        allocString = '''(StaticInstPtr)(new %(class_name)s(machInst,
+                    macrocodeBlock, %(flags)s, %(dataLow)s, %(dataHi)s,
+                    %(scale)s, %(index)s, %(base)s, %(disp)s, %(segment)s,
+                    %(dataSize)s, %(addressSize)s, %(memFlags)s))
+        '''
+        allocator = allocString % {
+            "class_name" : self.className,
+            "flags" : self.microFlagsText(microFlags) + self.instFlags,
+            "scale" : self.scale, "index" : self.index,
+            "base" : self.base,
+            "disp" : self.disp,
+            "segment" : self.segment,
+            "dataLow" : self.dataLow, "dataHi" : self.dataHi,
+            "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+            "memFlags" : self.memFlags}
+        return allocator
+
+class MemNoDataOp(X86Microop):
+    def __init__(self, segment, addr, disp=0,
+            dataSize="env.dataSize", addressSize="env.addressSize",
+            baseFlags="0"):
+        [self.scale, self.index, self.base] = addr
+        self.disp = disp
+        self.segment = segment
+        self.dataSize = dataSize
+        self.addressSize = addressSize
+        self.instFlags = ""
+        self.memFlags = baseFlags + \
+            " | ((log2i(%s) & AddrSizeFlagMask) << AddrSizeFlagShift)" % \
+            addressSize
+
+    def getAllocator(self, microFlags):
+        allocator = '''new %(class_name)s(machInst, macrocodeBlock,
+                %(flags)s, %(dataSize)s, %(addressSize)s, %(memFlags)s,
+                %(scale)s, %(index)s, %(base)s, %(disp)s,
+                %(segment)s)''' % {
+            "class_name" : self.className,
+            "flags" : self.microFlagsText(microFlags) + self.instFlags,
+            "scale" : self.scale, "index" : self.index,
+            "base" : self.base,
+            "disp" : self.disp,
+            "segment" : self.segment,
+            "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+            "memFlags" : self.memFlags}
+        return allocator
+
+loadops = []
+
+def defineMicroLoadOp(Name, code, bigCode='',
+                      mem_flags="0", big=True, nonSpec=False,
+                      is_float=False):
+
+    _code = code
+    _big_code = bigCode
+    _big = big
+    _is_float = is_float
+    class LoadOp(BigLdStOp if big else LdStOp):
+        className = Name
+        mnemonic = Name.lower()
+        code = _code
+        bigCode = _big_code
+        big = _big
+        is_float = _is_float
+
+        def __init__(self, data, segment, addr, disp=0,
+                dataSize="env.dataSize", addressSize="env.addressSize",
+                atCPL0=False, prefetch=False, nonSpec=nonSpec,
+                uncacheable=False):
+            super().__init__(data, segment, addr,
+                    disp, dataSize, addressSize, mem_flags,
+                    atCPL0, prefetch, nonSpec, uncacheable)
+
+    microops[LoadOp.mnemonic] = LoadOp
+    loadops.append(LoadOp)
+
+defineMicroLoadOp('Ld', 'Data = merge(Data, data, Mem, dataSize);',
+                        'Data = Mem & mask(dataSize * 8);')
+defineMicroLoadOp('Ldst', 'Data = merge(Data, data, Mem, dataSize);',
+                          'Data = Mem & mask(dataSize * 8);',
+                  'Request::READ_MODIFY_WRITE')
+defineMicroLoadOp('Ldstl', 'Data = merge(Data, data, Mem, dataSize);',
+                           'Data = Mem & mask(dataSize * 8);',
+                  'Request::READ_MODIFY_WRITE | Request::LOCKED_RMW',
+                  nonSpec=True)
+
+defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big=False,
+        is_float=True)
+
+defineMicroLoadOp('Ldfp87', code='''
+    switch (dataSize)
+    {
+      case 4:
+        FpData_df = *(float *)&Mem;
+        break;
+      case 8:
+        FpData_df = *(double *)&Mem;
+        break;
+      default:
+        panic("Unhandled data size in LdFp87.\\n");
+    }
+''', big=False, is_float=True)
+
+# Load integer from memory into x87 top-of-stack register.
+# Used to implement fild instruction.
+defineMicroLoadOp('Ldifp87', code='''
+    switch (dataSize)
+    {
+      case 2:
+        FpData_df = (int64_t)sext<16>(Mem);
+        break;
+      case 4:
+        FpData_df = (int64_t)sext<32>(Mem);
+        break;
+      case 8:
+        FpData_df = (int64_t)Mem;
+        break;
+      default:
+        panic("Unhandled data size in LdIFp87.\\n");
+    }
+''', big=False, is_float=True)
+
+splitloadops = []
+
+def defineMicroLoadSplitOp(Name, mem_flags="0", nonSpec=False):
+    class LoadOp(LdStSplitOp):
+        className = Name
+        mnemonic = Name.lower()
+        def __init__(self, data, segment, addr, disp=0,
+                dataSize="env.dataSize", addressSize="env.addressSize",
+                atCPL0=False, prefetch=False, nonSpec=nonSpec,
+                uncacheable=False):
+            super().__init__(data, segment, addr,
+                    disp, dataSize, addressSize, mem_flags,
+                    atCPL0, prefetch, nonSpec, uncacheable)
+
+    microops[LoadOp.mnemonic] = LoadOp
+    splitloadops.append(LoadOp)
+
+defineMicroLoadSplitOp('LdSplit', 'Request::READ_MODIFY_WRITE')
+
+defineMicroLoadSplitOp('LdSplitl',
+                       'Request::READ_MODIFY_WRITE | Request::LOCKED_RMW',
+                       nonSpec=True)
+
+storeops = []
+
+def defineMicroStoreOp(Name, code, mem_flags="0",
+                       is_float=False, has_data=True):
+
+    _is_float = is_float
+    _has_data = has_data
+    _code = code
+    if has_data:
+        class StoreOp(LdStOp):
+            className = Name
+            mnemonic = Name.lower()
+            is_float = _is_float
+            has_data = _has_data
+            code = _code
+            def __init__(self, data, segment, addr, disp=0,
+                    dataSize="env.dataSize", addressSize="env.addressSize",
+                    atCPL0=False, nonSpec=False, uncacheable=False):
+                super().__init__(data, segment, addr, disp,
+                        dataSize, addressSize, mem_flags, atCPL0, False,
+                        nonSpec, uncacheable)
+    else:
+        class StoreOp(MemNoDataOp):
+            className = Name
+            mnemonic = Name.lower()
+            is_float = _is_float
+            has_data = _has_data
+            code = _code
+            def __init__(self, segment, addr, disp=0,
+ dataSize="env.dataSize", addressSize="env.addressSize"):
+                super().__init__(segment, addr, disp,
+                        dataSize, addressSize, mem_flags)
+
+    microops[StoreOp.mnemonic] = StoreOp
+    storeops.append(StoreOp)
+
+defineMicroStoreOp('St', 'Mem = PData;')
+defineMicroStoreOp('Stis', 'Mem = PData;')
+defineMicroStoreOp('Stul', 'Mem = PData;', mem_flags="Request::LOCKED_RMW")
+
+defineMicroStoreOp('Stfp', 'Mem = FpData_uqw;', is_float=True)
+
+defineMicroStoreOp('Stfp87', '''
+    switch (dataSize)
+    {
+      case 4: {
+        float single(FpData_df);
+        Mem = *(uint32_t *)&single;
+      } break;
+      case 8:
+        Mem = *(uint64_t *)&FpData_df;
+        break;
+      default:
+        panic("Unhandled data size in StFp87.\\n");
+    }
+''', is_float=True)
+
+defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS",
+                   has_data=False)
+defineMicroStoreOp('Clflushopt', 'Mem = 0;',
+                   mem_flags="Request::CLEAN | Request::INVALIDATE" +
+                   " | Request::DST_POC", has_data=False)
+defineMicroStoreOp('Clwb', 'Mem = 0;', has_data=False,
+                   mem_flags="Request::CLEAN | Request::DST_POC")
+
+splitstoreops = []
+
+def defineMicroStoreSplitOp(Name, mem_flags="0"):
+    class StoreOp(LdStSplitOp):
+        className = Name
+        mnemonic = Name.lower()
+        def __init__(self, data, segment, addr, disp=0,
+                dataSize="env.dataSize", addressSize="env.addressSize",
+                atCPL0=False, nonSpec=False, uncacheable=False):
+            super().__init__(data, segment, addr, disp,
+                    dataSize, addressSize, mem_flags, atCPL0, False,
+                    nonSpec, uncacheable)
+
+    microops[StoreOp.mnemonic] = StoreOp
+    splitstoreops.append(StoreOp)
+
+defineMicroStoreSplitOp('StSplit');
+defineMicroStoreSplitOp('StSplitul', mem_flags='Request::LOCKED_RMW')
+
+class LeaOp(LdStOp):
+    def __init__(self, data, segment, addr, disp = 0,
+            dataSize="env.dataSize", addressSize="env.addressSize"):
+        super().__init__(data, segment, addr, disp,
+                dataSize, addressSize, "0",
+                False, False, False, False)
+        self.className = "Lea"
+        self.mnemonic = "lea"
+
+microops["lea"] = LeaOp
+
+class TiaOp(MemNoDataOp):
+    className = "Tia"
+    mnemonic = "tia"
+
+microops["tia"] = TiaOp

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/56492
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I0fd3d1193b42c90b5ae74c2fe52ef5a95aa9636e
Gerrit-Change-Number: 56492
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to