decodetree: Allow !function with no input bits

Call this form a "parameter", returning a value extracted
from the DisasContext.

Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2019-07-22 17:02:56 -07:00
parent 3fbd3405d2
commit 94597b6146
4 changed files with 56 additions and 12 deletions

View File

@ -23,7 +23,7 @@ Fields
Syntax:: Syntax::
field_def := '%' identifier ( unnamed_field )+ ( !function=identifier )? field_def := '%' identifier ( unnamed_field )* ( !function=identifier )?
unnamed_field := number ':' ( 's' ) number unnamed_field := number ':' ( 's' ) number
For *unnamed_field*, the first number is the least-significant bit position For *unnamed_field*, the first number is the least-significant bit position
@ -34,6 +34,12 @@ present, they are concatenated. In this way one can define disjoint fields.
If ``!function`` is specified, the concatenated result is passed through the If ``!function`` is specified, the concatenated result is passed through the
named function, taking and returning an integral value. named function, taking and returning an integral value.
One may use ``!function`` with zero ``unnamed_fields``. This case is called
a *parameter*, and the named function is only passed the ``DisasContext``
and returns an integral value extracted from there.
A field with no ``unnamed_fields`` and no ``!function`` is in error.
FIXME: the fields of the structure into which this result will be stored 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. is restricted to ``int``. Which means that we cannot expand 64-bit items.

View File

@ -245,7 +245,7 @@ class ConstField:
class FunctionField: class FunctionField:
"""Class representing a field passed through an expander""" """Class representing a field passed through a function"""
def __init__(self, func, base): def __init__(self, func, base):
self.mask = base.mask self.mask = base.mask
self.sign = base.sign self.sign = base.sign
@ -266,6 +266,27 @@ class FunctionField:
# end FunctionField # end FunctionField
class ParameterField:
"""Class representing a pseudo-field read from a function"""
def __init__(self, func):
self.mask = 0
self.sign = 0
self.func = func
def __str__(self):
return self.func
def str_extract(self):
return self.func + '(ctx)'
def __eq__(self, other):
return self.func == other.func
def __ne__(self, other):
return not self.__eq__(other)
# end ParameterField
class Arguments: class Arguments:
"""Class representing the extracted fields of a format""" """Class representing the extracted fields of a format"""
def __init__(self, nm, flds, extern): def __init__(self, nm, flds, extern):
@ -433,17 +454,23 @@ def parse_field(lineno, name, toks):
if width > insnwidth: if width > insnwidth:
error(lineno, 'field too large') error(lineno, 'field too large')
if len(subs) == 1: if len(subs) == 0:
f = subs[0] if func:
f = ParameterField(func)
else:
error(lineno, 'field with no value')
else: else:
mask = 0 if len(subs) == 1:
for s in subs: f = subs[0]
if mask & s.mask: else:
error(lineno, 'field components overlap') mask = 0
mask |= s.mask for s in subs:
f = MultiField(subs, mask) if mask & s.mask:
if func: error(lineno, 'field components overlap')
f = FunctionField(func, f) mask |= s.mask
f = MultiField(subs, mask)
if func:
f = FunctionField(func, f)
if name in fields: if name in fields:
error(lineno, 'duplicate field', name) error(lineno, 'duplicate field', name)

View File

@ -0,0 +1,5 @@
# This work is licensed under the terms of the GNU LGPL, version 2 or later.
# See the COPYING.LIB file in the top-level directory.
# Diagnose no bits in field
%field

View File

@ -0,0 +1,6 @@
# This work is licensed under the terms of the GNU LGPL, version 2 or later.
# See the COPYING.LIB file in the top-level directory.
# "Field" as parameter pulled from DisasContext.
%foo !function=foo
foo 00000000000000000000000000000000 %foo