Skip to content

Instantly share code, notes, and snippets.

@luhenry
Created August 7, 2023 14:46
Show Gist options
  • Save luhenry/c31f951abc6b22a91955b8c2a0b43fd4 to your computer and use it in GitHub Desktop.
Save luhenry/c31f951abc6b22a91955b8c2a0b43fd4 to your computer and use it in GitHub Desktop.
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index f8d391ee98b..17f8208c15a 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -676,23 +676,9 @@ riscv_disassemble_insn (bfd_vma memaddr,
disassemble_info *info)
{
const struct riscv_opcode *op;
- static bool init = false;
- static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
struct riscv_private_data *pd;
int insnlen;
-#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
-
- /* Build a hash table to shorten the search time. */
- if (! init)
- {
- for (op = riscv_opcodes; op->name; op++)
- if (!riscv_hash[OP_HASH_IDX (op->match)])
- riscv_hash[OP_HASH_IDX (op->match)] = op;
-
- init = true;
- }
-
if (info->private_data == NULL)
{
int i;
@@ -731,85 +717,81 @@ riscv_disassemble_insn (bfd_vma memaddr,
info->target = 0;
info->target2 = 0;
- op = riscv_hash[OP_HASH_IDX (word)];
- if (op != NULL)
+ /* If XLEN is not known, get its value from the ELF class. */
+ if (info->mach == bfd_mach_riscv64)
+ xlen = 64;
+ else if (info->mach == bfd_mach_riscv32)
+ xlen = 32;
+ else if (info->section != NULL)
{
- /* If XLEN is not known, get its value from the ELF class. */
- if (info->mach == bfd_mach_riscv64)
- xlen = 64;
- else if (info->mach == bfd_mach_riscv32)
- xlen = 32;
- else if (info->section != NULL)
- {
- Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
- xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
- }
-
- /* If arch has the Zfinx extension, replace FPR with GPR. */
- if (riscv_subset_supports (&riscv_rps_dis, "zfinx"))
- riscv_fpr_names = riscv_gpr_names;
- else
- riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi ?
- riscv_fpr_names_abi : riscv_fpr_names_numeric;
-
- for (; op->name; op++)
- {
- /* Does the opcode match? */
- if (! (op->match_func) (op, word))
- continue;
- /* Is this a pseudo-instruction and may we print it as such? */
- if (no_aliases && (op->pinfo & INSN_ALIAS))
- continue;
- /* Is this instruction restricted to a certain value of XLEN? */
- if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
- continue;
- /* Is this instruction supported by the current architecture? */
- if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class))
- continue;
-
- /* It's a match. */
- (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
- "%s", op->name);
- print_insn_args (op->args, word, memaddr, info);
-
- /* Try to disassemble multi-instruction addressing sequences. */
- if (pd->to_print_addr)
- {
- info->target = pd->print_addr;
- (*info->fprintf_styled_func)
- (info->stream, dis_style_comment_start, " # ");
- (*info->print_address_func) (info->target, info);
- pd->to_print_addr = false;
- }
-
- /* Finish filling out insn_info fields. */
- switch (op->pinfo & INSN_TYPE)
- {
- case INSN_BRANCH:
- info->insn_type = dis_branch;
- break;
- case INSN_CONDBRANCH:
- info->insn_type = dis_condbranch;
- break;
- case INSN_JSR:
- info->insn_type = dis_jsr;
- break;
- case INSN_DREF:
- info->insn_type = dis_dref;
- break;
- default:
- break;
- }
+ Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
+ xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
+ }
- if (op->pinfo & INSN_DATA_SIZE)
- {
- int size = ((op->pinfo & INSN_DATA_SIZE)
- >> INSN_DATA_SIZE_SHIFT);
- info->data_size = 1 << (size - 1);
- }
+ /* If arch has the Zfinx extension, replace FPR with GPR. */
+ if (riscv_subset_supports (&riscv_rps_dis, "zfinx"))
+ riscv_fpr_names = riscv_gpr_names;
+ else
+ riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi ?
+ riscv_fpr_names_abi : riscv_fpr_names_numeric;
- return insnlen;
- }
+ for (op = riscv_opcodes; op->name; op++)
+ {
+ /* Does the opcode match? */
+ if (! (op->match_func) (op, word))
+ continue;
+ /* Is this a pseudo-instruction and may we print it as such? */
+ if (no_aliases && (op->pinfo & INSN_ALIAS))
+ continue;
+ /* Is this instruction restricted to a certain value of XLEN? */
+ if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
+ continue;
+ /* Is this instruction supported by the current architecture? */
+ if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class))
+ continue;
+
+ /* It's a match. */
+ (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+ "%s", op->name);
+ print_insn_args (op->args, word, memaddr, info);
+
+ /* Try to disassemble multi-instruction addressing sequences. */
+ if (pd->to_print_addr)
+ {
+ info->target = pd->print_addr;
+ (*info->fprintf_styled_func)
+ (info->stream, dis_style_comment_start, " # ");
+ (*info->print_address_func) (info->target, info);
+ pd->to_print_addr = false;
+ }
+
+ /* Finish filling out insn_info fields. */
+ switch (op->pinfo & INSN_TYPE)
+ {
+ case INSN_BRANCH:
+ info->insn_type = dis_branch;
+ break;
+ case INSN_CONDBRANCH:
+ info->insn_type = dis_condbranch;
+ break;
+ case INSN_JSR:
+ info->insn_type = dis_jsr;
+ break;
+ case INSN_DREF:
+ info->insn_type = dis_dref;
+ break;
+ default:
+ break;
+ }
+
+ if (op->pinfo & INSN_DATA_SIZE)
+ {
+ int size = ((op->pinfo & INSN_DATA_SIZE)
+ >> INSN_DATA_SIZE_SHIFT);
+ info->data_size = 1 << (size - 1);
+ }
+
+ return insnlen;
}
/* We did not find a match, so just print the instruction bits. */
@@ -1120,7 +1102,7 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
disassembler_ftype
riscv_get_disassembler (bfd *abfd)
{
- const char *default_arch = "rv64gc";
+ const char *default_arch = "rv64gcv_zba_zbb_zbs_zicbom_zicboz_zicbop_zihintpause_zvknha_zvknhb_zacas";
if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index dc710921287..1d03e1afc6f 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -154,7 +154,8 @@ const char * const riscv_vma[2] =
static int
match_opcode (const struct riscv_opcode *op, insn_t insn)
{
- return ((insn ^ op->match) & op->mask) == 0;
+ return (insn & op->mask) == op->match;
+ // return ((insn ^ op->match) & op->mask) == 0;
}
static int
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment