Move the instruction specialization stuff out of the microassembler file, and added...
authorGabe Black <gblack@eecs.umich.edu>
Fri, 6 Apr 2007 16:55:56 +0000 (16:55 +0000)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 6 Apr 2007 16:55:56 +0000 (16:55 +0000)
--HG--
extra : convert_revision : 1534ae7d5a9e95bf662d79a04f9286c227541c6c

src/arch/x86/isa/main.isa
src/arch/x86/isa/microasm.isa
src/arch/x86/isa/specialize.isa [new file with mode: 0644]

index d9e90689da174385fdcfdd647ea57e43f1f552a8..063d7125d7feb11f7f2dfec9800e3ae42f7799a8 100644 (file)
 
 namespace X86ISA;
 
+////////////////////////////////////////////////////////////////////
+//
+// General infrastructure code. These files provide infrastructure
+// which was developed to support x86 but isn't specific to it.
+//
+
+//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"
 
-//Include code to build macroops.
-##include "macroop.isa"
+////////////////////////////////////////////////////////////////////
+//
+// X86 only infrastructure code.
+//
 
-//Include the base class for x86 instructions, and some support code
-//Code in this file should be general and useful everywhere
+//Include the base class for x86 instructions, and some support code.
 ##include "base.isa"
 
+//Include code to specialize an instruction template to operate on
+//a particular set of operands. This is specific to x86 and the x86
+//microcode ISA.
+##include "specialize.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// Code which directly specifies isa components like instructions
+// microops, and the decoder.
+//
+
 //Include the definitions for the instruction formats
 ##include "formats/formats.isa"
 
index d3ced71be0407263731fa656efe4bad989e8b26a..592941d04d62578a0a59deb468d950ade1af1070 100644 (file)
@@ -103,9 +103,6 @@ let {{
             self.reg = match.group("reg")
             self.tag = match.group("tag")
             self.size = match.group("size")
-}};
-
-let {{
 
     # This function specializes the given piece of code to use a particular
     # set of argument types described by "opTypes". These are "implemented"
diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa
new file mode 100644 (file)
index 0000000..9cac097
--- /dev/null
@@ -0,0 +1,172 @@
+// -*- mode:c++ -*-
+
+// 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
+
+////////////////////////////////////////////////////////////////////
+//
+//  Code to "specialize" a microcode sequence to use a particular
+//  variety of operands
+//
+
+let {{
+    # This code builds up a decode block which decodes based on switchval.
+    # vals is a dict which matches case values with what should be decoded to.
+    # builder is called on the exploded contents of "vals" values to generate
+    # whatever code should be used.
+    def doSplitDecode(name, Name, builder, switchVal, vals, default = None):
+        header_output = ''
+        decoder_output = ''
+        decode_block = 'switch(%s) {\n' % switchVal
+        exec_output = ''
+        for (val, todo) in vals.items():
+            (new_header_output,
+             new_decoder_output,
+             new_decode_block,
+             new_exec_output) = builder(name, Name, *todo)
+            header_output += new_header_output
+            decoder_output += new_decoder_output
+            decode_block += '\tcase %s: %s\n' % (val, new_decode_block)
+            exec_output += new_exec_output
+        if default:
+            (new_header_output,
+             new_decoder_output,
+             new_decode_block,
+             new_exec_output) = builder(name, Name, *default)
+            header_output += new_header_output
+            decoder_output += new_decoder_output
+            decode_block += '\tdefault: %s\n' % new_decode_block
+            exec_output += new_exec_output
+        decode_block += '}\n'
+        return (header_output, decoder_output, decode_block, exec_output)
+}};
+
+let {{
+    class OpType(object):
+        parser = re.compile(r"(?P<tag>[A-Z][A-Z]*)(?P<size>[a-z][a-z]*)|(r(?P<reg>[A-Za-z0-9][A-Za-z0-9]*))")
+        def __init__(self, opTypeString):
+            match = OpType.parser.search(opTypeString)
+            if match == None:
+                raise Exception, "Problem parsing operand type %s" % opTypeString
+            self.reg = match.group("reg")
+            self.tag = match.group("tag")
+            self.size = match.group("size")
+
+    # This function specializes the given piece of code to use a particular
+    # set of argument types described by "opTypes". These are "implemented"
+    # in reverse order.
+    def specializeInst(name, Name, code, opTypes):
+        opNum = len(opTypes) - 1
+        while len(opTypes):
+            # print "Building a composite op with tags", opTypes
+            # print "And code", code
+            opNum = len(opTypes) - 1
+            # A regular expression to find the operand placeholders we're
+            # interested in.
+            opRe = re.compile("\\^(?P<operandNum>%d)(?=[^0-9]|$)" % opNum)
+
+            # Parse the operand type strign we're working with
+            opType = OpType(opTypes[opNum])
+
+            if opType.reg:
+                #Figure out what to do with fixed register operands
+                if opType.reg in ("Ax", "Bx", "Cx", "Dx"):
+                    code = opRe.sub("%%{INTREG_R%s}" % opType.reg.upper(), code)
+                elif opType.reg == "Al":
+                    # We need a way to specify register width
+                    code = opRe.sub("%{INTREG_RAX}", code)
+                else:
+                    print "Didn't know how to encode fixed register %s!" % opType.reg
+            elif opType.tag == None or opType.size == None:
+                raise Exception, "Problem parsing operand tag: %s" % opType.tag
+            elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"):
+                # Use the "reg" field of the ModRM byte to select the register
+                code = opRe.sub("%{(uint8_t)MODRM_REG}", code)
+            elif opType.tag in ("E", "Q", "W"):
+                # This might refer to memory or to a register. We need to
+                # divide it up farther.
+                regCode = opRe.sub("%{(uint8_t)MODRM_RM}", code)
+                regTypes = copy.copy(opTypes)
+                regTypes.pop(-1)
+                # This needs to refer to memory, but we'll fill in the details
+                # later. It needs to take into account unaligned memory
+                # addresses.
+                memCode = opRe.sub("%0", code)
+                memTypes = copy.copy(opTypes)
+                memTypes.pop(-1)
+                return doSplitDecode(name, Name, specializeInst, "MODRM_MOD",
+                    {"3" : (regCode, regTypes)}, (memCode, memTypes))
+            elif opType.tag in ("I", "J"):
+                # Immediates are already in the instruction, so don't leave in
+                # those parameters
+                code = opRe.sub("${IMMEDIATE}", code)
+            elif opType.tag == "M":
+                # This needs to refer to memory, but we'll fill in the details
+                # later. It needs to take into account unaligned memory
+                # addresses.
+                code = opRe.sub("%0", code)
+            elif opType.tag in ("PR", "R", "VR"):
+                # There should probably be a check here to verify that mod
+                # is equal to 11b
+                code = opRe.sub("%{(uint8_t)MODRM_RM}", code)
+            else:
+                raise Exception, "Unrecognized tag %s." % opType.tag
+            opTypes.pop(-1)
+
+        # At this point, we've built up "code" to have all the necessary extra
+        # instructions needed to implement whatever types of operands were
+        # specified. Now we'll assemble it it into a StaticInst.
+        return assembleMicro(name, Name, code)
+}};