* genmloop.sh (engine_resume): Update insn_count before exiting.
[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.
b500809f 51 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
b9c8cd10
DE
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 {
b500809f
DE
191 /* Account for the last insn executed. */
192 ++insn_count;
193
dde54cb8
DE
194 engine->jmpbuf = NULL;
195 TRACE_INSN_FINI ((sim_cpu *) cpu);
196 PROFILE_EXEC_TIME (CPU_PROFILE_DATA (cpu))
b9c8cd10 197 += sim_elapsed_time_since (start_time);
dde54cb8 198 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu))
b9c8cd10 199 += insn_count;
b500809f 200
b9c8cd10
DE
201 return;
202 }
203
dde54cb8
DE
204 /* ??? Restart support to be added in time. */
205
206 /* The computed goto switch can be used, and while the number of blocks
207 may swamp the relatively few that this function contains, when running
208 with the scache we put the actual semantic code in their own
209 functions. */
210
211EOF
212
213if [ x$fast = xyes ] ; then
214 cat <<EOF
215 if (step
216 || !RUN_FAST_P (current_cpu))
217 engine_resume_full (sd);
218 else
219 engine_resume_fast (sd);
220EOF
221else
222 cat <<EOF
223 engine_resume_full (sd);
224EOF
225fi
226
227cat <<EOF
228
229 /* If the loop exits, either we single-stepped or engine_stop was called.
230 In either case we need to call engine_halt: to properly exit this
231 function we must go through the setjmp executed above. */
232 if (step)
233 sim_engine_halt (sd, current_cpu, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
234 sim_engine_halt (sd, current_cpu, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
235}
236
237EOF
238
b500809f
DE
239##########################################################################
240
dde54cb8
DE
241if [ x$scache = xyes ] ; then
242 cat <<EOF
243
244static void
245engine_resume_full (SIM_DESC sd)
246{
247#define FAST_P 0
248 /* current_{state,cpu} exist for the generated code to use. */
249 SIM_DESC current_state = sd;
250 sim_cpu *current_cpu = STATE_CPU (sd, 0);
251${parallel+ int icount = 0;}
252
b9c8cd10
DE
253EOF
254
255# Any initialization code before looping starts.
b500809f 256# Note that this code may declare some locals.
b9c8cd10
DE
257${SHELL} $file init
258
b500809f
DE
259if [ x$parallel = xyes ] ; then
260cat << EOF
261
262#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
263 {
264 static read_init_p = 0;
265 if (! read_init_p)
266 {
267/* ??? Later maybe paste read.c in when building mainloop.c. */
268#define DEFINE_LABELS
269#include "readx.c"
270 read_init_p = 1;
271 }
272 }
273#endif
274
275EOF
276fi
277
b9c8cd10
DE
278cat <<EOF
279
dde54cb8
DE
280 do
281 {
282 /* FIXME: Later check every insn for events and such. */
b9c8cd10 283
dde54cb8
DE
284 SIM_PRE_EXEC_HOOK (current_cpu);
285
286 {
287 unsigned int hash;
288 SCACHE *sc;
289 PCADDR pc = PC;
290
291 /* First step: look up current insn in hash table. */
292 hash = SCACHE_HASH_PC (sd, pc);
293 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
294
295 /* If the entry isn't the one we want (cache miss),
296 fetch and decode the instruction. */
297 if (sc->argbuf.addr != pc)
298 {
299 insn_t insn;
300
301 PROFILE_COUNT_SCACHE_MISS (current_cpu);
302
303/* begin full-extract-scache */
304EOF
305
306${SHELL} $file full-extract-scache
307
308cat <<EOF
309/* end full-extract-scache */
310 }
311 else
312 {
313 PROFILE_COUNT_SCACHE_HIT (current_cpu);
b500809f
DE
314 /* Make core access statistics come out right.
315 The size is a guess, but it's currently not used either. */
316 PROFILE_COUNT_CORE (current_cpu, pc, 2, sim_core_execute_map);
dde54cb8
DE
317 }
318
319/* begin full-exec-scache */
320EOF
321
322${SHELL} $file full-exec-scache
323
324cat <<EOF
325/* end full-exec-scache */
326 }
327
328 SIM_POST_EXEC_HOOK (current_cpu);
329
330 ++insn_count;
331 }
332 while (keep_running);
333#undef FAST_P
334}
335EOF
336
b500809f
DE
337##########################################################################
338
dde54cb8
DE
339else # ! WITH_SCACHE
340 cat <<EOF
341
342static void
343engine_resume_full (SIM_DESC sd)
344{
345#define FAST_P 0
346 SIM_DESC current_state = sd;
347 sim_cpu *current_cpu = STATE_CPU (sd, 0);
348 SCACHE cache[MAX_LIW_INSNS];
349 SCACHE *sc = &cache[0];
350${parallel+ int icount = 0;}
351
352EOF
353
354# Any initialization code before looping starts.
b500809f 355# Note that this code may declare some locals.
dde54cb8
DE
356${SHELL} $file init
357
b500809f
DE
358if [ x$parallel = xyes ] ; then
359cat << EOF
360
361#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
362 {
363 static read_init_p = 0;
364 if (! read_init_p)
365 {
366/* ??? Later maybe paste read.c in when building mainloop.c. */
367#define DEFINE_LABELS
368#include "readx.c"
369 read_init_p = 1;
370 }
371 }
372#endif
373
374EOF
375fi
376
dde54cb8
DE
377cat <<EOF
378
379 do
b9c8cd10 380 {
dde54cb8 381 /* FIXME: Later check every insn for events and such. */
b9c8cd10 382
dde54cb8 383 SIM_PRE_EXEC_HOOK (current_cpu);
b9c8cd10 384
dde54cb8
DE
385 {
386/* begin full-{extract,exec}-noscache */
b9c8cd10
DE
387EOF
388
dde54cb8
DE
389${SHELL} $file full-extract-noscache
390echo ""
391${SHELL} $file full-exec-noscache
b9c8cd10
DE
392
393cat <<EOF
dde54cb8
DE
394/* end full-{extract,exec}-noscache */
395 }
b9c8cd10 396
dde54cb8 397 SIM_POST_EXEC_HOOK (current_cpu);
b9c8cd10 398
dde54cb8 399 ++insn_count;
b9c8cd10 400 }
dde54cb8
DE
401 while (keep_running);
402#undef FAST_P
403}
404
405EOF
406fi # ! WITH_SCACHE
407
b500809f
DE
408##########################################################################
409
dde54cb8
DE
410if [ x$fast = xyes ] ; then
411 if [ x$scache = xyes ] ; then
412 cat <<EOF
413
414static void
415engine_resume_fast (SIM_DESC sd)
416{
417#define FAST_P 1
418 SIM_DESC current_state = sd;
419 sim_cpu *current_cpu = STATE_CPU (sd, 0);
420${parallel+ int icount = 0;}
421
422EOF
423
424# Any initialization code before looping starts.
b500809f 425# Note that this code may declare some locals.
dde54cb8
DE
426${SHELL} $file init
427
b500809f
DE
428if [ x$parallel = xyes ] ; then
429cat << EOF
430
431#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
432 {
433 static read_init_p = 0;
434 if (! read_init_p)
435 {
436/* ??? Later maybe paste read.c in when building mainloop.c. */
437#define DEFINE_LABELS
438#include "readx.c"
439 read_init_p = 1;
440 }
441 }
442#endif
443
444EOF
445fi
446
dde54cb8
DE
447cat <<EOF
448
449#if defined (WITH_SEM_SWITCH_FAST) && defined (__GNUC__)
450 {
451 static decode_init_p = 0;
452 if (! decode_init_p)
453 {
454/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
455#define DEFINE_LABELS
456#include "sem-switch.c"
457 decode_init_p = 1;
458 }
459 }
460#endif
461
462 do
b9c8cd10 463 {
dde54cb8
DE
464 {
465 unsigned int hash;
466 SCACHE *sc;
467 PCADDR pc = PC;
468
469 /* First step: look up current insn in hash table. */
470 hash = SCACHE_HASH_PC (sd, pc);
471 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
472
473 /* If the entry isn't the one we want (cache miss),
474 fetch and decode the instruction. */
475 if (sc->argbuf.addr != pc)
476 {
477 insn_t insn;
478
479/* begin fast-extract-scache */
480EOF
481
482${SHELL} $file fast-extract-scache
483
484cat <<EOF
485/* end fast-extract-scache */
486 }
487
488/* begin fast-exec-scache */
489EOF
490
491${SHELL} $file fast-exec-scache
492
493cat <<EOF
494/* end fast-exec-scache */
495
496 }
497
498 ++insn_count;
499 }
500 while (keep_running);
501#undef FAST_P
502}
503
504EOF
505
b500809f
DE
506##########################################################################
507
dde54cb8
DE
508else # ! WITH_SCACHE
509 cat <<EOF
510
511static void
512engine_resume_fast (SIM_DESC sd)
513{
514#define FAST_P 1
515 SIM_DESC current_state = sd;
516 sim_cpu *current_cpu = STATE_CPU (sd, 0);
517 SCACHE cache[MAX_LIW_INSNS];
518 SCACHE *sc = &cache[0];
519${parallel+ int icount = 0;}
b9c8cd10
DE
520
521EOF
522
dde54cb8 523# Any initialization code before looping starts.
b500809f 524# Note that this code may declare some locals.
dde54cb8 525${SHELL} $file init
b9c8cd10 526
b500809f
DE
527if [ x$parallel = xyes ] ; then
528cat << EOF
529
530#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
531 {
532 static read_init_p = 0;
533 if (! read_init_p)
534 {
535/* ??? Later maybe paste read.c in when building mainloop.c. */
536#define DEFINE_LABELS
537#include "readx.c"
538 read_init_p = 1;
539 }
540 }
541#endif
542
543EOF
544fi
545
b9c8cd10
DE
546cat <<EOF
547
dde54cb8
DE
548 do
549 {
550/* begin fast-{extract,exec}-noscache */
551EOF
552
553${SHELL} $file fast-extract-noscache
554echo ""
555${SHELL} $file fast-exec-noscache
556
557cat <<EOF
558/* end fast-{extract,exec}-noscache */
559
560 ++insn_count;
b9c8cd10 561 }
dde54cb8
DE
562 while (keep_running);
563#undef FAST_P
b9c8cd10 564}
dde54cb8 565
b9c8cd10 566EOF
dde54cb8
DE
567
568 fi # ! WITH_SCACHE
569fi # -fast
This page took 0.068396 seconds and 4 git commands to generate.