mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 13:24:57 +00:00 
			
		
		
		
	decodetree: Multi-cleanup
Includes multiple changes by Richard Henderson as follows: - Use proper varargs to print the arguments. (2fd51b19c9) - Rename MultiPattern to IncMultiPattern (040145c4f8) - Split out MultiPattern from IncMultiPattern (df63044d02) - Allow group covering the entire insn space (b44b3449a0) - Move semantic propagation into classes (08561fc128) - Implement non-overlapping groups (067e8b0f45) - Drop check for less than 2 patterns in a group (fe079aa13d)
This commit is contained in:
		
							parent
							
								
									7427cca6cc
								
							
						
					
					
						commit
						b45a02e2f7
					
				| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# Copyright (c) 2018 Linaro Limited
 | 
			
		||||
#
 | 
			
		||||
# This library is free software; you can redistribute it and/or
 | 
			
		||||
| 
						 | 
				
			
			@ -17,139 +17,7 @@
 | 
			
		|||
 | 
			
		||||
#
 | 
			
		||||
# Generate a decoding tree from a specification file.
 | 
			
		||||
#
 | 
			
		||||
# The tree is built from instruction "patterns".  A pattern may represent
 | 
			
		||||
# a single architectural instruction or a group of same, depending on what
 | 
			
		||||
# is convenient for further processing.
 | 
			
		||||
#
 | 
			
		||||
# Each pattern has "fixedbits" & "fixedmask", the combination of which
 | 
			
		||||
# describes the condition under which the pattern is matched:
 | 
			
		||||
#
 | 
			
		||||
#   (insn & fixedmask) == fixedbits
 | 
			
		||||
#
 | 
			
		||||
# Each pattern may have "fields", which are extracted from the insn and
 | 
			
		||||
# passed along to the translator.  Examples of such are registers,
 | 
			
		||||
# immediates, and sub-opcodes.
 | 
			
		||||
#
 | 
			
		||||
# In support of patterns, one may declare fields, argument sets, and
 | 
			
		||||
# formats, each of which may be re-used to simplify further definitions.
 | 
			
		||||
#
 | 
			
		||||
# *** Field syntax:
 | 
			
		||||
#
 | 
			
		||||
# field_def     := '%' identifier ( unnamed_field )+ ( !function=identifier )?
 | 
			
		||||
# unnamed_field := number ':' ( 's' ) number
 | 
			
		||||
#
 | 
			
		||||
# For unnamed_field, the first number is the least-significant bit position of
 | 
			
		||||
# the field and the second number is the length of the field.  If the 's' is
 | 
			
		||||
# present, the field is considered signed.  If multiple unnamed_fields are
 | 
			
		||||
# present, they are concatenated.  In this way one can define disjoint fields.
 | 
			
		||||
#
 | 
			
		||||
# If !function is specified, the concatenated result is passed through the
 | 
			
		||||
# named function, taking and returning an integral value.
 | 
			
		||||
#
 | 
			
		||||
# FIXME: the fields of the structure into which this result will be stored
 | 
			
		||||
# is restricted to "int".  Which means that we cannot expand 64-bit items.
 | 
			
		||||
#
 | 
			
		||||
# Field examples:
 | 
			
		||||
#
 | 
			
		||||
#   %disp   0:s16          -- sextract(i, 0, 16)
 | 
			
		||||
#   %imm9   16:6 10:3      -- extract(i, 16, 6) << 3 | extract(i, 10, 3)
 | 
			
		||||
#   %disp12 0:s1 1:1 2:10  -- sextract(i, 0, 1) << 11
 | 
			
		||||
#                             | extract(i, 1, 1) << 10
 | 
			
		||||
#                             | extract(i, 2, 10)
 | 
			
		||||
#   %shimm8 5:s8 13:1 !function=expand_shimm8
 | 
			
		||||
#                          -- expand_shimm8(sextract(i, 5, 8) << 1
 | 
			
		||||
#                                           | extract(i, 13, 1))
 | 
			
		||||
#
 | 
			
		||||
# *** Argument set syntax:
 | 
			
		||||
#
 | 
			
		||||
# args_def    := '&' identifier ( args_elt )+ ( !extern )?
 | 
			
		||||
# args_elt    := identifier
 | 
			
		||||
#
 | 
			
		||||
# Each args_elt defines an argument within the argument set.
 | 
			
		||||
# Each argument set will be rendered as a C structure "arg_$name"
 | 
			
		||||
# with each of the fields being one of the member arguments.
 | 
			
		||||
#
 | 
			
		||||
# If !extern is specified, the backing structure is assumed to
 | 
			
		||||
# have been already declared, typically via a second decoder.
 | 
			
		||||
#
 | 
			
		||||
# Argument set examples:
 | 
			
		||||
#
 | 
			
		||||
#   ®3       ra rb rc
 | 
			
		||||
#   &loadstore  reg base offset
 | 
			
		||||
#
 | 
			
		||||
# *** Format syntax:
 | 
			
		||||
#
 | 
			
		||||
# fmt_def      := '@' identifier ( fmt_elt )+
 | 
			
		||||
# fmt_elt      := fixedbit_elt | field_elt | field_ref | args_ref
 | 
			
		||||
# fixedbit_elt := [01.-]+
 | 
			
		||||
# field_elt    := identifier ':' 's'? number
 | 
			
		||||
# field_ref    := '%' identifier | identifier '=' '%' identifier
 | 
			
		||||
# args_ref     := '&' identifier
 | 
			
		||||
#
 | 
			
		||||
# Defining a format is a handy way to avoid replicating groups of fields
 | 
			
		||||
# across many instruction patterns.
 | 
			
		||||
#
 | 
			
		||||
# A fixedbit_elt describes a contiguous sequence of bits that must
 | 
			
		||||
# be 1, 0, [.-] for don't care.  The difference between '.' and '-'
 | 
			
		||||
# is that '.' means that the bit will be covered with a field or a
 | 
			
		||||
# final [01] from the pattern, and '-' means that the bit is really
 | 
			
		||||
# ignored by the cpu and will not be specified.
 | 
			
		||||
#
 | 
			
		||||
# A field_elt describes a simple field only given a width; the position of
 | 
			
		||||
# the field is implied by its position with respect to other fixedbit_elt
 | 
			
		||||
# and field_elt.
 | 
			
		||||
#
 | 
			
		||||
# If any fixedbit_elt or field_elt appear then all bits must be defined.
 | 
			
		||||
# Padding with a fixedbit_elt of all '.' is an easy way to accomplish that.
 | 
			
		||||
#
 | 
			
		||||
# A field_ref incorporates a field by reference.  This is the only way to
 | 
			
		||||
# add a complex field to a format.  A field may be renamed in the process
 | 
			
		||||
# via assignment to another identifier.  This is intended to allow the
 | 
			
		||||
# same argument set be used with disjoint named fields.
 | 
			
		||||
#
 | 
			
		||||
# A single args_ref may specify an argument set to use for the format.
 | 
			
		||||
# The set of fields in the format must be a subset of the arguments in
 | 
			
		||||
# the argument set.  If an argument set is not specified, one will be
 | 
			
		||||
# inferred from the set of fields.
 | 
			
		||||
#
 | 
			
		||||
# It is recommended, but not required, that all field_ref and args_ref
 | 
			
		||||
# appear at the end of the line, not interleaving with fixedbit_elf or
 | 
			
		||||
# field_elt.
 | 
			
		||||
#
 | 
			
		||||
# Format examples:
 | 
			
		||||
#
 | 
			
		||||
#   @opr    ...... ra:5 rb:5 ... 0 ....... rc:5
 | 
			
		||||
#   @opi    ...... ra:5 lit:8    1 ....... rc:5
 | 
			
		||||
#
 | 
			
		||||
# *** Pattern syntax:
 | 
			
		||||
#
 | 
			
		||||
# pat_def      := identifier ( pat_elt )+
 | 
			
		||||
# pat_elt      := fixedbit_elt | field_elt | field_ref
 | 
			
		||||
#               | args_ref | fmt_ref | const_elt
 | 
			
		||||
# fmt_ref      := '@' identifier
 | 
			
		||||
# const_elt    := identifier '=' number
 | 
			
		||||
#
 | 
			
		||||
# The fixedbit_elt and field_elt specifiers are unchanged from formats.
 | 
			
		||||
# A pattern that does not specify a named format will have one inferred
 | 
			
		||||
# from a referenced argument set (if present) and the set of fields.
 | 
			
		||||
#
 | 
			
		||||
# A const_elt allows a argument to be set to a constant value.  This may
 | 
			
		||||
# come in handy when fields overlap between patterns and one has to
 | 
			
		||||
# include the values in the fixedbit_elt instead.
 | 
			
		||||
#
 | 
			
		||||
# The decoder will call a translator function for each pattern matched.
 | 
			
		||||
#
 | 
			
		||||
# Pattern examples:
 | 
			
		||||
#
 | 
			
		||||
#   addl_r   010000 ..... ..... .... 0000000 ..... @opr
 | 
			
		||||
#   addl_i   010000 ..... ..... .... 0000000 ..... @opi
 | 
			
		||||
#
 | 
			
		||||
# which will, in part, invoke
 | 
			
		||||
#
 | 
			
		||||
#   trans_addl_r(ctx, &arg_opr, insn)
 | 
			
		||||
# and
 | 
			
		||||
#   trans_addl_i(ctx, &arg_opi, insn)
 | 
			
		||||
# See the syntax and semantics in docs/devel/decodetree.rst.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +31,6 @@ variablewidth = False
 | 
			
		|||
fields = {}
 | 
			
		||||
arguments = {}
 | 
			
		||||
formats = {}
 | 
			
		||||
patterns = []
 | 
			
		||||
allpatterns = []
 | 
			
		||||
anyextern = False
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -183,24 +50,26 @@ def error_with_file(file, lineno, *args):
 | 
			
		|||
    global output_file
 | 
			
		||||
    global output_fd
 | 
			
		||||
 | 
			
		||||
    prefix = ''
 | 
			
		||||
    if file:
 | 
			
		||||
        prefix += '{0}:'.format(file)
 | 
			
		||||
    if lineno:
 | 
			
		||||
        r = '{0}:{1}: error:'.format(file, lineno)
 | 
			
		||||
    elif input_file:
 | 
			
		||||
        r = '{0}: error:'.format(file)
 | 
			
		||||
    else:
 | 
			
		||||
        r = 'error:'
 | 
			
		||||
    for a in args:
 | 
			
		||||
        r += ' ' + str(a)
 | 
			
		||||
    r += '\n'
 | 
			
		||||
    sys.stderr.write(r)
 | 
			
		||||
        prefix += '{0}:'.format(lineno)
 | 
			
		||||
    if prefix:
 | 
			
		||||
        prefix += ' '
 | 
			
		||||
    print(prefix, end='error: ', file=sys.stderr)
 | 
			
		||||
    print(*args, file=sys.stderr)
 | 
			
		||||
 | 
			
		||||
    if output_file and output_fd:
 | 
			
		||||
        output_fd.close()
 | 
			
		||||
        os.remove(output_file)
 | 
			
		||||
    exit(1)
 | 
			
		||||
# end error_with_file
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def error(lineno, *args):
 | 
			
		||||
    error_with_file(input_file, lineno, args)
 | 
			
		||||
    error_with_file(input_file, lineno, *args)
 | 
			
		||||
# end error
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def output(*args):
 | 
			
		||||
| 
						 | 
				
			
			@ -209,13 +78,6 @@ def output(*args):
 | 
			
		|||
        output_fd.write(a)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if sys.version_info >= (3, 4):
 | 
			
		||||
    re_fullmatch = re.fullmatch
 | 
			
		||||
else:
 | 
			
		||||
    def re_fullmatch(pat, str):
 | 
			
		||||
        return re.match('^' + pat + '$', str)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def output_autogen():
 | 
			
		||||
    output('/* This file is autogenerated by scripts/decodetree.py.  */\n\n')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -261,6 +123,7 @@ def is_pow2(x):
 | 
			
		|||
 | 
			
		||||
def ctz(x):
 | 
			
		||||
    """Return the number of times 2 factors into X."""
 | 
			
		||||
    assert x != 0
 | 
			
		||||
    r = 0
 | 
			
		||||
    while ((x >> r) & 1) == 0:
 | 
			
		||||
        r += 1
 | 
			
		||||
| 
						 | 
				
			
			@ -268,6 +131,8 @@ def ctz(x):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def is_contiguous(bits):
 | 
			
		||||
    if bits == 0:
 | 
			
		||||
        return -1
 | 
			
		||||
    shift = ctz(bits)
 | 
			
		||||
    if is_pow2((bits >> shift) + 1):
 | 
			
		||||
        return shift
 | 
			
		||||
| 
						 | 
				
			
			@ -505,32 +370,99 @@ class Pattern(General):
 | 
			
		|||
            output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
 | 
			
		||||
        output(ind, 'if (', translate_prefix, '_', self.name,
 | 
			
		||||
               '(ctx, &u.f_', arg, ')) return true;\n')
 | 
			
		||||
 | 
			
		||||
    # Normal patterns do not have children.
 | 
			
		||||
    def build_tree(self):
 | 
			
		||||
        return
 | 
			
		||||
    def prop_masks(self):
 | 
			
		||||
        return
 | 
			
		||||
    def prop_format(self):
 | 
			
		||||
        return
 | 
			
		||||
    def prop_width(self):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
# end Pattern
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MultiPattern(General):
 | 
			
		||||
    """Class representing an overlapping set of instruction patterns"""
 | 
			
		||||
    """Class representing a set of instruction patterns"""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, lineno, pats, fixb, fixm, udfm, w):
 | 
			
		||||
    def __init__(self, lineno):
 | 
			
		||||
        self.file = input_file
 | 
			
		||||
        self.lineno = lineno
 | 
			
		||||
        self.pats = pats
 | 
			
		||||
        self.pats = []
 | 
			
		||||
        self.base = None
 | 
			
		||||
        self.fixedbits = fixb
 | 
			
		||||
        self.fixedmask = fixm
 | 
			
		||||
        self.undefmask = udfm
 | 
			
		||||
        self.width = w
 | 
			
		||||
        self.fixedbits = 0
 | 
			
		||||
        self.fixedmask = 0
 | 
			
		||||
        self.undefmask = 0
 | 
			
		||||
        self.width = None
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        r = "{"
 | 
			
		||||
        for p in self.pats:
 | 
			
		||||
           r = r + ' ' + str(p)
 | 
			
		||||
        return r + "}"
 | 
			
		||||
        r = 'group'
 | 
			
		||||
        if self.fixedbits is not None:
 | 
			
		||||
            r += ' ' + str_match_bits(self.fixedbits, self.fixedmask)
 | 
			
		||||
        return r
 | 
			
		||||
 | 
			
		||||
    def output_decl(self):
 | 
			
		||||
        for p in self.pats:
 | 
			
		||||
            p.output_decl()
 | 
			
		||||
 | 
			
		||||
    def prop_masks(self):
 | 
			
		||||
        global insnmask
 | 
			
		||||
 | 
			
		||||
        fixedmask = insnmask
 | 
			
		||||
        undefmask = insnmask
 | 
			
		||||
 | 
			
		||||
        # Collect fixedmask/undefmask for all of the children.
 | 
			
		||||
        for p in self.pats:
 | 
			
		||||
            p.prop_masks()
 | 
			
		||||
            fixedmask &= p.fixedmask
 | 
			
		||||
            undefmask &= p.undefmask
 | 
			
		||||
 | 
			
		||||
        # Widen fixedmask until all fixedbits match
 | 
			
		||||
        repeat = True
 | 
			
		||||
        fixedbits = 0
 | 
			
		||||
        while repeat and fixedmask != 0:
 | 
			
		||||
            fixedbits = None
 | 
			
		||||
            for p in self.pats:
 | 
			
		||||
                thisbits = p.fixedbits & fixedmask
 | 
			
		||||
                if fixedbits is None:
 | 
			
		||||
                    fixedbits = thisbits
 | 
			
		||||
                elif fixedbits != thisbits:
 | 
			
		||||
                    fixedmask &= ~(fixedbits ^ thisbits)
 | 
			
		||||
                    break
 | 
			
		||||
            else:
 | 
			
		||||
                repeat = False
 | 
			
		||||
 | 
			
		||||
        self.fixedbits = fixedbits
 | 
			
		||||
        self.fixedmask = fixedmask
 | 
			
		||||
        self.undefmask = undefmask
 | 
			
		||||
 | 
			
		||||
    def build_tree(self):
 | 
			
		||||
        for p in self.pats:
 | 
			
		||||
            p.build_tree()
 | 
			
		||||
 | 
			
		||||
    def prop_format(self):
 | 
			
		||||
        for p in self.pats:
 | 
			
		||||
            p.build_tree()
 | 
			
		||||
 | 
			
		||||
    def prop_width(self):
 | 
			
		||||
        width = None
 | 
			
		||||
        for p in self.pats:
 | 
			
		||||
            p.prop_width()
 | 
			
		||||
            if width is None:
 | 
			
		||||
                width = p.width
 | 
			
		||||
            elif width != p.width:
 | 
			
		||||
                error_with_file(self.file, self.lineno,
 | 
			
		||||
                                'width mismatch in patterns within braces')
 | 
			
		||||
        self.width = width
 | 
			
		||||
 | 
			
		||||
# end MultiPattern
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IncMultiPattern(MultiPattern):
 | 
			
		||||
    """Class representing an overlapping set of instruction patterns"""
 | 
			
		||||
 | 
			
		||||
    def output_code(self, i, extracted, outerbits, outermask):
 | 
			
		||||
        global translate_prefix
 | 
			
		||||
        ind = str_indent(i)
 | 
			
		||||
| 
						 | 
				
			
			@ -547,7 +479,154 @@ class MultiPattern(General):
 | 
			
		|||
                output(ind, '}\n')
 | 
			
		||||
            else:
 | 
			
		||||
                p.output_code(i, extracted, p.fixedbits, p.fixedmask)
 | 
			
		||||
#end MultiPattern
 | 
			
		||||
#end IncMultiPattern
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Tree:
 | 
			
		||||
    """Class representing a node in a decode tree"""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, fm, tm):
 | 
			
		||||
        self.fixedmask = fm
 | 
			
		||||
        self.thismask = tm
 | 
			
		||||
        self.subs = []
 | 
			
		||||
        self.base = None
 | 
			
		||||
 | 
			
		||||
    def str1(self, i):
 | 
			
		||||
        ind = str_indent(i)
 | 
			
		||||
        r = '{0}{1:08x}'.format(ind, self.fixedmask)
 | 
			
		||||
        if self.format:
 | 
			
		||||
            r += ' ' + self.format.name
 | 
			
		||||
        r += ' [\n'
 | 
			
		||||
        for (b, s) in self.subs:
 | 
			
		||||
            r += '{0}  {1:08x}:\n'.format(ind, b)
 | 
			
		||||
            r += s.str1(i + 4) + '\n'
 | 
			
		||||
        r += ind + ']'
 | 
			
		||||
        return r
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.str1(0)
 | 
			
		||||
 | 
			
		||||
    def output_code(self, i, extracted, outerbits, outermask):
 | 
			
		||||
        ind = str_indent(i)
 | 
			
		||||
 | 
			
		||||
        # If we identified all nodes below have the same format,
 | 
			
		||||
        # extract the fields now.
 | 
			
		||||
        if not extracted and self.base:
 | 
			
		||||
            output(ind, self.base.extract_name(),
 | 
			
		||||
                   '(ctx, &u.f_', self.base.base.name, ', insn);\n')
 | 
			
		||||
            extracted = True
 | 
			
		||||
 | 
			
		||||
        # Attempt to aid the compiler in producing compact switch statements.
 | 
			
		||||
        # If the bits in the mask are contiguous, extract them.
 | 
			
		||||
        sh = is_contiguous(self.thismask)
 | 
			
		||||
        if sh > 0:
 | 
			
		||||
            # Propagate SH down into the local functions.
 | 
			
		||||
            def str_switch(b, sh=sh):
 | 
			
		||||
                return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh)
 | 
			
		||||
 | 
			
		||||
            def str_case(b, sh=sh):
 | 
			
		||||
                return '0x{0:x}'.format(b >> sh)
 | 
			
		||||
        else:
 | 
			
		||||
            def str_switch(b):
 | 
			
		||||
                return 'insn & 0x{0:08x}'.format(b)
 | 
			
		||||
 | 
			
		||||
            def str_case(b):
 | 
			
		||||
                return '0x{0:08x}'.format(b)
 | 
			
		||||
 | 
			
		||||
        output(ind, 'switch (', str_switch(self.thismask), ') {\n')
 | 
			
		||||
        for b, s in sorted(self.subs):
 | 
			
		||||
            assert (self.thismask & ~s.fixedmask) == 0
 | 
			
		||||
            innermask = outermask | self.thismask
 | 
			
		||||
            innerbits = outerbits | b
 | 
			
		||||
            output(ind, 'case ', str_case(b), ':\n')
 | 
			
		||||
            output(ind, '    /* ',
 | 
			
		||||
                   str_match_bits(innerbits, innermask), ' */\n')
 | 
			
		||||
            s.output_code(i + 4, extracted, innerbits, innermask)
 | 
			
		||||
            output(ind, '    return false;\n')
 | 
			
		||||
        output(ind, '}\n')
 | 
			
		||||
# end Tree
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ExcMultiPattern(MultiPattern):
 | 
			
		||||
    """Class representing a non-overlapping set of instruction patterns"""
 | 
			
		||||
 | 
			
		||||
    def output_code(self, i, extracted, outerbits, outermask):
 | 
			
		||||
        # Defer everything to our decomposed Tree node
 | 
			
		||||
        self.tree.output_code(i, extracted, outerbits, outermask)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def __build_tree(pats, outerbits, outermask):
 | 
			
		||||
        # Find the intersection of all remaining fixedmask.
 | 
			
		||||
        innermask = ~outermask & insnmask
 | 
			
		||||
        for i in pats:
 | 
			
		||||
            innermask &= i.fixedmask
 | 
			
		||||
 | 
			
		||||
        if innermask == 0:
 | 
			
		||||
            # Edge condition: One pattern covers the entire insnmask
 | 
			
		||||
            if len(pats) == 1:
 | 
			
		||||
                t = Tree(outermask, innermask)
 | 
			
		||||
                t.subs.append((0, pats[0]))
 | 
			
		||||
                return t
 | 
			
		||||
 | 
			
		||||
            text = 'overlapping patterns:'
 | 
			
		||||
            for p in pats:
 | 
			
		||||
                text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p)
 | 
			
		||||
            error_with_file(pats[0].file, pats[0].lineno, text)
 | 
			
		||||
 | 
			
		||||
        fullmask = outermask | innermask
 | 
			
		||||
 | 
			
		||||
        # Sort each element of pats into the bin selected by the mask.
 | 
			
		||||
        bins = {}
 | 
			
		||||
        for i in pats:
 | 
			
		||||
            fb = i.fixedbits & innermask
 | 
			
		||||
            if fb in bins:
 | 
			
		||||
                bins[fb].append(i)
 | 
			
		||||
            else:
 | 
			
		||||
                bins[fb] = [i]
 | 
			
		||||
 | 
			
		||||
        # We must recurse if any bin has more than one element or if
 | 
			
		||||
        # the single element in the bin has not been fully matched.
 | 
			
		||||
        t = Tree(fullmask, innermask)
 | 
			
		||||
 | 
			
		||||
        for b, l in bins.items():
 | 
			
		||||
            s = l[0]
 | 
			
		||||
            if len(l) > 1 or s.fixedmask & ~fullmask != 0:
 | 
			
		||||
                s = ExcMultiPattern.__build_tree(l, b | outerbits, fullmask)
 | 
			
		||||
            t.subs.append((b, s))
 | 
			
		||||
 | 
			
		||||
        return t
 | 
			
		||||
 | 
			
		||||
    def build_tree(self):
 | 
			
		||||
        super().prop_format()
 | 
			
		||||
        self.tree = self.__build_tree(self.pats, self.fixedbits,
 | 
			
		||||
                                      self.fixedmask)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def __prop_format(tree):
 | 
			
		||||
        """Propagate Format objects into the decode tree"""
 | 
			
		||||
 | 
			
		||||
        # Depth first search.
 | 
			
		||||
        for (b, s) in tree.subs:
 | 
			
		||||
            if isinstance(s, Tree):
 | 
			
		||||
                ExcMultiPattern.__prop_format(s)
 | 
			
		||||
 | 
			
		||||
        # If all entries in SUBS have the same format, then
 | 
			
		||||
        # propagate that into the tree.
 | 
			
		||||
        f = None
 | 
			
		||||
        for (b, s) in tree.subs:
 | 
			
		||||
            if f is None:
 | 
			
		||||
                f = s.base
 | 
			
		||||
                if f is None:
 | 
			
		||||
                    return
 | 
			
		||||
            if f is not s.base:
 | 
			
		||||
                return
 | 
			
		||||
        tree.base = f
 | 
			
		||||
 | 
			
		||||
    def prop_format(self):
 | 
			
		||||
        super().prop_format()
 | 
			
		||||
        self.__prop_format(self.tree)
 | 
			
		||||
 | 
			
		||||
# end ExcMultiPattern
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_field(lineno, name, toks):
 | 
			
		||||
| 
						 | 
				
			
			@ -562,18 +641,18 @@ def parse_field(lineno, name, toks):
 | 
			
		|||
    width = 0
 | 
			
		||||
    func = None
 | 
			
		||||
    for t in toks:
 | 
			
		||||
        if re_fullmatch('!function=' + re_ident, t):
 | 
			
		||||
        if re.fullmatch('!function=' + re_ident, t):
 | 
			
		||||
            if func:
 | 
			
		||||
                error(lineno, 'duplicate function')
 | 
			
		||||
            func = t.split('=')
 | 
			
		||||
            func = func[1]
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if re_fullmatch('[0-9]+:s[0-9]+', t):
 | 
			
		||||
        if re.fullmatch('[0-9]+:s[0-9]+', t):
 | 
			
		||||
            # Signed field extract
 | 
			
		||||
            subtoks = t.split(':s')
 | 
			
		||||
            sign = True
 | 
			
		||||
        elif re_fullmatch('[0-9]+:[0-9]+', t):
 | 
			
		||||
        elif re.fullmatch('[0-9]+:[0-9]+', t):
 | 
			
		||||
            # Unsigned field extract
 | 
			
		||||
            subtoks = t.split(':')
 | 
			
		||||
            sign = False
 | 
			
		||||
| 
						 | 
				
			
			@ -622,11 +701,11 @@ def parse_arguments(lineno, name, toks):
 | 
			
		|||
    flds = []
 | 
			
		||||
    extern = False
 | 
			
		||||
    for t in toks:
 | 
			
		||||
        if re_fullmatch('!extern', t):
 | 
			
		||||
        if re.fullmatch('!extern', t):
 | 
			
		||||
            extern = True
 | 
			
		||||
            anyextern = True
 | 
			
		||||
            continue
 | 
			
		||||
        if not re_fullmatch(re_ident, t):
 | 
			
		||||
        if not re.fullmatch(re_ident, t):
 | 
			
		||||
            error(lineno, 'invalid argument set token "{0}"'.format(t))
 | 
			
		||||
        if t in flds:
 | 
			
		||||
            error(lineno, 'duplicate argument "{0}"'.format(t))
 | 
			
		||||
| 
						 | 
				
			
			@ -706,18 +785,19 @@ def infer_format(arg, fieldmask, flds, width):
 | 
			
		|||
# end infer_format
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_generic(lineno, is_format, name, toks):
 | 
			
		||||
def parse_generic(lineno, parent_pat, name, toks):
 | 
			
		||||
    """Parse one instruction format from TOKS at LINENO"""
 | 
			
		||||
    global fields
 | 
			
		||||
    global arguments
 | 
			
		||||
    global formats
 | 
			
		||||
    global patterns
 | 
			
		||||
    global allpatterns
 | 
			
		||||
    global re_ident
 | 
			
		||||
    global insnwidth
 | 
			
		||||
    global insnmask
 | 
			
		||||
    global variablewidth
 | 
			
		||||
 | 
			
		||||
    is_format = parent_pat is None
 | 
			
		||||
 | 
			
		||||
    fixedmask = 0
 | 
			
		||||
    fixedbits = 0
 | 
			
		||||
    undefmask = 0
 | 
			
		||||
| 
						 | 
				
			
			@ -755,13 +835,13 @@ def parse_generic(lineno, is_format, name, toks):
 | 
			
		|||
            continue
 | 
			
		||||
 | 
			
		||||
        # 'Foo=%Bar' imports a field with a different name.
 | 
			
		||||
        if re_fullmatch(re_ident + '=%' + re_ident, t):
 | 
			
		||||
        if re.fullmatch(re_ident + '=%' + re_ident, t):
 | 
			
		||||
            (fname, iname) = t.split('=%')
 | 
			
		||||
            flds = add_field_byname(lineno, flds, fname, iname)
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # 'Foo=number' sets an argument field to a constant value
 | 
			
		||||
        if re_fullmatch(re_ident + '=[+-]?[0-9]+', t):
 | 
			
		||||
        if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
 | 
			
		||||
            (fname, value) = t.split('=')
 | 
			
		||||
            value = int(value)
 | 
			
		||||
            flds = add_field(lineno, flds, fname, ConstField(value))
 | 
			
		||||
| 
						 | 
				
			
			@ -769,7 +849,7 @@ def parse_generic(lineno, is_format, name, toks):
 | 
			
		|||
 | 
			
		||||
        # Pattern of 0s, 1s, dots and dashes indicate required zeros,
 | 
			
		||||
        # required ones, or dont-cares.
 | 
			
		||||
        if re_fullmatch('[01.-]+', t):
 | 
			
		||||
        if re.fullmatch('[01.-]+', t):
 | 
			
		||||
            shift = len(t)
 | 
			
		||||
            fms = t.replace('0', '1')
 | 
			
		||||
            fms = fms.replace('.', '0')
 | 
			
		||||
| 
						 | 
				
			
			@ -786,7 +866,7 @@ def parse_generic(lineno, is_format, name, toks):
 | 
			
		|||
            fixedmask = (fixedmask << shift) | fms
 | 
			
		||||
            undefmask = (undefmask << shift) | ubm
 | 
			
		||||
        # Otherwise, fieldname:fieldwidth
 | 
			
		||||
        elif re_fullmatch(re_ident + ':s?[0-9]+', t):
 | 
			
		||||
        elif re.fullmatch(re_ident + ':s?[0-9]+', t):
 | 
			
		||||
            (fname, flen) = t.split(':')
 | 
			
		||||
            sign = False
 | 
			
		||||
            if flen[0] == 's':
 | 
			
		||||
| 
						 | 
				
			
			@ -868,7 +948,7 @@ def parse_generic(lineno, is_format, name, toks):
 | 
			
		|||
                error(lineno, 'field {0} not initialized'.format(f))
 | 
			
		||||
        pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
 | 
			
		||||
                      undefmask, fieldmask, flds, width)
 | 
			
		||||
        patterns.append(pat)
 | 
			
		||||
        parent_pat.pats.append(pat)
 | 
			
		||||
        allpatterns.append(pat)
 | 
			
		||||
 | 
			
		||||
    # Validate the masks that we have assembled.
 | 
			
		||||
| 
						 | 
				
			
			@ -889,63 +969,15 @@ def parse_generic(lineno, is_format, name, toks):
 | 
			
		|||
# end parse_general
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_multi_pattern(lineno, pats):
 | 
			
		||||
    """Validate the Patterns going into a MultiPattern."""
 | 
			
		||||
    global patterns
 | 
			
		||||
    global insnmask
 | 
			
		||||
 | 
			
		||||
    if len(pats) < 2:
 | 
			
		||||
        error(lineno, 'less than two patterns within braces')
 | 
			
		||||
 | 
			
		||||
    fixedmask = insnmask
 | 
			
		||||
    undefmask = insnmask
 | 
			
		||||
 | 
			
		||||
    # Collect fixed/undefmask for all of the children.
 | 
			
		||||
    # Move the defining lineno back to that of the first child.
 | 
			
		||||
    for p in pats:
 | 
			
		||||
        fixedmask &= p.fixedmask
 | 
			
		||||
        undefmask &= p.undefmask
 | 
			
		||||
        if p.lineno < lineno:
 | 
			
		||||
            lineno = p.lineno
 | 
			
		||||
 | 
			
		||||
    width = None
 | 
			
		||||
    for p in pats:
 | 
			
		||||
        if width is None:
 | 
			
		||||
            width = p.width
 | 
			
		||||
        elif width != p.width:
 | 
			
		||||
            error(lineno, 'width mismatch in patterns within braces')
 | 
			
		||||
 | 
			
		||||
    repeat = True
 | 
			
		||||
    while repeat:
 | 
			
		||||
        if fixedmask == 0:
 | 
			
		||||
            error(lineno, 'no overlap in patterns within braces')
 | 
			
		||||
        fixedbits = None
 | 
			
		||||
        for p in pats:
 | 
			
		||||
            thisbits = p.fixedbits & fixedmask
 | 
			
		||||
            if fixedbits is None:
 | 
			
		||||
                fixedbits = thisbits
 | 
			
		||||
            elif fixedbits != thisbits:
 | 
			
		||||
                fixedmask &= ~(fixedbits ^ thisbits)
 | 
			
		||||
                break
 | 
			
		||||
        else:
 | 
			
		||||
            repeat = False
 | 
			
		||||
 | 
			
		||||
    mp = MultiPattern(lineno, pats, fixedbits, fixedmask, undefmask, width)
 | 
			
		||||
    patterns.append(mp)
 | 
			
		||||
# end build_multi_pattern
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_file(f):
 | 
			
		||||
def parse_file(f, parent_pat):
 | 
			
		||||
    """Parse all of the patterns within a file"""
 | 
			
		||||
 | 
			
		||||
    global patterns
 | 
			
		||||
 | 
			
		||||
    # Read all of the lines of the file.  Concatenate lines
 | 
			
		||||
    # ending in backslash; discard empty lines and comments.
 | 
			
		||||
    toks = []
 | 
			
		||||
    lineno = 0
 | 
			
		||||
    nesting = 0
 | 
			
		||||
    saved_pats = []
 | 
			
		||||
    nesting_pats = []
 | 
			
		||||
 | 
			
		||||
    for line in f:
 | 
			
		||||
        lineno += 1
 | 
			
		||||
| 
						 | 
				
			
			@ -989,17 +1021,23 @@ def parse_file(f):
 | 
			
		|||
        del toks[0]
 | 
			
		||||
 | 
			
		||||
        # End nesting?
 | 
			
		||||
        if name == '}':
 | 
			
		||||
            if nesting == 0:
 | 
			
		||||
                error(start_lineno, 'mismatched close brace')
 | 
			
		||||
        if name == '}' or name == ']':
 | 
			
		||||
            if len(toks) != 0:
 | 
			
		||||
                error(start_lineno, 'extra tokens after close brace')
 | 
			
		||||
 | 
			
		||||
            # Make sure { } and [ ] nest properly.
 | 
			
		||||
            if (name == '}') != isinstance(parent_pat, IncMultiPattern):
 | 
			
		||||
                error(lineno, 'mismatched close brace')
 | 
			
		||||
 | 
			
		||||
            try:
 | 
			
		||||
                parent_pat = nesting_pats.pop()
 | 
			
		||||
            except:
 | 
			
		||||
                error(lineno, 'extra close brace')
 | 
			
		||||
 | 
			
		||||
            nesting -= 2
 | 
			
		||||
            if indent != nesting:
 | 
			
		||||
                error(start_lineno, 'indentation ', indent, ' != ', nesting)
 | 
			
		||||
            pats = patterns
 | 
			
		||||
            patterns = saved_pats.pop()
 | 
			
		||||
            build_multi_pattern(lineno, pats)
 | 
			
		||||
                error(lineno, 'indentation ', indent, ' != ', nesting)
 | 
			
		||||
 | 
			
		||||
            toks = []
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,11 +1046,18 @@ def parse_file(f):
 | 
			
		|||
            error(start_lineno, 'indentation ', indent, ' != ', nesting)
 | 
			
		||||
 | 
			
		||||
        # Start nesting?
 | 
			
		||||
        if name == '{':
 | 
			
		||||
        if name == '{' or name == '[':
 | 
			
		||||
            if len(toks) != 0:
 | 
			
		||||
                error(start_lineno, 'extra tokens after open brace')
 | 
			
		||||
            saved_pats.append(patterns)
 | 
			
		||||
            patterns = []
 | 
			
		||||
 | 
			
		||||
            if name == '{':
 | 
			
		||||
                nested_pat = IncMultiPattern(start_lineno)
 | 
			
		||||
            else:
 | 
			
		||||
                nested_pat = ExcMultiPattern(start_lineno)
 | 
			
		||||
            parent_pat.pats.append(nested_pat)
 | 
			
		||||
            nesting_pats.append(parent_pat)
 | 
			
		||||
            parent_pat = nested_pat
 | 
			
		||||
 | 
			
		||||
            nesting += 2
 | 
			
		||||
            toks = []
 | 
			
		||||
            continue
 | 
			
		||||
| 
						 | 
				
			
			@ -1023,115 +1068,16 @@ def parse_file(f):
 | 
			
		|||
        elif name[0] == '&':
 | 
			
		||||
            parse_arguments(start_lineno, name[1:], toks)
 | 
			
		||||
        elif name[0] == '@':
 | 
			
		||||
            parse_generic(start_lineno, True, name[1:], toks)
 | 
			
		||||
            parse_generic(start_lineno, None, name[1:], toks)
 | 
			
		||||
        else:
 | 
			
		||||
            parse_generic(start_lineno, False, name, toks)
 | 
			
		||||
            parse_generic(start_lineno, parent_pat, name, toks)
 | 
			
		||||
        toks = []
 | 
			
		||||
 | 
			
		||||
    if nesting != 0:
 | 
			
		||||
        error(lineno, 'missing close brace')
 | 
			
		||||
# end parse_file
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Tree:
 | 
			
		||||
    """Class representing a node in a decode tree"""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, fm, tm):
 | 
			
		||||
        self.fixedmask = fm
 | 
			
		||||
        self.thismask = tm
 | 
			
		||||
        self.subs = []
 | 
			
		||||
        self.base = None
 | 
			
		||||
 | 
			
		||||
    def str1(self, i):
 | 
			
		||||
        ind = str_indent(i)
 | 
			
		||||
        r = '{0}{1:08x}'.format(ind, self.fixedmask)
 | 
			
		||||
        if self.format:
 | 
			
		||||
            r += ' ' + self.format.name
 | 
			
		||||
        r += ' [\n'
 | 
			
		||||
        for (b, s) in self.subs:
 | 
			
		||||
            r += '{0}  {1:08x}:\n'.format(ind, b)
 | 
			
		||||
            r += s.str1(i + 4) + '\n'
 | 
			
		||||
        r += ind + ']'
 | 
			
		||||
        return r
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.str1(0)
 | 
			
		||||
 | 
			
		||||
    def output_code(self, i, extracted, outerbits, outermask):
 | 
			
		||||
        ind = str_indent(i)
 | 
			
		||||
 | 
			
		||||
        # If we identified all nodes below have the same format,
 | 
			
		||||
        # extract the fields now.
 | 
			
		||||
        if not extracted and self.base:
 | 
			
		||||
            output(ind, self.base.extract_name(),
 | 
			
		||||
                   '(ctx, &u.f_', self.base.base.name, ', insn);\n')
 | 
			
		||||
            extracted = True
 | 
			
		||||
 | 
			
		||||
        # Attempt to aid the compiler in producing compact switch statements.
 | 
			
		||||
        # If the bits in the mask are contiguous, extract them.
 | 
			
		||||
        sh = is_contiguous(self.thismask)
 | 
			
		||||
        if sh > 0:
 | 
			
		||||
            # Propagate SH down into the local functions.
 | 
			
		||||
            def str_switch(b, sh=sh):
 | 
			
		||||
                return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh)
 | 
			
		||||
 | 
			
		||||
            def str_case(b, sh=sh):
 | 
			
		||||
                return '0x{0:x}'.format(b >> sh)
 | 
			
		||||
        else:
 | 
			
		||||
            def str_switch(b):
 | 
			
		||||
                return 'insn & 0x{0:08x}'.format(b)
 | 
			
		||||
 | 
			
		||||
            def str_case(b):
 | 
			
		||||
                return '0x{0:08x}'.format(b)
 | 
			
		||||
 | 
			
		||||
        output(ind, 'switch (', str_switch(self.thismask), ') {\n')
 | 
			
		||||
        for b, s in sorted(self.subs):
 | 
			
		||||
            assert (self.thismask & ~s.fixedmask) == 0
 | 
			
		||||
            innermask = outermask | self.thismask
 | 
			
		||||
            innerbits = outerbits | b
 | 
			
		||||
            output(ind, 'case ', str_case(b), ':\n')
 | 
			
		||||
            output(ind, '    /* ',
 | 
			
		||||
                   str_match_bits(innerbits, innermask), ' */\n')
 | 
			
		||||
            s.output_code(i + 4, extracted, innerbits, innermask)
 | 
			
		||||
            output(ind, '    return false;\n')
 | 
			
		||||
        output(ind, '}\n')
 | 
			
		||||
# end Tree
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_tree(pats, outerbits, outermask):
 | 
			
		||||
    # Find the intersection of all remaining fixedmask.
 | 
			
		||||
    innermask = ~outermask & insnmask
 | 
			
		||||
    for i in pats:
 | 
			
		||||
        innermask &= i.fixedmask
 | 
			
		||||
 | 
			
		||||
    if innermask == 0:
 | 
			
		||||
        text = 'overlapping patterns:'
 | 
			
		||||
        for p in pats:
 | 
			
		||||
            text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p)
 | 
			
		||||
        error_with_file(pats[0].file, pats[0].lineno, text)
 | 
			
		||||
 | 
			
		||||
    fullmask = outermask | innermask
 | 
			
		||||
 | 
			
		||||
    # Sort each element of pats into the bin selected by the mask.
 | 
			
		||||
    bins = {}
 | 
			
		||||
    for i in pats:
 | 
			
		||||
        fb = i.fixedbits & innermask
 | 
			
		||||
        if fb in bins:
 | 
			
		||||
            bins[fb].append(i)
 | 
			
		||||
        else:
 | 
			
		||||
            bins[fb] = [i]
 | 
			
		||||
 | 
			
		||||
    # We must recurse if any bin has more than one element or if
 | 
			
		||||
    # the single element in the bin has not been fully matched.
 | 
			
		||||
    t = Tree(fullmask, innermask)
 | 
			
		||||
 | 
			
		||||
    for b, l in bins.items():
 | 
			
		||||
        s = l[0]
 | 
			
		||||
        if len(l) > 1 or s.fixedmask & ~fullmask != 0:
 | 
			
		||||
            s = build_tree(l, b | outerbits, fullmask)
 | 
			
		||||
        t.subs.append((b, s))
 | 
			
		||||
 | 
			
		||||
    return t
 | 
			
		||||
# end build_tree
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SizeTree:
 | 
			
		||||
    """Class representing a node in a size decode tree"""
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1273,28 +1219,6 @@ def build_size_tree(pats, width, outerbits, outermask):
 | 
			
		|||
# end build_size_tree
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def prop_format(tree):
 | 
			
		||||
    """Propagate Format objects into the decode tree"""
 | 
			
		||||
 | 
			
		||||
    # Depth first search.
 | 
			
		||||
    for (b, s) in tree.subs:
 | 
			
		||||
        if isinstance(s, Tree):
 | 
			
		||||
            prop_format(s)
 | 
			
		||||
 | 
			
		||||
    # If all entries in SUBS have the same format, then
 | 
			
		||||
    # propagate that into the tree.
 | 
			
		||||
    f = None
 | 
			
		||||
    for (b, s) in tree.subs:
 | 
			
		||||
        if f is None:
 | 
			
		||||
            f = s.base
 | 
			
		||||
            if f is None:
 | 
			
		||||
                return
 | 
			
		||||
        if f is not s.base:
 | 
			
		||||
            return
 | 
			
		||||
    tree.base = f
 | 
			
		||||
# end prop_format
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def prop_size(tree):
 | 
			
		||||
    """Propagate minimum widths up the decode size tree"""
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1315,7 +1239,6 @@ def prop_size(tree):
 | 
			
		|||
def main():
 | 
			
		||||
    global arguments
 | 
			
		||||
    global formats
 | 
			
		||||
    global patterns
 | 
			
		||||
    global allpatterns
 | 
			
		||||
    global translate_scope
 | 
			
		||||
    global translate_prefix
 | 
			
		||||
| 
						 | 
				
			
			@ -1362,18 +1285,29 @@ def main():
 | 
			
		|||
 | 
			
		||||
    if len(args) < 1:
 | 
			
		||||
        error(0, 'missing input file')
 | 
			
		||||
 | 
			
		||||
    toppat = ExcMultiPattern(0)
 | 
			
		||||
 | 
			
		||||
    for filename in args:
 | 
			
		||||
        input_file = filename
 | 
			
		||||
        f = open(filename, 'r')
 | 
			
		||||
        parse_file(f)
 | 
			
		||||
        parse_file(f, toppat)
 | 
			
		||||
        f.close()
 | 
			
		||||
 | 
			
		||||
    if variablewidth:
 | 
			
		||||
        stree = build_size_tree(patterns, 8, 0, 0)
 | 
			
		||||
        prop_size(stree)
 | 
			
		||||
    # We do not want to compute masks for toppat, because those masks
 | 
			
		||||
    # are used as a starting point for build_tree.  For toppat, we must
 | 
			
		||||
    # insist that decode begins from naught.
 | 
			
		||||
    for i in toppat.pats:
 | 
			
		||||
        i.prop_masks()
 | 
			
		||||
 | 
			
		||||
    dtree = build_tree(patterns, 0, 0)
 | 
			
		||||
    prop_format(dtree)
 | 
			
		||||
    toppat.build_tree()
 | 
			
		||||
    toppat.prop_format()
 | 
			
		||||
 | 
			
		||||
    if variablewidth:
 | 
			
		||||
        for i in toppat.pats:
 | 
			
		||||
            i.prop_width()
 | 
			
		||||
        stree = build_size_tree(toppat.pats, 8, 0, 0)
 | 
			
		||||
        prop_size(stree)
 | 
			
		||||
 | 
			
		||||
    if output_file:
 | 
			
		||||
        output_fd = open(output_file, 'w')
 | 
			
		||||
| 
						 | 
				
			
			@ -1425,13 +1359,14 @@ def main():
 | 
			
		|||
           '(DisasContext *ctx, ', insntype, ' insn)\n{\n')
 | 
			
		||||
 | 
			
		||||
    i4 = str_indent(4)
 | 
			
		||||
 | 
			
		||||
    if len(allpatterns) != 0:
 | 
			
		||||
        output(i4, 'union {\n')
 | 
			
		||||
        for n in sorted(arguments.keys()):
 | 
			
		||||
            f = arguments[n]
 | 
			
		||||
            output(i4, i4, f.struct_name(), ' f_', f.name, ';\n')
 | 
			
		||||
        output(i4, '} u;\n\n')
 | 
			
		||||
        dtree.output_code(4, False, 0, 0)
 | 
			
		||||
        toppat.output_code(4, False, 0, 0)
 | 
			
		||||
 | 
			
		||||
    output(i4, 'return false;\n')
 | 
			
		||||
    output('}\n')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue