microasm.isa (4349:b223256d0a79) microasm.isa (4371:c5003760793e)
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// The microcode assembler
61//
62
63let {{
64 # These are used when setting up microops so that they can specialize their
65 # base class template properly.
66 RegOpType = "RegisterOperand"
67 ImmOpType = "ImmediateOperand"
68}};
69
70let {{
71 class MicroOpStatement(object):
72 def __init__(self):
73 self.className = ''
74 self.label = ''
75 self.args = []
76
77 # This converts a list of python bools into
78 # a comma seperated list of C++ bools.
79 def microFlagsText(self, vals):
80 text = ""
81 for val in vals:
82 if val:
83 text += ", true"
84 else:
85 text += ", false"
86 return text
87
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// The microcode assembler
61//
62
63let {{
64 # These are used when setting up microops so that they can specialize their
65 # base class template properly.
66 RegOpType = "RegisterOperand"
67 ImmOpType = "ImmediateOperand"
68}};
69
70let {{
71 class MicroOpStatement(object):
72 def __init__(self):
73 self.className = ''
74 self.label = ''
75 self.args = []
76
77 # This converts a list of python bools into
78 # a comma seperated list of C++ bools.
79 def microFlagsText(self, vals):
80 text = ""
81 for val in vals:
82 if val:
83 text += ", true"
84 else:
85 text += ", false"
86 return text
87
88 def getAllocator(self, *microFlags):
88 def getAllocator(self, mnemonic, *microFlags):
89 args = ''
90 signature = "<"
91 emptySig = True
92 for arg in self.args:
93 if not emptySig:
94 signature += ", "
95 emptySig = False
96 if arg.has_key("operandImm"):
97 args += ", %s" % arg["operandImm"]
98 signature += ImmOpType
99 elif arg.has_key("operandReg"):
100 args += ", %s" % arg["operandReg"]
101 signature += RegOpType
102 elif arg.has_key("operandLabel"):
103 raise Exception, "Found a label while creating allocator string."
104 else:
105 raise Exception, "Unrecognized operand type."
106 signature += ">"
89 args = ''
90 signature = "<"
91 emptySig = True
92 for arg in self.args:
93 if not emptySig:
94 signature += ", "
95 emptySig = False
96 if arg.has_key("operandImm"):
97 args += ", %s" % arg["operandImm"]
98 signature += ImmOpType
99 elif arg.has_key("operandReg"):
100 args += ", %s" % arg["operandReg"]
101 signature += RegOpType
102 elif arg.has_key("operandLabel"):
103 raise Exception, "Found a label while creating allocator string."
104 else:
105 raise Exception, "Unrecognized operand type."
106 signature += ">"
107 return 'new %s%s(machInst%s%s)' % (self.className, signature, self.microFlagsText(microFlags), args)
107 return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args)
108}};
109
110let{{
111 def assembleMicro(name, Name, code):
112
113 # This function takes in a block of microcode assembly and returns
114 # a python list of objects which describe it.
115
116 # Keep this around in case we need it later
117 orig_code = code
118 # A list of the statements we've found thus far
119 statements = []
120
121 # Regular expressions to pull each piece of the statement out at a
122 # time. Each expression expects the thing it's looking for to be at
123 # the beginning of the line, so the previous component is stripped
124 # before continuing.
125 labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:')
108}};
109
110let{{
111 def assembleMicro(name, Name, code):
112
113 # This function takes in a block of microcode assembly and returns
114 # a python list of objects which describe it.
115
116 # Keep this around in case we need it later
117 orig_code = code
118 # A list of the statements we've found thus far
119 statements = []
120
121 # Regular expressions to pull each piece of the statement out at a
122 # time. Each expression expects the thing it's looking for to be at
123 # the beginning of the line, so the previous component is stripped
124 # before continuing.
125 labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:')
126 lineRe = re.compile(r'^(?P<line>[^\n][^\n]*)$')
126 lineRe = re.compile(r'^(?P<line>..*)(\n|$)')
127 classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)')
128 # This recognizes three different flavors of operands:
129 # 1. Raw decimal numbers composed of digits between 0 and 9
130 # 2. Code beginning with "{" and continuing until the first "}"
131 # ^ This one might need revising
132 # 3. A label, which starts with a capital or small letter, or
133 # underscore, which is optionally followed by a sequence of
134 # capital or small letters, underscores, or digts between 0 and 9
135 opRe = re.compile( \
136 r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' +
137 r'(\@\{(?P<operandLabel1>[^}]*)\})|' +
138 r'(\%(?P<operandReg0>\w\w*))|' +
139 r'(\%\{(?P<operandReg1>[^}]*)\})|' +
140 r'(\$(?P<operandImm0>\w\w*))|' +
141 r'(\$\{(?P<operandImm1>[^}]*)\}))')
142 lineMatch = lineRe.search(code)
143 while lineMatch != None:
144 statement = MicroOpStatement()
145 # Get a line and seperate it from the rest of the code
146 line = lineMatch.group("line")
147 orig_line = line
127 classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)')
128 # This recognizes three different flavors of operands:
129 # 1. Raw decimal numbers composed of digits between 0 and 9
130 # 2. Code beginning with "{" and continuing until the first "}"
131 # ^ This one might need revising
132 # 3. A label, which starts with a capital or small letter, or
133 # underscore, which is optionally followed by a sequence of
134 # capital or small letters, underscores, or digts between 0 and 9
135 opRe = re.compile( \
136 r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' +
137 r'(\@\{(?P<operandLabel1>[^}]*)\})|' +
138 r'(\%(?P<operandReg0>\w\w*))|' +
139 r'(\%\{(?P<operandReg1>[^}]*)\})|' +
140 r'(\$(?P<operandImm0>\w\w*))|' +
141 r'(\$\{(?P<operandImm1>[^}]*)\}))')
142 lineMatch = lineRe.search(code)
143 while lineMatch != None:
144 statement = MicroOpStatement()
145 # Get a line and seperate it from the rest of the code
146 line = lineMatch.group("line")
147 orig_line = line
148 # print "Parsing line %s" % line
148 #print "Parsing line %s" % line
149 code = lineRe.sub('', code, 1)
150
151 # Find the label, if any
152 labelMatch = labelRe.search(line)
153 if labelMatch != None:
154 statement.label = labelMatch.group("label")
149 code = lineRe.sub('', code, 1)
150
151 # Find the label, if any
152 labelMatch = labelRe.search(line)
153 if labelMatch != None:
154 statement.label = labelMatch.group("label")
155 # print "Found label %s." % statement.label
155 #print "Found label %s." % statement.label
156 # Clear the label from the statement
157 line = labelRe.sub('', line, 1)
158
159 # Find the class name which is roughly equivalent to the op name
160 classMatch = classRe.search(line)
161 if classMatch == None:
162 raise Exception, "Couldn't find class name in statement: %s" \
163 % orig_line
164 else:
165 statement.className = classMatch.group("className")
156 # Clear the label from the statement
157 line = labelRe.sub('', line, 1)
158
159 # Find the class name which is roughly equivalent to the op name
160 classMatch = classRe.search(line)
161 if classMatch == None:
162 raise Exception, "Couldn't find class name in statement: %s" \
163 % orig_line
164 else:
165 statement.className = classMatch.group("className")
166 # print "Found class name %s." % statement.className
166 #print "Found class name %s." % statement.className
167
168 # Clear the class name from the statement
169 line = classRe.sub('', line, 1)
170
171 #Find as many arguments as you can
172 statement.args = []
173 opMatch = opRe.search(line)
174 while opMatch is not None:
175 statement.args.append({})
176 # args is a list of dicts which collect different
177 # representations of operand values. Different forms might be
178 # needed in different places, for instance to replace a label
179 # with an offset.
180 for opType in ("operandLabel0", "operandReg0", "operandImm0",
181 "operandLabel1", "operandReg1", "operandImm1"):
182 if opMatch.group(opType):
183 statement.args[-1][opType[:-1]] = opMatch.group(opType)
184 if len(statement.args[-1]) == 0:
185 print "Problem parsing operand in statement: %s" \
186 % orig_line
187 line = opRe.sub('', line, 1)
167
168 # Clear the class name from the statement
169 line = classRe.sub('', line, 1)
170
171 #Find as many arguments as you can
172 statement.args = []
173 opMatch = opRe.search(line)
174 while opMatch is not None:
175 statement.args.append({})
176 # args is a list of dicts which collect different
177 # representations of operand values. Different forms might be
178 # needed in different places, for instance to replace a label
179 # with an offset.
180 for opType in ("operandLabel0", "operandReg0", "operandImm0",
181 "operandLabel1", "operandReg1", "operandImm1"):
182 if opMatch.group(opType):
183 statement.args[-1][opType[:-1]] = opMatch.group(opType)
184 if len(statement.args[-1]) == 0:
185 print "Problem parsing operand in statement: %s" \
186 % orig_line
187 line = opRe.sub('', line, 1)
188 # print "Found operand %s." % statement.args[-1]
188 #print "Found operand %s." % statement.args[-1]
189 opMatch = opRe.search(line)
189 opMatch = opRe.search(line)
190 # print "Found operands", statement.args
190 #print "Found operands", statement.args
191
192 # Add this statement to our collection
193 statements.append(statement)
194
195 # Get the next line
196 lineMatch = lineRe.search(code)
197
198 # Decode the labels into displacements
199
200 labels = {}
201 micropc = 0
202 for statement in statements:
203 if statement.label:
204 labels[statement.label] = count
205 micropc += 1
206 micropc = 0
207 for statement in statements:
208 for arg in statement.args:
209 if arg.has_key("operandLabel"):
210 if not labels.has_key(arg["operandLabel"]):
211 raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
212 # This is assuming that intra microcode branches go to
213 # the next micropc + displacement, or
214 # micropc + 1 + displacement.
215 arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
216 micropc += 1
217
191
192 # Add this statement to our collection
193 statements.append(statement)
194
195 # Get the next line
196 lineMatch = lineRe.search(code)
197
198 # Decode the labels into displacements
199
200 labels = {}
201 micropc = 0
202 for statement in statements:
203 if statement.label:
204 labels[statement.label] = count
205 micropc += 1
206 micropc = 0
207 for statement in statements:
208 for arg in statement.args:
209 if arg.has_key("operandLabel"):
210 if not labels.has_key(arg["operandLabel"]):
211 raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
212 # This is assuming that intra microcode branches go to
213 # the next micropc + displacement, or
214 # micropc + 1 + displacement.
215 arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
216 micropc += 1
217
218 if len(statements) == 0:
219 raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code
220
218 # If we can implement this instruction with exactly one microop, just
219 # use that directly.
220 if len(statements) == 1:
221 decode_block = "return %s;" % \
221 # If we can implement this instruction with exactly one microop, just
222 # use that directly.
223 if len(statements) == 1:
224 decode_block = "return %s;" % \
222 statements[0].getAllocator()
225 statements[0].getAllocator('"' + name + '"')
223 return ('', '', decode_block, '')
224 else:
225 # Build a macroop to contain the sequence of microops we've
226 # been given.
227 return genMacroOp(name, Name, statements)
228}};
226 return ('', '', decode_block, '')
227 else:
228 # Build a macroop to contain the sequence of microops we've
229 # been given.
230 return genMacroOp(name, Name, statements)
231}};