Disassemble RVC instructions based on XLEN
authorAndrew Waterman <waterman@cs.berkeley.edu>
Wed, 29 Jun 2016 22:00:22 +0000 (15:00 -0700)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Wed, 29 Jun 2016 22:02:12 +0000 (15:02 -0700)
The interpretation of RVC opcodes depends on XLEN, and the disassembler
always assumed RV32.

h/t Michael Clark

riscv/disasm.h
riscv/processor.cc
riscv/processor.h
spike_main/disasm.cc
spike_main/spike-dasm.cc

index a8da066feb6e11d32f3021ed9e8fed691316193e..e2981d4a75ef0b2c506e9ba30e118a79a5ad42c9 100644 (file)
@@ -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<const disasm_insn_t*> chain[HASH_SIZE+1];
-  const disasm_insn_t* lookup(insn_t insn);
+  const disasm_insn_t* lookup(insn_t insn) const;
 };
 
 #endif
index 2a31a447d394000762d2587cb8a737d7670fe543..b7500c46bbcf4153977d1e7daf7a72bcaf9bded7 100644 (file)
 
 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()
index 31d5f6ca7dd442ef3005e04a4832823bdfbbcf77..090ebe7a155a9157f2cc6c8e0d112d05f120acfc 100644 (file)
@@ -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*);
index 65977fc681144eb4bd933364c299b907ededb416..bdbef9cef869759a563c7e72b1d41fcbb31d6977 100644 (file)
@@ -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++)
index aecaa0a05ec3c3c13cf174572fe8be3c38949414..2852835a6dca5ee9947dda96a2b91b4b84a40f06 100644 (file)
@@ -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_t*()> 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();
     }