Skip to content

Commit 0336d5d

Browse files
committed
RISC-V: Fallback on faster hash table
Although it does not have a problem on current GNU Binutils implementation, if the custom vendor implements an instruction which spans across multiple major opcodes (e.g. uses both CUSTOM_0 and CUSTOM_1 in a *single* custom instruction), the original assumption of the sorted hash table breaks. In this case, this commit enables the fallback mode to disable all optimizations except filtering macros out. Note that, if a such instruction (that disables this disassembler optimization) is upstreamed to Binutils, a separate solution will be required to avoid major performance degradation when such instruction is not used. The intent of this commit is to make a room for custom vendors to implement such instructions in *their* tree without causing disassembler problems. opcodes/ChangeLog: * riscv-dis.c (is_riscv_hash_fallback) New. (build_riscv_opcodes_hash_table): If an instruction spans across multiple major opcodes, enable fallback mode and disable sorting. (riscv_disassemble_insn): If the fallback mode is enabled, scan through all instructions instead of scanning only instruction entries matching the hash value.
1 parent be06a17 commit 0336d5d

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

opcodes/riscv-dis.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,9 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
902902
static const struct riscv_opcode **riscv_hash[OP_HASH_LEN + 1];
903903
static const struct riscv_opcode **riscv_opcodes_sorted;
904904

905+
/* Whether the fallback should be used. */
906+
static bool is_riscv_hash_fallback = false;
907+
905908
/* Compare two riscv_opcode* objects to sort by hash index. */
906909

907910
static int
@@ -932,15 +935,25 @@ build_riscv_opcodes_hash_table (void)
932935

933936
/* Sort riscv_opcodes entry pointers (except macros). */
934937
for (op = riscv_opcodes; op->name; op++)
935-
if (op->pinfo != INSN_MACRO)
938+
{
939+
if (op->pinfo == INSN_MACRO)
940+
continue;
936941
len++;
942+
if (is_riscv_hash_fallback)
943+
continue;
944+
if (OP_HASH_IDX (op->match) < OP_MASK_OP2
945+
? (op->mask & OP_MASK_OP2) != OP_MASK_OP2
946+
: (op->mask & OP_MASK_OP) != OP_MASK_OP)
947+
is_riscv_hash_fallback = true;
948+
}
937949
riscv_opcodes_sorted = xcalloc (len, sizeof (struct riscv_opcode *));
938950
pop_end = riscv_opcodes_sorted;
939951
for (op = riscv_opcodes; op->name; op++)
940952
if (op->pinfo != INSN_MACRO)
941953
*pop_end++ = op;
942-
qsort (riscv_opcodes_sorted, len, sizeof (struct riscv_opcode *),
943-
compare_opcodes);
954+
if (!is_riscv_hash_fallback)
955+
qsort (riscv_opcodes_sorted, len, sizeof (struct riscv_opcode *),
956+
compare_opcodes);
944957

945958
/* Initialize faster hash table. */
946959
pop = riscv_opcodes_sorted;
@@ -987,8 +1000,16 @@ riscv_disassemble_insn (bfd_vma memaddr,
9871000
info->target2 = 0;
9881001

9891002
matched_op = NULL;
990-
pop = riscv_hash[OP_HASH_IDX (word)];
991-
pop_end = riscv_hash[OP_HASH_IDX (word) + 1];
1003+
if (!is_riscv_hash_fallback)
1004+
{
1005+
pop = riscv_hash[OP_HASH_IDX (word)];
1006+
pop_end = riscv_hash[OP_HASH_IDX (word) + 1];
1007+
}
1008+
else
1009+
{
1010+
pop = riscv_hash[0];
1011+
pop_end = riscv_hash[OP_HASH_LEN];
1012+
}
9921013
for (; pop != pop_end; pop++)
9931014
{
9941015
op = *pop;

0 commit comments

Comments
 (0)