microasm.isa revision 4371
14309Sgblack@eecs.umich.edu// -*- mode:c++ -*- 24309Sgblack@eecs.umich.edu 34309Sgblack@eecs.umich.edu// Copyright (c) 2007 The Hewlett-Packard Development Company 44309Sgblack@eecs.umich.edu// All rights reserved. 54309Sgblack@eecs.umich.edu// 64309Sgblack@eecs.umich.edu// Redistribution and use of this software in source and binary forms, 74309Sgblack@eecs.umich.edu// with or without modification, are permitted provided that the 84309Sgblack@eecs.umich.edu// following conditions are met: 94309Sgblack@eecs.umich.edu// 104309Sgblack@eecs.umich.edu// The software must be used only for Non-Commercial Use which means any 114309Sgblack@eecs.umich.edu// use which is NOT directed to receiving any direct monetary 124309Sgblack@eecs.umich.edu// compensation for, or commercial advantage from such use. Illustrative 134309Sgblack@eecs.umich.edu// examples of non-commercial use are academic research, personal study, 144309Sgblack@eecs.umich.edu// teaching, education and corporate research & development. 154309Sgblack@eecs.umich.edu// Illustrative examples of commercial use are distributing products for 164309Sgblack@eecs.umich.edu// commercial advantage and providing services using the software for 174309Sgblack@eecs.umich.edu// commercial advantage. 184309Sgblack@eecs.umich.edu// 194309Sgblack@eecs.umich.edu// If you wish to use this software or functionality therein that may be 204309Sgblack@eecs.umich.edu// covered by patents for commercial use, please contact: 214309Sgblack@eecs.umich.edu// Director of Intellectual Property Licensing 224309Sgblack@eecs.umich.edu// Office of Strategy and Technology 234309Sgblack@eecs.umich.edu// Hewlett-Packard Company 244309Sgblack@eecs.umich.edu// 1501 Page Mill Road 254309Sgblack@eecs.umich.edu// Palo Alto, California 94304 264309Sgblack@eecs.umich.edu// 274309Sgblack@eecs.umich.edu// Redistributions of source code must retain the above copyright notice, 284309Sgblack@eecs.umich.edu// this list of conditions and the following disclaimer. Redistributions 294309Sgblack@eecs.umich.edu// in binary form must reproduce the above copyright notice, this list of 304309Sgblack@eecs.umich.edu// conditions and the following disclaimer in the documentation and/or 314309Sgblack@eecs.umich.edu// other materials provided with the distribution. Neither the name of 324309Sgblack@eecs.umich.edu// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 334309Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from 344309Sgblack@eecs.umich.edu// this software without specific prior written permission. No right of 354309Sgblack@eecs.umich.edu// sublicense is granted herewith. Derivatives of the software and 364309Sgblack@eecs.umich.edu// output created using the software may be prepared, but only for 374309Sgblack@eecs.umich.edu// Non-Commercial Uses. Derivatives of the software may be shared with 384309Sgblack@eecs.umich.edu// others provided: (i) the others agree to abide by the list of 394309Sgblack@eecs.umich.edu// conditions herein which includes the Non-Commercial Use restrictions; 404309Sgblack@eecs.umich.edu// and (ii) such Derivatives of the software include the above copyright 414309Sgblack@eecs.umich.edu// notice to acknowledge the contribution from this software where 424309Sgblack@eecs.umich.edu// applicable, this list of conditions and the disclaimer below. 434309Sgblack@eecs.umich.edu// 444309Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 454309Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 464309Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 474309Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 484309Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 494309Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 504309Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 514309Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 524309Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 534309Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 544309Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 554309Sgblack@eecs.umich.edu// 564309Sgblack@eecs.umich.edu// Authors: Gabe Black 574309Sgblack@eecs.umich.edu 584309Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////// 594309Sgblack@eecs.umich.edu// 604336Sgblack@eecs.umich.edu// The microcode assembler 614336Sgblack@eecs.umich.edu// 624336Sgblack@eecs.umich.edu 634336Sgblack@eecs.umich.edulet {{ 644344Sgblack@eecs.umich.edu # These are used when setting up microops so that they can specialize their 654344Sgblack@eecs.umich.edu # base class template properly. 664344Sgblack@eecs.umich.edu RegOpType = "RegisterOperand" 674344Sgblack@eecs.umich.edu ImmOpType = "ImmediateOperand" 684344Sgblack@eecs.umich.edu}}; 694344Sgblack@eecs.umich.edu 704344Sgblack@eecs.umich.edulet {{ 714336Sgblack@eecs.umich.edu class MicroOpStatement(object): 724309Sgblack@eecs.umich.edu def __init__(self): 734309Sgblack@eecs.umich.edu self.className = '' 744309Sgblack@eecs.umich.edu self.label = '' 754309Sgblack@eecs.umich.edu self.args = [] 764309Sgblack@eecs.umich.edu 774323Sgblack@eecs.umich.edu # This converts a list of python bools into 784323Sgblack@eecs.umich.edu # a comma seperated list of C++ bools. 794323Sgblack@eecs.umich.edu def microFlagsText(self, vals): 804323Sgblack@eecs.umich.edu text = "" 814323Sgblack@eecs.umich.edu for val in vals: 824323Sgblack@eecs.umich.edu if val: 834323Sgblack@eecs.umich.edu text += ", true" 844323Sgblack@eecs.umich.edu else: 854323Sgblack@eecs.umich.edu text += ", false" 864323Sgblack@eecs.umich.edu return text 874323Sgblack@eecs.umich.edu 884371Sgblack@eecs.umich.edu def getAllocator(self, mnemonic, *microFlags): 894309Sgblack@eecs.umich.edu args = '' 904338Sgblack@eecs.umich.edu signature = "<" 914338Sgblack@eecs.umich.edu emptySig = True 924309Sgblack@eecs.umich.edu for arg in self.args: 934338Sgblack@eecs.umich.edu if not emptySig: 944338Sgblack@eecs.umich.edu signature += ", " 954338Sgblack@eecs.umich.edu emptySig = False 964338Sgblack@eecs.umich.edu if arg.has_key("operandImm"): 974338Sgblack@eecs.umich.edu args += ", %s" % arg["operandImm"] 984338Sgblack@eecs.umich.edu signature += ImmOpType 994338Sgblack@eecs.umich.edu elif arg.has_key("operandReg"): 1004338Sgblack@eecs.umich.edu args += ", %s" % arg["operandReg"] 1014338Sgblack@eecs.umich.edu signature += RegOpType 1024309Sgblack@eecs.umich.edu elif arg.has_key("operandLabel"): 1034323Sgblack@eecs.umich.edu raise Exception, "Found a label while creating allocator string." 1044309Sgblack@eecs.umich.edu else: 1054323Sgblack@eecs.umich.edu raise Exception, "Unrecognized operand type." 1064338Sgblack@eecs.umich.edu signature += ">" 1074371Sgblack@eecs.umich.edu return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args) 1084323Sgblack@eecs.umich.edu}}; 1094309Sgblack@eecs.umich.edu 1104344Sgblack@eecs.umich.edulet{{ 1114344Sgblack@eecs.umich.edu def assembleMicro(name, Name, code): 1124309Sgblack@eecs.umich.edu 1134309Sgblack@eecs.umich.edu # This function takes in a block of microcode assembly and returns 1144309Sgblack@eecs.umich.edu # a python list of objects which describe it. 1154309Sgblack@eecs.umich.edu 1164309Sgblack@eecs.umich.edu # Keep this around in case we need it later 1174309Sgblack@eecs.umich.edu orig_code = code 1184309Sgblack@eecs.umich.edu # A list of the statements we've found thus far 1194309Sgblack@eecs.umich.edu statements = [] 1204309Sgblack@eecs.umich.edu 1214309Sgblack@eecs.umich.edu # Regular expressions to pull each piece of the statement out at a 1224309Sgblack@eecs.umich.edu # time. Each expression expects the thing it's looking for to be at 1234309Sgblack@eecs.umich.edu # the beginning of the line, so the previous component is stripped 1244309Sgblack@eecs.umich.edu # before continuing. 1254338Sgblack@eecs.umich.edu labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:') 1264371Sgblack@eecs.umich.edu lineRe = re.compile(r'^(?P<line>..*)(\n|$)') 1274309Sgblack@eecs.umich.edu classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)') 1284309Sgblack@eecs.umich.edu # This recognizes three different flavors of operands: 1294309Sgblack@eecs.umich.edu # 1. Raw decimal numbers composed of digits between 0 and 9 1304309Sgblack@eecs.umich.edu # 2. Code beginning with "{" and continuing until the first "}" 1314309Sgblack@eecs.umich.edu # ^ This one might need revising 1324309Sgblack@eecs.umich.edu # 3. A label, which starts with a capital or small letter, or 1334309Sgblack@eecs.umich.edu # underscore, which is optionally followed by a sequence of 1344309Sgblack@eecs.umich.edu # capital or small letters, underscores, or digts between 0 and 9 1354309Sgblack@eecs.umich.edu opRe = re.compile( \ 1364338Sgblack@eecs.umich.edu r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' + 1374338Sgblack@eecs.umich.edu r'(\@\{(?P<operandLabel1>[^}]*)\})|' + 1384338Sgblack@eecs.umich.edu r'(\%(?P<operandReg0>\w\w*))|' + 1394338Sgblack@eecs.umich.edu r'(\%\{(?P<operandReg1>[^}]*)\})|' + 1404338Sgblack@eecs.umich.edu r'(\$(?P<operandImm0>\w\w*))|' + 1414338Sgblack@eecs.umich.edu r'(\$\{(?P<operandImm1>[^}]*)\}))') 1424309Sgblack@eecs.umich.edu lineMatch = lineRe.search(code) 1434309Sgblack@eecs.umich.edu while lineMatch != None: 1444309Sgblack@eecs.umich.edu statement = MicroOpStatement() 1454309Sgblack@eecs.umich.edu # Get a line and seperate it from the rest of the code 1464309Sgblack@eecs.umich.edu line = lineMatch.group("line") 1474323Sgblack@eecs.umich.edu orig_line = line 1484371Sgblack@eecs.umich.edu #print "Parsing line %s" % line 1494309Sgblack@eecs.umich.edu code = lineRe.sub('', code, 1) 1504309Sgblack@eecs.umich.edu 1514309Sgblack@eecs.umich.edu # Find the label, if any 1524309Sgblack@eecs.umich.edu labelMatch = labelRe.search(line) 1534309Sgblack@eecs.umich.edu if labelMatch != None: 1544309Sgblack@eecs.umich.edu statement.label = labelMatch.group("label") 1554371Sgblack@eecs.umich.edu #print "Found label %s." % statement.label 1564309Sgblack@eecs.umich.edu # Clear the label from the statement 1574309Sgblack@eecs.umich.edu line = labelRe.sub('', line, 1) 1584309Sgblack@eecs.umich.edu 1594309Sgblack@eecs.umich.edu # Find the class name which is roughly equivalent to the op name 1604309Sgblack@eecs.umich.edu classMatch = classRe.search(line) 1614309Sgblack@eecs.umich.edu if classMatch == None: 1624323Sgblack@eecs.umich.edu raise Exception, "Couldn't find class name in statement: %s" \ 1634323Sgblack@eecs.umich.edu % orig_line 1644309Sgblack@eecs.umich.edu else: 1654309Sgblack@eecs.umich.edu statement.className = classMatch.group("className") 1664371Sgblack@eecs.umich.edu #print "Found class name %s." % statement.className 1674309Sgblack@eecs.umich.edu 1684309Sgblack@eecs.umich.edu # Clear the class name from the statement 1694309Sgblack@eecs.umich.edu line = classRe.sub('', line, 1) 1704309Sgblack@eecs.umich.edu 1714309Sgblack@eecs.umich.edu #Find as many arguments as you can 1724309Sgblack@eecs.umich.edu statement.args = [] 1734309Sgblack@eecs.umich.edu opMatch = opRe.search(line) 1744309Sgblack@eecs.umich.edu while opMatch is not None: 1754309Sgblack@eecs.umich.edu statement.args.append({}) 1764309Sgblack@eecs.umich.edu # args is a list of dicts which collect different 1774309Sgblack@eecs.umich.edu # representations of operand values. Different forms might be 1784309Sgblack@eecs.umich.edu # needed in different places, for instance to replace a label 1794309Sgblack@eecs.umich.edu # with an offset. 1804338Sgblack@eecs.umich.edu for opType in ("operandLabel0", "operandReg0", "operandImm0", 1814338Sgblack@eecs.umich.edu "operandLabel1", "operandReg1", "operandImm1"): 1824309Sgblack@eecs.umich.edu if opMatch.group(opType): 1834338Sgblack@eecs.umich.edu statement.args[-1][opType[:-1]] = opMatch.group(opType) 1844309Sgblack@eecs.umich.edu if len(statement.args[-1]) == 0: 1854323Sgblack@eecs.umich.edu print "Problem parsing operand in statement: %s" \ 1864323Sgblack@eecs.umich.edu % orig_line 1874309Sgblack@eecs.umich.edu line = opRe.sub('', line, 1) 1884371Sgblack@eecs.umich.edu #print "Found operand %s." % statement.args[-1] 1894309Sgblack@eecs.umich.edu opMatch = opRe.search(line) 1904371Sgblack@eecs.umich.edu #print "Found operands", statement.args 1914309Sgblack@eecs.umich.edu 1924309Sgblack@eecs.umich.edu # Add this statement to our collection 1934309Sgblack@eecs.umich.edu statements.append(statement) 1944309Sgblack@eecs.umich.edu 1954309Sgblack@eecs.umich.edu # Get the next line 1964309Sgblack@eecs.umich.edu lineMatch = lineRe.search(code) 1974323Sgblack@eecs.umich.edu 1984323Sgblack@eecs.umich.edu # Decode the labels into displacements 1994344Sgblack@eecs.umich.edu 2004344Sgblack@eecs.umich.edu labels = {} 2014344Sgblack@eecs.umich.edu micropc = 0 2024344Sgblack@eecs.umich.edu for statement in statements: 2034344Sgblack@eecs.umich.edu if statement.label: 2044344Sgblack@eecs.umich.edu labels[statement.label] = count 2054344Sgblack@eecs.umich.edu micropc += 1 2064323Sgblack@eecs.umich.edu micropc = 0 2074323Sgblack@eecs.umich.edu for statement in statements: 2084323Sgblack@eecs.umich.edu for arg in statement.args: 2094323Sgblack@eecs.umich.edu if arg.has_key("operandLabel"): 2104323Sgblack@eecs.umich.edu if not labels.has_key(arg["operandLabel"]): 2114323Sgblack@eecs.umich.edu raise Exception, "Unrecognized label: %s." % arg["operandLabel"] 2124323Sgblack@eecs.umich.edu # This is assuming that intra microcode branches go to 2134323Sgblack@eecs.umich.edu # the next micropc + displacement, or 2144323Sgblack@eecs.umich.edu # micropc + 1 + displacement. 2154338Sgblack@eecs.umich.edu arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1 2164323Sgblack@eecs.umich.edu micropc += 1 2174344Sgblack@eecs.umich.edu 2184371Sgblack@eecs.umich.edu if len(statements) == 0: 2194371Sgblack@eecs.umich.edu raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code 2204371Sgblack@eecs.umich.edu 2214344Sgblack@eecs.umich.edu # If we can implement this instruction with exactly one microop, just 2224344Sgblack@eecs.umich.edu # use that directly. 2234344Sgblack@eecs.umich.edu if len(statements) == 1: 2244344Sgblack@eecs.umich.edu decode_block = "return %s;" % \ 2254371Sgblack@eecs.umich.edu statements[0].getAllocator('"' + name + '"') 2264344Sgblack@eecs.umich.edu return ('', '', decode_block, '') 2274344Sgblack@eecs.umich.edu else: 2284344Sgblack@eecs.umich.edu # Build a macroop to contain the sequence of microops we've 2294344Sgblack@eecs.umich.edu # been given. 2304344Sgblack@eecs.umich.edu return genMacroOp(name, Name, statements) 2314309Sgblack@eecs.umich.edu}}; 232