[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