processor_t::~processor_t()
{
+ delete disassembler;
}
void state_t::reset()
throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i);
}
+static void commit_log(state_t* state, insn_t insn)
+{
+#ifdef RISCV_ENABLE_COMMITLOG
+ if (!(state->sr & SR_S))
+ fprintf(stderr, "\n0x%016" PRIx64 " (0x%08" PRIx32 ") ", state->pc, insn.bits());
+#endif
+}
+
void processor_t::step(size_t n)
{
if(!run)
{
take_interrupt();
- // execute_insn fetches and executes one instruction
- #define execute_insn(noisy) \
- do { \
- insn_fetch_t fetch = mmu->load_insn(state.pc); \
- if(noisy) disasm(fetch.insn.insn); \
- state.pc = fetch.func(this, fetch.insn.insn, state.pc); \
- } while(0)
-
-
- // special execute_insn for commit log dumping
-#ifdef RISCV_ENABLE_COMMITLOG
- //static disassembler disasmblr;
- #undef execute_insn
- #define execute_insn(noisy) \
- do { \
- insn_fetch_t fetch = _mmu->load_insn(state.pc); \
- if(noisy) disasm(fetch.insn.insn); \
- bool in_spvr = state.sr & SR_S; \
- if (!in_spvr) fprintf(stderr, "\n0x%016" PRIx64 " (0x%08" PRIx32 ") ", state.pc, fetch.insn.insn.bits()); \
- /*if (!in_spvr) fprintf(stderr, "\n0x%016" PRIx64 " (0x%08" PRIx32 ") %s ", state.pc, fetch.insn.insn.bits(), disasmblr.disassemble(fetch.insn.insn).c_str());*/ \
- state.pc = fetch.func(this, fetch.insn.insn, state.pc); \
- } while(0)
-#endif
-
if (debug) // print out instructions as we go
{
for (size_t i = 0; i < n; state.count++, i++)
- execute_insn(true);
+ {
+ insn_fetch_t fetch = mmu->load_insn(state.pc);
+ disasm(fetch.insn.insn);
+ commit_log(&state, fetch.insn.insn);
+ state.pc = fetch.func(this, fetch.insn.insn, state.pc);
+ }
}
else while (n > 0)
{
size_t idx = (state.pc / sizeof(insn_t)) % ICACHE_SIZE;
- auto ic_entry_init = &_mmu->icache[idx], ic_entry = ic_entry_init;
-
- #define update_count() { \
- size_t i = ic_entry - ic_entry_init; \
- state.count += i; \
- if (i >= n) break; \
- n -= i; }
+ auto ic_entry = _mmu->access_icache(state.pc), ic_entry_init = ic_entry;
#define ICACHE_ACCESS(idx) { \
insn_t insn = ic_entry->data.insn.insn; \
insn_func_t func = ic_entry->data.func; \
- if (unlikely(ic_entry->tag != state.pc)) break; \
+ commit_log(&state, insn); \
ic_entry++; \
- state.pc = func(this, insn, state.pc); }
+ state.pc = func(this, insn, state.pc); \
+ if (idx < ICACHE_SIZE-1 && unlikely(ic_entry->tag != state.pc)) break; \
+ }
- switch (idx) while (true)
+ switch (idx)
{
- ICACHE_SWITCH;
- update_count();
- ic_entry_init = ic_entry = &_mmu->icache[0];
+ ICACHE_SWITCH; // auto-generated into icache.h
}
- _mmu->access_icache(state.pc);
- update_count();
+ size_t i = ic_entry - ic_entry_init;
+ state.count += i;
+ if (i >= n)
+ break;
+ n -= i;
}
}
catch(trap_t& t)
case CSR_EVEC:
state.evec = val & ~3;
break;
- case CSR_CYCLE:
- case CSR_TIME:
- case CSR_INSTRET:
case CSR_COUNT:
state.count = val;
break;
+ case CSR_COUNTH:
+ state.count = (val << 32) | (uint32_t)state.count;
+ break;
case CSR_COMPARE:
set_interrupt(IRQ_TIMER, false);
state.compare = val;
case CSR_INSTRET:
case CSR_COUNT:
return state.count;
+ case CSR_CYCLEH:
+ case CSR_TIMEH:
+ case CSR_INSTRETH:
+ case CSR_COUNTH:
+ if (rv64)
+ break;
+ return state.count >> 32;
case CSR_COMPARE:
return state.compare;
case CSR_CAUSE:
case CSR_FROMHOST:
sim->get_htif()->tick(); // not necessary, but faster
return state.fromhost;
- default:
- throw trap_illegal_instruction();
}
+ throw trap_illegal_instruction();
}
void processor_t::set_interrupt(int which, bool on)