microasm.isa (4371:c5003760793e) | microasm.isa (4519:f8da6b45573f) |
---|---|
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: --- 43 unchanged lines hidden (view full) --- 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// | 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: --- 43 unchanged lines hidden (view full) --- 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 | 60// Microcode assembler specialization for x86 |
61// 62 63let {{ | 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" | 64 from micro_asm import MicroAssembler, Combinational_Macroop, Rom_Macroop, Rom 65 class X86Macroop(Combinational_Macroop): 66 def __init__(self, name): 67 super(X86Macroop, self).__init__(name) 68 self.directives = { 69 } 70 71 mainRom = Rom('main ROM') |
68}}; 69 70let {{ | 72}}; 73 74let {{ |
71 class MicroOpStatement(object): 72 def __init__(self): 73 self.className = '' 74 self.label = '' 75 self.args = [] | 75 class X86Microop(object): 76 def __init__(self, name): 77 self.name = name |
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 = '' | 78 79 # This converts a list of python bools into 80 # a comma seperated list of C++ bools. 81 def microFlagsText(self, vals): 82 text = "" 83 for val in vals: 84 if val: 85 text += ", true" 86 else: 87 text += ", false" 88 return text 89 90 def getAllocator(self, mnemonic, *microFlags): 91 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) | 92 return 'new %s(machInst, %s%s%s)' % (self.className, mnemonic, self.microFlagsText(microFlags), args) |
108}}; | 93}}; |
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}}; | |