Skip to content

Commit d1e707e

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 ae55210 commit d1e707e

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
@@ -907,6 +907,9 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
907907
static const struct riscv_opcode **riscv_hash[OP_HASH_LEN + 1];
908908
static const struct riscv_opcode **riscv_opcodes_sorted;
909909

910+
/* Whether the fallback should be used. */
911+
static bool is_riscv_hash_fallback = false;
912+
910913
/* Compare two riscv_opcode* objects to sort by hash index. */
911914

912915
static int
@@ -937,15 +940,25 @@ build_riscv_opcodes_hash_table (void)
937940

938941
/* Sort riscv_opcodes entry pointers (except macros). */
939942
for (op = riscv_opcodes; op->name; op++)
940-
if (op->pinfo != INSN_MACRO)
943+
{
944+
if (op->pinfo == INSN_MACRO)
945+
continue;
941946
len++;
947+
if (is_riscv_hash_fallback)
948+
continue;
949+
if (OP_HASH_IDX (op->match) < OP_MASK_OP2
950+
? (op->mask & OP_MASK_OP2) != OP_MASK_OP2
951+
: (op->mask & OP_MASK_OP) != OP_MASK_OP)
952+
is_riscv_hash_fallback = true;
953+
}
942954
riscv_opcodes_sorted = xcalloc (len, sizeof (struct riscv_opcode *));
943955
pop_end = riscv_opcodes_sorted;
944956
for (op = riscv_opcodes; op->name; op++)
945957
if (op->pinfo != INSN_MACRO)
946958
*pop_end++ = op;
947-
qsort (riscv_opcodes_sorted, len, sizeof (struct riscv_opcode *),
948-
compare_opcodes);
959+
if (!is_riscv_hash_fallback)
960+
qsort (riscv_opcodes_sorted, len, sizeof (struct riscv_opcode *),
961+
compare_opcodes);
949962

950963
/* Initialize faster hash table. */
951964
pop = riscv_opcodes_sorted;
@@ -992,8 +1005,16 @@ riscv_disassemble_insn (bfd_vma memaddr,
9921005
info->target2 = 0;
9931006

9941007
matched_op = NULL;
995-
pop = riscv_hash[OP_HASH_IDX (word)];
996-
pop_end = riscv_hash[OP_HASH_IDX (word) + 1];
1008+
if (!is_riscv_hash_fallback)
1009+
{
1010+
pop = riscv_hash[OP_HASH_IDX (word)];
1011+
pop_end = riscv_hash[OP_HASH_IDX (word) + 1];
1012+
}
1013+
else
1014+
{
1015+
pop = riscv_hash[0];
1016+
pop_end = riscv_hash[OP_HASH_LEN];
1017+
}
9971018
for (; pop != pop_end; pop++)
9981019
{
9991020
op = *pop;

0 commit comments

Comments
 (0)