]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/cgen-run.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / sim / common / cgen-run.c
1 /* Main simulator loop for CGEN-based simulators.
2 Copyright (C) 1998 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
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 2, or (at your option)
10 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 along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 /* ??? These are old notes, kept around for now.
22 Collecting profile data and tracing slow us down so we don't do them in
23 "fast mode".
24 There are 6 possibilities on 2 axes:
25 - no-scaching, insn-scaching, basic-block-scaching
26 - run with full features or run fast
27 Supporting all six possibilities in one executable is a bit much but
28 supporting full/fast seems reasonable.
29 If the scache is configured in it is always used.
30 If pbb-scaching is configured in it is always used.
31 ??? Sometimes supporting more than one set of semantic functions will make
32 the simulator too large - this should be configurable. Blah blah blah.
33 ??? Supporting full/fast can be more modular, blah blah blah.
34 When the framework is more modular, this can be.
35 */
36
37 #include "sim-main.h"
38 #include "sim-assert.h"
39
40 #ifndef SIM_ENGINE_PREFIX_HOOK
41 #define SIM_ENGINE_PREFIX_HOOK(sd)
42 #endif
43 #ifndef SIM_ENGINE_POSTFIX_HOOK
44 #define SIM_ENGINE_POSTFIX_HOOK(sd)
45 #endif
46
47 static sim_event_handler has_stepped;
48 static void prime_cpu (SIM_CPU *, int);
49 static void engine_run_1 (SIM_DESC, int, int);
50 static void engine_run_n (SIM_DESC, int, int, int, int);
51
52 /* sim_resume for cgen */
53
54 void
55 sim_resume (SIM_DESC sd, int step, int siggnal)
56 {
57 sim_engine *engine = STATE_ENGINE (sd);
58 jmp_buf buf;
59 int jmpval;
60
61 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
62
63 /* we only want to be single stepping the simulator once */
64 if (engine->stepper != NULL)
65 {
66 sim_events_deschedule (sd, engine->stepper);
67 engine->stepper = NULL;
68 }
69 if (step)
70 engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);
71
72 sim_module_resume (sd);
73
74 #if WITH_SCACHE
75 if (USING_SCACHE_P (sd))
76 scache_flush (sd);
77 #endif
78
79 /* run/resume the simulator */
80
81 sim_engine_set_run_state (sd, sim_running, 0);
82
83 engine->jmpbuf = &buf;
84 jmpval = setjmp (buf);
85 if (jmpval == sim_engine_start_jmpval
86 || jmpval == sim_engine_restart_jmpval)
87 {
88 int last_cpu_nr = sim_engine_last_cpu_nr (sd);
89 int next_cpu_nr = sim_engine_next_cpu_nr (sd);
90 int nr_cpus = sim_engine_nr_cpus (sd);
91 /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is
92 useful if all one wants to do is run a benchmark. Need some better
93 way to identify this case. */
94 int max_insns = (step
95 ? 1
96 : (nr_cpus == 1 /*&& wip:no-events*/)
97 ? 0
98 : 4); /*FIXME: magic number*/
99 int fast_p = STATE_RUN_FAST_P (sd);
100
101 sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
102 if (next_cpu_nr >= nr_cpus)
103 next_cpu_nr = 0;
104 if (nr_cpus == 1)
105 engine_run_1 (sd, max_insns, fast_p);
106 else
107 engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p);
108 }
109 #if 1 /*wip*/
110 else
111 {
112 /* Account for the last insn executed. */
113 SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd));
114 ++ CPU_INSN_COUNT (cpu);
115 TRACE_INSN_FINI (cpu, NULL, 1);
116 }
117 #endif
118
119 engine->jmpbuf = NULL;
120
121 {
122 int i;
123 int nr_cpus = sim_engine_nr_cpus (sd);
124
125 #if 0 /*wip,ignore*/
126 /* If the loop exits, either we single-stepped or @cpu@_engine_stop
127 was called. */
128 if (step)
129 sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
130 else
131 sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
132 #endif
133
134 for (i = 0; i < nr_cpus; ++i)
135 {
136 SIM_CPU *cpu = STATE_CPU (sd, i);
137
138 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu);
139 }
140 }
141
142 sim_module_suspend (sd);
143 }
144
145 /* Halt the simulator after just one instruction. */
146
147 static void
148 has_stepped (SIM_DESC sd, void *data)
149 {
150 ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
151 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
152 }
153
154 /* Prepare a cpu for running.
155 MAX_INSNS is the number of insns to execute per time slice.
156 If 0 it means the cpu can run as long as it wants (e.g. until the
157 program completes).
158 ??? Perhaps this should be an argument to the engine_fn. */
159
160 static void
161 prime_cpu (SIM_CPU *cpu, int max_insns)
162 {
163 CPU_MAX_SLICE_INSNS (cpu) = max_insns;
164 CPU_INSN_COUNT (cpu) = 0;
165
166 /* Initialize the insn descriptor table.
167 This has to be done after all initialization so we just defer it to
168 here. */
169
170 if (MACH_PREPARE_RUN (CPU_MACH (cpu)))
171 (* MACH_PREPARE_RUN (CPU_MACH (cpu))) (cpu);
172 }
173
174 /* Main loop, for 1 cpu. */
175
176 static void
177 engine_run_1 (SIM_DESC sd, int max_insns, int fast_p)
178 {
179 sim_cpu *cpu = STATE_CPU (sd, 0);
180 ENGINE_FN *fn = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
181
182 prime_cpu (cpu, max_insns);
183
184 while (1)
185 {
186 SIM_ENGINE_PREFIX_HOOK (sd);
187
188 (*fn) (cpu);
189
190 SIM_ENGINE_POSTFIX_HOOK (sd);
191
192 /* process any events */
193 if (sim_events_tick (sd))
194 sim_events_process (sd);
195 }
196 }
197
198 /* Main loop, for multiple cpus. */
199
200 static void
201 engine_run_n (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int max_insns, int fast_p)
202 {
203 int i;
204 ENGINE_FN *engine_fns[MAX_NR_PROCESSORS];
205
206 for (i = 0; i < nr_cpus; ++i)
207 {
208 SIM_CPU *cpu = STATE_CPU (sd, i);
209
210 engine_fns[i] = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
211 prime_cpu (cpu, max_insns);
212 }
213
214 while (1)
215 {
216 SIM_ENGINE_PREFIX_HOOK (sd);
217
218 /* FIXME: proper cycling of all of them, blah blah blah. */
219 while (next_cpu_nr != nr_cpus)
220 {
221 SIM_CPU *cpu = STATE_CPU (sd, next_cpu_nr);
222
223 (* engine_fns[next_cpu_nr]) (cpu);
224 ++next_cpu_nr;
225 }
226
227 SIM_ENGINE_POSTFIX_HOOK (sd);
228
229 /* process any events */
230 if (sim_events_tick (sd))
231 sim_events_process (sd);
232 }
233 }