* genmloop.sh (@cpu@_engine_run): Delete `current_state'.
[deliverable/binutils-gdb.git] / sim / common / genmloop.sh
CommitLineData
b9c8cd10
DE
1# This shell script emits a C file. -*- C -*-
2# Generate the main loop of the simulator.
dde54cb8
DE
3# Syntax: genmloop.sh /bin/sh [options] cpu mainloop.in
4# Options: [-mono|-multi] -scache -fast -parallel
5#
6# -scache: use the scache
7# -fast: include support for fast execution in addition to full featured mode
8# -parallel: cpu can execute multiple instructions parallely
9#
b9c8cd10
DE
10# FIXME: "multi" support is wip.
11
dde54cb8
DE
12# TODO
13# - move this C code to mainloop.in
14# - keep genmloop.sh
15# - build exec.in from .cpu file
16# - have each cpu provide handwritten cycle.in
17# - integrate with common/sim-engine.[ch]
18# - for sparc, have two main loops, outer one handles delay slot when npc != 0
19# - inner loop does not handle delay slots, pc = pc + 4
20
21type=mono
22#scache=
23#fast=
24#parallel=
25
26shell=$1 ; shift
27
28while true
29do
30 case $1 in
31 -mono) type=mono ;;
32 -multi) type=multi ;;
33 -no-scache) ;;
34 -scache) scache=yes ;;
35 -no-fast) ;;
36 -fast) fast=yes ;;
37 -no-parallel) ;;
38 -parallel) parallel=yes ;;
39 *) break ;;
40 esac
41 shift
42done
43
44cpu=$1
45file=$2
b9c8cd10
DE
46
47cat <<EOF
48/* This file is is generated by the genmloop script. DO NOT EDIT! */
49
50/* Main loop for CGEN-based simulators.
51 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
52 Contributed by Cygnus Support.
53
dde54cb8 54This file is part of the GNU simulators.
b9c8cd10
DE
55
56This program is free software; you can redistribute it and/or modify
57it under the terms of the GNU General Public License as published by
58the Free Software Foundation; either version 2, or (at your option)
59any later version.
60
61This program is distributed in the hope that it will be useful,
62but WITHOUT ANY WARRANTY; without even the implied warranty of
63MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64GNU General Public License for more details.
65
66You should have received a copy of the GNU General Public License along
67with this program; if not, write to the Free Software Foundation, Inc.,
6859 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
69
dde54cb8
DE
70/* We want the scache version of SEM_ARG.
71 This is used by the switch() version of the semantic code. */
72EOF
73
74if [ x$scache = xyes ] ; then
75 echo "#define SCACHE_P"
76else
77 echo '/*#define SCACHE_P*/'
78 echo '#undef WITH_SCACHE'
79 echo '#define WITH_SCACHE 0'
80fi
81
82cat <<EOF
83
84#define WANT_CPU
85#define WANT_CPU_@CPU@
b9c8cd10
DE
86
87#include "sim-main.h"
88#include "bfd.h"
dde54cb8
DE
89#include "cgen-mem.h"
90#include "cgen-ops.h"
b9c8cd10
DE
91#include "cpu-opc.h"
92#include "cpu-sim.h"
dde54cb8 93#include "sim-assert.h"
b9c8cd10
DE
94
95/* Tell sim_main_loop to use the cache if it's active.
96 Collecting profile data and tracing slow us down so we don't do them in
97 "fast mode".
98 There are 2 possibilities on 2 axes:
99 - use or don't use the cache
100 - run normally (full featured) or run fast
101 Supporting all four possibilities in one executable is a bit much but
dde54cb8 102 supporting full/fast seems reasonable.
b9c8cd10
DE
103 If the cache is configured in it is always used.
104 ??? Need to see whether it speeds up profiling significantly or not.
105 Speeding up tracing doesn't seem worth it.
106 ??? Sometimes supporting more than one set of semantic functions will make
107 the simulator too large - this should be configurable.
108*/
109
110#if WITH_SCACHE
111#define RUN_FAST_P(cpu) (STATE_RUN_FAST_P (CPU_STATE (cpu)))
112#else
113#define RUN_FAST_P(cpu) 0
114#endif
115
116#ifndef SIM_PRE_EXEC_HOOK
117#define SIM_PRE_EXEC_HOOK(state)
118#endif
119
120#ifndef SIM_POST_EXEC_HOOK
121#define SIM_POST_EXEC_HOOK(state)
122#endif
123
dde54cb8
DE
124#if 0 /* FIXME:experiment */
125/* "sc" is local to the calling function.
126 It is done this way to keep the internals of the implementation out of
127 the description file. */
128#define EXTRACT(cpu, pc, insn, sc, num, fast_p) \
129@cpu@_extract (cpu, pc, insn, sc + num, fast_p)
130
131#define EXECUTE(cpu, sc, num, fast_p) \
132@cpu@_execute (cpu, sc + num, fast_p)
133#endif
134
135#define GET_ATTR(cpu, num, attr) \
136CGEN_INSN_ATTR (sc[num].argbuf.opcode, CGEN_INSN_##attr)
137
b9c8cd10
DE
138EOF
139
140${SHELL} $file support
141
142cat <<EOF
143
144static volatile int keep_running;
dde54cb8
DE
145/* Want to measure simulator speed even in fast mode. */
146static unsigned long insn_count;
147static SIM_ELAPSED_TIME start_time;
148
149/* Forward decls of cpu-specific functions. */
150static void engine_resume (SIM_DESC, int, int);
151static void engine_resume_full (SIM_DESC);
152${scache+static void engine_resume_fast (SIM_DESC);}
b9c8cd10
DE
153
154int
dde54cb8 155@cpu@_engine_stop (SIM_DESC sd)
b9c8cd10
DE
156{
157 keep_running = 0;
158 return 1;
159}
160
161void
dde54cb8 162@cpu@_engine_run (SIM_DESC sd, int step, int siggnal)
b9c8cd10 163{
b9c8cd10
DE
164#if WITH_SCACHE
165 if (USING_SCACHE_P (sd))
166 scache_flush (sd);
167#endif
168 engine_resume (sd, step, siggnal);
169}
170
dde54cb8 171static void
b9c8cd10
DE
172engine_resume (SIM_DESC sd, int step, int siggnal)
173{
b9c8cd10 174 sim_cpu *current_cpu = STATE_CPU (sd, 0);
dde54cb8
DE
175 /* These are volatile to survive setjmp. */
176 volatile sim_cpu *cpu = current_cpu;
177 volatile sim_engine *engine = STATE_ENGINE (sd);
178 jmp_buf buf;
179 int jmpval;
b9c8cd10 180
dde54cb8 181 keep_running = ! step;
b9c8cd10 182 start_time = sim_elapsed_time_get ();
dde54cb8
DE
183 /* FIXME: Having this global can slow things down a teensy bit.
184 After things are working see about moving engine_resume_{full,fast}
185 back into this function. */
b9c8cd10
DE
186 insn_count = 0;
187
dde54cb8
DE
188 engine->jmpbuf = &buf;
189 if (setjmp (buf))
b9c8cd10 190 {
dde54cb8
DE
191 engine->jmpbuf = NULL;
192 TRACE_INSN_FINI ((sim_cpu *) cpu);
193 PROFILE_EXEC_TIME (CPU_PROFILE_DATA (cpu))
b9c8cd10 194 += sim_elapsed_time_since (start_time);
dde54cb8 195 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu))
b9c8cd10
DE
196 += insn_count;
197 return;
198 }
199
dde54cb8
DE
200 /* ??? Restart support to be added in time. */
201
202 /* The computed goto switch can be used, and while the number of blocks
203 may swamp the relatively few that this function contains, when running
204 with the scache we put the actual semantic code in their own
205 functions. */
206
207EOF
208
209if [ x$fast = xyes ] ; then
210 cat <<EOF
211 if (step
212 || !RUN_FAST_P (current_cpu))
213 engine_resume_full (sd);
214 else
215 engine_resume_fast (sd);
216EOF
217else
218 cat <<EOF
219 engine_resume_full (sd);
220EOF
221fi
222
223cat <<EOF
224
225 /* If the loop exits, either we single-stepped or engine_stop was called.
226 In either case we need to call engine_halt: to properly exit this
227 function we must go through the setjmp executed above. */
228 if (step)
229 sim_engine_halt (sd, current_cpu, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
230 sim_engine_halt (sd, current_cpu, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
231}
232
233EOF
234
235if [ x$scache = xyes ] ; then
236 cat <<EOF
237
238static void
239engine_resume_full (SIM_DESC sd)
240{
241#define FAST_P 0
242 /* current_{state,cpu} exist for the generated code to use. */
243 SIM_DESC current_state = sd;
244 sim_cpu *current_cpu = STATE_CPU (sd, 0);
245${parallel+ int icount = 0;}
246
b9c8cd10
DE
247EOF
248
249# Any initialization code before looping starts.
250${SHELL} $file init
251
252cat <<EOF
253
dde54cb8
DE
254 do
255 {
256 /* FIXME: Later check every insn for events and such. */
b9c8cd10 257
dde54cb8
DE
258 SIM_PRE_EXEC_HOOK (current_cpu);
259
260 {
261 unsigned int hash;
262 SCACHE *sc;
263 PCADDR pc = PC;
264
265 /* First step: look up current insn in hash table. */
266 hash = SCACHE_HASH_PC (sd, pc);
267 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
268
269 /* If the entry isn't the one we want (cache miss),
270 fetch and decode the instruction. */
271 if (sc->argbuf.addr != pc)
272 {
273 insn_t insn;
274
275 PROFILE_COUNT_SCACHE_MISS (current_cpu);
276
277/* begin full-extract-scache */
278EOF
279
280${SHELL} $file full-extract-scache
281
282cat <<EOF
283/* end full-extract-scache */
284 }
285 else
286 {
287 PROFILE_COUNT_SCACHE_HIT (current_cpu);
288 }
289
290/* begin full-exec-scache */
291EOF
292
293${SHELL} $file full-exec-scache
294
295cat <<EOF
296/* end full-exec-scache */
297 }
298
299 SIM_POST_EXEC_HOOK (current_cpu);
300
301 ++insn_count;
302 }
303 while (keep_running);
304#undef FAST_P
305}
306EOF
307
308else # ! WITH_SCACHE
309 cat <<EOF
310
311static void
312engine_resume_full (SIM_DESC sd)
313{
314#define FAST_P 0
315 SIM_DESC current_state = sd;
316 sim_cpu *current_cpu = STATE_CPU (sd, 0);
317 SCACHE cache[MAX_LIW_INSNS];
318 SCACHE *sc = &cache[0];
319${parallel+ int icount = 0;}
320
321EOF
322
323# Any initialization code before looping starts.
324${SHELL} $file init
325
326cat <<EOF
327
328 do
b9c8cd10 329 {
dde54cb8 330 /* FIXME: Later check every insn for events and such. */
b9c8cd10 331
dde54cb8 332 SIM_PRE_EXEC_HOOK (current_cpu);
b9c8cd10 333
dde54cb8
DE
334 {
335/* begin full-{extract,exec}-noscache */
b9c8cd10
DE
336EOF
337
dde54cb8
DE
338${SHELL} $file full-extract-noscache
339echo ""
340${SHELL} $file full-exec-noscache
b9c8cd10
DE
341
342cat <<EOF
dde54cb8
DE
343/* end full-{extract,exec}-noscache */
344 }
b9c8cd10 345
dde54cb8 346 SIM_POST_EXEC_HOOK (current_cpu);
b9c8cd10 347
dde54cb8 348 ++insn_count;
b9c8cd10 349 }
dde54cb8
DE
350 while (keep_running);
351#undef FAST_P
352}
353
354EOF
355fi # ! WITH_SCACHE
356
357if [ x$fast = xyes ] ; then
358 if [ x$scache = xyes ] ; then
359 cat <<EOF
360
361static void
362engine_resume_fast (SIM_DESC sd)
363{
364#define FAST_P 1
365 SIM_DESC current_state = sd;
366 sim_cpu *current_cpu = STATE_CPU (sd, 0);
367${parallel+ int icount = 0;}
368
369EOF
370
371# Any initialization code before looping starts.
372${SHELL} $file init
373
374cat <<EOF
375
376#if defined (WITH_SEM_SWITCH_FAST) && defined (__GNUC__)
377 {
378 static decode_init_p = 0;
379 if (! decode_init_p)
380 {
381/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
382#define DEFINE_LABELS
383#include "sem-switch.c"
384 decode_init_p = 1;
385 }
386 }
387#endif
388
389 do
b9c8cd10 390 {
dde54cb8
DE
391 {
392 unsigned int hash;
393 SCACHE *sc;
394 PCADDR pc = PC;
395
396 /* First step: look up current insn in hash table. */
397 hash = SCACHE_HASH_PC (sd, pc);
398 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
399
400 /* If the entry isn't the one we want (cache miss),
401 fetch and decode the instruction. */
402 if (sc->argbuf.addr != pc)
403 {
404 insn_t insn;
405
406/* begin fast-extract-scache */
407EOF
408
409${SHELL} $file fast-extract-scache
410
411cat <<EOF
412/* end fast-extract-scache */
413 }
414
415/* begin fast-exec-scache */
416EOF
417
418${SHELL} $file fast-exec-scache
419
420cat <<EOF
421/* end fast-exec-scache */
422
423 }
424
425 ++insn_count;
426 }
427 while (keep_running);
428#undef FAST_P
429}
430
431EOF
432
433else # ! WITH_SCACHE
434 cat <<EOF
435
436static void
437engine_resume_fast (SIM_DESC sd)
438{
439#define FAST_P 1
440 SIM_DESC current_state = sd;
441 sim_cpu *current_cpu = STATE_CPU (sd, 0);
442 SCACHE cache[MAX_LIW_INSNS];
443 SCACHE *sc = &cache[0];
444${parallel+ int icount = 0;}
b9c8cd10
DE
445
446EOF
447
dde54cb8
DE
448# Any initialization code before looping starts.
449${SHELL} $file init
b9c8cd10
DE
450
451cat <<EOF
452
dde54cb8
DE
453 do
454 {
455/* begin fast-{extract,exec}-noscache */
456EOF
457
458${SHELL} $file fast-extract-noscache
459echo ""
460${SHELL} $file fast-exec-noscache
461
462cat <<EOF
463/* end fast-{extract,exec}-noscache */
464
465 ++insn_count;
b9c8cd10 466 }
dde54cb8
DE
467 while (keep_running);
468#undef FAST_P
b9c8cd10 469}
dde54cb8 470
b9c8cd10 471EOF
dde54cb8
DE
472
473 fi # ! WITH_SCACHE
474fi # -fast
This page took 0.08027 seconds and 4 git commands to generate.