Not for commit - Dump used opcodes to check test coverage

Alice Carlotti alice.carlotti@arm.com
Mon Apr 21 21:43:30 GMT 2025


This is a hacky patch to track coverage of the aarch64 gas testsuite.  It is
not threadsafe, and writes output to a hard coded directory.  The three output
files should be sorted and uniquified (e.g. with `sort -u`), and can then be
compared by line count or by using a diff viewer of your choice.

The assembly and disassembly hooks are placed late in the flow, once we are
committed to final assembly or disassembly using the data in that opcode table
entry.  For disassembly, some aliases depend on the aliased instruction to
handle decode, and then translate the decoded operand values.

This patch is shared primarily to clarify how I determined assembly and
disassembly test coverage while I was working to improve this coverage.


diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index dfe3f05820ab156bb7d5fc5c86dd6cbaba91065c..1ccc6b94534ed2936179d07ec245b78525877afd 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -2044,6 +2044,28 @@ extern const char *const aarch64_rprfmop_array[64];
 extern const char *const aarch64_sme_vlxn_array[2];
 extern const char *const aarch64_brbop_array[2];
 
+static int last_opcode_index = -1;
+
+static inline void
+aarch64_dump_opcode_index (char *dump_file_name,
+			   const struct aarch64_opcode *opcode)
+{
+  int opcode_index = opcode - aarch64_opcode_table;
+  if (opcode_index == last_opcode_index)
+    return;
+  last_opcode_index = opcode_index;
+
+  char buf[255] = "/binutils-scratch/";
+  strcat (buf, dump_file_name);
+  FILE *index_file = fopen (buf, "a");
+  fprintf (index_file, "%04d: %s (%08x,%08x)%s%s%s\n",
+	   opcode_index, opcode->name, opcode->opcode, opcode->mask,
+	   (opcode->flags & F_ALIAS) ? " F_ALIAS" : "",
+	   (opcode->flags & F_HAS_ALIAS) ? " F_HAS_ALIAS" : "",
+	   (opcode->flags & F_PSEUDO) ? " | F_PSEUDO" : "");
+  fclose (index_file);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
index f20bdf6ae67b74cfd67fdb46eeed5ce58ba3c3da..cfba4ca391b20f6c5c605a3fab7ed84d3aafd8a6 100644
--- a/opcodes/aarch64-asm.c
+++ b/opcodes/aarch64-asm.c
@@ -2606,6 +2606,8 @@ aarch64_opcode_encode (const aarch64_opcode *opcode,
       return 0;
     }
 
+  aarch64_dump_opcode_index ("asm_opcode_index", opcode);
+  
   /* Get the base value.
      Note: this has to be before the aliasing handling below in order to
      get the base value from the alias opcode before we move on to the
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 6552d0e202d54ff893b1c734c1af45022f6d999b..67c1d94da607190541a78f407a0c5aa71d8b17d3 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -4211,6 +4211,8 @@ print_insn_aarch64_word (bfd_vma pc,
 				    " ; %s", err_msg[ret]);
       break;
     case ERR_OK:
+      aarch64_dump_opcode_index ("dis_opcode_index", inst.opcode);
+
       user_friendly_fixup (&inst);
       if (inst.opcode->iclass == condbranch
 	  || inst.opcode->iclass == testbranch
diff --git a/opcodes/aarch64-gen.c b/opcodes/aarch64-gen.c
index ba48f06024e11ad34e72da71872b41cb902b64e2..7a090e5af5b2f26ad46e493a33a0851dc4949cef 100644
--- a/opcodes/aarch64-gen.c
+++ b/opcodes/aarch64-gen.c
@@ -144,6 +144,7 @@ read_table (const struct aarch64_opcode* table)
   do
     {
       bool match = false;
+      aarch64_dump_opcode_index ("full_opcode_index", ent);
 
       /* F_PSEUDO needs to be used together with F_ALIAS to indicate an alias
 	 opcode is a programmer friendly pseudo instruction available only in



More information about the Binutils mailing list