[PATCH 2/3] RISC-V: Implement "generic subsets" for disasm

Tsukasa OI research_trasio@irq.a4lg.com
Fri Jun 3 12:05:46 GMT 2022


There's a situation where an instruction is a specialized form of
another but they have different requirements (that can co-exist).  On
such cases, no-aliases option on diassembler will not work as expected.
This commit implements so called "generic subsets" to work with such
situation.

include/ChangeLog:

	* opcode/riscv.h (INSN_GENERICS): New.

opcodes/ChangeLog:

	* riscv-dis.c (riscv_disassemble_insn): Implement so called
	"generic subsets" for disassembler.
	* riscv-opc.c (riscv_opcodes): Add INSN_GENERICS to zext.h,
	pack and packw instructions.
---
 include/opcode/riscv.h |  4 ++++
 opcodes/riscv-dis.c    | 18 +++++++++++++++---
 opcodes/riscv-opc.c    |  8 ++++----
 3 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index f0beceaec44..b526dd8fc0d 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -438,6 +438,10 @@ struct riscv_opcode
 /* Instruction is a simple alias (e.g. "mv" for "addi").  */
 #define	INSN_ALIAS		0x00000001
 
+/* Instruction can be a simple instruction or an alias
+   depending on enabled ISA extensions. */
+#define INSN_GENERICS		0x00000100
+
 /* These are for setting insn_info fields.
 
    Nonbranch is the default.  Noninsn is used only if there is no match.
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 48858e61c38..74655a2acb5 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -576,7 +576,7 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
   static bool init = 0;
   static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
   struct riscv_private_data *pd;
-  int insnlen;
+  int insnlen, masklen = -1;
 
 #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
 
@@ -657,8 +657,20 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
 	  if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class))
 	    continue;
 
-	  matched_op = op;
-	  break;
+	  if (! (op->pinfo & INSN_GENERICS))
+	    {
+	      matched_op = op;
+	      break;
+	    }
+
+	  int curmasklen = __builtin_popcountll(op->mask);
+	  if (matched_op == NULL || (no_aliases
+				     ? (curmasklen < masklen)
+				     : (curmasklen >= masklen)))
+	    {
+	      matched_op = op;
+	      masklen = curmasklen;
+	    }
 	}
     }
 
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 6355f8059f5..0eae9a788ed 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -933,8 +933,8 @@ const struct riscv_opcode riscv_opcodes[] =
 {"sext.b",     0, INSN_CLASS_I,         "d,s",   0, (int) M_SEXTB, match_never, INSN_MACRO },
 {"sext.h",     0, INSN_CLASS_ZBB,  "d,s",   MATCH_SEXT_H, MASK_SEXT_H, match_opcode, 0 },
 {"sext.h",     0, INSN_CLASS_I,         "d,s",   0, (int) M_SEXTH, match_never, INSN_MACRO },
-{"zext.h",    32, INSN_CLASS_ZBB,  "d,s",   MATCH_PACK, MASK_PACK | MASK_RS2, match_opcode, 0 },
-{"zext.h",    64, INSN_CLASS_ZBB,  "d,s",   MATCH_PACKW, MASK_PACKW | MASK_RS2, match_opcode, 0 },
+{"zext.h",    32, INSN_CLASS_ZBB,  "d,s",   MATCH_PACK, MASK_PACK | MASK_RS2, match_opcode, INSN_GENERICS },
+{"zext.h",    64, INSN_CLASS_ZBB,  "d,s",   MATCH_PACKW, MASK_PACKW | MASK_RS2, match_opcode, INSN_GENERICS },
 {"zext.h",     0, INSN_CLASS_I,         "d,s",   0, (int) M_ZEXTH, match_never, INSN_MACRO },
 {"orc.b",      0, INSN_CLASS_ZBB,  "d,s",   MATCH_GORCI | MATCH_SHAMT_ORC_B, MASK_GORCI | MASK_SHAMT, match_opcode, 0 },
 {"clzw",      64, INSN_CLASS_ZBB,  "d,s",   MATCH_CLZW, MASK_CLZW, match_opcode, 0 },
@@ -944,9 +944,9 @@ const struct riscv_opcode riscv_opcodes[] =
 {"brev8",     64, INSN_CLASS_ZBKB,  "d,s",      MATCH_GREVI | MATCH_SHAMT_BREV8, MASK_GREVI | MASK_SHAMT, match_opcode, 0 },
 {"zip",       32, INSN_CLASS_ZBKB,  "d,s",      MATCH_SHFLI|MATCH_SHAMT_ZIP_32, MASK_SHFLI|MASK_SHAMT, match_opcode, INSN_ALIAS },
 {"unzip",     32, INSN_CLASS_ZBKB,  "d,s",      MATCH_UNSHFLI|MATCH_SHAMT_ZIP_32, MASK_UNSHFLI|MASK_SHAMT, match_opcode, INSN_ALIAS },
-{"pack",       0, INSN_CLASS_ZBKB,  "d,s,t",    MATCH_PACK, MASK_PACK, match_opcode, 0 },
+{"pack",       0, INSN_CLASS_ZBKB,  "d,s,t",    MATCH_PACK, MASK_PACK, match_opcode, INSN_GENERICS },
 {"packh",      0, INSN_CLASS_ZBKB,  "d,s,t",    MATCH_PACKH, MASK_PACKH, match_opcode, 0 },
-{"packw",     64, INSN_CLASS_ZBKB,  "d,s,t",    MATCH_PACKW, MASK_PACKW, match_opcode, 0 },
+{"packw",     64, INSN_CLASS_ZBKB,  "d,s,t",    MATCH_PACKW, MASK_PACKW, match_opcode, INSN_GENERICS },
 {"andn",       0, INSN_CLASS_ZBB_OR_ZBKB,  "d,s,t", MATCH_ANDN, MASK_ANDN, match_opcode, 0 },
 {"orn",        0, INSN_CLASS_ZBB_OR_ZBKB,  "d,s,t", MATCH_ORN, MASK_ORN, match_opcode, 0 },
 {"xnor",       0, INSN_CLASS_ZBB_OR_ZBKB,  "d,s,t", MATCH_XNOR, MASK_XNOR, match_opcode, 0 },
-- 
2.34.1



More information about the Binutils mailing list