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:
parent
5c4cc4b552
commit
e67a207ad3
2 changed files with 175 additions and 0 deletions
|
@ -72,6 +72,9 @@
|
|||
|
||||
namespace X86ISA;
|
||||
|
||||
//Include the simple microcode assembler
|
||||
##include "microasm.isa"
|
||||
|
||||
//Include the bitfield definitions
|
||||
##include "bitfields.isa"
|
||||
|
||||
|
|
172
src/arch/x86/isa/microasm.isa
Normal file
172
src/arch/x86/isa/microasm.isa
Normal 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
|
||||
}};
|
Loading…
Reference in a new issue