misc: Merge branch v20.1.0.3 hotfix into develop
[gem5.git] / src / arch / x86 / isa / microops / specop.isa
index a3ca7d91cdd501617f786b58bc7153e9e8387202..aad171a56c9dd18bdfdcb842fb134d9193d4e4c6 100644 (file)
@@ -1,43 +1,26 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
+// Copyright (c) 2011 Mark D. Hill and David A. Wood
 // All rights reserved.
 //
-// Redistribution and use of this software in source and binary forms,
-// with or without modification, are permitted provided that the
-// following conditions are met:
+// 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.
 //
-// The software must be used only for Non-Commercial Use which means any
-// use which is NOT directed to receiving any direct monetary
-// compensation for, or commercial advantage from such use.  Illustrative
-// examples of non-commercial use are academic research, personal study,
-// teaching, education and corporate research & development.
-// Illustrative examples of commercial use are distributing products for
-// commercial advantage and providing services using the software for
-// commercial advantage.
-//
-// If you wish to use this software or functionality therein that may be
-// covered by patents for commercial use, please contact:
-//     Director of Intellectual Property Licensing
-//     Office of Strategy and Technology
-//     Hewlett-Packard Company
-//     1501 Page Mill Road
-//     Palo Alto, California  94304
-//
-// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// 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.  No right of
-// sublicense is granted herewith.  Derivatives of the software and
-// output created using the software may be prepared, but only for
-// Non-Commercial Uses.  Derivatives of the software may be shared with
-// others provided: (i) the others agree to abide by the list of
-// conditions herein which includes the Non-Commercial Use restrictions;
-// and (ii) such Derivatives of the software include the above copyright
-// notice to acknowledge the contribution from this software where
-// applicable, this list of conditions and the disclaimer below.
+// 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
@@ -50,8 +33,6 @@
 // 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
 
 //////////////////////////////////////////////////////////////////////////
 //
 //
 //////////////////////////////////////////////////////////////////////////
 
-def template MicroFaultExecute {{
-        Fault %(class_name)s ::execute(%(CPU_exec_context)s *xc,
-                Trace::InstRecord *traceData) const
+output header {{
+    class MicroFaultBase : public X86ISA::X86MicroopBase
+    {
+      protected:
+        Fault fault;
+        uint8_t cc;
+
+      public:
+        MicroFaultBase(ExtMachInst _machInst, const char * instMnem,
+                uint64_t setFlags, Fault _fault, uint8_t _cc);
+
+        std::string generateDisassembly(Addr pc,
+                const Loader::SymbolTable *symtab) const override;
+    };
+
+    class MicroHalt : public X86ISA::X86MicroopBase
+    {
+      public:
+        MicroHalt(ExtMachInst _machInst, const char * instMnem,
+                uint64_t setFlags) :
+            X86MicroopBase(_machInst, "halt", instMnem,
+                           setFlags | (ULL(1) << StaticInst::IsNonSpeculative) |
+                           (ULL(1) << StaticInst::IsQuiesce),
+                           No_OpClass)
         {
-            //Return the fault we were constructed with
-            return fault;
         }
+
+        Fault execute(ExecContext *, Trace::InstRecord *) const override;
+
+        std::string generateDisassembly(Addr pc,
+                const Loader::SymbolTable *symtab) const override;
+    };
 }};
 
 def template MicroFaultDeclare {{
-    class %(class_name)s : public X86MicroOpBase
+    class %(class_name)s : public %(base_class)s
     {
-      protected:
-        Fault fault;
-        void buildMe();
+      private:
+        %(reg_idx_arr_decl)s;
 
       public:
-        %(class_name)s(ExtMachInst _machInst,
-                const char * instMnem,
-                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
-                Fault _fault);
-
-        %(class_name)s(ExtMachInst _machInst,
-                const char * instMnem,
-                Fault _fault);
+        %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+                uint64_t setFlags, Fault _fault, uint8_t _cc);
 
-        %(BasicExecDeclare)s
+        Fault execute(ExecContext *, Trace::InstRecord *) const override;
     };
 }};
 
-def template MicroFaultConstructor {{
+def template MicroFaultExecute {{
+        Fault %(class_name)s::execute(ExecContext *xc,
+                Trace::InstRecord *traceData) const
+        {
+            %(op_decl)s;
+            %(op_rd)s;
+            if (%(cond_test)s) {
+                //Return the fault we were constructed with
+                return fault;
+            } else {
+                return NoFault;
+            }
+        }
+}};
+
+output exec {{
+    Fault
+    MicroHalt::execute(ExecContext *xc, Trace::InstRecord * traceData) const
+    {
+        xc->tcBase()->suspend();
+        return NoFault;
+    }
+}};
 
-    inline void %(class_name)s::buildMe()
+output decoder {{
+    MicroFaultBase::MicroFaultBase(
+            ExtMachInst machInst, const char * instMnem,
+            uint64_t setFlags, Fault _fault, uint8_t _cc) :
+        X86MicroopBase(machInst, "fault", instMnem, setFlags, No_OpClass),
+                fault(_fault), cc(_cc)
     {
+    }
+}};
+
+def template MicroFaultConstructor {{
+    %(class_name)s::%(class_name)s(
+            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
+            Fault _fault, uint8_t _cc) :
+        %(base_class)s(machInst, instMnem, setFlags, _fault, _cc)
+    {
+        %(set_reg_idx_arr)s;
         %(constructor)s;
     }
+}};
 
-    inline %(class_name)s::%(class_name)s(
-            ExtMachInst machInst, const char * instMnem, Fault _fault) :
-        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                false, false, false, false, %(op_class)s), fault(_fault)
+output decoder {{
+    std::string
+    MicroFaultBase::generateDisassembly(
+            Addr pc, const Loader::SymbolTable *symtab) const
     {
-        buildMe();
+        std::stringstream response;
+
+        printMnemonic(response, instMnem, mnemonic);
+        if(fault)
+            response << fault->name();
+        else
+            response << "No Fault";
+
+        return response.str();
     }
 
-    inline %(class_name)s::%(class_name)s(
-            ExtMachInst machInst, const char * instMnem,
-            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
-            Fault _fault) :
-        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                isMicro, isDelayed, isFirst, isLast, %(op_class)s),
-                fault(_fault)
+    std::string
+    MicroHalt::generateDisassembly(
+            Addr pc, const Loader::SymbolTable *symtab) const
     {
-        buildMe();
+        std::stringstream response;
+
+        printMnemonic(response, instMnem, mnemonic);
+
+        return response.str();
     }
 }};
 
 let {{
-    # This microop takes in a single parameter, a fault to return.
-    iop = InstObjParams("fault", "GenFault", 'X86MicroOpBase', {"code" : ""})
+    class Fault(X86Microop):
+        className = "MicroFault"
+        def __init__(self, fault, flags=None):
+            self.fault = fault
+            if flags:
+                if not isinstance(flags, (list, tuple)):
+                    raise Exception("flags must be a list or tuple of flags")
+                self.cond = " | ".join(flags)
+                self.className += "Flags"
+            else:
+                self.cond = "0"
+
+        def getAllocator(self, microFlags):
+            allocator = '''new %(class_name)s(machInst, macrocodeBlock,
+                    %(flags)s, %(fault)s, %(cc)s)''' % {
+                "class_name" : self.className,
+                "flags" : self.microFlagsText(microFlags),
+                "fault" : self.fault,
+                "cc" : self.cond}
+            return allocator
+
+    iop = InstObjParams("fault", "MicroFaultFlags", "MicroFaultBase",
+            {"code": "",
+             "cond_test": "checkCondition(ccFlagBits | cfofBits | dfBit | \
+                                          ecfBit | ezfBit, cc)"})
+    exec_output = MicroFaultExecute.subst(iop)
+    header_output = MicroFaultDeclare.subst(iop)
+    decoder_output = MicroFaultConstructor.subst(iop)
+    iop = InstObjParams("fault", "MicroFault", "MicroFaultBase",
+            {"code": "",
+             "cond_test": "true"})
+    exec_output += MicroFaultExecute.subst(iop)
     header_output += MicroFaultDeclare.subst(iop)
     decoder_output += MicroFaultConstructor.subst(iop)
-    exec_output += MicroFaultExecute.subst(iop)
+    microopClasses["fault"] = Fault
+
+    class Halt(X86Microop):
+        className = "MicroHalt"
+        def __init__(self):
+            pass
+
+        def getAllocator(self, microFlags):
+            return "new MicroHalt(machInst, macrocodeBlock, %s)" % \
+                    self.microFlagsText(microFlags)
+
+    microopClasses["halt"] = Halt
+}};
+
+def template MicroFenceOpDeclare {{
+    class %(class_name)s : public X86ISA::X86MicroopBase
+    {
+      private:
+        %(reg_idx_arr_decl)s;
+
+      public:
+        %(class_name)s(ExtMachInst _machInst,
+                const char * instMnem,
+                uint64_t setFlags);
+
+        Fault execute(ExecContext *, Trace::InstRecord *) const override;
+    };
+}};
+
+def template MicroFenceOpConstructor {{
+    %(class_name)s::%(class_name)s(
+            ExtMachInst machInst, const char * instMnem, uint64_t setFlags) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                setFlags, %(op_class)s)
+    {
+        %(set_reg_idx_arr)s;
+        %(constructor)s;
+    }
+}};
+
+let {{
+    class MfenceOp(X86Microop):
+        def __init__(self):
+            self.className = "Mfence"
+            self.mnemonic = "mfence"
+            self.instFlags = "| (1ULL << StaticInst::IsReadBarrier)" + \
+                             "| (1ULL << StaticInst::IsWriteBarrier)"
+
+        def getAllocator(self, microFlags):
+            allocString = '''
+                    (StaticInstPtr)(new %(class_name)s(machInst,
+                        macrocodeBlock, %(flags)s))
+            '''
+            allocator = allocString % {
+                "class_name" : self.className,
+                "mnemonic" : self.mnemonic,
+                "flags" : self.microFlagsText(microFlags) + self.instFlags}
+            return allocator
+
+    microopClasses["mfence"] = MfenceOp
+}};
+
+let {{
+    # Build up the all register version of this micro op
+    iop = InstObjParams("mfence", "Mfence", 'X86MicroopBase',
+            {"code" : ""})
+    header_output += MicroFenceOpDeclare.subst(iop)
+    decoder_output += MicroFenceOpConstructor.subst(iop)
+    exec_output += BasicExecute.subst(iop)
 }};