microasm.isa revision 4323
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// Code to "assemble" microcode sequences 61// 62 63let {{ 64 class MicroOpStatement: 65 def __init__(self): 66 self.className = '' 67 self.label = '' 68 self.args = [] 69 70 # This converts a list of python bools into 71 # a comma seperated list of C++ bools. 72 def microFlagsText(self, vals): 73 text = "" 74 for val in vals: 75 if val: 76 text += ", true" 77 else: 78 text += ", false" 79 return text 80 81 def getAllocator(self, *microFlags): 82 args = '' 83 for arg in self.args: 84 if arg.has_key("operandConst"): 85 args += ", %s" % arg["operandConst"] 86 elif arg.has_key("operandCode"): 87 args += ", %s" % arg["operandCode"] 88 elif arg.has_key("operandLabel"): 89 raise Exception, "Found a label while creating allocator string." 90 else: 91 raise Exception, "Unrecognized operand type." 92 return 'new %s(machInst%s%s)' % (self.className, self.microFlagsText(microFlags), args) 93}}; 94 95let {{ 96 def buildLabelDict(ops): 97 labels = {} 98 micropc = 0 99 for op in ops: 100 if op.label: 101 labels[op.label] = count 102 micropc += 1 103 return labels 104 105 def assembleMicro(code): 106 # This function takes in a block of microcode assembly and returns 107 # a python list of objects which describe it. 108 109 # Keep this around in case we need it later 110 orig_code = code 111 # A list of the statements we've found thus far 112 statements = [] 113 114 # Regular expressions to pull each piece of the statement out at a 115 # time. Each expression expects the thing it's looking for to be at 116 # the beginning of the line, so the previous component is stripped 117 # before continuing. 118 labelRe = re.compile(r'^[ \t]*(?P<label>[a-zA-Z_]\w*)[ \t]:') 119 lineRe = re.compile(r'^(?P<line>[^\n][^\n]*)$') 120 classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)') 121 # This recognizes three different flavors of operands: 122 # 1. Raw decimal numbers composed of digits between 0 and 9 123 # 2. Code beginning with "{" and continuing until the first "}" 124 # ^ This one might need revising 125 # 3. A label, which starts with a capital or small letter, or 126 # underscore, which is optionally followed by a sequence of 127 # capital or small letters, underscores, or digts between 0 and 9 128 opRe = re.compile( \ 129 r'^[ \t]*((?P<operandLabel>[a-zA-Z_]\w*)|(?P<operandConst>[0-9][0-9]*)|(\{(?P<operandCode>[^}]*)\}))') 130 lineMatch = lineRe.search(code) 131 while lineMatch != None: 132 statement = MicroOpStatement() 133 # Get a line and seperate it from the rest of the code 134 line = lineMatch.group("line") 135 orig_line = line 136 # print "Parsing line %s" % line 137 code = lineRe.sub('', code, 1) 138 139 # Find the label, if any 140 labelMatch = labelRe.search(line) 141 if labelMatch != None: 142 statement.label = labelMatch.group("label") 143 # print "Found label %s." % statement.label 144 # Clear the label from the statement 145 line = labelRe.sub('', line, 1) 146 147 # Find the class name which is roughly equivalent to the op name 148 classMatch = classRe.search(line) 149 if classMatch == None: 150 raise Exception, "Couldn't find class name in statement: %s" \ 151 % orig_line 152 else: 153 statement.className = classMatch.group("className") 154 # print "Found class name %s." % statement.className 155 156 # Clear the class name from the statement 157 line = classRe.sub('', line, 1) 158 159 #Find as many arguments as you can 160 statement.args = [] 161 opMatch = opRe.search(line) 162 while opMatch is not None: 163 statement.args.append({}) 164 # args is a list of dicts which collect different 165 # representations of operand values. Different forms might be 166 # needed in different places, for instance to replace a label 167 # with an offset. 168 for opType in ("operandLabel", "operandConst", "operandCode"): 169 if opMatch.group(opType): 170 statement.args[-1][opType] = opMatch.group(opType) 171 if len(statement.args[-1]) == 0: 172 print "Problem parsing operand in statement: %s" \ 173 % orig_line 174 line = opRe.sub('', line, 1) 175 # print "Found operand %s." % statement.args[-1] 176 opMatch = opRe.search(line) 177 # print "Found operands", statement.args 178 179 # Add this statement to our collection 180 statements.append(statement) 181 182 # Get the next line 183 lineMatch = lineRe.search(code) 184 185 # Decode the labels into displacements 186 labels = buildLabelDict(statements) 187 micropc = 0 188 for statement in statements: 189 for arg in statement.args: 190 if arg.has_key("operandLabel"): 191 if not labels.has_key(arg["operandLabel"]): 192 raise Exception, "Unrecognized label: %s." % arg["operandLabel"] 193 # This is assuming that intra microcode branches go to 194 # the next micropc + displacement, or 195 # micropc + 1 + displacement. 196 arg["operandConst"] = labels[arg["operandLabel"]] - micropc - 1 197 micropc += 1 198 return statements 199}}; 200