summaryrefslogtreecommitdiff
path: root/src/arch/x86/isa/microasm.isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/isa/microasm.isa')
-rw-r--r--src/arch/x86/isa/microasm.isa125
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)
}};