| /* Generic simulator halt/restart. | 
 |    Copyright (C) 1997-2024 Free Software Foundation, Inc. | 
 |    Contributed by Cygnus Support. | 
 |  | 
 | This file is part of GDB, the GNU debugger. | 
 |  | 
 | This program is free software; you can redistribute it and/or modify | 
 | it under the terms of the GNU General Public License as published by | 
 | the Free Software Foundation; either version 3 of the License, or | 
 | (at your option) any later version. | 
 |  | 
 | This program is distributed in the hope that it will be useful, | 
 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | GNU General Public License for more details. | 
 |  | 
 | You should have received a copy of the GNU General Public License | 
 | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | /* This must come before any other includes.  */ | 
 | #include "defs.h" | 
 |  | 
 | #include <stdarg.h> | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 |  | 
 | #include "sim-main.h" | 
 | #include "sim-assert.h" | 
 | #include "sim-signal.h" | 
 |  | 
 | /* Get the run state. | 
 |    REASON/SIGRC are the values returned by sim_stop_reason. | 
 |    ??? Should each cpu have its own copy?  */ | 
 |  | 
 | void | 
 | sim_engine_get_run_state (SIM_DESC sd, enum sim_stop *reason, int *sigrc) | 
 | { | 
 |   sim_engine *engine = STATE_ENGINE (sd); | 
 |   ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); | 
 |   *reason = engine->reason; | 
 |   *sigrc = engine->sigrc; | 
 | } | 
 |  | 
 | /* Set the run state to REASON/SIGRC. | 
 |    REASON/SIGRC are the values returned by sim_stop_reason. | 
 |    ??? Should each cpu have its own copy?  */ | 
 |  | 
 | 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; | 
 | } | 
 |  | 
 | /* Generic halt */ | 
 |  | 
 | 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 (); | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | /* Generic restart */ | 
 |  | 
 | 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"); | 
 | } | 
 |  | 
 |  | 
 | /* Generic error code */ | 
 |  | 
 | 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_engine_abort (SIM_DESC sd, | 
 | 		  sim_cpu *cpu, | 
 | 		  sim_cia cia, | 
 | 		  const char *fmt, | 
 | 		  ...) | 
 | { | 
 |   va_list ap; | 
 |   ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); | 
 |   va_start (ap, fmt); | 
 |   sim_engine_vabort (sd, cpu, cia, fmt, ap); | 
 |   va_end (ap); | 
 | } | 
 |  | 
 |  | 
 | /* Generic next/last cpu */ | 
 |  | 
 | 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; | 
 | } | 
 |  | 
 | 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_nr_cpus (SIM_DESC sd) | 
 | { | 
 |   sim_engine *engine = STATE_ENGINE (sd); | 
 |   return engine->nr_cpus; | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 | /* Initialization */ | 
 |  | 
 | 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; | 
 | } | 
 |  | 
 | /* Provide a prototype to silence -Wmissing-prototypes.  */ | 
 | SIM_RC sim_install_engine (SIM_DESC sd); | 
 |  | 
 | SIM_RC | 
 | sim_install_engine (SIM_DESC sd) | 
 | { | 
 |   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); | 
 |   sim_module_add_init_fn (sd, sim_engine_init); | 
 |   return SIM_RC_OK; | 
 | } |