microasm.isa revision 4371:c5003760793e
1// -*- mode:c++ -*- 2 3// Copyright (c) 2007 The Hewlett-Packard Development Company 4// All rights reserved. 5// 6// Redistribution and use of this software in source and binary forms, 7// with or without modification, are permitted provided that the 8// following conditions are met: 9// 10// The software must be used only for Non-Commercial Use which means any 11// use which is NOT directed to receiving any direct monetary 12// compensation for, or commercial advantage from such use. Illustrative 13// examples of non-commercial use are academic research, personal study, 14// teaching, education and corporate research & development. 15// Illustrative examples of commercial use are distributing products for 16// commercial advantage and providing services using the software for 17// commercial advantage. 18// 19// If you wish to use this software or functionality therein that may be 20// covered by patents for commercial use, please contact: 21// Director of Intellectual Property Licensing 22// Office of Strategy and Technology 23// Hewlett-Packard Company 24// 1501 Page Mill Road 25// Palo Alto, California 94304 26// 27// Redistributions of source code must retain the above copyright notice, 28// this list of conditions and the following disclaimer. Redistributions 29// in binary form must reproduce the above copyright notice, this list of 30// conditions and the following disclaimer in the documentation and/or 31// other materials provided with the distribution. Neither the name of 32// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 33// contributors may be used to endorse or promote products derived from 34// this software without specific prior written permission. No right of 35// sublicense is granted herewith. Derivatives of the software and 36// output created using the software may be prepared, but only for 37// Non-Commercial Uses. Derivatives of the software may be shared with 38// others provided: (i) the others agree to abide by the list of 39// conditions herein which includes the Non-Commercial Use restrictions; 40// and (ii) such Derivatives of the software include the above copyright 41// notice to acknowledge the contribution from this software where 42// applicable, this list of conditions and the disclaimer below. 43// 44// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 45// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 46// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 47// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 48// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 49// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 50// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 54// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55// 56// Authors: Gabe Black 57 58//////////////////////////////////////////////////////////////////// 59// 60// The microcode assembler 61// 62 63let {{ 64 # These are used when setting up microops so that they can specialize their 65 # base class template properly. 66 RegOpType = "RegisterOperand" 67 ImmOpType = "ImmediateOperand" 68}}; 69 70let {{ 71 class MicroOpStatement(object): 72 def __init__(self): 73 self.className = '' 74 self.label = '' 75 self.args = [] 76 77 # This converts a list of python bools into 78 # a comma seperated list of C++ bools. 79 def microFlagsText(self, vals): 80 text = "" 81 for val in vals: 82 if val: 83 text += ", true" 84 else: 85 text += ", false" 86 return text 87 88 def getAllocator(self, mnemonic, *microFlags): 89 args = '' 90 signature = "<" 91 emptySig = True 92 for arg in self.args: 93 if not emptySig: 94 signature += ", " 95 emptySig = False 96 if arg.has_key("operandImm"): 97 args += ", %s" % arg["operandImm"] 98 signature += ImmOpType 99 elif arg.has_key("operandReg"): 100 args += ", %s" % arg["operandReg"] 101 signature += RegOpType 102 elif arg.has_key("operandLabel"): 103 raise Exception, "Found a label while creating allocator string." 104 else: 105 raise Exception, "Unrecognized operand type." 106 signature += ">" 107 return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args) 108}}; 109 110let{{ 111 def assembleMicro(name, Name, code): 112 113 # This function takes in a block of microcode assembly and returns 114 # a python list of objects which describe it. 115 116 # Keep this around in case we need it later 117 orig_code = code 118 # A list of the statements we've found thus far 119 statements = [] 120 121 # Regular expressions to pull each piece of the statement out at a 122 # time. Each expression expects the thing it's looking for to be at 123 # the beginning of the line, so the previous component is stripped 124 # before continuing. 125 labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:') 126 lineRe = re.compile(r'^(?P<line>..*)(\n|$)') 127 classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)') 128 # This recognizes three different flavors of operands: 129 # 1. Raw decimal numbers composed of digits between 0 and 9 130 # 2. Code beginning with "{" and continuing until the first "}" 131 # ^ This one might need revising 132 # 3. A label, which starts with a capital or small letter, or 133 # underscore, which is optionally followed by a sequence of 134 # capital or small letters, underscores, or digts between 0 and 9 135 opRe = re.compile( \ 136 r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' + 137 r'(\@\{(?P<operandLabel1>[^}]*)\})|' + 138 r'(\%(?P<operandReg0>\w\w*))|' + 139 r'(\%\{(?P<operandReg1>[^}]*)\})|' + 140 r'(\$(?P<operandImm0>\w\w*))|' + 141 r'(\$\{(?P<operandImm1>[^}]*)\}))') 142 lineMatch = lineRe.search(code) 143 while lineMatch != None: 144 statement = MicroOpStatement() 145 # Get a line and seperate it from the rest of the code 146 line = lineMatch.group("line") 147 orig_line = line 148 #print "Parsing line %s" % line 149 code = lineRe.sub('', code, 1) 150 151 # Find the label, if any 152 labelMatch = labelRe.search(line) 153 if labelMatch != None: 154 statement.label = labelMatch.group("label") 155 #print "Found label %s." % statement.label 156 # Clear the label from the statement 157 line = labelRe.sub('', line, 1) 158 159 # Find the class name which is roughly equivalent to the op name 160 classMatch = classRe.search(line) 161 if classMatch == None: 162 raise Exception, "Couldn't find class name in statement: %s" \ 163 % orig_line 164 else: 165 statement.className = classMatch.group("className") 166 #print "Found class name %s." % statement.className 167 168 # Clear the class name from the statement 169 line = classRe.sub('', line, 1) 170 171 #Find as many arguments as you can 172 statement.args = [] 173 opMatch = opRe.search(line) 174 while opMatch is not None: 175 statement.args.append({}) 176 # args is a list of dicts which collect different 177 # representations of operand values. Different forms might be 178 # needed in different places, for instance to replace a label 179 # with an offset. 180 for opType in ("operandLabel0", "operandReg0", "operandImm0", 181 "operandLabel1", "operandReg1", "operandImm1"): 182 if opMatch.group(opType): 183 statement.args[-1][opType[:-1]] = opMatch.group(opType) 184 if len(statement.args[-1]) == 0: 185 print "Problem parsing operand in statement: %s" \ 186 % orig_line 187 line = opRe.sub('', line, 1) 188 #print "Found operand %s." % statement.args[-1] 189 opMatch = opRe.search(line) 190 #print "Found operands", statement.args 191 192 # Add this statement to our collection 193 statements.append(statement) 194 195 # Get the next line 196 lineMatch = lineRe.search(code) 197 198 # Decode the labels into displacements 199 200 labels = {} 201 micropc = 0 202 for statement in statements: 203 if statement.label: 204 labels[statement.label] = count 205 micropc += 1 206 micropc = 0 207 for statement in statements: 208 for arg in statement.args: 209 if arg.has_key("operandLabel"): 210 if not labels.has_key(arg["operandLabel"]): 211 raise Exception, "Unrecognized label: %s." % arg["operandLabel"] 212 # This is assuming that intra microcode branches go to 213 # the next micropc + displacement, or 214 # micropc + 1 + displacement. 215 arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1 216 micropc += 1 217 218 if len(statements) == 0: 219 raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code 220 221 # If we can implement this instruction with exactly one microop, just 222 # use that directly. 223 if len(statements) == 1: 224 decode_block = "return %s;" % \ 225 statements[0].getAllocator('"' + name + '"') 226 return ('', '', decode_block, '') 227 else: 228 # Build a macroop to contain the sequence of microops we've 229 # been given. 230 return genMacroOp(name, Name, statements) 231}}; 232