microasm.isa (4343:3f11bcf873b3) microasm.isa (4344:174e31456abe)
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:

--- 48 unchanged lines hidden (view full) ---

57
58////////////////////////////////////////////////////////////////////
59//
60// Code to "specialize" a microcode sequence to use a particular
61// variety of operands
62//
63
64let {{
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:

--- 48 unchanged lines hidden (view full) ---

57
58////////////////////////////////////////////////////////////////////
59//
60// Code to "specialize" a microcode sequence to use a particular
61// variety of operands
62//
63
64let {{
65 # This builds either a regular or macro op to implement the sequence of
66 # ops we give it.
67 def genInst(name, Name, ops):
68 # If we can implement this instruction with exactly one microop, just
69 # use that directly.
70 newStmnt = ''
71 if len(ops) == 1:
72 decode_block = "return %s;" % \
73 ops[0].getAllocator()
74 return ('', '', decode_block, '')
75 else:
76 # Build a macroop to contain the sequence of microops we've
77 # been given.
78 return genMacroOp(name, Name, ops)
79}};
80
81let {{
82 # This code builds up a decode block which decodes based on switchval.
83 # vals is a dict which matches case values with what should be decoded to.
84 # builder is called on the exploded contents of "vals" values to generate
85 # whatever code should be used.
86 def doSplitDecode(name, Name, builder, switchVal, vals, default = None):
87 header_output = ''
88 decoder_output = ''
89 decode_block = 'switch(%s) {\n' % switchVal

--- 92 unchanged lines hidden (view full) ---

182 # is equal to 11b
183 code = opRe.sub("%{(uint8_t)MODRM_RM}", code)
184 else:
185 raise Exception, "Unrecognized tag %s." % opType.tag
186 opTypes.pop(-1)
187
188 # At this point, we've built up "code" to have all the necessary extra
189 # instructions needed to implement whatever types of operands were
65 # This code builds up a decode block which decodes based on switchval.
66 # vals is a dict which matches case values with what should be decoded to.
67 # builder is called on the exploded contents of "vals" values to generate
68 # whatever code should be used.
69 def doSplitDecode(name, Name, builder, switchVal, vals, default = None):
70 header_output = ''
71 decoder_output = ''
72 decode_block = 'switch(%s) {\n' % switchVal

--- 92 unchanged lines hidden (view full) ---

165 # is equal to 11b
166 code = opRe.sub("%{(uint8_t)MODRM_RM}", code)
167 else:
168 raise Exception, "Unrecognized tag %s." % opType.tag
169 opTypes.pop(-1)
170
171 # At this point, we've built up "code" to have all the necessary extra
172 # instructions needed to implement whatever types of operands were
190 # specified. Now we'll assemble it it into a microOp sequence.
191 ops = assembleMicro(code)
192
193 # Build a macroop to contain the sequence of microops we've
194 # constructed. The decode block will be used to fill in our
195 # inner decode structure, and the rest will be concatenated and
196 # passed back.
197 return genInst(name, Name, ops)
173 # specified. Now we'll assemble it it into a StaticInst.
174 return assembleMicro(name, Name, code)
198}};
199
200////////////////////////////////////////////////////////////////////
201//
202// The microcode assembler
203//
204
205let {{
175}};
176
177////////////////////////////////////////////////////////////////////
178//
179// The microcode assembler
180//
181
182let {{
183 # These are used when setting up microops so that they can specialize their
184 # base class template properly.
185 RegOpType = "RegisterOperand"
186 ImmOpType = "ImmediateOperand"
187}};
188
189let {{
206 class MicroOpStatement(object):
207 def __init__(self):
208 self.className = ''
209 self.label = ''
210 self.args = []
211
212 # This converts a list of python bools into
213 # a comma seperated list of C++ bools.

--- 23 unchanged lines hidden (view full) ---

237 elif arg.has_key("operandLabel"):
238 raise Exception, "Found a label while creating allocator string."
239 else:
240 raise Exception, "Unrecognized operand type."
241 signature += ">"
242 return 'new %s%s(machInst%s%s)' % (self.className, signature, self.microFlagsText(microFlags), args)
243}};
244
190 class MicroOpStatement(object):
191 def __init__(self):
192 self.className = ''
193 self.label = ''
194 self.args = []
195
196 # This converts a list of python bools into
197 # a comma seperated list of C++ bools.

--- 23 unchanged lines hidden (view full) ---

221 elif arg.has_key("operandLabel"):
222 raise Exception, "Found a label while creating allocator string."
223 else:
224 raise Exception, "Unrecognized operand type."
225 signature += ">"
226 return 'new %s%s(machInst%s%s)' % (self.className, signature, self.microFlagsText(microFlags), args)
227}};
228
245let {{
246 def buildLabelDict(ops):
247 labels = {}
248 micropc = 0
249 for op in ops:
250 if op.label:
251 labels[op.label] = count
252 micropc += 1
253 return labels
254}};
255
256let{{
229let{{
257 def assembleMicro(code):
230 def assembleMicro(name, Name, code):
231
258 # This function takes in a block of microcode assembly and returns
259 # a python list of objects which describe it.
260
261 # Keep this around in case we need it later
262 orig_code = code
263 # A list of the statements we've found thus far
264 statements = []
265

--- 70 unchanged lines hidden (view full) ---

336
337 # Add this statement to our collection
338 statements.append(statement)
339
340 # Get the next line
341 lineMatch = lineRe.search(code)
342
343 # Decode the labels into displacements
232 # This function takes in a block of microcode assembly and returns
233 # a python list of objects which describe it.
234
235 # Keep this around in case we need it later
236 orig_code = code
237 # A list of the statements we've found thus far
238 statements = []
239

--- 70 unchanged lines hidden (view full) ---

310
311 # Add this statement to our collection
312 statements.append(statement)
313
314 # Get the next line
315 lineMatch = lineRe.search(code)
316
317 # Decode the labels into displacements
344 labels = buildLabelDict(statements)
318
319 labels = {}
345 micropc = 0
346 for statement in statements:
320 micropc = 0
321 for statement in statements:
322 if statement.label:
323 labels[statement.label] = count
324 micropc += 1
325 micropc = 0
326 for statement in statements:
347 for arg in statement.args:
348 if arg.has_key("operandLabel"):
349 if not labels.has_key(arg["operandLabel"]):
350 raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
351 # This is assuming that intra microcode branches go to
352 # the next micropc + displacement, or
353 # micropc + 1 + displacement.
354 arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
355 micropc += 1
327 for arg in statement.args:
328 if arg.has_key("operandLabel"):
329 if not labels.has_key(arg["operandLabel"]):
330 raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
331 # This is assuming that intra microcode branches go to
332 # the next micropc + displacement, or
333 # micropc + 1 + displacement.
334 arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
335 micropc += 1
356 return statements
336
337 # If we can implement this instruction with exactly one microop, just
338 # use that directly.
339 if len(statements) == 1:
340 decode_block = "return %s;" % \
341 statements[0].getAllocator()
342 return ('', '', decode_block, '')
343 else:
344 # Build a macroop to contain the sequence of microops we've
345 # been given.
346 return genMacroOp(name, Name, statements)
357}};
347}};