From: Andrew Waterman Date: Wed, 29 Jun 2016 22:00:22 +0000 (-0700) Subject: Disassemble RVC instructions based on XLEN X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=03b8bad375217fbc2143046e8caad9d80301abdb;p=riscv-isa-sim.git Disassemble RVC instructions based on XLEN The interpretation of RVC opcodes depends on XLEN, and the disassembler always assumed RV32. h/t Michael Clark --- diff --git a/riscv/disasm.h b/riscv/disasm.h index a8da066..e2981d4 100644 --- a/riscv/disasm.h +++ b/riscv/disasm.h @@ -60,14 +60,14 @@ class disasm_insn_t class disassembler_t { public: - disassembler_t(); + disassembler_t(int xlen); ~disassembler_t(); - std::string disassemble(insn_t insn); + std::string disassemble(insn_t insn) const; void add_insn(disasm_insn_t* insn); private: static const int HASH_SIZE = 256; std::vector chain[HASH_SIZE+1]; - const disasm_insn_t* lookup(insn_t insn); + const disasm_insn_t* lookup(insn_t insn) const; }; #endif diff --git a/riscv/processor.cc b/riscv/processor.cc index 2a31a44..b7500c4 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -22,16 +22,15 @@ processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id, bool halt_on_reset) - : debug(false), sim(sim), ext(NULL), disassembler(new disassembler_t), - id(id), halt_on_reset(halt_on_reset) + : debug(false), sim(sim), ext(NULL), id(id), halt_on_reset(halt_on_reset) { parse_isa_string(isa); + register_base_instructions(); mmu = new mmu_t(sim, this); + disassembler = new disassembler_t(max_xlen); reset(); - - register_base_instructions(); } processor_t::~processor_t() diff --git a/riscv/processor.h b/riscv/processor.h index 31d5f6c..090ebe7 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -121,6 +121,7 @@ public: void set_privilege(reg_t); void yield_load_reservation() { state.load_reservation = (reg_t)-1; } void update_histogram(reg_t pc); + const disassembler_t* get_disassembler() { return disassembler; } void register_insn(insn_desc_t); void register_extension(extension_t*); diff --git a/spike_main/disasm.cc b/spike_main/disasm.cc index 65977fc..bdbef9c 100644 --- a/spike_main/disasm.cc +++ b/spike_main/disasm.cc @@ -248,13 +248,13 @@ struct : public arg_t { } } rvc_jump_target; -std::string disassembler_t::disassemble(insn_t insn) +std::string disassembler_t::disassemble(insn_t insn) const { const disasm_insn_t* disasm_insn = lookup(insn); return disasm_insn ? disasm_insn->to_string(insn) : "unknown"; } -disassembler_t::disassembler_t() +disassembler_t::disassembler_t(int xlen) { const uint32_t mask_rd = 0x1fUL << 7; const uint32_t match_rd_ra = 1UL << 7; @@ -509,7 +509,6 @@ disassembler_t::disassembler_t() DISASM_INSN("li", c_li, 0, {&xrd, &rvc_imm}); DISASM_INSN("lui", c_lui, 0, {&xrd, &rvc_uimm}); DISASM_INSN("addi", c_addi, 0, {&xrd, &xrd, &rvc_imm}); - DISASM_INSN("addiw", c_addiw, 0, {&xrd, &xrd, &rvc_imm}); DISASM_INSN("slli", c_slli, 0, {&xrd, &rvc_shamt}); DISASM_INSN("mv", c_mv, 0, {&xrd, &rvc_rs2}); DISASM_INSN("add", c_add, 0, {&xrd, &xrd, &rvc_rs2}); @@ -520,17 +519,28 @@ disassembler_t::disassembler_t() DISASM_INSN("or", c_or, 0, {&rvc_rs1s, &rvc_rs1s, &rvc_rs2s}); DISASM_INSN("xor", c_xor, 0, {&rvc_rs1s, &rvc_rs1s, &rvc_rs2s}); DISASM_INSN("lw", c_lwsp, 0, {&xrd, &rvc_lwsp_address}); - DISASM_INSN("flw", c_flwsp, 0, {&xrd, &rvc_lwsp_address}); + DISASM_INSN("fld", c_fld, 0, {&rvc_rs2s, &rvc_ld_address}); DISASM_INSN("sw", c_swsp, 0, {&rvc_rs2, &rvc_swsp_address}); - DISASM_INSN("fsw", c_fswsp, 0, {&rvc_rs2, &rvc_swsp_address}); DISASM_INSN("lw", c_lw, 0, {&rvc_rs2s, &rvc_lw_address}); - DISASM_INSN("flw", c_flw, 0, {&rvc_rs2s, &rvc_lw_address}); DISASM_INSN("sw", c_sw, 0, {&rvc_rs2s, &rvc_lw_address}); - DISASM_INSN("fsw", c_fsw, 0, {&rvc_rs2s, &rvc_lw_address}); DISASM_INSN("beqz", c_beqz, 0, {&rvc_rs1s, &rvc_branch_target}); DISASM_INSN("bnez", c_bnez, 0, {&rvc_rs1s, &rvc_branch_target}); DISASM_INSN("j", c_j, 0, {&rvc_jump_target}); + if (xlen == 32) { + DISASM_INSN("flw", c_flw, 0, {&rvc_rs2s, &rvc_lw_address}); + DISASM_INSN("flw", c_flwsp, 0, {&xrd, &rvc_lwsp_address}); + DISASM_INSN("fsw", c_fsw, 0, {&rvc_rs2s, &rvc_lw_address}); + DISASM_INSN("fsw", c_fswsp, 0, {&rvc_rs2, &rvc_swsp_address}); + DISASM_INSN("jal", c_jal, 0, {&rvc_jump_target}); + } else { + DISASM_INSN("ld", c_ld, 0, {&rvc_rs2s, &rvc_ld_address}); + DISASM_INSN("ld", c_ldsp, 0, {&xrd, &rvc_ldsp_address}); + DISASM_INSN("sd", c_sd, 0, {&rvc_rs2s, &rvc_ld_address}); + DISASM_INSN("sd", c_sdsp, 0, {&rvc_rs2, &rvc_sdsp_address}); + DISASM_INSN("addiw", c_addiw, 0, {&xrd, &xrd, &rvc_imm}); + } + // provide a default disassembly for all instructions as a fallback #define DECLARE_INSN(code, match, mask) \ add_insn(new disasm_insn_t(#code " (args unknown)", match, mask, {})); @@ -538,7 +548,7 @@ disassembler_t::disassembler_t() #undef DECLARE_INSN } -const disasm_insn_t* disassembler_t::lookup(insn_t insn) +const disasm_insn_t* disassembler_t::lookup(insn_t insn) const { size_t idx = insn.bits() % HASH_SIZE; for (size_t j = 0; j < chain[idx].size(); j++) diff --git a/spike_main/spike-dasm.cc b/spike_main/spike-dasm.cc index aecaa0a..2852835 100644 --- a/spike_main/spike-dasm.cc +++ b/spike_main/spike-dasm.cc @@ -17,17 +17,17 @@ using namespace std; int main(int argc, char** argv) { string s; - disassembler_t d; + const char* isa = DEFAULT_ISA; std::function extension; option_parser_t parser; parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); + parser.option(0, "isa", 1, [&](const char* s){isa = s;}); parser.parse(argv); - if (extension) { - for (auto disasm_insn : extension()->get_disasms()) - d.add_insn(disasm_insn); - } + processor_t p(isa, 0, 0); + if (extension) + p.register_extension(extension()); while (getline(cin, s)) { @@ -44,7 +44,7 @@ int main(int argc, char** argv) if (nbits < 64) bits = bits << (64 - nbits) >> (64 - nbits); - string dis = d.disassemble(bits); + string dis = p.get_disassembler()->disassemble(bits); s = s.substr(0, start) + dis + s.substr(end+1); start += dis.length(); }