1 /* Main simulator loop for CGEN-based simulators.
2 Copyright (C) 1998-2015 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
5 This file is part of GDB, the GNU debugger.
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.
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.
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/>. */
20 /* ??? These are old notes, kept around for now.
21 Collecting profile data and tracing slow us down so we don't do them in
23 There are 6 possibilities on 2 axes:
24 - no-scaching, insn-scaching, basic-block-scaching
25 - run with full features or run fast
26 Supporting all six possibilities in one executable is a bit much but
27 supporting full/fast seems reasonable.
28 If the scache is configured in it is always used.
29 If pbb-scaching is configured in it is always used.
30 ??? Sometimes supporting more than one set of semantic functions will make
31 the simulator too large - this should be configurable. Blah blah blah.
32 ??? Supporting full/fast can be more modular, blah blah blah.
33 When the framework is more modular, this can be.
37 #include "sim-assert.h"
39 #ifndef SIM_ENGINE_PREFIX_HOOK
40 #define SIM_ENGINE_PREFIX_HOOK(sd)
42 #ifndef SIM_ENGINE_POSTFIX_HOOK
43 #define SIM_ENGINE_POSTFIX_HOOK(sd)
46 static sim_event_handler has_stepped;
47 static void prime_cpu (SIM_CPU *, int);
48 static void engine_run_1 (SIM_DESC, int, int);
49 static void engine_run_n (SIM_DESC, int, int, int, int);
51 /* sim_resume for cgen */
54 sim_resume (SIM_DESC sd, int step, int siggnal)
56 sim_engine *engine = STATE_ENGINE (sd);
60 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
62 /* we only want to be single stepping the simulator once */
63 if (engine->stepper != NULL)
65 sim_events_deschedule (sd, engine->stepper);
66 engine->stepper = NULL;
69 engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);
71 sim_module_resume (sd);
74 if (USING_SCACHE_P (sd))
78 /* run/resume the simulator */
80 sim_engine_set_run_state (sd, sim_running, 0);
82 engine->jmpbuf = &buf;
83 jmpval = setjmp (buf);
84 if (jmpval == sim_engine_start_jmpval
85 || jmpval == sim_engine_restart_jmpval)
87 int last_cpu_nr = sim_engine_last_cpu_nr (sd);
88 int next_cpu_nr = sim_engine_next_cpu_nr (sd);
89 int nr_cpus = sim_engine_nr_cpus (sd);
90 /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is
91 useful if all one wants to do is run a benchmark. Need some better
92 way to identify this case. */
97 /* Don't do this if running under gdb, need to
98 poll ui for events. */
99 && STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
101 : 8); /*FIXME: magic number*/
102 int fast_p = STATE_RUN_FAST_P (sd);
104 sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
105 if (next_cpu_nr >= nr_cpus)
108 engine_run_1 (sd, max_insns, fast_p);
110 engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p);
115 /* Account for the last insn executed. */
116 SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd));
117 ++ CPU_INSN_COUNT (cpu);
118 CGEN_TRACE_INSN_FINI (cpu, NULL, 1);
122 engine->jmpbuf = NULL;
126 int nr_cpus = sim_engine_nr_cpus (sd);
129 /* If the loop exits, either we single-stepped or @cpu@_engine_stop
132 sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
134 sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
137 for (i = 0; i < nr_cpus; ++i)
139 SIM_CPU *cpu = STATE_CPU (sd, i);
141 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu);
145 sim_module_suspend (sd);
148 /* Halt the simulator after just one instruction. */
151 has_stepped (SIM_DESC sd, void *data)
153 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
154 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
157 /* Prepare a cpu for running.
158 MAX_INSNS is the number of insns to execute per time slice.
159 If 0 it means the cpu can run as long as it wants (e.g. until the
161 ??? Perhaps this should be an argument to the engine_fn. */
164 prime_cpu (SIM_CPU *cpu, int max_insns)
166 CPU_MAX_SLICE_INSNS (cpu) = max_insns;
167 CPU_INSN_COUNT (cpu) = 0;
169 /* Initialize the insn descriptor table.
170 This has to be done after all initialization so we just defer it to
173 if (MACH_PREPARE_RUN (CPU_MACH (cpu)))
174 (* MACH_PREPARE_RUN (CPU_MACH (cpu))) (cpu);
177 /* Main loop, for 1 cpu. */
180 engine_run_1 (SIM_DESC sd, int max_insns, int fast_p)
182 sim_cpu *cpu = STATE_CPU (sd, 0);
183 ENGINE_FN *fn = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
185 prime_cpu (cpu, max_insns);
189 SIM_ENGINE_PREFIX_HOOK (sd);
193 SIM_ENGINE_POSTFIX_HOOK (sd);
195 /* process any events */
196 if (sim_events_tick (sd))
197 sim_events_process (sd);
201 /* Main loop, for multiple cpus. */
204 engine_run_n (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int max_insns, int fast_p)
207 ENGINE_FN *engine_fns[MAX_NR_PROCESSORS];
209 for (i = 0; i < nr_cpus; ++i)
211 SIM_CPU *cpu = STATE_CPU (sd, i);
213 engine_fns[i] = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
214 prime_cpu (cpu, max_insns);
219 SIM_ENGINE_PREFIX_HOOK (sd);
221 /* FIXME: proper cycling of all of them, blah blah blah. */
222 while (next_cpu_nr != nr_cpus)
224 SIM_CPU *cpu = STATE_CPU (sd, next_cpu_nr);
226 (* engine_fns[next_cpu_nr]) (cpu);
230 SIM_ENGINE_POSTFIX_HOOK (sd);
232 /* process any events */
233 if (sim_events_tick (sd))
234 sim_events_process (sd);