diff options
author | Andrew Waterman <andrew@sifive.com> | 2021-10-18 18:39:17 -0700 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2021-10-18 18:39:17 -0700 |
commit | 1453b3588bdb6f42767c0c2ee2ffcd70ddf97afa (patch) | |
tree | e29afc0a2c2ec67ba505c0fa428464dd8698e268 /disasm | |
parent | 35cfde167a31f19a93557d7ecb41e18a989f85af (diff) | |
download | riscv-isa-sim-1453b3588bdb6f42767c0c2ee2ffcd70ddf97afa.zip riscv-isa-sim-1453b3588bdb6f42767c0c2ee2ffcd70ddf97afa.tar.gz riscv-isa-sim-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.cc | 27 |
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); } |