microasm.isa revision 4323:13ca4002d2ac
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:
9//
10// The software must be used only for Non-Commercial Use which means any
11// use which is NOT directed to receiving any direct monetary
12// compensation for, or commercial advantage from such use.  Illustrative
13// examples of non-commercial use are academic research, personal study,
14// teaching, education and corporate research & development.
15// Illustrative examples of commercial use are distributing products for
16// commercial advantage and providing services using the software for
17// commercial advantage.
18//
19// If you wish to use this software or functionality therein that may be
20// covered by patents for commercial use, please contact:
21//     Director of Intellectual Property Licensing
22//     Office of Strategy and Technology
23//     Hewlett-Packard Company
24//     1501 Page Mill Road
25//     Palo Alto, California  94304
26//
27// Redistributions of source code must retain the above copyright notice,
28// this list of conditions and the following disclaimer.  Redistributions
29// in binary form must reproduce the above copyright notice, this list of
30// conditions and the following disclaimer in the documentation and/or
31// other materials provided with the distribution.  Neither the name of
32// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
33// contributors may be used to endorse or promote products derived from
34// this software without specific prior written permission.  No right of
35// sublicense is granted herewith.  Derivatives of the software and
36// output created using the software may be prepared, but only for
37// Non-Commercial Uses.  Derivatives of the software may be shared with
38// others provided: (i) the others agree to abide by the list of
39// conditions herein which includes the Non-Commercial Use restrictions;
40// and (ii) such Derivatives of the software include the above copyright
41// notice to acknowledge the contribution from this software where
42// applicable, this list of conditions and the disclaimer below.
43//
44// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
46// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
47// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
48// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
50// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
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//  Code to "assemble" microcode sequences
61//
62
63let {{
64    class MicroOpStatement:
65        def __init__(self):
66            self.className = ''
67            self.label = ''
68            self.args = []
69
70        # This converts a list of python bools into
71        # a comma seperated list of C++ bools.
72        def microFlagsText(self, vals):
73            text = ""
74            for val in vals:
75                if val:
76                    text += ", true"
77                else:
78                    text += ", false"
79            return text
80
81        def getAllocator(self, *microFlags):
82            args = ''
83            for arg in self.args:
84                if arg.has_key("operandConst"):
85                    args += ", %s" % arg["operandConst"]
86                elif arg.has_key("operandCode"):
87                    args += ", %s" % arg["operandCode"]
88                elif arg.has_key("operandLabel"):
89                    raise Exception, "Found a label while creating allocator string."
90                else:
91                    raise Exception, "Unrecognized operand type."
92            return 'new %s(machInst%s%s)' % (self.className, self.microFlagsText(microFlags), args)
93}};
94
95let {{
96    def buildLabelDict(ops):
97        labels = {}
98        micropc = 0
99        for op in ops:
100            if op.label:
101                labels[op.label] = count
102            micropc += 1
103        return labels
104
105    def assembleMicro(code):
106        # This function takes in a block of microcode assembly and returns
107        # a python list of objects which describe it.
108
109        # Keep this around in case we need it later
110        orig_code = code
111        # A list of the statements we've found thus far
112        statements = []
113
114        # Regular expressions to pull each piece of the statement out at a
115        # time. Each expression expects the thing it's looking for to be at
116        # the beginning of the line, so the previous component is stripped
117        # before continuing.
118        labelRe = re.compile(r'^[ \t]*(?P<label>[a-zA-Z_]\w*)[ \t]:')
119        lineRe = re.compile(r'^(?P<line>[^\n][^\n]*)$')
120        classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)')
121        # This recognizes three different flavors of operands:
122        # 1. Raw decimal numbers composed of digits between 0 and 9
123        # 2. Code beginning with "{" and continuing until the first "}"
124        #         ^ This one might need revising
125        # 3. A label, which starts with a capital or small letter, or
126        #    underscore, which is optionally followed by a sequence of
127        #    capital or small letters, underscores, or digts between 0 and 9
128        opRe = re.compile( \
129            r'^[ \t]*((?P<operandLabel>[a-zA-Z_]\w*)|(?P<operandConst>[0-9][0-9]*)|(\{(?P<operandCode>[^}]*)\}))')
130        lineMatch = lineRe.search(code)
131        while lineMatch != None:
132            statement = MicroOpStatement()
133            # Get a line and seperate it from the rest of the code
134            line = lineMatch.group("line")
135            orig_line = line
136            # print "Parsing line %s" % line
137            code = lineRe.sub('', code, 1)
138
139            # Find the label, if any
140            labelMatch = labelRe.search(line)
141            if labelMatch != None:
142                statement.label = labelMatch.group("label")
143                # print "Found label %s." % statement.label
144            # Clear the label from the statement
145            line = labelRe.sub('', line, 1)
146
147            # Find the class name which is roughly equivalent to the op name
148            classMatch = classRe.search(line)
149            if classMatch == None:
150                raise Exception, "Couldn't find class name in statement: %s" \
151                        % orig_line
152            else:
153                statement.className = classMatch.group("className")
154                # print "Found class name %s." % statement.className
155
156            # Clear the class name from the statement
157            line = classRe.sub('', line, 1)
158
159            #Find as many arguments as you can
160            statement.args = []
161            opMatch = opRe.search(line)
162            while opMatch is not None:
163                statement.args.append({})
164                # args is a list of dicts which collect different
165                # representations of operand values. Different forms might be
166                # needed in different places, for instance to replace a label
167                # with an offset.
168                for opType in ("operandLabel", "operandConst", "operandCode"):
169                    if opMatch.group(opType):
170                        statement.args[-1][opType] = opMatch.group(opType)
171                if len(statement.args[-1]) == 0:
172                    print "Problem parsing operand in statement: %s" \
173                            % orig_line
174                line = opRe.sub('', line, 1)
175                # print "Found operand %s." % statement.args[-1]
176                opMatch = opRe.search(line)
177            # print "Found operands", statement.args
178
179            # Add this statement to our collection
180            statements.append(statement)
181
182            # Get the next line
183            lineMatch = lineRe.search(code)
184
185        # Decode the labels into displacements
186        labels = buildLabelDict(statements)
187        micropc = 0
188        for statement in statements:
189            for arg in statement.args:
190                if arg.has_key("operandLabel"):
191                    if not labels.has_key(arg["operandLabel"]):
192                        raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
193                    # This is assuming that intra microcode branches go to
194                    # the next micropc + displacement, or
195                    # micropc + 1 + displacement.
196                    arg["operandConst"] = labels[arg["operandLabel"]] - micropc - 1
197            micropc += 1
198        return statements
199}};
200