X86: Implement the ldstl microop.
[gem5.git] / src / arch / x86 / isa / microops / ldstop.isa
index 2e98a42bf945df69f9647963190e7b923ee14fc5..5df423ea9770a1b130dc34775ae366edfa506acc 100644 (file)
@@ -1,4 +1,32 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// 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.
+//
+// Authors: Gabe Black
+
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,
@@ -96,14 +124,16 @@ def template MicroLeaDeclare {{
                 uint8_t _scale, RegIndex _index, RegIndex _base,
                 uint64_t _disp, uint8_t _segment,
                 RegIndex _data,
-                uint8_t _dataSize, uint8_t _addressSize);
+                uint8_t _dataSize, uint8_t _addressSize,
+                Request::FlagsType _memFlags);
 
         %(class_name)s(ExtMachInst _machInst,
                 const char * instMnem,
                 uint8_t _scale, RegIndex _index, RegIndex _base,
                 uint64_t _disp, uint8_t _segment,
                 RegIndex _data,
-                uint8_t _dataSize, uint8_t _addressSize);
+                uint8_t _dataSize, uint8_t _addressSize,
+                Request::FlagsType _memFlags);
 
         %(BasicExecDeclare)s
     };
@@ -123,10 +153,13 @@ def template MicroLoadExecute {{
         %(ea_code)s;
         DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
 
-        fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
-        if(fault == NoFault)
-        {
+        fault = read(xc, EA, Mem, memFlags);
+
+        if (fault == NoFault) {
             %(code)s;
+        } else if (memFlags & Request::PF_EXCLUSIVE) {
+            // For prefetches, ignore any faults/exceptions.
+            return NoFault;
         }
         if(fault == NoFault)
         {
@@ -149,7 +182,7 @@ def template MicroLoadInitiateAcc {{
         %(ea_code)s;
         DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
 
-        fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
+        fault = read(xc, EA, Mem, memFlags);
 
         return fault;
     }
@@ -165,7 +198,8 @@ def template MicroLoadCompleteAcc {{
         %(op_decl)s;
         %(op_rd)s;
 
-        Mem = pkt->get<typeof(Mem)>();
+        Mem = get(pkt);
+
         %(code)s;
 
         if(fault == NoFault)
@@ -195,12 +229,12 @@ def template MicroStoreExecute {{
 
         if(fault == NoFault)
         {
-            fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
-                    EA, 0, 0);
-        }
-        if(fault == NoFault)
-        {
-            %(op_wb)s;
+            fault = write(xc, Mem, EA, memFlags);
+            if(fault == NoFault)
+            {
+                %(post_code)s;
+                %(op_wb)s;
+            }
         }
 
         return fault;
@@ -223,21 +257,20 @@ def template MicroStoreInitiateAcc {{
 
         if(fault == NoFault)
         {
-            fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
-                    EA, 0, 0);
-        }
-        if(fault == NoFault)
-        {
-            %(op_wb)s;
+            write(xc, Mem, EA, memFlags);
         }
         return fault;
     }
 }};
 
 def template MicroStoreCompleteAcc {{
-    Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
-            Trace::InstRecord * traceData) const
+    Fault %(class_name)s::completeAcc(PacketPtr pkt,
+            %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const
     {
+        %(op_decl)s;
+        %(op_rd)s;
+        %(complete_code)s;
+        %(op_wb)s;
         return NoFault;
     }
 }};
@@ -267,14 +300,16 @@ def template MicroLdStOpDeclare {{
                 uint8_t _scale, RegIndex _index, RegIndex _base,
                 uint64_t _disp, uint8_t _segment,
                 RegIndex _data,
-                uint8_t _dataSize, uint8_t _addressSize);
+                uint8_t _dataSize, uint8_t _addressSize,
+                Request::FlagsType _memFlags);
 
         %(class_name)s(ExtMachInst _machInst,
                 const char * instMnem,
                 uint8_t _scale, RegIndex _index, RegIndex _base,
                 uint64_t _disp, uint8_t _segment,
                 RegIndex _data,
-                uint8_t _dataSize, uint8_t _addressSize);
+                uint8_t _dataSize, uint8_t _addressSize,
+                Request::FlagsType _memFlags);
 
         %(BasicExecDeclare)s
 
@@ -296,12 +331,13 @@ def template MicroLdStOpConstructor {{
             uint8_t _scale, RegIndex _index, RegIndex _base,
             uint64_t _disp, uint8_t _segment,
             RegIndex _data,
-            uint8_t _dataSize, uint8_t _addressSize) :
+            uint8_t _dataSize, uint8_t _addressSize,
+            Request::FlagsType _memFlags) :
         %(base_class)s(machInst, "%(mnemonic)s", instMnem,
                 false, false, false, false,
                 _scale, _index, _base,
                 _disp, _segment, _data,
-                _dataSize, _addressSize, %(op_class)s)
+                _dataSize, _addressSize, _memFlags, %(op_class)s)
     {
         buildMe();
     }
@@ -312,12 +348,13 @@ def template MicroLdStOpConstructor {{
             uint8_t _scale, RegIndex _index, RegIndex _base,
             uint64_t _disp, uint8_t _segment,
             RegIndex _data,
-            uint8_t _dataSize, uint8_t _addressSize) :
+            uint8_t _dataSize, uint8_t _addressSize,
+            Request::FlagsType _memFlags) :
         %(base_class)s(machInst, "%(mnemonic)s", instMnem,
                 isMicro, isDelayed, isFirst, isLast,
                 _scale, _index, _base,
                 _disp, _segment, _data,
-                _dataSize, _addressSize, %(op_class)s)
+                _dataSize, _addressSize, _memFlags, %(op_class)s)
     {
         buildMe();
     }
@@ -325,26 +362,35 @@ def template MicroLdStOpConstructor {{
 
 let {{
     class LdStOp(X86Microop):
-        def __init__(self, data, segment, addr, disp):
+        def __init__(self, data, segment, addr, disp,
+                dataSize, addressSize, baseFlags, atCPL0, prefetch):
             self.data = data
             [self.scale, self.index, self.base] = addr
             self.disp = disp
             self.segment = segment
-            self.dataSize = "env.dataSize"
-            self.addressSize = "env.addressSize"
+            self.dataSize = dataSize
+            self.addressSize = addressSize
+            self.memFlags = baseFlags
+            if atCPL0:
+                self.memFlags += " | (CPL0FlagBit << FlagShift)"
+            if prefetch:
+                self.memFlags += " | Request::PF_EXCLUSIVE"
+            self.memFlags += " | (machInst.legacy.addr ? " + \
+                             "(AddrSizeFlagBit << FlagShift) : 0)"
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, mnemonic
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock
                     %(flags)s, %(scale)s, %(index)s, %(base)s,
                     %(disp)s, %(segment)s, %(data)s,
-                    %(dataSize)s, %(addressSize)s)''' % {
+                    %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
                 "class_name" : self.className,
                 "flags" : self.microFlagsText(microFlags),
                 "scale" : self.scale, "index" : self.index,
                 "base" : self.base,
                 "disp" : self.disp,
                 "segment" : self.segment, "data" : self.data,
-                "dataSize" : self.dataSize, "addressSize" : self.addressSize}
+                "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+                "memFlags" : self.memFlags}
             return allocator
 }};
 
@@ -356,9 +402,11 @@ let {{
     decoder_output = ""
     exec_output = ""
 
-    calculateEA = "EA = scale * Index + Base + disp;"
+    calculateEA = '''
+    EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0);
+    '''
 
-    def defineMicroLoadOp(mnemonic, code):
+    def defineMicroLoadOp(mnemonic, code, mem_flags="0"):
         global header_output
         global decoder_output
         global exec_output
@@ -368,7 +416,8 @@ let {{
 
         # Build up the all register version of this micro op
         iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
-                {"code": code, "ea_code": calculateEA})
+                {"code": code,
+                 "ea_code": calculateEA})
         header_output += MicroLdStOpDeclare.subst(iop)
         decoder_output += MicroLdStOpConstructor.subst(iop)
         exec_output += MicroLoadExecute.subst(iop)
@@ -376,16 +425,27 @@ let {{
         exec_output += MicroLoadCompleteAcc.subst(iop)
 
         class LoadOp(LdStOp):
-            def __init__(self, data, segment, addr, disp = 0):
-                super(LoadOp, self).__init__(data, segment, addr, disp)
+            def __init__(self, data, segment, addr, disp = 0,
+                    dataSize="env.dataSize",
+                    addressSize="env.addressSize",
+                    atCPL0=False, prefetch=False):
+                super(LoadOp, self).__init__(data, segment, addr,
+                        disp, dataSize, addressSize, mem_flags,
+                        atCPL0, prefetch)
                 self.className = Name
                 self.mnemonic = name
 
         microopClasses[name] = LoadOp
 
     defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
-
-    def defineMicroStoreOp(mnemonic, code):
+    defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
+            'X86ISA::StoreCheck')
+    defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);',
+            'X86ISA::StoreCheck | Request::LOCKED')
+    defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
+
+    def defineMicroStoreOp(mnemonic, code, \
+            postCode="", completeCode="", mem_flags="0"):
         global header_output
         global decoder_output
         global exec_output
@@ -395,7 +455,10 @@ let {{
 
         # Build up the all register version of this micro op
         iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
-                {"code": code, "ea_code": calculateEA})
+                {"code": code,
+                 "post_code": postCode,
+                 "complete_code": completeCode,
+                 "ea_code": calculateEA})
         header_output += MicroLdStOpDeclare.subst(iop)
         decoder_output += MicroLdStOpConstructor.subst(iop)
         exec_output += MicroStoreExecute.subst(iop)
@@ -403,27 +466,71 @@ let {{
         exec_output += MicroStoreCompleteAcc.subst(iop)
 
         class StoreOp(LdStOp):
-            def __init__(self, data, segment, addr, disp = 0):
-                super(LoadOp, self).__init__(data, segment, addr, disp)
+            def __init__(self, data, segment, addr, disp = 0,
+                    dataSize="env.dataSize",
+                    addressSize="env.addressSize",
+                    atCPL0=False):
+                super(StoreOp, self).__init__(data, segment, addr,
+                        disp, dataSize, addressSize, mem_flags, atCPL0, False)
                 self.className = Name
                 self.mnemonic = name
 
         microopClasses[name] = StoreOp
 
-    defineMicroLoadOp('St', 'Mem = Data;')
+    defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
+    defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
+    defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);',
+            'Base = merge(Base, EA - SegBase, addressSize);',
+            'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);');
+    defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
 
     iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
-            {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA})
+            {"code": "Data = merge(Data, EA, dataSize);",
+             "ea_code": '''
+             EA = bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);
+             '''})
     header_output += MicroLeaDeclare.subst(iop)
     decoder_output += MicroLdStOpConstructor.subst(iop)
     exec_output += MicroLeaExecute.subst(iop)
 
     class LeaOp(LdStOp):
-        def __init__(self, data, segment, addr, disp = 0):
-            super(LeaOp, self).__init__(data, segment, addr, disp)
+        def __init__(self, data, segment, addr, disp = 0,
+                dataSize="env.dataSize", addressSize="env.addressSize"):
+            super(LeaOp, self).__init__(data, segment,
+                    addr, disp, dataSize, addressSize, "0", False, False)
             self.className = "Lea"
             self.mnemonic = "lea"
 
     microopClasses["lea"] = LeaOp
+
+
+    iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
+            {"code": "xc->demapPage(EA, 0);",
+             "ea_code": calculateEA})
+    header_output += MicroLeaDeclare.subst(iop)
+    decoder_output += MicroLdStOpConstructor.subst(iop)
+    exec_output += MicroLeaExecute.subst(iop)
+
+    class TiaOp(LdStOp):
+        def __init__(self, segment, addr, disp = 0,
+                dataSize="env.dataSize",
+                addressSize="env.addressSize"):
+            super(TiaOp, self).__init__("NUM_INTREGS", segment,
+                    addr, disp, dataSize, addressSize, "0", False, False)
+            self.className = "Tia"
+            self.mnemonic = "tia"
+
+    microopClasses["tia"] = TiaOp
+
+    class CdaOp(LdStOp):
+        def __init__(self, segment, addr, disp = 0,
+                dataSize="env.dataSize",
+                addressSize="env.addressSize", atCPL0=False):
+            super(CdaOp, self).__init__("NUM_INTREGS", segment,
+                    addr, disp, dataSize, addressSize, "0", atCPL0, False)
+            self.className = "Cda"
+            self.mnemonic = "cda"
+
+    microopClasses["cda"] = CdaOp
 }};