public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] aarch64: Make AARCH64_OPDE_REG_LIST take a bitfield
@ 2023-03-30 10:13 Richard Sandiford
  0 siblings, 0 replies; only message in thread
From: Richard Sandiford @ 2023-03-30 10:13 UTC (permalink / raw)
  To: bfd-cvs

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

commit 38c5aa5e88406193fe184a129cd397bc09c304e2
Author: Richard Sandiford <richard.sandiford@arm.com>
Date:   Thu Mar 30 11:09:08 2023 +0100

    aarch64: Make AARCH64_OPDE_REG_LIST take a bitfield
    
    AARCH64_OPDE_REG_LIST took a single operand that specified the
    expected number of registers.  However, there are quite a few
    SME2 instructions that have both 2-register forms and (separate)
    4-register forms.  If the user tries to use a 3-register list,
    it isn't obvious which opcode entry they meant.  Saying that we
    expect 2 registers and saying that we expect 4 registers would
    both be wrong.
    
    This patch therefore switches the operand to a bitfield.  If a
    AARCH64_OPDE_REG_LIST is reported against multiple opcode entries,
    the patch ORs up the expected lengths.
    
    This has no user-visible effect yet.  A later patch adds more error
    strings, alongside tests that use them.

Diff:
---
 gas/config/tc-aarch64.c | 54 +++++++++++++++++++++++++++++++------------------
 opcodes/aarch64-opc.c   |  2 +-
 2 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 145e241b13b..a57cc2bc080 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -4914,6 +4914,20 @@ parse_sys_ins_reg (char **str, htab_t sys_ins_regs)
       goto failure;						\
   } while (0)
 \f
+/* A primitive log calculator.  */
+
+static inline unsigned int
+get_log2 (unsigned int n)
+{
+  unsigned int count = 0;
+  while (n > 1)
+    {
+      n >>= 1;
+      count += 1;
+    }
+  return count;
+}
+
 /* encode the 12-bit imm field of Add/sub immediate */
 static inline uint32_t
 encode_addsub_imm (uint32_t imm)
@@ -5732,14 +5746,17 @@ output_operand_error_record (const operand_error_record *record, char *str)
       break;
 
     case AARCH64_OPDE_REG_LIST:
-      if (detail->data[0].i == 1)
+      if (detail->data[0].i == (1 << 1))
 	handler (_("invalid number of registers in the list; "
 		   "only 1 register is expected at operand %d -- `%s'"),
 		 idx + 1, str);
-      else
+      else if ((detail->data[0].i & -detail->data[0].i) == detail->data[0].i)
 	handler (_("invalid number of registers in the list; "
 		   "%d registers are expected at operand %d -- `%s'"),
-	       detail->data[0].i, idx + 1, str);
+		 get_log2 (detail->data[0].i), idx + 1, str);
+      else
+	handler (_("invalid number of registers in the list"
+		   " at operand %d -- `%s'"), idx + 1, str);
       break;
 
     case AARCH64_OPDE_UNALIGNED:
@@ -5807,6 +5824,12 @@ output_operand_error_report (char *str, bool non_fatal_only)
 		       curr->detail.data[0].i, curr->detail.data[1].i,
 		       curr->detail.data[2].i);
 	}
+      else if (curr->detail.kind == AARCH64_OPDE_REG_LIST)
+	{
+	  DEBUG_TRACE ("\t%s [%x]",
+		       operand_mismatch_kind_names[curr->detail.kind],
+		       curr->detail.data[0].i);
+	}
       else
 	{
 	  DEBUG_TRACE ("\t%s", operand_mismatch_kind_names[curr->detail.kind]);
@@ -5847,6 +5870,13 @@ output_operand_error_report (char *str, bool non_fatal_only)
 			   curr->detail.data[0].i, curr->detail.data[1].i,
 			   curr->detail.data[2].i);
 	    }
+	  else if (kind == AARCH64_OPDE_REG_LIST)
+	    {
+	      record->detail.data[0].i |= curr->detail.data[0].i;
+	      DEBUG_TRACE ("\t--> %s [%x]",
+			   operand_mismatch_kind_names[kind],
+			   curr->detail.data[0].i);
+	    }
 	}
     }
 
@@ -6191,22 +6221,6 @@ process_movw_reloc_info (void)
   return true;
 }
 
-/* A primitive log calculator.  */
-
-static inline unsigned int
-get_logsz (unsigned int size)
-{
-  const unsigned char ls[16] =
-    {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4};
-  if (size > 16)
-    {
-      gas_assert (0);
-      return -1;
-    }
-  gas_assert (ls[size - 1] != (unsigned char)-1);
-  return ls[size - 1];
-}
-
 /* Determine and return the real reloc type code for an instruction
    with the pseudo reloc type code BFD_RELOC_AARCH64_LDST_LO12.  */
 
@@ -6271,7 +6285,7 @@ ldst_lo12_determine_real_reloc_type (void)
 				      1, opd0_qlf, 0);
   gas_assert (opd1_qlf != AARCH64_OPND_QLF_NIL);
 
-  logsz = get_logsz (aarch64_get_qualifier_esize (opd1_qlf));
+  logsz = get_log2 (aarch64_get_qualifier_esize (opd1_qlf));
 
   if (inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
       || inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index dfffbf6f6e5..590d227fde3 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -1438,7 +1438,7 @@ set_reg_list_error (aarch64_operand_error *mismatch_detail, int idx,
   if (mismatch_detail == NULL)
     return;
   set_error (mismatch_detail, AARCH64_OPDE_REG_LIST, idx, NULL);
-  mismatch_detail->data[0].i = expected_num;
+  mismatch_detail->data[0].i = 1 << expected_num;
 }
 
 static inline void

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-03-30 10:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-30 10:13 [binutils-gdb] aarch64: Make AARCH64_OPDE_REG_LIST take a bitfield Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).