1 /* Generic simulator halt/restart. 2 Copyright (C) 1997-2024 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5 This file is part of GDB, the GNU debugger. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 /* This must come before any other includes. */ 21 #include "defs.h" 22 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 27 #include "sim-main.h" 28 #include "sim-assert.h" 29 #include "sim-signal.h" 30 31 /* Get the run state. 32 REASON/SIGRC are the values returned by sim_stop_reason. 33 ??? Should each cpu have its own copy? */ 34 35 void 36 sim_engine_get_run_state (SIM_DESC sd, enum sim_stop *reason, int *sigrc) 37 { 38 sim_engine *engine = STATE_ENGINE (sd); 39 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 40 *reason = engine->reason; 41 *sigrc = engine->sigrc; 42 } 43 44 /* Set the run state to REASON/SIGRC. 45 REASON/SIGRC are the values returned by sim_stop_reason. 46 ??? Should each cpu have its own copy? */ 47 48 void 49 sim_engine_set_run_state (SIM_DESC sd, enum sim_stop reason, int sigrc) 50 { 51 sim_engine *engine = STATE_ENGINE (sd); 52 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 53 engine->reason = reason; 54 engine->sigrc = sigrc; 55 } 56 57 /* Generic halt */ 58 59 void 60 sim_engine_halt (SIM_DESC sd, 61 sim_cpu *last_cpu, 62 sim_cpu *next_cpu, /* NULL - use default */ 63 sim_cia cia, 64 enum sim_stop reason, 65 int sigrc) 66 { 67 sim_engine *engine = STATE_ENGINE (sd); 68 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 69 if (engine->jmpbuf != NULL) 70 { 71 jmp_buf *halt_buf = engine->jmpbuf; 72 engine->last_cpu = last_cpu; 73 engine->next_cpu = next_cpu; 74 engine->reason = reason; 75 engine->sigrc = sigrc; 76 77 SIM_ENGINE_HALT_HOOK (sd, last_cpu, cia); 78 79 #ifdef SIM_CPU_EXCEPTION_SUSPEND 80 if (last_cpu != NULL && reason != sim_exited) 81 SIM_CPU_EXCEPTION_SUSPEND (sd, last_cpu, sim_signal_to_host (sd, sigrc)); 82 #endif 83 84 longjmp (*halt_buf, sim_engine_halt_jmpval); 85 } 86 else 87 { 88 sim_io_error (sd, "sim_halt - bad long jump"); 89 abort (); 90 } 91 } 92 93 94 /* Generic restart */ 95 96 void 97 sim_engine_restart (SIM_DESC sd, 98 sim_cpu *last_cpu, 99 sim_cpu *next_cpu, 100 sim_cia cia) 101 { 102 sim_engine *engine = STATE_ENGINE (sd); 103 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 104 if (engine->jmpbuf != NULL) 105 { 106 jmp_buf *halt_buf = engine->jmpbuf; 107 engine->last_cpu = last_cpu; 108 engine->next_cpu = next_cpu; 109 SIM_ENGINE_RESTART_HOOK (sd, last_cpu, cia); 110 longjmp (*halt_buf, sim_engine_restart_jmpval); 111 } 112 else 113 sim_io_error (sd, "sim_restart - bad long jump"); 114 } 115 116 117 /* Generic error code */ 118 119 void 120 sim_engine_vabort (SIM_DESC sd, 121 sim_cpu *cpu, 122 sim_cia cia, 123 const char *fmt, 124 va_list ap) 125 { 126 ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 127 if (sd == NULL) 128 { 129 vfprintf (stderr, fmt, ap); 130 fprintf (stderr, "\nQuit\n"); 131 abort (); 132 } 133 else if (STATE_ENGINE (sd)->jmpbuf == NULL) 134 { 135 sim_io_evprintf (sd, fmt, ap); 136 sim_io_eprintf (sd, "\n"); 137 sim_io_error (sd, "Quit Simulator"); 138 abort (); 139 } 140 else 141 { 142 sim_io_evprintf (sd, fmt, ap); 143 sim_io_eprintf (sd, "\n"); 144 sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGABRT); 145 } 146 } 147 148 void 149 sim_engine_abort (SIM_DESC sd, 150 sim_cpu *cpu, 151 sim_cia cia, 152 const char *fmt, 153 ...) 154 { 155 va_list ap; 156 ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 157 va_start (ap, fmt); 158 sim_engine_vabort (sd, cpu, cia, fmt, ap); 159 va_end (ap); 160 } 161 162 163 /* Generic next/last cpu */ 164 165 int 166 sim_engine_last_cpu_nr (SIM_DESC sd) 167 { 168 sim_engine *engine = STATE_ENGINE (sd); 169 if (engine->last_cpu != NULL) 170 return engine->last_cpu - STATE_CPU (sd, 0); 171 else 172 return MAX_NR_PROCESSORS; 173 } 174 175 int 176 sim_engine_next_cpu_nr (SIM_DESC sd) 177 { 178 sim_engine *engine = STATE_ENGINE (sd); 179 if (engine->next_cpu != NULL) 180 return engine->next_cpu - STATE_CPU (sd, 0); 181 else 182 return sim_engine_last_cpu_nr (sd) + 1; 183 } 184 185 int 186 sim_engine_nr_cpus (SIM_DESC sd) 187 { 188 sim_engine *engine = STATE_ENGINE (sd); 189 return engine->nr_cpus; 190 } 191 192 193 194 195 /* Initialization */ 196 197 static SIM_RC 198 sim_engine_init (SIM_DESC sd) 199 { 200 /* initialize the start/stop/resume engine */ 201 sim_engine *engine = STATE_ENGINE (sd); 202 engine->jmpbuf = NULL; 203 engine->last_cpu = NULL; 204 engine->next_cpu = NULL; 205 engine->nr_cpus = MAX_NR_PROCESSORS; 206 engine->reason = sim_running; 207 engine->sigrc = 0; 208 engine->stepper = NULL; /* sim_events_init will clean it up */ 209 return SIM_RC_OK; 210 } 211 212 /* Provide a prototype to silence -Wmissing-prototypes. */ 213 SIM_RC sim_install_engine (SIM_DESC sd); 214 215 SIM_RC 216 sim_install_engine (SIM_DESC sd) 217 { 218 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 219 sim_module_add_init_fn (sd, sim_engine_init); 220 return SIM_RC_OK; 221 } 222