multi.isa revision 4323
14278Sgblack@eecs.umich.edu// -*- mode:c++ -*-
24278Sgblack@eecs.umich.edu
34278Sgblack@eecs.umich.edu// Copyright (c) 2007 The Hewlett-Packard Development Company
44278Sgblack@eecs.umich.edu// All rights reserved.
54278Sgblack@eecs.umich.edu//
64278Sgblack@eecs.umich.edu// Redistribution and use of this software in source and binary forms,
74278Sgblack@eecs.umich.edu// with or without modification, are permitted provided that the
84278Sgblack@eecs.umich.edu// following conditions are met:
94278Sgblack@eecs.umich.edu//
104278Sgblack@eecs.umich.edu// The software must be used only for Non-Commercial Use which means any
114278Sgblack@eecs.umich.edu// use which is NOT directed to receiving any direct monetary
124278Sgblack@eecs.umich.edu// compensation for, or commercial advantage from such use.  Illustrative
134278Sgblack@eecs.umich.edu// examples of non-commercial use are academic research, personal study,
144278Sgblack@eecs.umich.edu// teaching, education and corporate research & development.
154278Sgblack@eecs.umich.edu// Illustrative examples of commercial use are distributing products for
164278Sgblack@eecs.umich.edu// commercial advantage and providing services using the software for
174278Sgblack@eecs.umich.edu// commercial advantage.
184278Sgblack@eecs.umich.edu//
194278Sgblack@eecs.umich.edu// If you wish to use this software or functionality therein that may be
204278Sgblack@eecs.umich.edu// covered by patents for commercial use, please contact:
214278Sgblack@eecs.umich.edu//     Director of Intellectual Property Licensing
224278Sgblack@eecs.umich.edu//     Office of Strategy and Technology
234278Sgblack@eecs.umich.edu//     Hewlett-Packard Company
244278Sgblack@eecs.umich.edu//     1501 Page Mill Road
254278Sgblack@eecs.umich.edu//     Palo Alto, California  94304
264278Sgblack@eecs.umich.edu//
274278Sgblack@eecs.umich.edu// Redistributions of source code must retain the above copyright notice,
284278Sgblack@eecs.umich.edu// this list of conditions and the following disclaimer.  Redistributions
294278Sgblack@eecs.umich.edu// in binary form must reproduce the above copyright notice, this list of
304278Sgblack@eecs.umich.edu// conditions and the following disclaimer in the documentation and/or
314278Sgblack@eecs.umich.edu// other materials provided with the distribution.  Neither the name of
324278Sgblack@eecs.umich.edu// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
334278Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
344278Sgblack@eecs.umich.edu// this software without specific prior written permission.  No right of
354278Sgblack@eecs.umich.edu// sublicense is granted herewith.  Derivatives of the software and
364278Sgblack@eecs.umich.edu// output created using the software may be prepared, but only for
374278Sgblack@eecs.umich.edu// Non-Commercial Uses.  Derivatives of the software may be shared with
384278Sgblack@eecs.umich.edu// others provided: (i) the others agree to abide by the list of
394278Sgblack@eecs.umich.edu// conditions herein which includes the Non-Commercial Use restrictions;
404278Sgblack@eecs.umich.edu// and (ii) such Derivatives of the software include the above copyright
414278Sgblack@eecs.umich.edu// notice to acknowledge the contribution from this software where
424278Sgblack@eecs.umich.edu// applicable, this list of conditions and the disclaimer below.
434278Sgblack@eecs.umich.edu//
444278Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
454278Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
464278Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
474278Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
484278Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
494278Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
504278Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
514278Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
524278Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
534278Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
544278Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
554278Sgblack@eecs.umich.edu//
564278Sgblack@eecs.umich.edu// Authors: Gabe Black
574278Sgblack@eecs.umich.edu
584278Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////
594278Sgblack@eecs.umich.edu//
604278Sgblack@eecs.umich.edu// Instructions that do the same thing to multiple sets of arguments.
614278Sgblack@eecs.umich.edu//
624278Sgblack@eecs.umich.edu
634323Sgblack@eecs.umich.edulet {{
644323Sgblack@eecs.umich.edu    # This builds either a regular or macro op to implement the sequence of
654323Sgblack@eecs.umich.edu    # ops we give it.
664323Sgblack@eecs.umich.edu    def genInst(name, Name, ops):
674323Sgblack@eecs.umich.edu        # If we can implement this instruction with exactly one microop, just
684323Sgblack@eecs.umich.edu        # use that directly.
694323Sgblack@eecs.umich.edu        newStmnt = ''
704323Sgblack@eecs.umich.edu        if len(ops) == 1:
714323Sgblack@eecs.umich.edu            decode_block = "return (X86StaticInst *)(%s);" % \
724323Sgblack@eecs.umich.edu                            ops[0].getAllocator()
734323Sgblack@eecs.umich.edu            return ('', '', decode_block, '')
744323Sgblack@eecs.umich.edu        else:
754323Sgblack@eecs.umich.edu            # Build a macroop to contain the sequence of microops we've
764323Sgblack@eecs.umich.edu            # been given.
774323Sgblack@eecs.umich.edu            return genMacroOp(name, Name, ops)
784278Sgblack@eecs.umich.edu}};
794278Sgblack@eecs.umich.edu
804278Sgblack@eecs.umich.edulet {{
814323Sgblack@eecs.umich.edu    # This code builds up a decode block which decodes based on switchval.
824323Sgblack@eecs.umich.edu    # vals is a dict which matches case values with what should be decoded to.
834323Sgblack@eecs.umich.edu    # builder is called on the exploded contents of "vals" values to generate
844323Sgblack@eecs.umich.edu    # whatever code should be used.
854323Sgblack@eecs.umich.edu    def doMultiOp(name, Name, builder, switchVal, vals, default = None):
864323Sgblack@eecs.umich.edu        header_output = ''
874323Sgblack@eecs.umich.edu        decoder_output = ''
884323Sgblack@eecs.umich.edu        decode_block = 'switch(%s) {\n' % switchVal
894323Sgblack@eecs.umich.edu        exec_output = ''
904323Sgblack@eecs.umich.edu        for (val, todo) in vals.items():
914323Sgblack@eecs.umich.edu            (new_header_output,
924323Sgblack@eecs.umich.edu             new_decoder_output,
934323Sgblack@eecs.umich.edu             new_decode_block,
944323Sgblack@eecs.umich.edu             new_exec_output) = builder(name, Name, *todo)
954323Sgblack@eecs.umich.edu            header_output += new_header_output
964323Sgblack@eecs.umich.edu            decoder_output += new_decoder_output
974323Sgblack@eecs.umich.edu            decode_block += '\tcase %s: %s\n' % (val, new_decode_block)
984323Sgblack@eecs.umich.edu            exec_output += new_exec_output
994323Sgblack@eecs.umich.edu        if default:
1004323Sgblack@eecs.umich.edu            (new_header_output,
1014323Sgblack@eecs.umich.edu             new_decoder_output,
1024323Sgblack@eecs.umich.edu             new_decode_block,
1034323Sgblack@eecs.umich.edu             new_exec_output) = builder(name, Name, *default)
1044323Sgblack@eecs.umich.edu            header_output += new_header_output
1054323Sgblack@eecs.umich.edu            decoder_output += new_decoder_output
1064323Sgblack@eecs.umich.edu            decode_block += '\tdefault: %s\n' % new_decode_block
1074323Sgblack@eecs.umich.edu            exec_output += new_exec_output
1084323Sgblack@eecs.umich.edu        decode_block += '}\n'
1094323Sgblack@eecs.umich.edu        return (header_output, decoder_output, decode_block, exec_output)
1104323Sgblack@eecs.umich.edu}};
1114323Sgblack@eecs.umich.edu
1124323Sgblack@eecs.umich.edulet {{
1134323Sgblack@eecs.umich.edu
1144323Sgblack@eecs.umich.edu    # This function specializes the given piece of code to use a particular
1154323Sgblack@eecs.umich.edu    # set of argument types described by "opTags". These are "implemented"
1164323Sgblack@eecs.umich.edu    # in reverse order.
1174323Sgblack@eecs.umich.edu    def doCompOps(name, Name, code, opTags, postfix):
1184323Sgblack@eecs.umich.edu        opNum = len(opTags) - 1
1194323Sgblack@eecs.umich.edu        while len(opTags):
1204323Sgblack@eecs.umich.edu            # print "Building a composite op with tags", opTags
1214323Sgblack@eecs.umich.edu            # print "And code", code
1224323Sgblack@eecs.umich.edu            opNum = len(opTags) - 1
1234323Sgblack@eecs.umich.edu            # A regular expression to find the operand placeholders we're
1244323Sgblack@eecs.umich.edu            # interested in.
1254323Sgblack@eecs.umich.edu            opRe = re.compile("%%(?P<operandNum>%d)(?=[^0-9]|$)" % opNum)
1264323Sgblack@eecs.umich.edu            tag = opTags[opNum]
1274323Sgblack@eecs.umich.edu            # Build up a name for this instructions class using the argument
1284323Sgblack@eecs.umich.edu            # types. Each variation will get its own name this way.
1294323Sgblack@eecs.umich.edu            postfix = '_' + tag + postfix
1304323Sgblack@eecs.umich.edu            tagParser = re.compile(r"(?P<tagType>[A-Z][A-Z]*)(?P<tagSize>[a-z][a-z]*)|(r(?P<tagReg>[A-Za-z0-9][A-Za-z0-9]*))")
1314323Sgblack@eecs.umich.edu            tagMatch = tagParser.search(tag)
1324323Sgblack@eecs.umich.edu            if tagMatch == None:
1334323Sgblack@eecs.umich.edu                raise Exception, "Problem parsing operand tag %s" % tag
1344323Sgblack@eecs.umich.edu            reg = tagMatch.group("tagReg")
1354323Sgblack@eecs.umich.edu            tagType = tagMatch.group("tagType")
1364323Sgblack@eecs.umich.edu            tagSize = tagMatch.group("tagSize")
1374323Sgblack@eecs.umich.edu            if reg:
1384323Sgblack@eecs.umich.edu                #Figure out what to do with fixed register operands
1394323Sgblack@eecs.umich.edu                if reg in ("Ax", "Bx", "Cx", "Dx"):
1404323Sgblack@eecs.umich.edu                    code = opRe.sub("{INTREG_R%s}" % reg.upper(), code)
1414323Sgblack@eecs.umich.edu                elif reg == "Al":
1424323Sgblack@eecs.umich.edu                    # We need a way to specify register width
1434323Sgblack@eecs.umich.edu                    code = opRe.sub("{INTREG_RAX}", code)
1444323Sgblack@eecs.umich.edu                else:
1454323Sgblack@eecs.umich.edu                    print "Didn't know how to encode fixed register %s!" % reg
1464323Sgblack@eecs.umich.edu            elif tagType == None or tagSize == None:
1474323Sgblack@eecs.umich.edu                raise Exception, "Problem parsing operand tag: %s" % tag
1484323Sgblack@eecs.umich.edu            elif tagType == "C" or tagType == "D" or tagType == "G" or \
1494323Sgblack@eecs.umich.edu                                   tagType == "P" or tagType == "S" or \
1504323Sgblack@eecs.umich.edu                                   tagType == "T" or tagType == "V":
1514323Sgblack@eecs.umich.edu                # Use the "reg" field of the ModRM byte to select the register
1524323Sgblack@eecs.umich.edu                code = opRe.sub("{(uint8_t)MODRM_REG}", code)
1534323Sgblack@eecs.umich.edu            elif tagType == "E" or tagType == "Q" or tagType == "W":
1544323Sgblack@eecs.umich.edu                # This might refer to memory or to a register. We need to
1554323Sgblack@eecs.umich.edu                # divide it up farther.
1564323Sgblack@eecs.umich.edu                regCode = opRe.sub("{(uint8_t)MODRM_RM}", code)
1574323Sgblack@eecs.umich.edu                regTags = copy.copy(opTags)
1584323Sgblack@eecs.umich.edu                regTags.pop(-1)
1594323Sgblack@eecs.umich.edu                # This needs to refer to memory, but we'll fill in the details
1604323Sgblack@eecs.umich.edu                # later. It needs to take into account unaligned memory
1614323Sgblack@eecs.umich.edu                # addresses.
1624323Sgblack@eecs.umich.edu                memCode = opRe.sub("0", code)
1634323Sgblack@eecs.umich.edu                memTags = copy.copy(opTags)
1644323Sgblack@eecs.umich.edu                memTags.pop(-1)
1654323Sgblack@eecs.umich.edu                return doMultiOp(name, Name, doCompOps, "MODRM_MOD",
1664323Sgblack@eecs.umich.edu                    {"3" : (regCode, regTags, postfix)},
1674323Sgblack@eecs.umich.edu                           (memCode, memTags, postfix))
1684323Sgblack@eecs.umich.edu            elif tagType == "I" or tagType == "J":
1694323Sgblack@eecs.umich.edu                # Substitute in an immediate
1704323Sgblack@eecs.umich.edu                code = opRe.sub("{IMMEDIATE}", code)
1714323Sgblack@eecs.umich.edu            elif tagType == "M":
1724323Sgblack@eecs.umich.edu                # This needs to refer to memory, but we'll fill in the details
1734323Sgblack@eecs.umich.edu                # later. It needs to take into account unaligned memory
1744323Sgblack@eecs.umich.edu                # addresses.
1754323Sgblack@eecs.umich.edu                code = opRe.sub("0", code)
1764323Sgblack@eecs.umich.edu            elif tagType == "PR" or tagType == "R" or tagType == "VR":
1774323Sgblack@eecs.umich.edu                # There should probably be a check here to verify that mod
1784323Sgblack@eecs.umich.edu                # is equal to 11b
1794323Sgblack@eecs.umich.edu                code = opRe.sub("{(uint8_t)MODRM_RM}", code)
1804323Sgblack@eecs.umich.edu            else:
1814323Sgblack@eecs.umich.edu                raise Exception, "Unrecognized tag %s." % tag
1824323Sgblack@eecs.umich.edu            opTags.pop(-1)
1834323Sgblack@eecs.umich.edu
1844323Sgblack@eecs.umich.edu        # At this point, we've built up "code" to have all the necessary extra
1854323Sgblack@eecs.umich.edu        # instructions needed to implement whatever types of operands were
1864323Sgblack@eecs.umich.edu        # specified. Now we'll assemble it it into a microOp sequence.
1874323Sgblack@eecs.umich.edu        ops = assembleMicro(code)
1884323Sgblack@eecs.umich.edu
1894323Sgblack@eecs.umich.edu        # Build a macroop to contain the sequence of microops we've
1904323Sgblack@eecs.umich.edu        # constructed. The decode block will be used to fill in our
1914323Sgblack@eecs.umich.edu        # inner decode structure, and the rest will be concatenated and
1924323Sgblack@eecs.umich.edu        # passed back.
1934323Sgblack@eecs.umich.edu        return genInst(name, Name + postfix, ops)
1944323Sgblack@eecs.umich.edu}};
1954323Sgblack@eecs.umich.edu
1964323Sgblack@eecs.umich.edudef format TaggedOp(code, tagSet) {{
1974323Sgblack@eecs.umich.edu    (header_output,
1984323Sgblack@eecs.umich.edu     decoder_output,
1994323Sgblack@eecs.umich.edu     decode_block,
2004323Sgblack@eecs.umich.edu     exec_output) = doCompOps(name, Name, code, tagSet, '')
2014278Sgblack@eecs.umich.edu}};
2024278Sgblack@eecs.umich.edu
2034278Sgblack@eecs.umich.edudef format MultiOp(code, switchVal, opTags, *opt_flags) {{
2044323Sgblack@eecs.umich.edu    switcher = {}
2054323Sgblack@eecs.umich.edu    for (count, tagSet) in zip(xrange(len(opTags) - 1), opTags):
2064323Sgblack@eecs.umich.edu        switcher[count] = (code, tagSet, '')
2074323Sgblack@eecs.umich.edu    (header_output,
2084323Sgblack@eecs.umich.edu     decoder_output,
2094323Sgblack@eecs.umich.edu     decode_block,
2104323Sgblack@eecs.umich.edu     exec_output) = doMultiOp(name, Name, doCompOps, switchVal, switcher)
2114278Sgblack@eecs.umich.edu}};
212