void sim_engine_vabort (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, const char *fmt, va_list ap) { ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); if (sd == NULL) { vfprintf (stderr, fmt, ap); fprintf (stderr, "\nQuit\n"); abort (); } else if (STATE_ENGINE (sd)->jmpbuf == NULL) { sim_io_evprintf (sd, fmt, ap); sim_io_eprintf (sd, "\n"); sim_io_error (sd, "Quit Simulator"); abort (); } else { sim_io_evprintf (sd, fmt, ap); sim_io_eprintf (sd, "\n"); sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGABRT); } }
void sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc) { sim_engine *engine = NULL; SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); engine = STATE_ENGINE (sd); *reason = engine->reason; switch (*reason) { case sim_exited : *sigrc = engine->sigrc; break; case sim_signalled : /* ??? See the comment below case `sim_signalled' in gdb/remote-sim.c:gdbsim_wait. ??? Consider the case of the target requesting that it kill(2) itself with SIGNAL. That SIGNAL, being target specific, will not correspond to either of the SIM_SIGNAL enum nor the HOST_SIGNAL. A mapping from TARGET_SIGNAL to HOST_SIGNAL is needed. */ *sigrc = sim_signal_to_host (sd, engine->sigrc); break; case sim_stopped : /* The gdb/simulator interface calls for us to return the host version of the signal which gdb then converts into the target's version. This is obviously a bit clumsy. */ *sigrc = sim_signal_to_host (sd, engine->sigrc); break; default : abort (); } }
void sim_engine_halt (SIM_DESC sd, sim_cpu *last_cpu, sim_cpu *next_cpu, /* NULL - use default */ sim_cia cia, enum sim_stop reason, int sigrc) { sim_engine *engine = STATE_ENGINE (sd); ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); if (engine->jmpbuf != NULL) { jmp_buf *halt_buf = engine->jmpbuf; engine->last_cpu = last_cpu; engine->next_cpu = next_cpu; engine->reason = reason; engine->sigrc = sigrc; SIM_ENGINE_HALT_HOOK (sd, last_cpu, cia); #ifdef SIM_CPU_EXCEPTION_SUSPEND if (last_cpu != NULL && reason != sim_exited) SIM_CPU_EXCEPTION_SUSPEND (sd, last_cpu, sim_signal_to_host (sd, sigrc)); #endif longjmp (*halt_buf, sim_engine_halt_jmpval); } else { sim_io_error (sd, "sim_halt - bad long jump"); abort (); } }
void sim_resume (SIM_DESC sd, int step, int siggnal) { sim_engine *engine = STATE_ENGINE (sd); jmp_buf buf; int jmpval; ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); /* we only want to be single stepping the simulator once */ if (engine->stepper != NULL) { sim_events_deschedule (sd, engine->stepper); engine->stepper = NULL; } if (step) engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd); sim_module_resume (sd); /* run/resume the simulator */ engine->jmpbuf = &buf; jmpval = setjmp (buf); if (jmpval == sim_engine_start_jmpval || jmpval == sim_engine_restart_jmpval) { int last_cpu_nr = sim_engine_last_cpu_nr (sd); int next_cpu_nr = sim_engine_next_cpu_nr (sd); int nr_cpus = sim_engine_nr_cpus (sd); int sig_to_deliver; sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus); if (next_cpu_nr >= nr_cpus) next_cpu_nr = 0; /* Only deliver the SIGGNAL [sic] the first time through - don't re-deliver any SIGGNAL during a restart. NOTE: A new local variable is used to avoid problems with the automatic variable ``siggnal'' being trashed by a long jump. */ if (jmpval == sim_engine_start_jmpval) sig_to_deliver = siggnal; else sig_to_deliver = 0; #ifdef SIM_CPU_EXCEPTION_RESUME { sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr); SIM_CPU_EXCEPTION_RESUME(sd, cpu, sig_to_deliver); } #endif sim_engine_run (sd, next_cpu_nr, nr_cpus, sig_to_deliver); } engine->jmpbuf = NULL; sim_module_suspend (sd); }
void sim_engine_set_run_state (SIM_DESC sd, enum sim_stop reason, int sigrc) { sim_engine *engine = STATE_ENGINE (sd); ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); engine->reason = reason; engine->sigrc = sigrc; }
int sim_engine_next_cpu_nr (SIM_DESC sd) { sim_engine *engine = STATE_ENGINE (sd); if (engine->next_cpu != NULL) return engine->next_cpu - STATE_CPU (sd, 0); else return sim_engine_last_cpu_nr (sd) + 1; }
int sim_engine_last_cpu_nr (SIM_DESC sd) { sim_engine *engine = STATE_ENGINE (sd); if (engine->last_cpu != NULL) return engine->last_cpu - STATE_CPU (sd, 0); else return MAX_NR_PROCESSORS; }
static SIM_RC sim_engine_init (SIM_DESC sd) { /* initialize the start/stop/resume engine */ sim_engine *engine = STATE_ENGINE (sd); engine->jmpbuf = NULL; engine->last_cpu = NULL; engine->next_cpu = NULL; engine->nr_cpus = MAX_NR_PROCESSORS; engine->reason = sim_running; engine->sigrc = 0; engine->stepper = NULL; /* sim_events_init will clean it up */ return SIM_RC_OK; }
void sim_engine_restart (SIM_DESC sd, sim_cpu *last_cpu, sim_cpu *next_cpu, sim_cia cia) { sim_engine *engine = STATE_ENGINE (sd); ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); if (engine->jmpbuf != NULL) { jmp_buf *halt_buf = engine->jmpbuf; engine->last_cpu = last_cpu; engine->next_cpu = next_cpu; SIM_ENGINE_RESTART_HOOK (sd, last_cpu, cia); longjmp (*halt_buf, sim_engine_restart_jmpval); } else sim_io_error (sd, "sim_restart - bad long jump"); }
void sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc) { sim_engine *engine = NULL; SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); engine = STATE_ENGINE (sd); *reason = engine->reason; switch (*reason) { case sim_exited : *sigrc = engine->sigrc; break; case sim_stopped : case sim_signalled : *sigrc = sim_signal_to_gdb_signal (sd, engine->sigrc); break; default : abort (); } }
int sim_engine_nr_cpus (SIM_DESC sd) { sim_engine *engine = STATE_ENGINE (sd); return engine->nr_cpus; }
void sim_resume (SIM_DESC sd, int step, int siggnal) { sim_engine *engine = STATE_ENGINE (sd); jmp_buf buf; int jmpval; ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); /* we only want to be single stepping the simulator once */ if (engine->stepper != NULL) { sim_events_deschedule (sd, engine->stepper); engine->stepper = NULL; } if (step) engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd); sim_module_resume (sd); #if WITH_SCACHE if (USING_SCACHE_P (sd)) scache_flush (sd); #endif /* run/resume the simulator */ sim_engine_set_run_state (sd, sim_running, 0); engine->jmpbuf = &buf; jmpval = setjmp (buf); if (jmpval == sim_engine_start_jmpval || jmpval == sim_engine_restart_jmpval) { int last_cpu_nr = sim_engine_last_cpu_nr (sd); int next_cpu_nr = sim_engine_next_cpu_nr (sd); int nr_cpus = sim_engine_nr_cpus (sd); /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is useful if all one wants to do is run a benchmark. Need some better way to identify this case. */ int max_insns = (step ? 1 : (nr_cpus == 1 /*&& wip:no-events*/ /* Don't do this if running under gdb, need to poll ui for events. */ && STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) ? 0 : 8); /*FIXME: magic number*/ int fast_p = STATE_RUN_FAST_P (sd); sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus); if (next_cpu_nr >= nr_cpus) next_cpu_nr = 0; if (nr_cpus == 1) engine_run_1 (sd, max_insns, fast_p); else engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p); } #if 1 /*wip*/ else { /* Account for the last insn executed. */ SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd)); ++ CPU_INSN_COUNT (cpu); CGEN_TRACE_INSN_FINI (cpu, NULL, 1); } #endif engine->jmpbuf = NULL; { int i; int nr_cpus = sim_engine_nr_cpus (sd); #if 0 /*wip,ignore*/ /* If the loop exits, either we single-stepped or @cpu@_engine_stop was called. */ if (step) sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP); else sim_engine_set_run_state (sd, pending_reason, pending_sigrc); #endif for (i = 0; i < nr_cpus; ++i) { SIM_CPU *cpu = STATE_CPU (sd, i); PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu); } } sim_module_suspend (sd); }
void sim_resume (SIM_DESC sd, int step, int siggnal) { sim_engine *engine = STATE_ENGINE (sd); jmp_buf buf; int jmpval; ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); /* we only want to be single stepping the simulator once */ if (engine->stepper != NULL) { sim_events_deschedule (sd, engine->stepper); engine->stepper = NULL; } sim_module_resume (sd); /* run/resume the simulator */ engine->jmpbuf = &buf; jmpval = setjmp (buf); if (jmpval == sim_engine_start_jmpval || jmpval == sim_engine_restart_jmpval) { int last_cpu_nr = sim_engine_last_cpu_nr (sd); int next_cpu_nr = sim_engine_next_cpu_nr (sd); int nr_cpus = sim_engine_nr_cpus (sd); sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus); if (next_cpu_nr >= nr_cpus) next_cpu_nr = 0; /* Only deliver the siggnal ]sic] the first time through - don't re-deliver any siggnal during a restart. */ if (jmpval == sim_engine_restart_jmpval) siggnal = 0; /* Install the stepping event after having processed some pending events. This is necessary for HC11/HC12 simulator because the tick counter is incremented by the number of cycles the instruction took. Some pending ticks to process can still be recorded internally by the simulator and sim_events_preprocess will handle them. If the stepping event is inserted before, these pending ticks will raise the event and the simulator will stop without having executed any instruction. */ if (step) engine->stepper = sim_events_schedule (sd, 0, has_stepped, sd); #ifdef SIM_CPU_EXCEPTION_RESUME { sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr); SIM_CPU_EXCEPTION_RESUME(sd, cpu, siggnal); } #endif sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal); } engine->jmpbuf = NULL; sim_module_suspend (sd); }