|  | /* Generic simulator halt/restart. | 
|  | Copyright (C) 1997-2022 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; | 
|  | } |