* cgen-sim.h (cgen_state): New member opcode_table.
[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 94
6de2add2 95/* Tell sim_main_loop to use the scache if it's active.
b9c8cd10
DE
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:
6de2add2 99 - use or don't use the scache
b9c8cd10
DE
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.
6de2add2 103 If the scache is configured in it is always used.
b9c8cd10
DE
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;
ebd58f4d
DE
145/* FIXME: Should each cpu have its own copy? */
146static volatile enum sim_stop pending_reason;
147static volatile int pending_sigrc;
148
dde54cb8
DE
149/* Want to measure simulator speed even in fast mode. */
150static unsigned long insn_count;
151static SIM_ELAPSED_TIME start_time;
152
153/* Forward decls of cpu-specific functions. */
154static void engine_resume (SIM_DESC, int, int);
155static void engine_resume_full (SIM_DESC);
156${scache+static void engine_resume_fast (SIM_DESC);}
b9c8cd10 157
ebd58f4d
DE
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. */
161
b9c8cd10 162int
ebd58f4d
DE
163@cpu@_engine_stop (SIM_DESC sd, SIM_CPU *cpu, PCADDR pc,
164 enum sim_stop reason, int sigrc)
b9c8cd10
DE
165{
166 keep_running = 0;
ebd58f4d
DE
167 pending_reason = reason;
168 pending_sigrc = sigrc;
b9c8cd10
DE
169 return 1;
170}
171
172void
dde54cb8 173@cpu@_engine_run (SIM_DESC sd, int step, int siggnal)
b9c8cd10 174{
b9c8cd10
DE
175#if WITH_SCACHE
176 if (USING_SCACHE_P (sd))
177 scache_flush (sd);
178#endif
179 engine_resume (sd, step, siggnal);
180}
181
dde54cb8 182static void
b9c8cd10
DE
183engine_resume (SIM_DESC sd, int step, int siggnal)
184{
b9c8cd10 185 sim_cpu *current_cpu = STATE_CPU (sd, 0);
dde54cb8
DE
186 /* These are volatile to survive setjmp. */
187 volatile sim_cpu *cpu = current_cpu;
188 volatile sim_engine *engine = STATE_ENGINE (sd);
189 jmp_buf buf;
190 int jmpval;
b9c8cd10 191
dde54cb8 192 keep_running = ! step;
b9c8cd10 193 start_time = sim_elapsed_time_get ();
dde54cb8
DE
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. */
b9c8cd10
DE
197 insn_count = 0;
198
dde54cb8 199 engine->jmpbuf = &buf;
ebd58f4d
DE
200 sim_engine_set_run_state (sd, sim_running, 0);
201 pending_reason = sim_running;
202 pending_sigrc = 0;
203
204 /* ??? Restart support to be added in time. */
205
dde54cb8 206 if (setjmp (buf))
b9c8cd10 207 {
b500809f
DE
208 /* Account for the last insn executed. */
209 ++insn_count;
bcb829fd 210 TRACE_INSN_FINI ((sim_cpu *) cpu, 1);
b9c8cd10 211 }
ebd58f4d
DE
212 else
213 {
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
217 functions. */
dde54cb8
DE
218
219EOF
220
221if [ x$fast = xyes ] ; then
222 cat <<EOF
ebd58f4d
DE
223 if (step
224 || !RUN_FAST_P (current_cpu))
225 engine_resume_full (sd);
226 else
227 engine_resume_fast (sd);
dde54cb8
DE
228EOF
229else
230 cat <<EOF
ebd58f4d 231 engine_resume_full (sd);
dde54cb8
DE
232EOF
233fi
234
235cat <<EOF
236
ebd58f4d
DE
237 /* If the loop exits, either we single-stepped or @cpu@_engine_stop
238 was called. */
239 if (step)
240 sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
241 else
242 sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
243 }
244
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))
249 += insn_count;
dde54cb8
DE
250}
251
252EOF
253
b500809f
DE
254##########################################################################
255
dde54cb8
DE
256if [ x$scache = xyes ] ; then
257 cat <<EOF
258
259static void
260engine_resume_full (SIM_DESC sd)
261{
262#define FAST_P 0
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);
dde54cb8 266
b9c8cd10
DE
267EOF
268
269# Any initialization code before looping starts.
b500809f 270# Note that this code may declare some locals.
b9c8cd10
DE
271${SHELL} $file init
272
b500809f
DE
273if [ x$parallel = xyes ] ; then
274cat << EOF
275
276#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
277 {
6de2add2 278 if (! CPU_IDESC_READ_INIT_P (current_cpu))
b500809f
DE
279 {
280/* ??? Later maybe paste read.c in when building mainloop.c. */
281#define DEFINE_LABELS
282#include "readx.c"
6de2add2 283 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
b500809f
DE
284 }
285 }
286#endif
287
288EOF
289fi
290
b9c8cd10
DE
291cat <<EOF
292
dde54cb8
DE
293 do
294 {
295 /* FIXME: Later check every insn for events and such. */
b9c8cd10 296
dde54cb8
DE
297 SIM_PRE_EXEC_HOOK (current_cpu);
298
299 {
300 unsigned int hash;
301 SCACHE *sc;
302 PCADDR pc = PC;
303
304 /* First step: look up current insn in hash table. */
305 hash = SCACHE_HASH_PC (sd, pc);
306 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
307
308 /* If the entry isn't the one we want (cache miss),
309 fetch and decode the instruction. */
310 if (sc->argbuf.addr != pc)
311 {
312 insn_t insn;
313
314 PROFILE_COUNT_SCACHE_MISS (current_cpu);
315
316/* begin full-extract-scache */
317EOF
318
319${SHELL} $file full-extract-scache
320
321cat <<EOF
322/* end full-extract-scache */
323 }
324 else
325 {
326 PROFILE_COUNT_SCACHE_HIT (current_cpu);
b500809f
DE
327 /* Make core access statistics come out right.
328 The size is a guess, but it's currently not used either. */
bcb829fd 329 PROFILE_COUNT_CORE (current_cpu, pc, 2, exec_map);
dde54cb8
DE
330 }
331
332/* begin full-exec-scache */
333EOF
334
335${SHELL} $file full-exec-scache
336
337cat <<EOF
338/* end full-exec-scache */
339 }
340
341 SIM_POST_EXEC_HOOK (current_cpu);
342
343 ++insn_count;
344 }
345 while (keep_running);
346#undef FAST_P
347}
348EOF
349
b500809f
DE
350##########################################################################
351
dde54cb8
DE
352else # ! WITH_SCACHE
353 cat <<EOF
354
355static void
356engine_resume_full (SIM_DESC sd)
357{
358#define FAST_P 0
359 SIM_DESC current_state = sd;
360 sim_cpu *current_cpu = STATE_CPU (sd, 0);
361 SCACHE cache[MAX_LIW_INSNS];
362 SCACHE *sc = &cache[0];
dde54cb8
DE
363
364EOF
365
366# Any initialization code before looping starts.
b500809f 367# Note that this code may declare some locals.
dde54cb8
DE
368${SHELL} $file init
369
b500809f
DE
370if [ x$parallel = xyes ] ; then
371cat << EOF
372
373#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
374 {
6de2add2 375 if (! CPU_IDESC_READ_INIT_P (current_cpu))
b500809f
DE
376 {
377/* ??? Later maybe paste read.c in when building mainloop.c. */
378#define DEFINE_LABELS
379#include "readx.c"
6de2add2 380 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
b500809f
DE
381 }
382 }
383#endif
384
385EOF
386fi
387
dde54cb8
DE
388cat <<EOF
389
390 do
b9c8cd10 391 {
dde54cb8 392 /* FIXME: Later check every insn for events and such. */
b9c8cd10 393
dde54cb8 394 SIM_PRE_EXEC_HOOK (current_cpu);
b9c8cd10 395
dde54cb8
DE
396 {
397/* begin full-{extract,exec}-noscache */
b9c8cd10
DE
398EOF
399
dde54cb8
DE
400${SHELL} $file full-extract-noscache
401echo ""
402${SHELL} $file full-exec-noscache
b9c8cd10
DE
403
404cat <<EOF
dde54cb8
DE
405/* end full-{extract,exec}-noscache */
406 }
b9c8cd10 407
dde54cb8 408 SIM_POST_EXEC_HOOK (current_cpu);
b9c8cd10 409
dde54cb8 410 ++insn_count;
b9c8cd10 411 }
dde54cb8
DE
412 while (keep_running);
413#undef FAST_P
414}
415
416EOF
417fi # ! WITH_SCACHE
418
b500809f
DE
419##########################################################################
420
dde54cb8
DE
421if [ x$fast = xyes ] ; then
422 if [ x$scache = xyes ] ; then
423 cat <<EOF
424
425static void
426engine_resume_fast (SIM_DESC sd)
427{
428#define FAST_P 1
429 SIM_DESC current_state = sd;
430 sim_cpu *current_cpu = STATE_CPU (sd, 0);
dde54cb8
DE
431
432EOF
433
434# Any initialization code before looping starts.
b500809f 435# Note that this code may declare some locals.
dde54cb8
DE
436${SHELL} $file init
437
b500809f
DE
438if [ x$parallel = xyes ] ; then
439cat << EOF
440
441#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
442 {
6de2add2 443 if (! CPU_IDESC_READ_INIT_P (current_cpu))
b500809f
DE
444 {
445/* ??? Later maybe paste read.c in when building mainloop.c. */
446#define DEFINE_LABELS
447#include "readx.c"
6de2add2 448 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
b500809f
DE
449 }
450 }
451#endif
452
453EOF
454fi
455
dde54cb8
DE
456cat <<EOF
457
458#if defined (WITH_SEM_SWITCH_FAST) && defined (__GNUC__)
459 {
6de2add2 460 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
dde54cb8
DE
461 {
462/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
463#define DEFINE_LABELS
464#include "sem-switch.c"
6de2add2 465 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
dde54cb8
DE
466 }
467 }
468#endif
469
470 do
b9c8cd10 471 {
dde54cb8
DE
472 {
473 unsigned int hash;
474 SCACHE *sc;
475 PCADDR pc = PC;
476
477 /* First step: look up current insn in hash table. */
478 hash = SCACHE_HASH_PC (sd, pc);
479 sc = CPU_SCACHE_CACHE (current_cpu) + hash;
480
481 /* If the entry isn't the one we want (cache miss),
482 fetch and decode the instruction. */
483 if (sc->argbuf.addr != pc)
484 {
485 insn_t insn;
486
487/* begin fast-extract-scache */
488EOF
489
490${SHELL} $file fast-extract-scache
491
492cat <<EOF
493/* end fast-extract-scache */
494 }
495
496/* begin fast-exec-scache */
497EOF
498
499${SHELL} $file fast-exec-scache
500
501cat <<EOF
502/* end fast-exec-scache */
503
504 }
505
506 ++insn_count;
507 }
508 while (keep_running);
509#undef FAST_P
510}
511
512EOF
513
b500809f
DE
514##########################################################################
515
dde54cb8
DE
516else # ! WITH_SCACHE
517 cat <<EOF
518
519static void
520engine_resume_fast (SIM_DESC sd)
521{
522#define FAST_P 1
523 SIM_DESC current_state = sd;
524 sim_cpu *current_cpu = STATE_CPU (sd, 0);
525 SCACHE cache[MAX_LIW_INSNS];
526 SCACHE *sc = &cache[0];
b9c8cd10
DE
527
528EOF
529
dde54cb8 530# Any initialization code before looping starts.
b500809f 531# Note that this code may declare some locals.
dde54cb8 532${SHELL} $file init
b9c8cd10 533
b500809f
DE
534if [ x$parallel = xyes ] ; then
535cat << EOF
536
537#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
538 {
6de2add2 539 if (! CPU_IDESC_READ_INIT_P (current_cpu))
b500809f
DE
540 {
541/* ??? Later maybe paste read.c in when building mainloop.c. */
542#define DEFINE_LABELS
543#include "readx.c"
6de2add2 544 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
b500809f
DE
545 }
546 }
547#endif
548
549EOF
550fi
551
b9c8cd10
DE
552cat <<EOF
553
dde54cb8
DE
554 do
555 {
556/* begin fast-{extract,exec}-noscache */
557EOF
558
559${SHELL} $file fast-extract-noscache
560echo ""
561${SHELL} $file fast-exec-noscache
562
563cat <<EOF
564/* end fast-{extract,exec}-noscache */
565
566 ++insn_count;
b9c8cd10 567 }
dde54cb8
DE
568 while (keep_running);
569#undef FAST_P
b9c8cd10 570}
dde54cb8 571
b9c8cd10 572EOF
dde54cb8
DE
573
574 fi # ! WITH_SCACHE
575fi # -fast
This page took 0.086243 seconds and 4 git commands to generate.