Forráskód Böngészése

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>
Richard Henderson 6 éve
szülő
commit
94597b6146

+ 7 - 1
docs/devel/decodetree.rst

@@ -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.
 
 

+ 38 - 11
scripts/decodetree.py

@@ -245,7 +245,7 @@ def __cmp__(self, other):
 
 
 
 
 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 @@ def __ne__(self, other):
 # 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:
-        f = subs[0]
+    if len(subs) == 0:
+        if func:
+            f = ParameterField(func)
+        else:
+            error(lineno, 'field with no value')
     else:
     else:
-        mask = 0
-        for s in subs:
-            if mask & s.mask:
-                error(lineno, 'field components overlap')
-            mask |= s.mask
-        f = MultiField(subs, mask)
-    if func:
-        f = FunctionField(func, f)
+        if len(subs) == 1:
+            f = subs[0]
+        else:
+            mask = 0
+            for s in subs:
+                if mask & s.mask:
+                    error(lineno, 'field components overlap')
+                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)

+ 5 - 0
tests/decode/err_field6.decode

@@ -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

+ 6 - 0
tests/decode/succ_function.decode

@@ -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