// fetch/decode/execute loop
void processor_t::step(size_t n)
{
- // TODO: get_interrupt() isn't super fast. Does that matter?
- if (state.dcsr.cause == DCSR_CAUSE_NONE &&
- sim->debug_module.get_interrupt(id)) {
- enter_debug_mode(DCSR_CAUSE_DEBUGINT);
- }
-
- if (state.dcsr.cause != DCSR_CAUSE_NONE) {
- // In Debug Mode, just do 10 steps at a time. Otherwise we're going to be
+ if (state.dcsr.cause == DCSR_CAUSE_NONE) {
+ // TODO: get_interrupt() isn't super fast. Does that matter?
+ if (sim->debug_module.get_interrupt(id)) {
+ enter_debug_mode(DCSR_CAUSE_DEBUGINT);
+ } else if (state.dcsr.halt) {
+ enter_debug_mode(DCSR_CAUSE_HALT);
+ }
+ } else {
+ // In Debug Mode, just do 11 steps at a time. Otherwise we're going to be
// spinning the rest of the time anyway.
- n = std::max(n, (size_t) 10);
+ n = std::min(n, (size_t) 11);
}
while (n > 0) {
{
take_interrupt();
- if (unlikely(debug))
+ // When we might single step, use the slow loop instead of the fast one.
+ if (unlikely(debug || state.single_step != state.STEP_NONE || state.dcsr.cause))
{
while (instret < n)
{
+ if (unlikely(state.single_step == state.STEP_STEPPING)) {
+ state.single_step = state.STEP_STEPPED;
+ } else if (unlikely(state.single_step == state.STEP_STEPPED)) {
+ state.single_step = state.STEP_NONE;
+ enter_debug_mode(DCSR_CAUSE_STEP);
+ // enter_debug_mode changed state.pc, so we can't just continue.
+ break;
+ }
+
insn_fetch_t fetch = mmu->load_insn(pc);
- if (!state.serialized)
+ if (debug && !state.serialized)
disasm(fetch.insn);
pc = execute_insn(this, pc, fetch);
advance_pc();