Add a microcode assembler. A microcode "program" is a series of statements. Each statement has an optional label at the beginning, a capitilized microcode class name which is roughly equivalent to a mnemonic in a regular ISA, and then an optional series of operands seperated by white space. The operands are either a decimal constant, a label, or a code fragment surrounded by non nested {}s. Labels are a letter or underscore followed by letters, underscores, or digits. The syntax for describing code segments might need to be changed if a need arrises to have {}s in the code itself.

--HG--
extra : convert_revision : 8e5cfdd1a3c9a7e3731fdf6acd615ee82ac2b9b7
This commit is contained in:
Gabe Black 2007-03-29 17:57:18 +00:00
parent 5c4cc4b552
commit e67a207ad3
2 changed files with 175 additions and 0 deletions

View file

@ -72,6 +72,9 @@
namespace X86ISA;
//Include the simple microcode assembler
##include "microasm.isa"
//Include the bitfield definitions
##include "bitfields.isa"

View file

@ -0,0 +1,172 @@
// -*- mode:c++ -*-
// Copyright (c) 2007 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
// with or without modification, are permitted provided that the
// following conditions are met:
//
// The software must be used only for Non-Commercial Use which means any
// use which is NOT directed to receiving any direct monetary
// compensation for, or commercial advantage from such use. Illustrative
// examples of non-commercial use are academic research, personal study,
// teaching, education and corporate research & development.
// Illustrative examples of commercial use are distributing products for
// commercial advantage and providing services using the software for
// commercial advantage.
//
// If you wish to use this software or functionality therein that may be
// covered by patents for commercial use, please contact:
// Director of Intellectual Property Licensing
// Office of Strategy and Technology
// Hewlett-Packard Company
// 1501 Page Mill Road
// Palo Alto, California 94304
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. Redistributions
// in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution. Neither the name of
// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission. No right of
// sublicense is granted herewith. Derivatives of the software and
// output created using the software may be prepared, but only for
// Non-Commercial Uses. Derivatives of the software may be shared with
// others provided: (i) the others agree to abide by the list of
// conditions herein which includes the Non-Commercial Use restrictions;
// and (ii) such Derivatives of the software include the above copyright
// notice to acknowledge the contribution from this software where
// applicable, this list of conditions and the disclaimer below.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
////////////////////////////////////////////////////////////////////
//
// Code to "assemble" microcode sequences
//
let {{
class MicroOpStatement:
def __init__(self):
self.className = ''
self.label = ''
self.args = []
def getAllocator(self, labelDict = {}):
args = ''
for arg in self.args:
if arg.has_key("operandConst"):
args += ", %s" % arg["operandConst"]
elif arg.has_key("operandCode"):
args += ", %s" % arg["operandCode"]
elif arg.has_key("operandLabel"):
if not labelDict.has_key(arg["operandLabel"]):
print "Unrecognized label %s!" % arg["operandLabel"]
args += ", %s" % labelDict[arg["operandLabel"]]
else:
print "Unrecognized operand type!"
return 'new %s(machInst %s)' % (self.className, args)
def assembleMicro(code):
# This function takes in a block of microcode assembly and returns
# a python list of objects which describe it.
# Keep this around in case we need it later
orig_code = code
# A list of the statements we've found thus far
statements = []
# Regular expressions to pull each piece of the statement out at a
# 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]*)$')
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
# 2. Code beginning with "{" and continuing until the first "}"
# ^ This one might need revising
# 3. A label, which starts with a capital or small letter, or
# 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>[^}]*)\}))')
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
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
# 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!"
else:
statement.className = classMatch.group("className")
print "Found class name %s." % statement.className
# Clear the class name from the statement
line = classRe.sub('', line, 1)
#Find as many arguments as you can
statement.args = []
opMatch = opRe.search(line)
while opMatch is not None:
statement.args.append({})
# args is a list of dicts which collect different
# 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"):
if opMatch.group(opType):
statement.args[-1][opType] = opMatch.group(opType)
if len(statement.args[-1]) == 0:
print "I had a problem parsing an operand!"
line = opRe.sub('', line, 1)
print "Found operand %s." % statement.args[-1]
opMatch = opRe.search(line)
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):
labels = {}
count = 0
for op in ops:
if op.label:
labels[op.label] = count
count += 1
}};