aboutsummaryrefslogtreecommitdiff
path: root/disasm
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2021-10-18 18:39:17 -0700
committerAndrew Waterman <andrew@sifive.com>2021-10-18 18:39:17 -0700
commit1453b3588bdb6f42767c0c2ee2ffcd70ddf97afa (patch)
treee29afc0a2c2ec67ba505c0fa428464dd8698e268 /disasm
parent35cfde167a31f19a93557d7ecb41e18a989f85af (diff)
downloadspike-1453b3588bdb6f42767c0c2ee2ffcd70ddf97afa.zip
spike-1453b3588bdb6f42767c0c2ee2ffcd70ddf97afa.tar.gz
spike-1453b3588bdb6f42767c0c2ee2ffcd70ddf97afa.tar.bz2
Speed up disassembler_t::lookup
Optimize the hash functions for RISC-V instruction encodings. This is only a perf optimization; instructions that don't adhere to RISC-V standard practice will still disassemble correctly, just more slowly.
Diffstat (limited to 'disasm')
-rw-r--r--disasm/disasm.cc27
1 files changed, 17 insertions, 10 deletions
diff --git a/disasm/disasm.cc b/disasm/disasm.cc
index 1a7a092..e441f99 100644
--- a/disasm/disasm.cc
+++ b/disasm/disasm.cc
@@ -1826,14 +1826,8 @@ disassembler_t::disassembler_t(int xlen)
add_unknown_insns(this);
}
-const disasm_insn_t* disassembler_t::lookup(insn_t insn) const
+const disasm_insn_t* disassembler_t::probe_once(insn_t insn, size_t idx) const
{
- size_t idx = insn.bits() % HASH_SIZE;
- for (size_t j = 0; j < chain[idx].size(); j++)
- if(*chain[idx][j] == insn)
- return chain[idx][j];
-
- idx = HASH_SIZE;
for (size_t j = 0; j < chain[idx].size(); j++)
if(*chain[idx][j] == insn)
return chain[idx][j];
@@ -1841,11 +1835,24 @@ const disasm_insn_t* disassembler_t::lookup(insn_t insn) const
return NULL;
}
+const disasm_insn_t* disassembler_t::lookup(insn_t insn) const
+{
+ if (auto p = probe_once(insn, hash(insn.bits(), MASK1)))
+ return p;
+
+ if (auto p = probe_once(insn, hash(insn.bits(), MASK2)))
+ return p;
+
+ return probe_once(insn, HASH_SIZE);
+}
+
void NOINLINE disassembler_t::add_insn(disasm_insn_t* insn)
{
- size_t idx = HASH_SIZE;
- if (insn->get_mask() % HASH_SIZE == HASH_SIZE - 1)
- idx = insn->get_match() % HASH_SIZE;
+ size_t idx =
+ (insn->get_mask() & MASK1) == MASK1 ? hash(insn->get_match(), MASK1) :
+ (insn->get_mask() & MASK2) == MASK2 ? hash(insn->get_match(), MASK2) :
+ HASH_SIZE;
+
chain[idx].push_back(insn);
}