|
@@ -31,6 +31,7 @@
|
|
arguments = {}
|
|
arguments = {}
|
|
formats = {}
|
|
formats = {}
|
|
patterns = []
|
|
patterns = []
|
|
|
|
+allpatterns = []
|
|
|
|
|
|
translate_prefix = 'trans'
|
|
translate_prefix = 'trans'
|
|
translate_scope = 'static '
|
|
translate_scope = 'static '
|
|
@@ -300,13 +301,7 @@ def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds):
|
|
self.fields = flds
|
|
self.fields = flds
|
|
|
|
|
|
def __str__(self):
|
|
def __str__(self):
|
|
- r = self.name
|
|
|
|
- if self.base:
|
|
|
|
- r = r + ' ' + self.base.name
|
|
|
|
- else:
|
|
|
|
- r = r + ' ' + str(self.fields)
|
|
|
|
- r = r + ' ' + str_match_bits(self.fixedbits, self.fixedmask)
|
|
|
|
- return r
|
|
|
|
|
|
+ return self.name + ' ' + str_match_bits(self.fixedbits, self.fixedmask)
|
|
|
|
|
|
def str1(self, i):
|
|
def str1(self, i):
|
|
return str_indent(i) + self.__str__()
|
|
return str_indent(i) + self.__str__()
|
|
@@ -353,6 +348,47 @@ def output_code(self, i, extracted, outerbits, outermask):
|
|
# end Pattern
|
|
# end Pattern
|
|
|
|
|
|
|
|
|
|
|
|
+class MultiPattern(General):
|
|
|
|
+ """Class representing an overlapping set of instruction patterns"""
|
|
|
|
+
|
|
|
|
+ def __init__(self, lineno, pats, fixb, fixm, udfm):
|
|
|
|
+ self.file = input_file
|
|
|
|
+ self.lineno = lineno
|
|
|
|
+ self.pats = pats
|
|
|
|
+ self.base = None
|
|
|
|
+ self.fixedbits = fixb
|
|
|
|
+ self.fixedmask = fixm
|
|
|
|
+ self.undefmask = udfm
|
|
|
|
+
|
|
|
|
+ def __str__(self):
|
|
|
|
+ r = "{"
|
|
|
|
+ for p in self.pats:
|
|
|
|
+ r = r + ' ' + str(p)
|
|
|
|
+ return r + "}"
|
|
|
|
+
|
|
|
|
+ def output_decl(self):
|
|
|
|
+ for p in self.pats:
|
|
|
|
+ p.output_decl()
|
|
|
|
+
|
|
|
|
+ def output_code(self, i, extracted, outerbits, outermask):
|
|
|
|
+ global translate_prefix
|
|
|
|
+ ind = str_indent(i)
|
|
|
|
+ for p in self.pats:
|
|
|
|
+ if outermask != p.fixedmask:
|
|
|
|
+ innermask = p.fixedmask & ~outermask
|
|
|
|
+ innerbits = p.fixedbits & ~outermask
|
|
|
|
+ output(ind, 'if ((insn & ',
|
|
|
|
+ '0x{0:08x}) == 0x{1:08x}'.format(innermask, innerbits),
|
|
|
|
+ ') {\n')
|
|
|
|
+ output(ind, ' /* ',
|
|
|
|
+ str_match_bits(p.fixedbits, p.fixedmask), ' */\n')
|
|
|
|
+ p.output_code(i + 4, extracted, p.fixedbits, p.fixedmask)
|
|
|
|
+ output(ind, '}\n')
|
|
|
|
+ else:
|
|
|
|
+ p.output_code(i, extracted, p.fixedbits, p.fixedmask)
|
|
|
|
+#end MultiPattern
|
|
|
|
+
|
|
|
|
+
|
|
def parse_field(lineno, name, toks):
|
|
def parse_field(lineno, name, toks):
|
|
"""Parse one instruction field from TOKS at LINENO"""
|
|
"""Parse one instruction field from TOKS at LINENO"""
|
|
global fields
|
|
global fields
|
|
@@ -505,6 +541,7 @@ def parse_generic(lineno, is_format, name, toks):
|
|
global arguments
|
|
global arguments
|
|
global formats
|
|
global formats
|
|
global patterns
|
|
global patterns
|
|
|
|
+ global allpatterns
|
|
global re_ident
|
|
global re_ident
|
|
global insnwidth
|
|
global insnwidth
|
|
global insnmask
|
|
global insnmask
|
|
@@ -649,6 +686,7 @@ def parse_generic(lineno, is_format, name, toks):
|
|
pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
|
|
pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
|
|
undefmask, fieldmask, flds)
|
|
undefmask, fieldmask, flds)
|
|
patterns.append(pat)
|
|
patterns.append(pat)
|
|
|
|
+ allpatterns.append(pat)
|
|
|
|
|
|
# Validate the masks that we have assembled.
|
|
# Validate the masks that we have assembled.
|
|
if fieldmask & fixedmask:
|
|
if fieldmask & fixedmask:
|
|
@@ -667,17 +705,66 @@ def parse_generic(lineno, is_format, name, toks):
|
|
.format(allbits ^ insnmask))
|
|
.format(allbits ^ insnmask))
|
|
# end parse_general
|
|
# 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
|
|
|
|
+
|
|
|
|
+ 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)
|
|
|
|
+ patterns.append(mp)
|
|
|
|
+# end build_multi_pattern
|
|
|
|
|
|
def parse_file(f):
|
|
def parse_file(f):
|
|
"""Parse all of the patterns within a file"""
|
|
"""Parse all of the patterns within a file"""
|
|
|
|
|
|
|
|
+ global patterns
|
|
|
|
+
|
|
# Read all of the lines of the file. Concatenate lines
|
|
# Read all of the lines of the file. Concatenate lines
|
|
# ending in backslash; discard empty lines and comments.
|
|
# ending in backslash; discard empty lines and comments.
|
|
toks = []
|
|
toks = []
|
|
lineno = 0
|
|
lineno = 0
|
|
|
|
+ nesting = 0
|
|
|
|
+ saved_pats = []
|
|
|
|
+
|
|
for line in f:
|
|
for line in f:
|
|
lineno += 1
|
|
lineno += 1
|
|
|
|
|
|
|
|
+ # Expand and strip spaces, to find indent.
|
|
|
|
+ line = line.rstrip()
|
|
|
|
+ line = line.expandtabs()
|
|
|
|
+ len1 = len(line)
|
|
|
|
+ line = line.lstrip()
|
|
|
|
+ len2 = len(line)
|
|
|
|
+
|
|
# Discard comments
|
|
# Discard comments
|
|
end = line.find('#')
|
|
end = line.find('#')
|
|
if end >= 0:
|
|
if end >= 0:
|
|
@@ -687,10 +774,18 @@ def parse_file(f):
|
|
if len(toks) != 0:
|
|
if len(toks) != 0:
|
|
# Next line after continuation
|
|
# Next line after continuation
|
|
toks.extend(t)
|
|
toks.extend(t)
|
|
- elif len(t) == 0:
|
|
|
|
- # Empty line
|
|
|
|
- continue
|
|
|
|
else:
|
|
else:
|
|
|
|
+ # Allow completely blank lines.
|
|
|
|
+ if len1 == 0:
|
|
|
|
+ continue
|
|
|
|
+ indent = len1 - len2
|
|
|
|
+ # Empty line due to comment.
|
|
|
|
+ if len(t) == 0:
|
|
|
|
+ # Indentation must be correct, even for comment lines.
|
|
|
|
+ if indent != nesting:
|
|
|
|
+ error(lineno, 'indentation ', indent, ' != ', nesting)
|
|
|
|
+ continue
|
|
|
|
+ start_lineno = lineno
|
|
toks = t
|
|
toks = t
|
|
|
|
|
|
# Continuation?
|
|
# Continuation?
|
|
@@ -698,21 +793,47 @@ def parse_file(f):
|
|
toks.pop()
|
|
toks.pop()
|
|
continue
|
|
continue
|
|
|
|
|
|
- if len(toks) < 2:
|
|
|
|
- error(lineno, 'short line')
|
|
|
|
-
|
|
|
|
name = toks[0]
|
|
name = toks[0]
|
|
del toks[0]
|
|
del toks[0]
|
|
|
|
|
|
|
|
+ # End nesting?
|
|
|
|
+ if name == '}':
|
|
|
|
+ if nesting == 0:
|
|
|
|
+ error(start_lineno, 'mismatched close brace')
|
|
|
|
+ if len(toks) != 0:
|
|
|
|
+ error(start_lineno, 'extra tokens after close brace')
|
|
|
|
+ nesting -= 2
|
|
|
|
+ if indent != nesting:
|
|
|
|
+ error(start_lineno, 'indentation ', indent, ' != ', nesting)
|
|
|
|
+ pats = patterns
|
|
|
|
+ patterns = saved_pats.pop()
|
|
|
|
+ build_multi_pattern(lineno, pats)
|
|
|
|
+ toks = []
|
|
|
|
+ continue
|
|
|
|
+
|
|
|
|
+ # Everything else should have current indentation.
|
|
|
|
+ if indent != nesting:
|
|
|
|
+ error(start_lineno, 'indentation ', indent, ' != ', nesting)
|
|
|
|
+
|
|
|
|
+ # Start nesting?
|
|
|
|
+ if name == '{':
|
|
|
|
+ if len(toks) != 0:
|
|
|
|
+ error(start_lineno, 'extra tokens after open brace')
|
|
|
|
+ saved_pats.append(patterns)
|
|
|
|
+ patterns = []
|
|
|
|
+ nesting += 2
|
|
|
|
+ toks = []
|
|
|
|
+ continue
|
|
|
|
+
|
|
# Determine the type of object needing to be parsed.
|
|
# Determine the type of object needing to be parsed.
|
|
if name[0] == '%':
|
|
if name[0] == '%':
|
|
- parse_field(lineno, name[1:], toks)
|
|
|
|
|
|
+ parse_field(start_lineno, name[1:], toks)
|
|
elif name[0] == '&':
|
|
elif name[0] == '&':
|
|
- parse_arguments(lineno, name[1:], toks)
|
|
|
|
|
|
+ parse_arguments(start_lineno, name[1:], toks)
|
|
elif name[0] == '@':
|
|
elif name[0] == '@':
|
|
- parse_generic(lineno, True, name[1:], toks)
|
|
|
|
|
|
+ parse_generic(start_lineno, True, name[1:], toks)
|
|
else:
|
|
else:
|
|
- parse_generic(lineno, False, name, toks)
|
|
|
|
|
|
+ parse_generic(start_lineno, False, name, toks)
|
|
toks = []
|
|
toks = []
|
|
# end parse_file
|
|
# end parse_file
|
|
|
|
|
|
@@ -789,11 +910,10 @@ def build_tree(pats, outerbits, outermask):
|
|
innermask &= i.fixedmask
|
|
innermask &= i.fixedmask
|
|
|
|
|
|
if innermask == 0:
|
|
if innermask == 0:
|
|
- pnames = []
|
|
|
|
|
|
+ text = 'overlapping patterns:'
|
|
for p in pats:
|
|
for p in pats:
|
|
- pnames.append(p.name + ':' + p.file + ':' + str(p.lineno))
|
|
|
|
- error_with_file(pats[0].file, pats[0].lineno,
|
|
|
|
- 'overlapping patterns:', pnames)
|
|
|
|
|
|
+ text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p)
|
|
|
|
+ error_with_file(pats[0].file, pats[0].lineno, text)
|
|
|
|
|
|
fullmask = outermask | innermask
|
|
fullmask = outermask | innermask
|
|
|
|
|
|
@@ -846,6 +966,7 @@ def main():
|
|
global arguments
|
|
global arguments
|
|
global formats
|
|
global formats
|
|
global patterns
|
|
global patterns
|
|
|
|
+ global allpatterns
|
|
global translate_scope
|
|
global translate_scope
|
|
global translate_prefix
|
|
global translate_prefix
|
|
global output_fd
|
|
global output_fd
|
|
@@ -907,7 +1028,7 @@ def main():
|
|
# Make sure that the argument sets are the same, and declare the
|
|
# Make sure that the argument sets are the same, and declare the
|
|
# function only once.
|
|
# function only once.
|
|
out_pats = {}
|
|
out_pats = {}
|
|
- for i in patterns:
|
|
|
|
|
|
+ for i in allpatterns:
|
|
if i.name in out_pats:
|
|
if i.name in out_pats:
|
|
p = out_pats[i.name]
|
|
p = out_pats[i.name]
|
|
if i.base.base != p.base.base:
|
|
if i.base.base != p.base.base:
|