]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/cgen-run.c
sim/cgen: initialize variable at creation in engine_run_n
[thirdparty/binutils-gdb.git] / sim / common / cgen-run.c
CommitLineData
c906108c 1/* Main simulator loop for CGEN-based simulators.
4a94e368 2 Copyright (C) 1998-2022 Free Software Foundation, Inc.
c906108c
SS
3 Contributed by Cygnus Solutions.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4744ac1b
JB
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
c906108c
SS
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
4744ac1b
JB
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
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
22 "fast mode".
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.
34*/
35
6df01ab8
MF
36/* This must come before any other includes. */
37#include "defs.h"
38
c906108c
SS
39#include "sim-main.h"
40#include "sim-assert.h"
1fef66b0 41#include "sim-signal.h"
c906108c
SS
42
43#ifndef SIM_ENGINE_PREFIX_HOOK
44#define SIM_ENGINE_PREFIX_HOOK(sd)
45#endif
46#ifndef SIM_ENGINE_POSTFIX_HOOK
47#define SIM_ENGINE_POSTFIX_HOOK(sd)
48#endif
49
50static sim_event_handler has_stepped;
51static void prime_cpu (SIM_CPU *, int);
52static void engine_run_1 (SIM_DESC, int, int);
53static void engine_run_n (SIM_DESC, int, int, int, int);
54
906192d7
MF
55/* If no profiling or tracing has been enabled, run in fast mode. */
56static int
57cgen_get_fast_p (SIM_DESC sd)
58{
59 int i, c;
60 int run_fast_p = 1;
61
62 for (c = 0; c < MAX_NR_PROCESSORS; ++c)
63 {
64 SIM_CPU *cpu = STATE_CPU (sd, c);
65
66 if (PROFILE_ANY_P (cpu) || TRACE_ANY_P (cpu))
67 return 0;
68 }
69
70 return 1;
71}
72
c906108c
SS
73/* sim_resume for cgen */
74
75void
76sim_resume (SIM_DESC sd, int step, int siggnal)
77{
78 sim_engine *engine = STATE_ENGINE (sd);
79 jmp_buf buf;
80 int jmpval;
906192d7 81 static int fast_p = -1;
c906108c
SS
82
83 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
84
906192d7
MF
85 if (fast_p == -1)
86 fast_p = cgen_get_fast_p (sd);
87
c906108c
SS
88 /* we only want to be single stepping the simulator once */
89 if (engine->stepper != NULL)
90 {
91 sim_events_deschedule (sd, engine->stepper);
92 engine->stepper = NULL;
93 }
94 if (step)
95 engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);
96
97 sim_module_resume (sd);
98
99#if WITH_SCACHE
100 if (USING_SCACHE_P (sd))
101 scache_flush (sd);
102#endif
103
104 /* run/resume the simulator */
105
106 sim_engine_set_run_state (sd, sim_running, 0);
107
108 engine->jmpbuf = &buf;
109 jmpval = setjmp (buf);
110 if (jmpval == sim_engine_start_jmpval
111 || jmpval == sim_engine_restart_jmpval)
112 {
113 int last_cpu_nr = sim_engine_last_cpu_nr (sd);
114 int next_cpu_nr = sim_engine_next_cpu_nr (sd);
115 int nr_cpus = sim_engine_nr_cpus (sd);
116 /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is
117 useful if all one wants to do is run a benchmark. Need some better
118 way to identify this case. */
119 int max_insns = (step
120 ? 1
7a292a7a
SS
121 : (nr_cpus == 1
122 /*&& wip:no-events*/
123 /* Don't do this if running under gdb, need to
124 poll ui for events. */
125 && STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
c906108c 126 ? 0
7a292a7a 127 : 8); /*FIXME: magic number*/
c906108c
SS
128
129 sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
130 if (next_cpu_nr >= nr_cpus)
131 next_cpu_nr = 0;
132 if (nr_cpus == 1)
133 engine_run_1 (sd, max_insns, fast_p);
134 else
135 engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p);
136 }
137#if 1 /*wip*/
138 else
139 {
140 /* Account for the last insn executed. */
141 SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd));
142 ++ CPU_INSN_COUNT (cpu);
db7858e2 143 CGEN_TRACE_INSN_FINI (cpu, NULL, 1);
c906108c
SS
144 }
145#endif
146
147 engine->jmpbuf = NULL;
148
149 {
150 int i;
151 int nr_cpus = sim_engine_nr_cpus (sd);
152
153#if 0 /*wip,ignore*/
154 /* If the loop exits, either we single-stepped or @cpu@_engine_stop
155 was called. */
156 if (step)
157 sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
158 else
159 sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
160#endif
161
162 for (i = 0; i < nr_cpus; ++i)
163 {
164 SIM_CPU *cpu = STATE_CPU (sd, i);
165
166 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu);
167 }
168 }
169
170 sim_module_suspend (sd);
171}
172
173/* Halt the simulator after just one instruction. */
174
175static void
176has_stepped (SIM_DESC sd, void *data)
177{
178 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
179 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
180}
181
182/* Prepare a cpu for running.
183 MAX_INSNS is the number of insns to execute per time slice.
184 If 0 it means the cpu can run as long as it wants (e.g. until the
185 program completes).
186 ??? Perhaps this should be an argument to the engine_fn. */
187
188static void
189prime_cpu (SIM_CPU *cpu, int max_insns)
190{
191 CPU_MAX_SLICE_INSNS (cpu) = max_insns;
192 CPU_INSN_COUNT (cpu) = 0;
193
194 /* Initialize the insn descriptor table.
195 This has to be done after all initialization so we just defer it to
196 here. */
197
198 if (MACH_PREPARE_RUN (CPU_MACH (cpu)))
199 (* MACH_PREPARE_RUN (CPU_MACH (cpu))) (cpu);
200}
201
202/* Main loop, for 1 cpu. */
203
204static void
205engine_run_1 (SIM_DESC sd, int max_insns, int fast_p)
206{
207 sim_cpu *cpu = STATE_CPU (sd, 0);
208 ENGINE_FN *fn = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
209
210 prime_cpu (cpu, max_insns);
211
212 while (1)
213 {
214 SIM_ENGINE_PREFIX_HOOK (sd);
215
216 (*fn) (cpu);
217
218 SIM_ENGINE_POSTFIX_HOOK (sd);
219
220 /* process any events */
221 if (sim_events_tick (sd))
222 sim_events_process (sd);
223 }
224}
225
226/* Main loop, for multiple cpus. */
227
228static void
229engine_run_n (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int max_insns, int fast_p)
230{
231 int i;
a09f33be
AB
232 /* Ensure that engine_fns is fully initialized, this silences a compiler
233 warning when engine_fns is used below. */
234 ENGINE_FN *engine_fns[MAX_NR_PROCESSORS] = {};
c906108c 235
b69bd9e7
MF
236 SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);
237 SIM_ASSERT (next_cpu_nr >= 0 && next_cpu_nr < nr_cpus);
238
c906108c
SS
239 for (i = 0; i < nr_cpus; ++i)
240 {
241 SIM_CPU *cpu = STATE_CPU (sd, i);
242
243 engine_fns[i] = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
244 prime_cpu (cpu, max_insns);
245 }
246
247 while (1)
248 {
249 SIM_ENGINE_PREFIX_HOOK (sd);
250
251 /* FIXME: proper cycling of all of them, blah blah blah. */
b69bd9e7 252 while (next_cpu_nr < nr_cpus)
c906108c
SS
253 {
254 SIM_CPU *cpu = STATE_CPU (sd, next_cpu_nr);
255
256 (* engine_fns[next_cpu_nr]) (cpu);
257 ++next_cpu_nr;
258 }
259
260 SIM_ENGINE_POSTFIX_HOOK (sd);
261
262 /* process any events */
263 if (sim_events_tick (sd))
264 sim_events_process (sd);
265 }
266}