[binutils-gdb] s390: Treat addressing operand sequence as one in assembler

Jens Remus jremus@sourceware.org
Fri Nov 29 14:38:34 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=453f481aabf6b552dc83dc63c4f62ed2a6b41ded

commit 453f481aabf6b552dc83dc63c4f62ed2a6b41ded
Author: Jens Remus <jremus@linux.ibm.com>
Date:   Fri Nov 29 15:37:19 2024 +0100

    s390: Treat addressing operand sequence as one in assembler
    
    The assembler erroneously treated any number of operands as optional,
    if the instruction was flagged to have one or two optional operands
    (i.e. optparm or optparm2).
    
    Only treat the exact specified number of operands as optional while
    treating addressing operand sequences D(X,B), D(B), and D(L,B) as one
    operand.
    
    gas/
            * config/tc-s390.c (operand_count): New helper to count the
            remaining operands, treating D(X,B), D(B), and D(L,B) as one.
            (skip_optargs_p): Use new helper operand_count to treat
            D(X,B), D(B), and D(L,B) as one operand.
            (md_gather_operands): Use skip_optargs_p to skip only the
            optional last operands.
    
    Signed-off-by: Jens Remus <jremus@linux.ibm.com>

Diff:
---
 gas/config/tc-s390.c | 48 ++++++++++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c
index d8f31daeef2..5d589910881 100644
--- a/gas/config/tc-s390.c
+++ b/gas/config/tc-s390.c
@@ -1359,21 +1359,42 @@ operand_type_str(const struct s390_operand * operand)
     }
 }
 
-/* Return true if all remaining operands in the opcode with
-   OPCODE_FLAGS can be skipped.  */
+/* Return remaining operand count.  */
+
+static unsigned int
+operand_count (const unsigned char *opindex_ptr)
+{
+  unsigned int count = 0;
+
+  for (; *opindex_ptr != 0; opindex_ptr++)
+    {
+      /* Count D(X,B), D(B), and D(L,B) as one operand.  Assuming correct
+	 instruction operand definitions simply do not count D, X, and L.  */
+      if (!(s390_operands[*opindex_ptr].flags & (S390_OPERAND_DISP
+						| S390_OPERAND_INDEX
+						| S390_OPERAND_LENGTH)))
+	count++;
+    }
+
+  return count;
+}
+
+/* Return true if all remaining instruction operands are optional.  */
+
 static bool
 skip_optargs_p (unsigned int opcode_flags, const unsigned char *opindex_ptr)
 {
-  if ((opcode_flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2))
-      && opindex_ptr[0] != '\0'
-      && opindex_ptr[1] == '\0')
-    return true;
-
-  if ((opcode_flags & S390_INSTR_FLAG_OPTPARM2)
-      && opindex_ptr[0] != '\0'
-      && opindex_ptr[1] != '\0'
-      && opindex_ptr[2] == '\0')
-    return true;
+  if ((opcode_flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2)))
+    {
+      unsigned int opcount = operand_count (opindex_ptr);
+
+      if (opcount == 1)
+	return true;
+
+      if ((opcode_flags & S390_INSTR_FLAG_OPTPARM2) && opcount == 2)
+	return true;
+    }
+
   return false;
 }
 
@@ -1421,8 +1442,7 @@ md_gather_operands (char *str,
 
       operand = s390_operands + *opindex_ptr;
 
-      if ((opcode->flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2))
-	  && *str == '\0')
+      if (*str == '\0' && skip_optargs_p (opcode->flags, opindex_ptr))
 	{
 	  /* Optional parameters might need to be ORed with a
 	     value so calling s390_insert_operand is needed.  */


More information about the Binutils-cvs mailing list