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);
}
Beispiel #2
0
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);
}