diff options
Diffstat (limited to 'src/arch/x86/isa/microasm.isa')
-rw-r--r-- | src/arch/x86/isa/microasm.isa | 125 |
1 files changed, 92 insertions, 33 deletions
diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index 2abce6e7f..9d21b6bcc 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -57,33 +57,59 @@ //////////////////////////////////////////////////////////////////// // -// Code to "assemble" microcode sequences +// The microcode assembler // let {{ - class MicroOpStatement: + # These are used when setting up microops so that they can specialize their + # base class template properly. + RegOpType = "RegisterOperand" + ImmOpType = "ImmediateOperand" +}}; + +let {{ + class MicroOpStatement(object): def __init__(self): self.className = '' self.label = '' self.args = [] - def getAllocator(self, labelDict = {}): + # This converts a list of python bools into + # a comma seperated list of C++ bools. + def microFlagsText(self, vals): + text = "" + for val in vals: + if val: + text += ", true" + else: + text += ", false" + return text + + def getAllocator(self, mnemonic, *microFlags): args = '' + signature = "<" + emptySig = True for arg in self.args: - if arg.has_key("operandConst"): - args += ", %s" % arg["operandConst"] - elif arg.has_key("operandCode"): - args += ", %s" % arg["operandCode"] + if not emptySig: + signature += ", " + emptySig = False + if arg.has_key("operandImm"): + args += ", %s" % arg["operandImm"] + signature += ImmOpType + elif arg.has_key("operandReg"): + args += ", %s" % arg["operandReg"] + signature += RegOpType elif arg.has_key("operandLabel"): - if not labelDict.has_key(arg["operandLabel"]): - print "Unrecognized label %s!" % arg["operandLabel"] - args += ", %s" % labelDict[arg["operandLabel"]] + raise Exception, "Found a label while creating allocator string." else: - print "Unrecognized operand type!" - return 'new %s(machInst %s)' % (self.className, args) + raise Exception, "Unrecognized operand type." + signature += ">" + return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args) +}}; +let{{ + def assembleMicro(name, Name, code): - def assembleMicro(code): # This function takes in a block of microcode assembly and returns # a python list of objects which describe it. @@ -96,8 +122,8 @@ let {{ # time. Each expression expects the thing it's looking for to be at # the beginning of the line, so the previous component is stripped # before continuing. - labelRe = re.compile(r'^[ \t]*(?P<label>[a-zA-Z_]\w*)[ \t]:') - lineRe = re.compile(r'^(?P<line>[^\n][^\n]*)$') + labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:') + lineRe = re.compile(r'^(?P<line>..*)(\n|$)') classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)') # This recognizes three different flavors of operands: # 1. Raw decimal numbers composed of digits between 0 and 9 @@ -107,31 +133,37 @@ let {{ # underscore, which is optionally followed by a sequence of # capital or small letters, underscores, or digts between 0 and 9 opRe = re.compile( \ - r'^[ \t]*((?P<operandLabel>[a-zA-Z_]\w*)|(?P<operandConst>[0-9][0-9]*)|(\{(?P<operandCode>[^}]*)\}))') + r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' + + r'(\@\{(?P<operandLabel1>[^}]*)\})|' + + r'(\%(?P<operandReg0>\w\w*))|' + + r'(\%\{(?P<operandReg1>[^}]*)\})|' + + r'(\$(?P<operandImm0>\w\w*))|' + + r'(\$\{(?P<operandImm1>[^}]*)\}))') lineMatch = lineRe.search(code) while lineMatch != None: statement = MicroOpStatement() # Get a line and seperate it from the rest of the code line = lineMatch.group("line") - print "Parsing line %s" % line + orig_line = line + #print "Parsing line %s" % line code = lineRe.sub('', code, 1) # Find the label, if any labelMatch = labelRe.search(line) if labelMatch != None: statement.label = labelMatch.group("label") - print "Found label %s." % statement.label + #print "Found label %s." % statement.label # Clear the label from the statement line = labelRe.sub('', line, 1) # Find the class name which is roughly equivalent to the op name classMatch = classRe.search(line) if classMatch == None: - print "Oh no! I can't find what instruction you want!" - print "I should really bail out here, but I don't know how!" + raise Exception, "Couldn't find class name in statement: %s" \ + % orig_line else: statement.className = classMatch.group("className") - print "Found class name %s." % statement.className + #print "Found class name %s." % statement.className # Clear the class name from the statement line = classRe.sub('', line, 1) @@ -145,28 +177,55 @@ let {{ # representations of operand values. Different forms might be # needed in different places, for instance to replace a label # with an offset. - for opType in ("operandLabel", "operandConst", "operandCode"): + for opType in ("operandLabel0", "operandReg0", "operandImm0", + "operandLabel1", "operandReg1", "operandImm1"): if opMatch.group(opType): - statement.args[-1][opType] = opMatch.group(opType) + statement.args[-1][opType[:-1]] = opMatch.group(opType) if len(statement.args[-1]) == 0: - print "I had a problem parsing an operand!" + print "Problem parsing operand in statement: %s" \ + % orig_line line = opRe.sub('', line, 1) - print "Found operand %s." % statement.args[-1] + #print "Found operand %s." % statement.args[-1] opMatch = opRe.search(line) - print "Found operands", statement.args + #print "Found operands", statement.args # Add this statement to our collection statements.append(statement) # Get the next line lineMatch = lineRe.search(code) - return statements - def buildLabelDict(ops): + # Decode the labels into displacements + labels = {} - count = 0 - for op in ops: - if op.label: - labels[op.label] = count - count += 1 + micropc = 0 + for statement in statements: + if statement.label: + labels[statement.label] = count + micropc += 1 + micropc = 0 + for statement in statements: + for arg in statement.args: + if arg.has_key("operandLabel"): + if not labels.has_key(arg["operandLabel"]): + raise Exception, "Unrecognized label: %s." % arg["operandLabel"] + # This is assuming that intra microcode branches go to + # the next micropc + displacement, or + # micropc + 1 + displacement. + arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1 + micropc += 1 + + if len(statements) == 0: + raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code + + # If we can implement this instruction with exactly one microop, just + # use that directly. + if len(statements) == 1: + decode_block = "return %s;" % \ + statements[0].getAllocator('"' + name + '"') + return ('', '', decode_block, '') + else: + # Build a macroop to contain the sequence of microops we've + # been given. + return genMacroOp(name, Name, statements) }}; |