14e98e3e1Schristos /* Generic simulator halt/restart. 2*88241920Schristos Copyright (C) 1997-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Contributed by Cygnus Support. 44e98e3e1Schristos 54e98e3e1Schristos This file is part of GDB, the GNU debugger. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224e98e3e1Schristos 234b169a6bSchristos #include <stdarg.h> 248dffb485Schristos #include <stdio.h> 258dffb485Schristos #include <stdlib.h> 268dffb485Schristos 274b169a6bSchristos #include "sim-main.h" 284b169a6bSchristos #include "sim-assert.h" 294b169a6bSchristos #include "sim-signal.h" 304b169a6bSchristos 314e98e3e1Schristos /* Get the run state. 324e98e3e1Schristos REASON/SIGRC are the values returned by sim_stop_reason. 334e98e3e1Schristos ??? Should each cpu have its own copy? */ 344e98e3e1Schristos 354e98e3e1Schristos void 364e98e3e1Schristos sim_engine_get_run_state (SIM_DESC sd, enum sim_stop *reason, int *sigrc) 374e98e3e1Schristos { 384e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 394e98e3e1Schristos ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 404e98e3e1Schristos *reason = engine->reason; 414e98e3e1Schristos *sigrc = engine->sigrc; 424e98e3e1Schristos } 434e98e3e1Schristos 444e98e3e1Schristos /* Set the run state to REASON/SIGRC. 454e98e3e1Schristos REASON/SIGRC are the values returned by sim_stop_reason. 464e98e3e1Schristos ??? Should each cpu have its own copy? */ 474e98e3e1Schristos 484e98e3e1Schristos void 494e98e3e1Schristos sim_engine_set_run_state (SIM_DESC sd, enum sim_stop reason, int sigrc) 504e98e3e1Schristos { 514e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 524e98e3e1Schristos ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 534e98e3e1Schristos engine->reason = reason; 544e98e3e1Schristos engine->sigrc = sigrc; 554e98e3e1Schristos } 564e98e3e1Schristos 574e98e3e1Schristos /* Generic halt */ 584e98e3e1Schristos 594e98e3e1Schristos void 604e98e3e1Schristos sim_engine_halt (SIM_DESC sd, 614e98e3e1Schristos sim_cpu *last_cpu, 624e98e3e1Schristos sim_cpu *next_cpu, /* NULL - use default */ 634e98e3e1Schristos sim_cia cia, 644e98e3e1Schristos enum sim_stop reason, 654e98e3e1Schristos int sigrc) 664e98e3e1Schristos { 674e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 684e98e3e1Schristos ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 694e98e3e1Schristos if (engine->jmpbuf != NULL) 704e98e3e1Schristos { 714e98e3e1Schristos jmp_buf *halt_buf = engine->jmpbuf; 724e98e3e1Schristos engine->last_cpu = last_cpu; 734e98e3e1Schristos engine->next_cpu = next_cpu; 744e98e3e1Schristos engine->reason = reason; 754e98e3e1Schristos engine->sigrc = sigrc; 764e98e3e1Schristos 774e98e3e1Schristos SIM_ENGINE_HALT_HOOK (sd, last_cpu, cia); 784e98e3e1Schristos 794e98e3e1Schristos #ifdef SIM_CPU_EXCEPTION_SUSPEND 804e98e3e1Schristos if (last_cpu != NULL && reason != sim_exited) 814e98e3e1Schristos SIM_CPU_EXCEPTION_SUSPEND (sd, last_cpu, sim_signal_to_host (sd, sigrc)); 824e98e3e1Schristos #endif 834e98e3e1Schristos 844e98e3e1Schristos longjmp (*halt_buf, sim_engine_halt_jmpval); 854e98e3e1Schristos } 864e98e3e1Schristos else 874e98e3e1Schristos { 884e98e3e1Schristos sim_io_error (sd, "sim_halt - bad long jump"); 894e98e3e1Schristos abort (); 904e98e3e1Schristos } 914e98e3e1Schristos } 924e98e3e1Schristos 934e98e3e1Schristos 944e98e3e1Schristos /* Generic restart */ 954e98e3e1Schristos 964e98e3e1Schristos void 974e98e3e1Schristos sim_engine_restart (SIM_DESC sd, 984e98e3e1Schristos sim_cpu *last_cpu, 994e98e3e1Schristos sim_cpu *next_cpu, 1004e98e3e1Schristos sim_cia cia) 1014e98e3e1Schristos { 1024e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 1034e98e3e1Schristos ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1044e98e3e1Schristos if (engine->jmpbuf != NULL) 1054e98e3e1Schristos { 1064e98e3e1Schristos jmp_buf *halt_buf = engine->jmpbuf; 1074e98e3e1Schristos engine->last_cpu = last_cpu; 1084e98e3e1Schristos engine->next_cpu = next_cpu; 1094e98e3e1Schristos SIM_ENGINE_RESTART_HOOK (sd, last_cpu, cia); 1104e98e3e1Schristos longjmp (*halt_buf, sim_engine_restart_jmpval); 1114e98e3e1Schristos } 1124e98e3e1Schristos else 1134e98e3e1Schristos sim_io_error (sd, "sim_restart - bad long jump"); 1144e98e3e1Schristos } 1154e98e3e1Schristos 1164e98e3e1Schristos 1174e98e3e1Schristos /* Generic error code */ 1184e98e3e1Schristos 1194e98e3e1Schristos void 1204e98e3e1Schristos sim_engine_vabort (SIM_DESC sd, 1214e98e3e1Schristos sim_cpu *cpu, 1224e98e3e1Schristos sim_cia cia, 1234e98e3e1Schristos const char *fmt, 1244e98e3e1Schristos va_list ap) 1254e98e3e1Schristos { 1264e98e3e1Schristos ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1274e98e3e1Schristos if (sd == NULL) 1284e98e3e1Schristos { 1294e98e3e1Schristos vfprintf (stderr, fmt, ap); 1304e98e3e1Schristos fprintf (stderr, "\nQuit\n"); 1314e98e3e1Schristos abort (); 1324e98e3e1Schristos } 1334e98e3e1Schristos else if (STATE_ENGINE (sd)->jmpbuf == NULL) 1344e98e3e1Schristos { 1354e98e3e1Schristos sim_io_evprintf (sd, fmt, ap); 1364e98e3e1Schristos sim_io_eprintf (sd, "\n"); 1374e98e3e1Schristos sim_io_error (sd, "Quit Simulator"); 1384e98e3e1Schristos abort (); 1394e98e3e1Schristos } 1404e98e3e1Schristos else 1414e98e3e1Schristos { 1424e98e3e1Schristos sim_io_evprintf (sd, fmt, ap); 1434e98e3e1Schristos sim_io_eprintf (sd, "\n"); 1444e98e3e1Schristos sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGABRT); 1454e98e3e1Schristos } 1464e98e3e1Schristos } 1474e98e3e1Schristos 1484e98e3e1Schristos void 1494e98e3e1Schristos sim_engine_abort (SIM_DESC sd, 1504e98e3e1Schristos sim_cpu *cpu, 1514e98e3e1Schristos sim_cia cia, 1524e98e3e1Schristos const char *fmt, 1534e98e3e1Schristos ...) 1544e98e3e1Schristos { 1554e98e3e1Schristos va_list ap; 1564e98e3e1Schristos ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1574e98e3e1Schristos va_start (ap, fmt); 1584e98e3e1Schristos sim_engine_vabort (sd, cpu, cia, fmt, ap); 1594e98e3e1Schristos va_end (ap); 1604e98e3e1Schristos } 1614e98e3e1Schristos 1624e98e3e1Schristos 1634e98e3e1Schristos /* Generic next/last cpu */ 1644e98e3e1Schristos 1654e98e3e1Schristos int 1664e98e3e1Schristos sim_engine_last_cpu_nr (SIM_DESC sd) 1674e98e3e1Schristos { 1684e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 1694e98e3e1Schristos if (engine->last_cpu != NULL) 1704e98e3e1Schristos return engine->last_cpu - STATE_CPU (sd, 0); 1714e98e3e1Schristos else 1724e98e3e1Schristos return MAX_NR_PROCESSORS; 1734e98e3e1Schristos } 1744e98e3e1Schristos 1754e98e3e1Schristos int 1764e98e3e1Schristos sim_engine_next_cpu_nr (SIM_DESC sd) 1774e98e3e1Schristos { 1784e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 1794e98e3e1Schristos if (engine->next_cpu != NULL) 1804e98e3e1Schristos return engine->next_cpu - STATE_CPU (sd, 0); 1814e98e3e1Schristos else 1824e98e3e1Schristos return sim_engine_last_cpu_nr (sd) + 1; 1834e98e3e1Schristos } 1844e98e3e1Schristos 1854e98e3e1Schristos int 1864e98e3e1Schristos sim_engine_nr_cpus (SIM_DESC sd) 1874e98e3e1Schristos { 1884e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 1894e98e3e1Schristos return engine->nr_cpus; 1904e98e3e1Schristos } 1914e98e3e1Schristos 1924e98e3e1Schristos 1934e98e3e1Schristos 1944e98e3e1Schristos 1954e98e3e1Schristos /* Initialization */ 1964e98e3e1Schristos 1974e98e3e1Schristos static SIM_RC 1984e98e3e1Schristos sim_engine_init (SIM_DESC sd) 1994e98e3e1Schristos { 2004e98e3e1Schristos /* initialize the start/stop/resume engine */ 2014e98e3e1Schristos sim_engine *engine = STATE_ENGINE (sd); 2024e98e3e1Schristos engine->jmpbuf = NULL; 2034e98e3e1Schristos engine->last_cpu = NULL; 2044e98e3e1Schristos engine->next_cpu = NULL; 2054e98e3e1Schristos engine->nr_cpus = MAX_NR_PROCESSORS; 2064e98e3e1Schristos engine->reason = sim_running; 2074e98e3e1Schristos engine->sigrc = 0; 2084e98e3e1Schristos engine->stepper = NULL; /* sim_events_init will clean it up */ 2094e98e3e1Schristos return SIM_RC_OK; 2104e98e3e1Schristos } 2114e98e3e1Schristos 2124b169a6bSchristos /* Provide a prototype to silence -Wmissing-prototypes. */ 2134b169a6bSchristos SIM_RC sim_install_engine (SIM_DESC sd); 2144e98e3e1Schristos 2154e98e3e1Schristos SIM_RC 2164b169a6bSchristos sim_install_engine (SIM_DESC sd) 2174e98e3e1Schristos { 2184e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 2194e98e3e1Schristos sim_module_add_init_fn (sd, sim_engine_init); 2204e98e3e1Schristos return SIM_RC_OK; 2214e98e3e1Schristos } 222