Skip to content

Commit

Permalink
RISC-V: Fallback on faster hash table
Browse files Browse the repository at this point in the history
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, the faster hash table breaks.

In this case, this commit enables the fallback mode to disable all
optimizations except filtering macros out.

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.
  • Loading branch information
a4lg committed Aug 26, 2022
1 parent 8e3001f commit 3223dfc
Showing 1 changed file with 26 additions and 5 deletions.
31 changes: 26 additions & 5 deletions opcodes/riscv-dis.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ update_riscv_dis_xlen (struct disassemble_info *info)
static const struct riscv_opcode **riscv_hash[OP_HASH_LEN + 1];
static const struct riscv_opcode **riscv_opcodes_sorted;

/* Whether the fallback should be used. */
static bool is_riscv_hash_fallback = false;

/* Compare two riscv_opcode* objects to sort by hash index. */

static int
Expand Down Expand Up @@ -290,15 +293,25 @@ build_riscv_opcodes_hash_table (void)

/* Sort riscv_opcodes entry pointers (except macros). */
for (op = riscv_opcodes; op->name; op++)
if (op->pinfo != INSN_MACRO)
{
if (op->pinfo == INSN_MACRO)
continue;
len++;
if (is_riscv_hash_fallback)
continue;
if (OP_HASH_IDX (op->match) < OP_MASK_OP2
? (op->mask & OP_MASK_OP2) != OP_MASK_OP2
: (op->mask & OP_MASK_OP) != OP_MASK_OP)
is_riscv_hash_fallback = true;
}
riscv_opcodes_sorted = xcalloc (len, sizeof (struct riscv_opcode *));
pop_end = riscv_opcodes_sorted;
for (op = riscv_opcodes; op->name; op++)
if (op->pinfo != INSN_MACRO)
*pop_end++ = op;
qsort (riscv_opcodes_sorted, len, sizeof (struct riscv_opcode *),
compare_opcodes);
if (!is_riscv_hash_fallback)
qsort (riscv_opcodes_sorted, len, sizeof (struct riscv_opcode *),
compare_opcodes);

/* Initialize faster hash table. */
pop = riscv_opcodes_sorted;
Expand Down Expand Up @@ -813,8 +826,16 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
info->target2 = 0;

matched_op = NULL;
pop = riscv_hash[OP_HASH_IDX (word)];
pop_end = riscv_hash[OP_HASH_IDX (word) + 1];
if (!is_riscv_hash_fallback)
{
pop = riscv_hash[OP_HASH_IDX (word)];
pop_end = riscv_hash[OP_HASH_IDX (word) + 1];
}
else
{
pop = riscv_hash[0];
pop_end = riscv_hash[OP_HASH_LEN];
}
for (; pop != pop_end; pop++)
{
op = *pop;
Expand Down

0 comments on commit 3223dfc

Please sign in to comment.