1 # This shell script emits a C file. -*- C -*-
2 # Generate the main loop of the simulator.
3 # Syntax: genmloop.sh /bin/sh [options] cpu mainloop.in
4 # Options: [-mono|-multi] -scache -fast -parallel
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
10 # FIXME: "multi" support is wip.
13 # - move this C code to mainloop.in
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
34 -scache) scache
=yes ;;
38 -parallel) parallel
=yes ;;
48 /* This file is is generated by the genmloop script. DO NOT EDIT! */
50 /* Main loop for CGEN-based simulators.
51 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
52 Contributed by Cygnus Support.
54 This file is part of the GNU simulators.
56 This program is free software; you can redistribute it and/or modify
57 it under the terms of the GNU General Public License as published by
58 the Free Software Foundation; either version 2, or (at your option)
61 This program is distributed in the hope that it will be useful,
62 but WITHOUT ANY WARRANTY; without even the implied warranty of
63 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64 GNU General Public License for more details.
66 You should have received a copy of the GNU General Public License along
67 with this program; if not, write to the Free Software Foundation, Inc.,
68 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
70 /* We want the scache version of SEM_ARG.
71 This is used by the switch() version of the semantic code. */
74 if [ x
$scache = xyes
] ; then
75 echo "#define SCACHE_P"
77 echo '/*#define SCACHE_P*/'
78 echo '#undef WITH_SCACHE'
79 echo '#define WITH_SCACHE 0'
85 #define WANT_CPU_@CPU@
93 #include "sim-assert.h"
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
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
102 supporting full/fast seems reasonable.
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.
111 #define RUN_FAST_P(cpu) (STATE_RUN_FAST_P (CPU_STATE (cpu)))
113 #define RUN_FAST_P(cpu) 0
116 #ifndef SIM_PRE_EXEC_HOOK
117 #define SIM_PRE_EXEC_HOOK(state)
120 #ifndef SIM_POST_EXEC_HOOK
121 #define SIM_POST_EXEC_HOOK(state)
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)
131 #define EXECUTE(cpu, sc, num, fast_p) \
132 @cpu@_execute (cpu, sc + num, fast_p)
135 #define GET_ATTR(cpu, num, attr) \
136 CGEN_INSN_ATTR (sc[num].argbuf.opcode, CGEN_INSN_##attr)
140 ${SHELL} $file support
144 static volatile int keep_running;
145 /* FIXME: Should each cpu have its own copy? */
146 static volatile enum sim_stop pending_reason;
147 static volatile int pending_sigrc;
149 /* Want to measure simulator speed even in fast mode. */
150 static unsigned long insn_count;
151 static SIM_ELAPSED_TIME start_time;
153 /* Forward decls of cpu-specific functions. */
154 static void engine_resume (SIM_DESC, int, int);
155 static void engine_resume_full (SIM_DESC);
156 ${scache+static void engine_resume_fast (SIM_DESC);}
158 /* Stop the simulation for REASON/SIGRC.
159 CPU is the cpu being stopped [at address PC].
160 If CPU is NULL, all cpu's are stopping for the same reason. */
163 @cpu@_engine_stop (SIM_DESC sd, SIM_CPU *cpu, PCADDR pc,
164 enum sim_stop reason, int sigrc)
167 pending_reason = reason;
168 pending_sigrc = sigrc;
173 @cpu@_engine_run (SIM_DESC sd, int step, int siggnal)
176 if (USING_SCACHE_P (sd))
179 engine_resume (sd, step, siggnal);
183 engine_resume (SIM_DESC sd, int step, int siggnal)
185 sim_cpu *current_cpu = STATE_CPU (sd, 0);
186 /* These are volatile to survive setjmp. */
187 volatile sim_cpu *cpu = current_cpu;
188 volatile sim_engine *engine = STATE_ENGINE (sd);
192 keep_running = ! step;
193 start_time = sim_elapsed_time_get ();
194 /* FIXME: Having this global can slow things down a teensy bit.
195 After things are working see about moving engine_resume_{full,fast}
196 back into this function. */
199 engine->jmpbuf = &buf;
200 sim_engine_set_run_state (sd, sim_running, 0);
201 pending_reason = sim_running;
204 /* ??? Restart support to be added in time. */
208 /* Account for the last insn executed. */
210 TRACE_INSN_FINI ((sim_cpu *) cpu, 1);
214 /* The computed goto switch can be used, and while the number of blocks
215 may swamp the relatively few that this function contains, when running
216 with the scache we put the actual semantic code in their own
221 if [ x
$fast = xyes
] ; then
224 || !RUN_FAST_P (current_cpu))
225 engine_resume_full (sd);
227 engine_resume_fast (sd);
231 engine_resume_full (sd);
237 /* If the loop exits, either we single-stepped or @cpu@_engine_stop
240 sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
242 sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
245 engine->jmpbuf = NULL;
246 PROFILE_EXEC_TIME (CPU_PROFILE_DATA (cpu))
247 += sim_elapsed_time_since (start_time);
248 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu))
254 ##########################################################################
256 if [ x
$scache = xyes
] ; then
260 engine_resume_full (SIM_DESC sd)
263 /* current_{state,cpu} exist for the generated code to use. */
264 SIM_DESC current_state = sd;
265 sim_cpu *current_cpu = STATE_CPU (sd, 0);
266 ${parallel+ int icount = 0;}
270 # Any initialization code before looping starts.
271 # Note that this code may declare some locals.
274 if [ x
$parallel = xyes
] ; then
277 #if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
279 static read_init_p = 0;
282 /* ??? Later maybe paste read.c in when building mainloop.c. */
283 #define DEFINE_LABELS
297 /* FIXME: Later check every insn for events and such. */
299 SIM_PRE_EXEC_HOOK (current_cpu);
306 /* First step: look up current insn in hash table. */
307 hash = SCACHE_HASH_PC (sd, pc);
308 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
310 /* If the entry isn't the one we want (cache miss),
311 fetch and decode the instruction. */
312 if (sc->argbuf.addr != pc)
316 PROFILE_COUNT_SCACHE_MISS (current_cpu);
318 /* begin full-extract-scache */
321 ${SHELL} $file full-extract-scache
324 /* end full-extract-scache */
328 PROFILE_COUNT_SCACHE_HIT (current_cpu);
329 /* Make core access statistics come out right.
330 The size is a guess, but it's currently not used either. */
331 PROFILE_COUNT_CORE (current_cpu, pc, 2, exec_map);
334 /* begin full-exec-scache */
337 ${SHELL} $file full-exec-scache
340 /* end full-exec-scache */
343 SIM_POST_EXEC_HOOK (current_cpu);
347 while (keep_running);
352 ##########################################################################
358 engine_resume_full (SIM_DESC sd)
361 SIM_DESC current_state = sd;
362 sim_cpu *current_cpu = STATE_CPU (sd, 0);
363 SCACHE cache[MAX_LIW_INSNS];
364 SCACHE *sc = &cache[0];
365 ${parallel+ int icount = 0;}
369 # Any initialization code before looping starts.
370 # Note that this code may declare some locals.
373 if [ x
$parallel = xyes
] ; then
376 #if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
378 static read_init_p = 0;
381 /* ??? Later maybe paste read.c in when building mainloop.c. */
382 #define DEFINE_LABELS
396 /* FIXME: Later check every insn for events and such. */
398 SIM_PRE_EXEC_HOOK (current_cpu);
401 /* begin full-{extract,exec}-noscache */
404 ${SHELL} $file full-extract-noscache
406 ${SHELL} $file full-exec-noscache
409 /* end full-{extract,exec}-noscache */
412 SIM_POST_EXEC_HOOK (current_cpu);
416 while (keep_running);
423 ##########################################################################
425 if [ x
$fast = xyes
] ; then
426 if [ x
$scache = xyes
] ; then
430 engine_resume_fast (SIM_DESC sd)
433 SIM_DESC current_state = sd;
434 sim_cpu *current_cpu = STATE_CPU (sd, 0);
435 ${parallel+ int icount = 0;}
439 # Any initialization code before looping starts.
440 # Note that this code may declare some locals.
443 if [ x
$parallel = xyes
] ; then
446 #if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
448 static read_init_p = 0;
451 /* ??? Later maybe paste read.c in when building mainloop.c. */
452 #define DEFINE_LABELS
464 #if defined (WITH_SEM_SWITCH_FAST) && defined (__GNUC__)
466 static decode_init_p = 0;
469 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
470 #define DEFINE_LABELS
471 #include "sem-switch.c"
484 /* First step: look up current insn in hash table. */
485 hash = SCACHE_HASH_PC (sd, pc);
486 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
488 /* If the entry isn't the one we want (cache miss),
489 fetch and decode the instruction. */
490 if (sc->argbuf.addr != pc)
494 /* begin fast-extract-scache */
497 ${SHELL} $file fast-extract-scache
500 /* end fast-extract-scache */
503 /* begin fast-exec-scache */
506 ${SHELL} $file fast-exec-scache
509 /* end fast-exec-scache */
515 while (keep_running);
521 ##########################################################################
527 engine_resume_fast (SIM_DESC sd)
530 SIM_DESC current_state = sd;
531 sim_cpu *current_cpu = STATE_CPU (sd, 0);
532 SCACHE cache[MAX_LIW_INSNS];
533 SCACHE *sc = &cache[0];
534 ${parallel+ int icount = 0;}
538 # Any initialization code before looping starts.
539 # Note that this code may declare some locals.
542 if [ x
$parallel = xyes
] ; then
545 #if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
547 static read_init_p = 0;
550 /* ??? Later maybe paste read.c in when building mainloop.c. */
551 #define DEFINE_LABELS
565 /* begin fast-{extract,exec}-noscache */
568 ${SHELL} $file fast-extract-noscache
570 ${SHELL} $file fast-exec-noscache
573 /* end fast-{extract,exec}-noscache */
577 while (keep_running);
This page took 0.042125 seconds and 4 git commands to generate.