+ def updateExportContext(self):
+
+ # create a continuation that allows us to grab the current parser
+ def wrapInstObjParams(*args):
+ return InstObjParams(self, *args)
+ self.exportContext['InstObjParams'] = wrapInstObjParams
+ self.exportContext.update(self.templateMap)
+
+ def defFormat(self, id, params, code, lineno):
+ '''Define a new format'''
+
+ # make sure we haven't already defined this one
+ if id in self.formatMap:
+ error(lineno, 'format %s redefined.' % id)
+
+ # create new object and store in global map
+ self.formatMap[id] = Format(id, params, code)
+
+ def expandCpuSymbolsToDict(self, template):
+ '''Expand template with CPU-specific references into a
+ dictionary with an entry for each CPU model name. The entry
+ key is the model name and the corresponding value is the
+ template with the CPU-specific refs substituted for that
+ model.'''
+
+ # Protect '%'s that don't go with CPU-specific terms
+ t = re.sub(r'%(?!\(CPU_)', '%%', template)
+ result = {}
+ for cpu in self.cpuModels:
+ result[cpu.name] = t % cpu.strings
+ return result
+
+ def expandCpuSymbolsToString(self, template):
+ '''*If* the template has CPU-specific references, return a
+ single string containing a copy of the template for each CPU
+ model with the corresponding values substituted in. If the
+ template has no CPU-specific references, it is returned
+ unmodified.'''
+
+ if template.find('%(CPU_') != -1:
+ return reduce(lambda x,y: x+y,
+ self.expandCpuSymbolsToDict(template).values())
+ else:
+ return template
+
+ def protectCpuSymbols(self, template):
+ '''Protect CPU-specific references by doubling the
+ corresponding '%'s (in preparation for substituting a different
+ set of references into the template).'''
+
+ return re.sub(r'%(?=\(CPU_)', '%%', template)
+
+ def protectNonSubstPercents(self, s):
+ '''Protect any non-dict-substitution '%'s in a format string
+ (i.e. those not followed by '(')'''
+
+ return re.sub(r'%(?!\()', '%%', s)
+
+ def buildOperandTypeMap(self, user_dict, lineno):
+ """Generate operandTypeMap from the user's 'def operand_types'
+ statement."""
+ operand_type = {}
+ for (ext, (desc, size)) in user_dict.iteritems():
+ if desc == 'signed int':
+ ctype = 'int%d_t' % size
+ is_signed = 1
+ elif desc == 'unsigned int':
+ ctype = 'uint%d_t' % size
+ is_signed = 0
+ elif desc == 'float':
+ is_signed = 1 # shouldn't really matter
+ if size == 32:
+ ctype = 'float'
+ elif size == 64:
+ ctype = 'double'
+ elif desc == 'twin64 int':
+ is_signed = 0
+ ctype = 'Twin64_t'
+ elif desc == 'twin32 int':
+ is_signed = 0
+ ctype = 'Twin32_t'
+ if ctype == '':
+ error(parser, lineno,
+ 'Unrecognized type description "%s" in user_dict')
+ operand_type[ext] = (size, ctype, is_signed)
+
+ self.operandTypeMap = operand_type
+
+ def buildOperandNameMap(self, user_dict, lineno):
+ operand_name = {}
+ for op_name, val in user_dict.iteritems():
+ base_cls_name, dflt_ext, reg_spec, flags, sort_pri = val[:5]
+ if len(val) > 5:
+ read_code = val[5]
+ else:
+ read_code = None
+ if len(val) > 6:
+ write_code = val[6]
+ else:
+ write_code = None
+ if len(val) > 7:
+ error(lineno,
+ 'error: too many attributes for operand "%s"' %
+ base_cls_name)
+
+ (dflt_size, dflt_ctype, dflt_is_signed) = \
+ self.operandTypeMap[dflt_ext]
+ # Canonical flag structure is a triple of lists, where each list
+ # indicates the set of flags implied by this operand always, when
+ # used as a source, and when used as a dest, respectively.
+ # For simplicity this can be initialized using a variety of fairly
+ # obvious shortcuts; we convert these to canonical form here.
+ if not flags:
+ # no flags specified (e.g., 'None')
+ flags = ( [], [], [] )
+ elif isinstance(flags, str):
+ # a single flag: assumed to be unconditional
+ flags = ( [ flags ], [], [] )
+ elif isinstance(flags, list):
+ # a list of flags: also assumed to be unconditional
+ flags = ( flags, [], [] )
+ elif isinstance(flags, tuple):
+ # it's a tuple: it should be a triple,
+ # but each item could be a single string or a list
+ (uncond_flags, src_flags, dest_flags) = flags
+ flags = (makeList(uncond_flags),
+ makeList(src_flags), makeList(dest_flags))
+ # Accumulate attributes of new operand class in tmp_dict
+ tmp_dict = {}
+ for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
+ 'dflt_size', 'dflt_ctype', 'dflt_is_signed',
+ 'read_code', 'write_code'):
+ tmp_dict[attr] = eval(attr)
+ tmp_dict['base_name'] = op_name
+ # New class name will be e.g. "IntReg_Ra"
+ cls_name = base_cls_name + '_' + op_name
+ # Evaluate string arg to get class object. Note that the
+ # actual base class for "IntReg" is "IntRegOperand", i.e. we
+ # have to append "Operand".
+ try:
+ base_cls = eval(base_cls_name + 'Operand')
+ except NameError:
+ error(lineno,
+ 'error: unknown operand base class "%s"' % base_cls_name)
+ # The following statement creates a new class called
+ # <cls_name> as a subclass of <base_cls> with the attributes
+ # in tmp_dict, just as if we evaluated a class declaration.
+ operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict)
+
+ self.operandNameMap = operand_name
+
+ # Define operand variables.
+ operands = user_dict.keys()
+
+ operandsREString = (r'''
+ (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
+ ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
+ (?![\w\.]) # neg. lookahead assertion: prevent partial matches
+ '''
+ % string.join(operands, '|'))
+
+ self.operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
+
+ # Same as operandsREString, but extension is mandatory, and only two
+ # groups are returned (base and ext, not full name as above).
+ # Used for subtituting '_' for '.' to make C++ identifiers.
+ operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
+ % string.join(operands, '|'))
+
+ self.operandsWithExtRE = \
+ re.compile(operandsWithExtREString, re.MULTILINE)
+
+ def substMungedOpNames(self, code):
+ '''Munge operand names in code string to make legal C++
+ variable names. This means getting rid of the type extension
+ if any. Will match base_name attribute of Operand object.)'''
+ return self.operandsWithExtRE.sub(r'\1', code)
+
+ def mungeSnippet(self, s):
+ '''Fix up code snippets for final substitution in templates.'''
+ if isinstance(s, str):
+ return self.substMungedOpNames(substBitOps(s))
+ else:
+ return s
+