Reworking x86's microcode system. This is a work in progress, and X86 doesn't compile.
authorGabe Black <gblack@eecs.umich.edu>
Mon, 4 Jun 2007 15:59:20 +0000 (15:59 +0000)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 4 Jun 2007 15:59:20 +0000 (15:59 +0000)
src/arch/x86/isa/decoder/one_byte_opcodes.isa:
src/arch/x86/isa/macroop.isa:
src/arch/x86/isa/main.isa:
src/arch/x86/isa/microasm.isa:
src/arch/x86/isa/microops/base.isa:
src/arch/x86/isa/microops/microops.isa:
src/arch/x86/isa/operands.isa:
src/arch/x86/isa/microops/regop.isa:
src/arch/x86/isa/microops/specop.isa:
    Reworking x86's microcode system

--HG--
extra : convert_revision : cab66be59ed758b192226af17eddd5a86aa190f3

src/arch/x86/isa/decoder/one_byte_opcodes.isa
src/arch/x86/isa/macroop.isa
src/arch/x86/isa/main.isa
src/arch/x86/isa/microasm.isa
src/arch/x86/isa/microops/base.isa
src/arch/x86/isa/microops/microops.isa
src/arch/x86/isa/microops/regop.isa [new file with mode: 0644]
src/arch/x86/isa/microops/specop.isa [new file with mode: 0644]
src/arch/x86/isa/operands.isa

index 12f3c5f96b8411bf73409f977d215b2a5acc7708..0ee9c53c6718da40dccf34c242933c5e993e67d6 100644 (file)
 0x1: decode OPCODE_OP_TOP5 {
     format WarnUnimpl {
         0x00: decode OPCODE_OP_BOTTOM3 {
-            0x4: Inst::ADD(rAl,Ib);
-            0x5: Inst::ADD(rAx,Iz);
+            0x4: ADD();
+            0x5: ADD();
             0x6: push_ES();
             0x7: pop_ES();
-            default: MultiInst::ADD(OPCODE_OP_BOTTOM3,
-                             [Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
+            default: ADD();
         }
         0x01: decode OPCODE_OP_BOTTOM3 {
             0x0: or_Eb_Gb();
             0x7: das();
         }
         0x06: decode OPCODE_OP_BOTTOM3 {
-            0x4: Inst::XOR(rAl,Ib);
-            0x5: Inst::XOR(rAx,Iz);
+            0x4: Inst::XOR(ALIb);
+            0x5: Inst::XOR(rAX,Iz);
             0x6: M5InternalError::error(
                 {{"Tried to execute the SS segment override prefix!"}});
             0x7: aaa();
-            default: MultiInst::XOR(OPCODE_OP_BOTTOM3,
-                                    [Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
+            default: MultiInst::XOR(EbGb, EvGv, GbEb, GvEv);
         }
         0x07: decode OPCODE_OP_BOTTOM3 {
             0x0: cmp_Eb_Gb();
             0x7: xchg_Ev_Gv();
         }
         0x11: decode OPCODE_OP_BOTTOM3 {
-            0x0: Inst::MOV(Eb, Gb);
-            0x1: Inst::MOV(Ev, Gv);
-            0x2: Inst::MOV(Gb, Eb);
-            0x3: Inst::MOV(Gv, Ev);
+            0x0: MOV();
+            0x1: MOV();
+            0x2: MOV();
+            0x3: MOV();
             0x4: mov_MwRv_Sw(); //What to do with this one?
             0x5: lea_Gv_M();
             0x6: mov_Sw_MwRv();
index 663ec7aeeed33dbeb74616b68456a5e2b708a3d6..ba21c41a78a63e9a3cc9eb67e2c44433ba4470bb 100644 (file)
@@ -149,7 +149,8 @@ let {{
         for op in opSeq:
             allocMicroOps += \
                 "microOps[%d] = %s;\n" % \
-                (micropc, op.getAllocator('"' + name + '"', True, False, #op.delayed,
+                (micropc, op.getAllocator('"' + name + '"', True, False,
+                                          #op.delayed,
                                           micropc == 0,
                                           micropc == numMicroOps - 1))
             micropc += 1
index 063d7125d7feb11f7f2dfec9800e3ae42f7799a8..a9f01d3e045efa7074d58d6560cb75febbfd59ff 100644 (file)
@@ -81,10 +81,6 @@ namespace X86ISA;
 //Include code to build macroops.
 ##include "macroop.isa"
 
-//Include the simple microcode assembler. This will hopefully stay
-//unspecialized for x86 and can later be made available to other ISAs.
-##include "microasm.isa"
-
 ////////////////////////////////////////////////////////////////////
 //
 // X86 only infrastructure code.
index 9d21b6bcc1f8deed74110463ad30b0817b5ca1e8..50a0b10e79c70a40ac58cace908c9616328ad4db 100644 (file)
 
 ////////////////////////////////////////////////////////////////////
 //
-//  The microcode assembler
+// Microcode assembler specialization for x86
 //
 
 let {{
-    # These are used when setting up microops so that they can specialize their
-    # base class template properly.
-    RegOpType = "RegisterOperand"
-    ImmOpType = "ImmediateOperand"
+    from micro_asm import MicroAssembler, Combinational_Macroop, Rom_Macroop, Rom
+    class X86Macroop(Combinational_Macroop):
+        def __init__(self, name):
+            super(X86Macroop, self).__init__(name)
+            self.directives = {
+            }
+
+    mainRom = Rom('main ROM')
 }};
 
 let {{
-    class MicroOpStatement(object):
-        def __init__(self):
-            self.className = ''
-            self.label = ''
-            self.args = []
+    class X86Microop(object):
+        def __init__(self, name):
+            self.name = name
 
         # This converts a list of python bools into
         # a comma seperated list of C++ bools.
@@ -87,145 +89,5 @@ let {{
 
         def getAllocator(self, mnemonic, *microFlags):
             args = ''
-            signature = "<"
-            emptySig = True
-            for arg in self.args:
-                if not emptySig:
-                    signature += ", "
-                emptySig = False
-                if arg.has_key("operandImm"):
-                    args += ", %s" % arg["operandImm"]
-                    signature += ImmOpType
-                elif arg.has_key("operandReg"):
-                    args += ", %s" % arg["operandReg"]
-                    signature += RegOpType
-                elif arg.has_key("operandLabel"):
-                    raise Exception, "Found a label while creating allocator string."
-                else:
-                    raise Exception, "Unrecognized operand type."
-            signature += ">"
-            return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args)
-}};
-
-let{{
-    def assembleMicro(name, Name, code):
-
-        # This function takes in a block of microcode assembly and returns
-        # a python list of objects which describe it.
-
-        # Keep this around in case we need it later
-        orig_code = code
-        # A list of the statements we've found thus far
-        statements = []
-
-        # Regular expressions to pull each piece of the statement out at a
-        # time. Each expression expects the thing it's looking for to be at
-        # the beginning of the line, so the previous component is stripped
-        # before continuing.
-        labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:')
-        lineRe = re.compile(r'^(?P<line>..*)(\n|$)')
-        classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)')
-        # This recognizes three different flavors of operands:
-        # 1. Raw decimal numbers composed of digits between 0 and 9
-        # 2. Code beginning with "{" and continuing until the first "}"
-        #         ^ This one might need revising
-        # 3. A label, which starts with a capital or small letter, or
-        #    underscore, which is optionally followed by a sequence of
-        #    capital or small letters, underscores, or digts between 0 and 9
-        opRe = re.compile( \
-            r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' +
-                    r'(\@\{(?P<operandLabel1>[^}]*)\})|' +
-                    r'(\%(?P<operandReg0>\w\w*))|' +
-                    r'(\%\{(?P<operandReg1>[^}]*)\})|' +
-                    r'(\$(?P<operandImm0>\w\w*))|' +
-                    r'(\$\{(?P<operandImm1>[^}]*)\}))')
-        lineMatch = lineRe.search(code)
-        while lineMatch != None:
-            statement = MicroOpStatement()
-            # Get a line and seperate it from the rest of the code
-            line = lineMatch.group("line")
-            orig_line = line
-            #print "Parsing line %s" % line
-            code = lineRe.sub('', code, 1)
-
-            # Find the label, if any
-            labelMatch = labelRe.search(line)
-            if labelMatch != None:
-                statement.label = labelMatch.group("label")
-                #print "Found label %s." % statement.label
-            # Clear the label from the statement
-            line = labelRe.sub('', line, 1)
-
-            # Find the class name which is roughly equivalent to the op name
-            classMatch = classRe.search(line)
-            if classMatch == None:
-                raise Exception, "Couldn't find class name in statement: %s" \
-                        % orig_line
-            else:
-                statement.className = classMatch.group("className")
-                #print "Found class name %s." % statement.className
-
-            # Clear the class name from the statement
-            line = classRe.sub('', line, 1)
-
-            #Find as many arguments as you can
-            statement.args = []
-            opMatch = opRe.search(line)
-            while opMatch is not None:
-                statement.args.append({})
-                # args is a list of dicts which collect different
-                # representations of operand values. Different forms might be
-                # needed in different places, for instance to replace a label
-                # with an offset.
-                for opType in ("operandLabel0", "operandReg0", "operandImm0",
-                               "operandLabel1", "operandReg1", "operandImm1"):
-                    if opMatch.group(opType):
-                        statement.args[-1][opType[:-1]] = opMatch.group(opType)
-                if len(statement.args[-1]) == 0:
-                    print "Problem parsing operand in statement: %s" \
-                            % orig_line
-                line = opRe.sub('', line, 1)
-                #print "Found operand %s." % statement.args[-1]
-                opMatch = opRe.search(line)
-            #print "Found operands", statement.args
-
-            # Add this statement to our collection
-            statements.append(statement)
-
-            # Get the next line
-            lineMatch = lineRe.search(code)
-
-        # Decode the labels into displacements
-
-        labels = {}
-        micropc = 0
-        for statement in statements:
-            if statement.label:
-                labels[statement.label] = count
-            micropc += 1
-        micropc = 0
-        for statement in statements:
-            for arg in statement.args:
-                if arg.has_key("operandLabel"):
-                    if not labels.has_key(arg["operandLabel"]):
-                        raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
-                    # This is assuming that intra microcode branches go to
-                    # the next micropc + displacement, or
-                    # micropc + 1 + displacement.
-                    arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
-            micropc += 1
-
-        if len(statements) == 0:
-            raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code
-
-        # If we can implement this instruction with exactly one microop, just
-        # use that directly.
-        if len(statements) == 1:
-            decode_block = "return %s;" % \
-                            statements[0].getAllocator('"' + name + '"')
-            return ('', '', decode_block, '')
-        else:
-            # Build a macroop to contain the sequence of microops we've
-            # been given.
-            return genMacroOp(name, Name, statements)
+            return 'new %s(machInst, %s%s%s)' % (self.className, mnemonic, self.microFlagsText(microFlags), args)
 }};
index f0aab78720da8c65b06ffc1adf0f7fc9a0c4e289..04cfa6e5714bc13082a76863add4c33bbff7870a 100644 (file)
 //
 // Authors: Gabe Black
 
-//The operand types a microop template can be specialized with
-output header {{
-    enum OperandType {
-        RegisterOperand,
-        ImmediateOperand
-    };
+let {{
+    # This will be populated with mappings between microop mnemonics and
+    # the classes that represent them.
+    microopClasses = {}
 }};
 
 //A class which is the base of all x86 micro ops. It provides a function to
@@ -99,96 +97,172 @@ output header {{
     };
 }};
 
-// This sets up a class which is templated on the type of
-// arguments a particular flavor of a microcode instruction
-// can accept. It's parameters are specialized to create polymorphic
-// behavior in microops.
-def template BaseMicroOpTemplateDeclare {{
-    template%(signature)s
-    class %(class_name)s;
-}};
+//////////////////////////////////////////////////////////////////////////
+//
+// Base class for the python representation of x86 microops
 
 let {{
-    def buildBaseMicroOpTemplate(Name, numParams):
-        assert(numParams > 0)
-        signature = "<"
-        signature += "int SignatureOperandTypeSpecifier0"
-        for count in xrange(1,numParams):
-            signature += \
-                ", int SingatureOperandTypeSpecifier%d" % count
-        signature += ">"
-        subs = {"signature" : signature, "class_name" : Name}
-        return BaseMicroOpTemplateDeclare.subst(subs)
+    class X86Microop(object):
+        def __init__(self, name):
+            self.name = name
+
+        # This converts a list of python bools into
+        # a comma seperated list of C++ bools.
+        def microFlagsText(self, vals):
+            text = ""
+            for val in vals:
+                if val:
+                    text += ", true"
+                else:
+                    text += ", false"
+            return text
+
+        def getAllocator(self, mnemonic, *microFlags):
+            return 'new %s(machInst, %s)' % (self.className, mnemonic, self.microFlagsText(microFlags))
 }};
 
-let {{
-    def buildMicroOpTemplateDict(*params):
-        signature = "<"
-        if len(params):
-            signature += params[0]
-            if len(params) > 1:
-                for param in params[1:]:
-                    signature += ", %s" % param
-        signature += ">"
-        subs = {"param_dec" : "", "param_arg_dec" : "",
-                "param_init" : "", "signature" : signature}
-        for count in xrange(len(params)):
-            subs["param_dec"] += "uint64_t param%d;\n" % count
-            subs["param_arg_dec"] += ", uint64_t _param%d" % count
-            subs["param_init"] += ", param%d(_param%d)" % (count, count)
-        return subs
+//////////////////////////////////////////////////////////////////////////
+//
+// LdStOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroLdStOpDeclare {{
+    class %(class_name)s : public X86MicroOpBase
+    {
+      protected:
+        const uint8_t scale;
+        const RegIndex index;
+        const RegIndex base;
+        const uint64_t disp;
+        const uint8_t segment;
+        const RegIndex data;
+        const uint8_t dataSize;
+        const uint8_t addressSize;
+        void buildMe();
+
+      public:
+        %(class_name)s(ExtMachInst _machInst,
+                const char * instMnem,
+                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+                uint8_t _scale, RegIndex _index, RegIndex _base,
+                uint64_t _disp, uint8_t _segment,
+                RegIndex _data,
+                uint8_t _dataSize, uint8_t _addressSize);
+
+        %(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);
+
+        %(BasicExecDeclare)s
+    };
 }};
 
-// A tmeplate for building a specialized version of the microcode
-// instruction which specifies which arguments it wants
-def template MicroOpDeclare {{
-    template<>
-    class %(class_name)s%(signature)s : public X86MicroOpBase
+def template MicroLdStOpConstructor {{
+
+    inline void %(class_name)s::buildMe()
+    {
+        %(constructor)s;
+    }
+
+    inline %(class_name)s::%(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) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                false, false, false, false, %(op_class)s),
+                scale(_scale), index(_index), base(_base),
+                disp(_disp), segment(_segment),
+                data(_data),
+                dataSize(_dataSize), addressSize(_addressSize)
+    {
+        buildMe();
+    }
+
+    inline %(class_name)s::%(class_name)s(
+            ExtMachInst machInst, const char * instMnem,
+            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+            uint8_t _scale, RegIndex _index, RegIndex _base,
+            uint64_t _disp, uint8_t segment,
+            RegIndex data,
+            uint8_t dataSize, uint8_t addressSize) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+                scale(_scale), index(_index), base(_base),
+                disp(_disp), segment(_segment),
+                data(_data),
+                dataSize(_dataSize), addressSize(_addressSize)
+    {
+        buildMe();
+    }
+}};
+
+//////////////////////////////////////////////////////////////////////////
+//
+// LIMMOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroLIMMOpDeclare {{
+    class %(class_name)s : public X86MicroOpBase
     {
       protected:
-        %(param_dec)s
+        const RegIndex dest;
+        const uint64_t imm;
         void buildMe();
 
       public:
         %(class_name)s(ExtMachInst _machInst,
                 const char * instMnem,
-                bool isMicro, bool isDelayed,
-                bool isFirst, bool isLast
-                %(param_arg_dec)s);
+                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+                RegIndex _dest, uint64_t _imm);
 
         %(class_name)s(ExtMachInst _machInst,
-                const char * instMnem
-                %(param_arg_dec)s);
+                const char * instMnem,
+                RegIndex _dest, uint64_t _imm);
 
         %(BasicExecDeclare)s
     };
 }};
 
-def template MicroOpConstructor {{
+def template MicroLIMMOpConstructor {{
 
-    inline void %(class_name)s%(signature)s::buildMe()
+    inline void %(class_name)s::buildMe()
     {
         %(constructor)s;
     }
 
-    inline %(class_name)s%(signature)s::%(class_name)s(
-            ExtMachInst machInst, const char * instMnem
-            %(param_arg_dec)s) :
+    inline %(class_name)s::%(class_name)s(
+            ExtMachInst machInst, const char * instMnem,
+            RegIndex _dest, uint64_t _imm) :
         %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                false, false, false, false, %(op_class)s)
-                %(param_init)s
+                false, false, false, false, %(op_class)s),
+                dest(_dest), imm(_imm)
     {
         buildMe();
     }
 
-    inline %(class_name)s%(signature)s::%(class_name)s(
+    inline %(class_name)s::%(class_name)s(
             ExtMachInst machInst, const char * instMnem,
-            bool isMicro, bool isDelayed, bool isFirst, bool isLast
-            %(param_arg_dec)s)
-        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                isMicro, isDelayed, isFirst, isLast, %(op_class)s)
-                %(param_init)s
+            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+            RegIndex _dest, uint64_t _imm) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+                dest(_dest), imm(_imm)
     {
         buildMe();
     }
 }};
+
+//////////////////////////////////////////////////////////////////////////
+//
+// FpOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+//TODO Actually write an fp microop base class.
index d877152eb34e766ef98ad9fd7bec3d434c7d562d..0262cde0254162eaa305bdc37eb257c92a7d0fb5 100644 (file)
@@ -56,8 +56,8 @@
 //Common microop stuff
 ##include "base.isa"
 
-//A microop that generates a specified fault
-##include "fault.isa"
+//Miscellaneous microop definitions
+##include "specop.isa"
 
-//Integer microop definitions
-##include "int.isa"
+//Register microop definitions
+##include "regop.isa"
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
new file mode 100644 (file)
index 0000000..7411f6a
--- /dev/null
@@ -0,0 +1,328 @@
+// Copyright (c) 2007 The Hewlett-Packard Development Company
+// 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 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
+// 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 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
+
+//////////////////////////////////////////////////////////////////////////
+//
+// RegOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroRegOpExecute {{
+        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+                Trace::InstRecord *traceData) const
+        {
+            Fault fault = NoFault;
+
+            %(op_decl)s;
+            %(op_rd)s;
+            %(code)s;
+
+            //Write the resulting state to the execution context
+            if(fault == NoFault)
+            {
+                %(op_wb)s;
+            }
+            return fault;
+        }
+}};
+
+def template MicroRegOpImmExecute {{
+        Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc,
+                Trace::InstRecord *traceData) const
+        {
+            Fault fault = NoFault;
+
+            %(op_decl)s;
+            %(op_rd)s;
+            %(code)s;
+
+            //Write the resulting state to the execution context
+            if(fault == NoFault)
+            {
+                %(op_wb)s;
+            }
+            return fault;
+        }
+}};
+
+def template MicroRegOpDeclare {{
+    class %(class_name)s : public %(base_class)s
+    {
+      protected:
+        const RegIndex src1;
+        const RegIndex src2;
+        const RegIndex dest;
+        const bool setStatus;
+        const uint8_t dataSize;
+        const uint8_t ext;
+        void buildMe();
+
+      public:
+        %(class_name)s(ExtMachInst _machInst,
+                const char * instMnem,
+                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+                RegIndex _src1, RegIndex _src2, RegIndex _dest,
+                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+        %(class_name)s(ExtMachInst _machInst,
+                const char * instMnem,
+                RegIndex _src1, RegIndex _src2, RegIndex _dest,
+                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+        %(BasicExecDeclare)s
+    };
+}};
+
+def template MicroRegOpImmDeclare {{
+
+    class %(class_name)sImm : public %(base_class)s
+    {
+      protected:
+        const RegIndex src1;
+        const uint8_t imm8;
+        const RegIndex dest;
+        const bool setStatus;
+        const uint8_t dataSize;
+        const uint8_t ext;
+        void buildMe();
+
+      public:
+        %(class_name)sImm(ExtMachInst _machInst,
+                const char * instMnem,
+                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+                RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+        %(class_name)sImm(ExtMachInst _machInst,
+                const char * instMnem,
+                RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+        %(BasicExecDeclare)s
+    };
+}};
+
+def template MicroRegOpConstructor {{
+
+    inline void %(class_name)s::buildMe()
+    {
+        %(constructor)s;
+    }
+
+    inline %(class_name)s::%(class_name)s(
+            ExtMachInst machInst, const char * instMnem,
+            RegIndex _src1, RegIndex _src2, RegIndex _dest,
+            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                false, false, false, false, %(op_class)s),
+                src1(_src1), src2(_src2), dest(_dest),
+                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+    {
+        buildMe();
+    }
+
+    inline %(class_name)s::%(class_name)s(
+            ExtMachInst machInst, const char * instMnem,
+            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+            RegIndex _src1, RegIndex _src2, RegIndex _dest,
+            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+                src1(_src1), src2(_src2), dest(_dest),
+                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+    {
+        buildMe();
+    }
+}};
+
+def template MicroRegOpImmConstructor {{
+
+    inline void %(class_name)sImm::buildMe()
+    {
+        %(constructor)s;
+    }
+
+    inline %(class_name)sImm::%(class_name)sImm(
+            ExtMachInst machInst, const char * instMnem,
+            RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                false, false, false, false, %(op_class)s),
+                src1(_src1), imm8(_imm8), dest(_dest),
+                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+    {
+        buildMe();
+    }
+
+    inline %(class_name)sImm::%(class_name)sImm(
+            ExtMachInst machInst, const char * instMnem,
+            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+            RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+                isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+                src1(_src1), imm8(_imm8), dest(_dest),
+                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+    {
+        buildMe();
+    }
+}};
+
+let {{
+    class RegOp(object):
+        def __init__(self, dest, src1, src2):
+            self.dest = dest
+            self.src1 = src1
+            self.src2 = src2
+            self.setStatus = False
+            self.dataSize = 1
+            self.ext = 0
+
+        def getAllocator(self, *microFlags):
+            allocator = '''new %(class_name)s(machInst, %(mnemonic)s,
+                    %(flags)s %(src1)s, %(src2)s, %(dest)s,
+                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
+                "class_name" : self.className,
+                "mnemonic" : self.mnemonic,
+                "flags" : self.microFlagsText(microFlags),
+                "src1" : self.src1, "src2" : self.src2,
+                "dest" : self.dest,
+                "setStatus" : self.setStatus,
+                "dataSize" : self.dataSize,
+                "ext" : self.ext}
+
+    class RegOpImm(object):
+        def __init__(self, dest, src1, imm):
+            self.dest = dest
+            self.src1 = src1
+            self.imm = imm
+            self.setStatus = False
+            self.dataSize = 1
+            self.ext = 0
+
+        def getAllocator(self, *microFlags):
+            allocator = '''new %(class_name)s(machInst, %(mnemonic)s,
+                    %(flags)s %(src1)s, %(imm8)s, %(dest)s,
+                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
+                "class_name" : self.className,
+                "mnemonic" : self.mnemonic,
+                "flags" : self.microFlagsText(microFlags),
+                "src1" : self.src1, "imm8" : self.imm8,
+                "dest" : self.dest,
+                "setStatus" : self.setStatus,
+                "dataSize" : self.dataSize,
+                "ext" : self.ext}
+}};
+
+let {{
+
+    # Make these empty strings so that concatenating onto
+    # them will always work.
+    header_output = ""
+    decoder_output = ""
+    exec_output = ""
+
+    def defineMicroIntOp(mnemonic, code):
+        global header_output
+        global decoder_output
+        global exec_output
+        Name = mnemonic
+        name = mnemonic.lower()
+
+        # Find op2 in each of the instruction definitions. Create two versions
+        # of the code, one with an integer operand, and one with an immediate
+        # operand.
+        matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
+        regCode = matcher.sub("SrcReg2", code)
+        immCode = matcher.sub("imm8", code)
+
+        # Build up the all register version of this micro op
+        iop = InstObjParams(name, Name, 'X86MicroOpBase', {"code" : regCode})
+        header_output += MicroRegOpDeclare.subst(iop)
+        decoder_output += MicroRegOpConstructor.subst(iop)
+        exec_output += MicroRegOpExecute.subst(iop)
+
+        class RegOpChild(RegOp):
+            def __init__(self, dest, src1, src2):
+                super(RegOpChild, self).__init__(self, dest, src1, src2)
+                self.mnemonic = name
+
+        microopClasses[name] = RegOpChild
+
+        # Build up the immediate version of this micro op
+        iop = InstObjParams(name + "i", Name,
+                'X86MicroOpBase', {"code" : immCode})
+        header_output += MicroRegOpImmDeclare.subst(iop)
+        decoder_output += MicroRegOpImmConstructor.subst(iop)
+        exec_output += MicroRegOpImmExecute.subst(iop)
+
+        class RegOpImmChild(RegOpImm):
+            def __init__(self, dest, src1, imm):
+                super(RegOpImmChild, self).__init__(self, dest, src1, imm)
+                self.mnemonic = name + "i"
+
+        microopClasses[name + "i"] = RegOpChild
+
+    defineMicroIntOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to set OF,CF,SF
+    defineMicroIntOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)')
+    defineMicroIntOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to add in CF, set OF,CF,SF
+    defineMicroIntOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to subtract CF, set OF,CF,SF
+    defineMicroIntOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)')
+    defineMicroIntOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to set OF,CF,SF
+    defineMicroIntOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)')
+    defineMicroIntOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)') #Needs to set OF,CF,SF and not DestReg
+    defineMicroIntOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)')
+
+}};
diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa
new file mode 100644 (file)
index 0000000..a3ca7d9
--- /dev/null
@@ -0,0 +1,125 @@
+// Copyright (c) 2007 The Hewlett-Packard Development Company
+// 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 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
+// 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 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
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Fault Microop
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroFaultExecute {{
+        Fault %(class_name)s ::execute(%(CPU_exec_context)s *xc,
+                Trace::InstRecord *traceData) const
+        {
+            //Return the fault we were constructed with
+            return fault;
+        }
+}};
+
+def template MicroFaultDeclare {{
+    class %(class_name)s : public X86MicroOpBase
+    {
+      protected:
+        Fault fault;
+        void buildMe();
+
+      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);
+
+        %(BasicExecDeclare)s
+    };
+}};
+
+def template MicroFaultConstructor {{
+
+    inline void %(class_name)s::buildMe()
+    {
+        %(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)
+    {
+        buildMe();
+    }
+
+    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)
+    {
+        buildMe();
+    }
+}};
+
+let {{
+    # This microop takes in a single parameter, a fault to return.
+    iop = InstObjParams("fault", "GenFault", 'X86MicroOpBase', {"code" : ""})
+    header_output += MicroFaultDeclare.subst(iop)
+    decoder_output += MicroFaultConstructor.subst(iop)
+    exec_output += MicroFaultExecute.subst(iop)
+}};
index af469ab3de03baedaa872537c0e594e811a70b74..1564c23e9a7d47599aa85c56bf0d617f1ed478b4 100644 (file)
@@ -96,6 +96,9 @@ def operand_types {{
 }};
 
 def operands {{
+        'DestReg':       ('IntReg', 'uqw', 'dest', 'IsInteger', 1),
+        'SrcReg1':       ('IntReg', 'uqw', 'src1', 'IsInteger', 2),
+        'SrcReg2':       ('IntReg', 'uqw', 'src2', 'IsInteger', 3),
         'IntRegOp0':     ('IntReg', 'udw', 'param0', 'IsInteger', 1),
         'IntRegOp1':     ('IntReg', 'udw', 'param1', 'IsInteger', 2),
         'IntRegOp2':     ('IntReg', 'udw', 'param2', 'IsInteger', 2),