#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
- if (get_field(state->mstatus, MSTATUS_IE)) {
- 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",
- 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);
- }
+ 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, "%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, "%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;
// 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; \
try
{
- check_timer();
take_interrupt();
if (unlikely(debug))
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);
+ }
}