[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/2] decodetree: Initial support for variable-length
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 1/2] decodetree: Initial support for variable-length ISAs |
Date: |
Thu, 31 Jan 2019 13:08:50 -0800 |
Assuming that the ISA clearly describes how to determine
the length of the instruction, and the ISA has a reasonable
maximum instruction length, the input to the decoder can be
right-justified in an appropriate insn word.
This is not 100% convenient, as out-of-line %fields are
numbered relative to the maximum instruction length, but
this appears to still be usable.
Signed-off-by: Richard Henderson <address@hidden>
---
scripts/decodetree.py | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 2f8b5a1c92..5fb0acaa15 100755
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -159,6 +159,7 @@ import getopt
insnwidth = 32
insnmask = 0xffffffff
+variablewidth = False
fields = {}
arguments = {}
formats = {}
@@ -420,7 +421,7 @@ class Arguments:
class General:
"""Common code between instruction formats and instruction patterns"""
- def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds):
+ def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds, w):
self.name = name
self.file = input_file
self.lineno = lineno
@@ -430,6 +431,7 @@ class General:
self.undefmask = udfm
self.fieldmask = fldm
self.fields = flds
+ self.width = w
def __str__(self):
r = self.name
@@ -597,7 +599,7 @@ def infer_argument_set(flds):
return arg
-def infer_format(arg, fieldmask, flds):
+def infer_format(arg, fieldmask, flds, width):
global arguments
global formats
global decode_function
@@ -616,6 +618,8 @@ def infer_format(arg, fieldmask, flds):
continue
if fieldmask != fmt.fieldmask:
continue
+ if width != fmt.width:
+ continue
if not eq_fields_for_fmts(flds, fmt.fields):
continue
return (fmt, const_flds)
@@ -624,7 +628,7 @@ def infer_format(arg, fieldmask, flds):
if not arg:
arg = infer_argument_set(flds)
- fmt = Format(name, 0, arg, 0, 0, 0, fieldmask, var_flds)
+ fmt = Format(name, 0, arg, 0, 0, 0, fieldmask, var_flds, width)
formats[name] = fmt
return (fmt, const_flds)
@@ -640,6 +644,7 @@ def parse_generic(lineno, is_format, name, toks):
global re_ident
global insnwidth
global insnmask
+ global variablewidth
fixedmask = 0
fixedbits = 0
@@ -725,8 +730,15 @@ def parse_generic(lineno, is_format, name, toks):
error(lineno, 'invalid token "{0}"'.format(t))
width += shift
+ if variablewidth and width < insnwidth and width % 8 == 0:
+ shift = insnwidth - width
+ fixedbits <<= shift
+ fixedmask <<= shift
+ undefmask <<= shift
+ undefmask |= (1 << shift) - 1
+
# We should have filled in all of the bits of the instruction.
- if not (is_format and width == 0) and width != insnwidth:
+ elif not (is_format and width == 0) and width != insnwidth:
error(lineno, 'definition has {0} bits'.format(width))
# Do not check for fields overlaping fields; one valid usage
@@ -752,7 +764,7 @@ def parse_generic(lineno, is_format, name, toks):
if name in formats:
error(lineno, 'duplicate format name', name)
fmt = Format(name, lineno, arg, fixedbits, fixedmask,
- undefmask, fieldmask, flds)
+ undefmask, fieldmask, flds, width)
formats[name] = fmt
else:
# Patterns can reference a format ...
@@ -762,12 +774,14 @@ def parse_generic(lineno, is_format, name, toks):
error(lineno, 'pattern specifies both format and argument set')
if fixedmask & fmt.fixedmask:
error(lineno, 'pattern fixed bits overlap format fixed bits')
+ if width != fmt.width:
+ error(lineno, 'pattern uses format of different width')
fieldmask |= fmt.fieldmask
fixedbits |= fmt.fixedbits
fixedmask |= fmt.fixedmask
undefmask |= fmt.undefmask
else:
- (fmt, flds) = infer_format(arg, fieldmask, flds)
+ (fmt, flds) = infer_format(arg, fieldmask, flds, width)
arg = fmt.base
for f in flds.keys():
if f not in arg.fields:
@@ -779,7 +793,7 @@ def parse_generic(lineno, is_format, name, toks):
if f not in flds.keys() and f not in fmt.fields.keys():
error(lineno, 'field {0} not initialized'.format(f))
pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
- undefmask, fieldmask, flds)
+ undefmask, fieldmask, flds, width)
patterns.append(pat)
# Validate the masks that we have assembled.
@@ -987,12 +1001,14 @@ def main():
global insntype
global insnmask
global decode_function
+ global variablewidth
decode_scope = 'static '
- long_opts = ['decode=', 'translate=', 'output=', 'insnwidth=']
+ long_opts = ['decode=', 'translate=',
+ 'output=', 'insnwidth=', 'varinsnwidth=']
try:
- (opts, args) = getopt.getopt(sys.argv[1:], 'o:w:', long_opts)
+ (opts, args) = getopt.getopt(sys.argv[1:], 'o:vw:', long_opts)
except getopt.GetoptError as err:
error(0, err)
for o, a in opts:
@@ -1004,7 +1020,9 @@ def main():
elif o == '--translate':
translate_prefix = a
translate_scope = ''
- elif o in ('-w', '--insnwidth'):
+ elif o in ('-w', '--insnwidth', '--varinsnwidth'):
+ if o == '--varinsnwidth':
+ variablewidth = True
insnwidth = int(a)
if insnwidth == 16:
insntype = 'uint16_t'
--
2.17.2