diff mbox series

[1/3] decodetree: Allow !function with no input bits

Message ID 20190809154153.31763-2-richard.henderson@linaro.org
State Superseded
Headers show
Series decodetree improvements | expand

Commit Message

Richard Henderson Aug. 9, 2019, 3:41 p.m. UTC
Call this form a "parameter", returning a value extracted
from the DisasContext.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 docs/devel/decodetree.rst         |  8 ++++-
 scripts/decodetree.py             | 54 ++++++++++++++++++++++++-------
 tests/decode/err_field6.decode    |  5 +++
 tests/decode/succ_function.decode |  6 ++++
 4 files changed, 60 insertions(+), 13 deletions(-)
 create mode 100644 tests/decode/err_field6.decode
 create mode 100644 tests/decode/succ_function.decode

-- 
2.17.1

Comments

Peter Maydell Aug. 9, 2019, 3:52 p.m. UTC | #1
On Fri, 9 Aug 2019 at 16:41, Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> Call this form a "parameter", returning a value extracted

> from the DisasContext.

>

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> ---

>  docs/devel/decodetree.rst         |  8 ++++-

>  scripts/decodetree.py             | 54 ++++++++++++++++++++++++-------

>  tests/decode/err_field6.decode    |  5 +++

>  tests/decode/succ_function.decode |  6 ++++

>  4 files changed, 60 insertions(+), 13 deletions(-)

>  create mode 100644 tests/decode/err_field6.decode

>  create mode 100644 tests/decode/succ_function.decode

>

> diff --git a/docs/devel/decodetree.rst b/docs/devel/decodetree.rst

> index 44ac621ea8..ce7f52308f 100644

> --- a/docs/devel/decodetree.rst

> +++ b/docs/devel/decodetree.rst

> @@ -23,7 +23,7 @@ Fields

>

>  Syntax::

>

> -  field_def     := '%' identifier ( unnamed_field )+ ( !function=identifier )?

> +  field_def     := '%' identifier ( unnamed_field )* ( !function=identifier )?

>    unnamed_field := number ':' ( 's' ) number

>

>  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

>  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

>  is restricted to ``int``.  Which means that we cannot expand 64-bit items.

>

> diff --git a/scripts/decodetree.py b/scripts/decodetree.py

> index d7a59d63ac..a2490aeb74 100755

> --- a/scripts/decodetree.py

> +++ b/scripts/decodetree.py

> @@ -195,7 +195,10 @@ class MultiField:

>      """Class representing a compound instruction field"""

>      def __init__(self, subs, mask):

>          self.subs = subs

> -        self.sign = subs[0].sign

> +        if len(subs):

> +            self.sign = subs[0].sign

> +        else:

> +            self.sign = 0

>          self.mask = mask

>

>      def __str__(self):


Is this change to MultiField left over from the previous
implementation ? I was expecting a zero-length MultiField
to now be a bug in this python script (ie we should never
try to create one).

> @@ -245,7 +248,7 @@ class ConstField:

>

>

>  class FunctionField:

> -    """Class representing a field passed through an expander"""

> +    """Class representing a field passed through a function"""

>      def __init__(self, func, base):

>          self.mask = base.mask

>          self.sign = base.sign

> @@ -266,6 +269,27 @@ class FunctionField:

>  # end FunctionField

>

>

> +class ParameterField:

> +    """Class representing a psuedo-field read from a function"""


"pseudo"

> +    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 FunctionField

>


thanks
-- PMM
Richard Henderson Aug. 9, 2019, 3:57 p.m. UTC | #2
On 8/9/19 8:52 AM, Peter Maydell wrote:
>> @@ -195,7 +195,10 @@ class MultiField:

>>      """Class representing a compound instruction field"""

>>      def __init__(self, subs, mask):

>>          self.subs = subs

>> -        self.sign = subs[0].sign

>> +        if len(subs):

>> +            self.sign = subs[0].sign

>> +        else:

>> +            self.sign = 0

>>          self.mask = mask

>>

>>      def __str__(self):

> Is this change to MultiField left over from the previous

> implementation ? I was expecting a zero-length MultiField

> to now be a bug in this python script (ie we should never

> try to create one).

> 


Oops, yes.

The error is emitted here:

> +    if len(subs) == 0:

> +        if func:

> +            f = ParameterField(func)

> +        else:

> +            error(lineno, 'field with no value')


and tested:

> +++ b/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
diff mbox series

Patch

diff --git a/docs/devel/decodetree.rst b/docs/devel/decodetree.rst
index 44ac621ea8..ce7f52308f 100644
--- a/docs/devel/decodetree.rst
+++ b/docs/devel/decodetree.rst
@@ -23,7 +23,7 @@  Fields
 
 Syntax::
 
-  field_def     := '%' identifier ( unnamed_field )+ ( !function=identifier )?
+  field_def     := '%' identifier ( unnamed_field )* ( !function=identifier )?
   unnamed_field := number ':' ( 's' ) number
 
 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
 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
 is restricted to ``int``.  Which means that we cannot expand 64-bit items.
 
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index d7a59d63ac..a2490aeb74 100755
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -195,7 +195,10 @@  class MultiField:
     """Class representing a compound instruction field"""
     def __init__(self, subs, mask):
         self.subs = subs
-        self.sign = subs[0].sign
+        if len(subs):
+            self.sign = subs[0].sign
+        else:
+            self.sign = 0
         self.mask = mask
 
     def __str__(self):
@@ -245,7 +248,7 @@  class ConstField:
 
 
 class FunctionField:
-    """Class representing a field passed through an expander"""
+    """Class representing a field passed through a function"""
     def __init__(self, func, base):
         self.mask = base.mask
         self.sign = base.sign
@@ -266,6 +269,27 @@  class FunctionField:
 # end FunctionField
 
 
+class ParameterField:
+    """Class representing a psuedo-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 FunctionField
+
+
 class Arguments:
     """Class representing the extracted fields of a format"""
     def __init__(self, nm, flds, extern):
@@ -433,17 +457,23 @@  def parse_field(lineno, name, toks):
 
     if width > insnwidth:
         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:
-        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:
         error(lineno, 'duplicate field', name)
diff --git a/tests/decode/err_field6.decode b/tests/decode/err_field6.decode
new file mode 100644
index 0000000000..a719884572
--- /dev/null
+++ b/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
diff --git a/tests/decode/succ_function.decode b/tests/decode/succ_function.decode
new file mode 100644
index 0000000000..7751b1784e
--- /dev/null
+++ b/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