aboutsummaryrefslogtreecommitdiff
path: root/disasm/disasm.cc
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2022-05-13 13:58:10 -0700
committerGitHub <noreply@github.com>2022-05-13 13:58:10 -0700
commit78dfe62633ce4fe6e6a70afae04168e1f102b673 (patch)
tree8a62f17aa8f261bc9ac8015cd28257da100727ab /disasm/disasm.cc
parentff645fb4eb9cd8a957dd8826369de8dd7e1fb8a3 (diff)
downloadspike-78dfe62633ce4fe6e6a70afae04168e1f102b673.zip
spike-78dfe62633ce4fe6e6a70afae04168e1f102b673.tar.gz
spike-78dfe62633ce4fe6e6a70afae04168e1f102b673.tar.bz2
Fix disassembly of custom instructions that overlap standard ones (#999)
Iterate over the instruction chains in reverse order, prioritizing the last call to `disassembler_t::add_insn`. To preserve behavior for the standard instructions, reverse the order in which we add instructions in the `disassembler_t` constructor. Supersedes #995.
Diffstat (limited to 'disasm/disasm.cc')
-rw-r--r--disasm/disasm.cc13
1 files changed, 10 insertions, 3 deletions
diff --git a/disasm/disasm.cc b/disasm/disasm.cc
index c8e92d6..7df39da 100644
--- a/disasm/disasm.cc
+++ b/disasm/disasm.cc
@@ -7,6 +7,8 @@
#include <cstdarg>
#include <sstream>
#include <stdlib.h>
+// For std::reverse:
+#include <algorithm>
// Indicates that the next arg (only) is optional.
// If the result of converting the next arg to a string is ""
@@ -2116,13 +2118,18 @@ disassembler_t::disassembler_t(const isa_parser_t *isa)
// finally: instructions with known opcodes but unknown arguments
add_unknown_insns(this);
+
+ // Now, reverse the lists, because we search them back-to-front (so that
+ // custom instructions later added with add_insn have highest priority).
+ for (size_t i = 0; i < HASH_SIZE+1; i++)
+ std::reverse(chain[i].begin(), chain[i].end());
}
const disasm_insn_t* disassembler_t::probe_once(insn_t insn, size_t idx) const
{
- for (size_t j = 0; j < chain[idx].size(); j++)
- if(*chain[idx][j] == insn)
- return chain[idx][j];
+ for (auto it = chain[idx].rbegin(); it != chain[idx].rend(); ++it)
+ if (*(*it) == insn)
+ return *it;
return NULL;
}