Flush icache when using swbps and report to gdb.
[riscv-isa-sim.git] / riscv / execute.cc
index f64cbaa268113a6d8f986a3ed24fb5d7fc70bd06..c36cb4ff4aab7542417fa3624de3f2aeaea6eaa3 100644 (file)
@@ -4,37 +4,47 @@
 #include "mmu.h"
 #include <cassert>
 
-static void commit_log(state_t* state, reg_t pc, insn_t insn)
+
+static void commit_log_stash_privilege(state_t* state)
+{
+#ifdef RISCV_ENABLE_COMMITLOG
+  state->last_inst_priv = state->prv;
+#endif
+}
+
+static void commit_log_print_insn(state_t* state, reg_t pc, insn_t insn)
 {
 #ifdef RISCV_ENABLE_COMMITLOG
+  int32_t priv = state->last_inst_priv;
   uint64_t mask = (insn.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn.length() * 8))) - 1;
   if (state->log_reg_write.addr) {
-    fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIu64 " 0x%016" PRIx64 "\n",
+    fprintf(stderr, "%1d 0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIu64 " 0x%016" PRIx64 "\n",
+            priv,
             pc,
             insn.bits() & mask,
             state->log_reg_write.addr & 1 ? 'f' : 'x',
             state->log_reg_write.addr >> 1,
             state->log_reg_write.data);
   } else {
-    fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ")\n", pc, insn.bits() & mask);
+    fprintf(stderr, "%1d 0x%016" PRIx64 " (0x%08" PRIx64 ")\n", priv, pc, insn.bits() & mask);
   }
   state->log_reg_write.addr = 0;
 #endif
 }
 
-inline void processor_t::update_histogram(size_t pc)
+inline void processor_t::update_histogram(reg_t pc)
 {
 #ifdef RISCV_ENABLE_HISTOGRAM
-  size_t idx = pc >> 2;
-  pc_histogram[idx]++;
+  pc_histogram[pc]++;
 #endif
 }
 
 static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
 {
+  commit_log_stash_privilege(p->get_state());
   reg_t npc = fetch.func(p, fetch.insn, pc);
-  if (npc != PC_SERIALIZE) {
-    commit_log(p->get_state(), pc, fetch.insn);
+  if (!invalid_pc(npc)) {
+    commit_log_print_insn(p->get_state(), pc, fetch.insn);
     p->update_histogram(pc);
   }
   return npc;
@@ -43,15 +53,26 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
 // fetch/decode/execute loop
 void processor_t::step(size_t n)
 {
-  while (run && n > 0) {
+  // TODO: We should really not call this function at all when halted, to avoid
+  // burning CPU.
+  if (single_step) {
+    set_halted(false, HR_NONE);
+    n = 1;
+  }
+
+  while (run && !halted && n > 0) {
     size_t instret = 0;
     reg_t pc = state.pc;
     mmu_t* _mmu = mmu;
 
     #define advance_pc() \
-     if (unlikely(pc == PC_SERIALIZE)) { \
+     if (unlikely(invalid_pc(pc))) { \
+       switch (pc) { \
+         case PC_SERIALIZE_BEFORE: state.serialized = true; break; \
+         case PC_SERIALIZE_AFTER: instret++; break; \
+         default: abort(); \
+       } \
        pc = state.pc; \
-       state.serialized = true; \
        break; \
      } else { \
        state.pc = pc; \
@@ -60,7 +81,6 @@ void processor_t::step(size_t n)
 
     try
     {
-      check_timer();
       take_interrupt();
 
       if (unlikely(debug))
@@ -107,9 +127,15 @@ miss:
     catch(trap_t& t)
     {
       take_trap(t, pc);
+      n = instret;
     }
 
     state.minstret += instret;
     n -= instret;
   }
+
+  if (single_step) {
+    single_step = false;
+    set_halted(true, HR_STEPPED);
+  }
 }