]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/genmloop.sh
sim: common: add $LINENO rewriting support to genmloop scripts
[thirdparty/binutils-gdb.git] / sim / common / genmloop.sh
CommitLineData
c906108c 1# Generate the main loop of the simulator.
213516ef 2# Copyright (C) 1996-2023 Free Software Foundation, Inc.
c906108c
SS
3# Contributed by Cygnus Support.
4#
5# This file is part of the GNU simulators.
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
4744ac1b
JB
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
c906108c
SS
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#
4744ac1b
JB
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
c906108c
SS
19#
20# This file creates two files: eng.hin and mloop.cin.
21# eng.hin defines a few macros that specify what kind of engine was selected
22# based on the arguments to this script.
23# mloop.cin contains the engine.
24#
25# ??? Rename mloop.c to eng.c?
26# ??? Rename mainloop.in to engine.in?
27# ??? Add options to specify output file names?
28# ??? Rename this file to genengine.sh?
29#
30# Syntax: genmloop.sh [options]
31#
32# Options:
33#
34# -mono | -multi
35# - specify single cpu or multiple cpus (number specifyable at runtime),
36# maximum number is a configuration parameter
37# - -multi wip
38#
39# -fast: include support for fast execution in addition to full featured mode
40#
41# Full featured mode is for tracing, profiling, etc. and is always
42# provided. Fast mode contains no frills, except speed.
43# A target need only provide a "full" version of one of
44# simple,scache,pbb. If the target wants it can also provide a fast
45# version of same. It can't provide more than this.
46# ??? Later add ability to have another set of full/fast semantics
47# for use in with-devices/with-smp situations (pbb can be inappropriate
48# here).
49#
50# -full-switch: same as -fast but for full featured version of -switch
51# Only needed if -fast present.
52#
53# -simple: simple execution engine (the default)
54#
55# This engine fetches and executes one instruction at a time.
56# Field extraction is done in the semantic routines.
57#
58# ??? There are two possible flavours of -simple. One that extracts
59# fields in the semantic routine (which is what is implemented here),
60# and one that stores the extracted fields in ARGBUF before calling the
61# semantic routine. The latter is essentially the -scache case with a
62# cache size of one (and the scache lookup code removed). There are no
63# current uses of this and it's not clear when doing this would be a win.
64# More complicated ISA's that want to use -simple may find this a win.
65# Should this ever be desirable, implement a new engine style here and
66# call it -extract (or some such). It's believed that the CGEN-generated
67# code for the -scache case would be usable here, so no new code
68# generation option would be needed for CGEN.
69#
70# -scache: use the scache to speed things up (not always a win)
71#
72# This engine caches the extracted instruction before executing it.
73# When executing instructions they are first looked up in the scache.
74#
75# -pbb: same as -scache but extract a (pseudo-) basic block at a time
76#
77# This engine is basically identical to the scache version except that
78# extraction is done a pseudo-basic-block at a time and the address of
79# the scache entry of a branch target is recorded as well.
80# Additional speedups are then possible by defering Ctrl-C checking
81# to the end of basic blocks and by threading the insns together.
82# We call them pseudo-basic-block's instead of just basic-blocks because
83# they're not necessarily basic-blocks, though normally are.
84#
85# -parallel-read: support parallel execution with read-before-exec support.
86# -parallel-write: support parallel execution with write-after-exec support.
53a5351d
JM
87# -parallel-generic-write: support parallel execution with generic queued
88# writes.
c906108c
SS
89#
90# One of these options is specified in addition to -simple, -scache,
91# -pbb. Note that while the code can determine if the cpu supports
92# parallel execution with HAVE_PARALLEL_INSNS [and thus this option is
93# technically unnecessary], having this option cuts down on the clutter
94# in the result.
95#
53a5351d
JM
96# -parallel-only: semantic code only supports parallel version of insn
97#
98# Semantic code only supports parallel versions of each insn.
99# Things can be sped up by generating both serial and parallel versions
100# and is better suited to mixed parallel architectures like the m32r.
101#
bb4e03e5
BE
102# -prefix: string to prepend to function names in mloop.c/eng.h.
103#
104# If no prefix is specified, the cpu type is used.
105#
c906108c
SS
106# -switch file: specify file containing semantics implemented as a switch()
107#
108# -cpu <cpu-family>
109#
110# Specify the cpu family name.
111#
112# -infile <input-file>
113#
114# Specify the mainloop.in input file.
115#
bb4e03e5
BE
116# -outfile-suffix <output-file-suffix>
117#
118# Specify the suffix to append to output files.
119#
086c6838
NC
120# -shell <shell>
121#
122# Specify the shell to use to execute <input-file>
123#
c906108c
SS
124# Only one of -scache/-pbb may be selected.
125# -simple is the default.
126#
127####
128#
129# TODO
130# - build mainloop.in from .cpu file
131
132type=mono
133#scache=
134#fast=
135#full_switch=
136#pbb=
137parallel=no
53a5351d 138parallel_only=no
c906108c
SS
139switch=
140cpu="unknown"
141infile=""
bb4e03e5 142prefix="unknown"
0a129eb1 143outprefix=""
bb4e03e5 144outsuffix=""
c0e97c85 145lineno=""
c906108c
SS
146
147while test $# -gt 0
148do
149 case $1 in
150 -mono) type=mono ;;
151 -multi) type=multi ;;
152 -no-fast) ;;
153 -fast) fast=yes ;;
154 -full-switch) full_switch=yes ;;
155 -simple) ;;
156 -scache) scache=yes ;;
157 -pbb) pbb=yes ;;
158 -no-parallel) ;;
0a129eb1 159 -outfile-prefix) shift ; outprefix=$1 ;;
bb4e03e5 160 -outfile-suffix) shift ; outsuffix=$1 ;;
c906108c
SS
161 -parallel-read) parallel=read ;;
162 -parallel-write) parallel=write ;;
53a5351d
JM
163 -parallel-generic-write) parallel=genwrite ;;
164 -parallel-only) parallel_only=yes ;;
bb4e03e5 165 -prefix) shift ; prefix=$1 ;;
c906108c
SS
166 -switch) shift ; switch=$1 ;;
167 -cpu) shift ; cpu=$1 ;;
168 -infile) shift ; infile=$1 ;;
086c6838 169 -shell) shift ; SHELL=$1 ;;
c0e97c85
MF
170 -awk) shift ; AWK=$1 ; export AWK ;;
171 -lineno) shift ; lineno=$1 ;;
c906108c
SS
172 *) echo "unknown option: $1" >&2 ; exit 1 ;;
173 esac
174 shift
175done
176
177# Argument validation.
178
179if [ x$scache = xyes -a x$pbb = xyes ] ; then
180 echo "only one of -scache and -pbb may be selected" >&2
181 exit 1
182fi
183
184if [ "x$cpu" = xunknown ] ; then
185 echo "cpu family not specified" >&2
186 exit 1
187fi
188
189if [ "x$infile" = x ] ; then
190 echo "mainloop.in not specified" >&2
191 exit 1
192fi
193
bb4e03e5
BE
194if [ "x$prefix" = xunknown ] ; then
195 prefix=$cpu
196fi
197
c906108c
SS
198lowercase='abcdefghijklmnopqrstuvwxyz'
199uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
200CPU=`echo ${cpu} | tr "${lowercase}" "${uppercase}"`
bb4e03e5 201PREFIX=`echo ${prefix} | tr "${lowercase}" "${uppercase}"`
c906108c
SS
202
203##########################################################################
204
c0e97c85
MF
205load_infile_section() {
206 if [ -n "${lineno}" ]; then
207 ${SHELL} ${lineno} \
208 "${infile}" "${outprefix}mloop${outsuffix}.tmp" \
209 "$@"
210 else
211 ${SHELL} ${infile} "$@"
212 fi
213}
214
0a129eb1
MF
215rm -f ${outprefix}eng${outsuffix}.hin
216exec 1>${outprefix}eng${outsuffix}.hin
c906108c
SS
217
218echo "/* engine configuration for ${cpu} */"
219echo ""
220
221echo "/* WITH_FAST: non-zero if a fast version of the engine is available"
222echo " in addition to the full-featured version. */"
223if [ x$fast = xyes ] ; then
224 echo "#define WITH_FAST 1"
225else
226 echo "#define WITH_FAST 0"
227fi
228
229echo ""
bb4e03e5 230echo "/* WITH_SCACHE_PBB_${PREFIX}: non-zero if the pbb engine was selected. */"
c906108c 231if [ x$pbb = xyes ] ; then
bb4e03e5 232 echo "#define WITH_SCACHE_PBB_${PREFIX} 1"
c906108c 233else
bb4e03e5 234 echo "#define WITH_SCACHE_PBB_${PREFIX} 0"
c906108c
SS
235fi
236
237echo ""
238echo "/* HAVE_PARALLEL_INSNS: non-zero if cpu can parallelly execute > 1 insn. */"
53a5351d
JM
239# blah blah blah, other ways to do this, blah blah blah
240case x$parallel in
241xno)
242 echo "#define HAVE_PARALLEL_INSNS 0"
243 echo "#define WITH_PARALLEL_READ 0"
244 echo "#define WITH_PARALLEL_WRITE 0"
245 echo "#define WITH_PARALLEL_GENWRITE 0"
246 ;;
247xread)
248 echo "#define HAVE_PARALLEL_INSNS 1"
249 echo "/* Parallel execution is supported by read-before-exec. */"
250 echo "#define WITH_PARALLEL_READ 1"
251 echo "#define WITH_PARALLEL_WRITE 0"
252 echo "#define WITH_PARALLEL_GENWRITE 0"
253 ;;
254xwrite)
255 echo "#define HAVE_PARALLEL_INSNS 1"
256 echo "/* Parallel execution is supported by write-after-exec. */"
257 echo "#define WITH_PARALLEL_READ 0"
258 echo "#define WITH_PARALLEL_WRITE 1"
259 echo "#define WITH_PARALLEL_GENWRITE 0"
260 ;;
261xgenwrite)
262 echo "#define HAVE_PARALLEL_INSNS 1"
263 echo "/* Parallel execution is supported by generic write-after-exec. */"
264 echo "#define WITH_PARALLEL_READ 0"
265 echo "#define WITH_PARALLEL_WRITE 0"
266 echo "#define WITH_PARALLEL_GENWRITE 1"
267 ;;
268esac
c906108c
SS
269
270if [ "x$switch" != x ] ; then
271 echo ""
272 echo "/* WITH_SEM_SWITCH_FULL: non-zero if full-featured engine is"
273 echo " implemented as a switch(). */"
274 if [ x$fast != xyes -o x$full_switch = xyes ] ; then
275 echo "#define WITH_SEM_SWITCH_FULL 1"
276 else
277 echo "#define WITH_SEM_SWITCH_FULL 0"
278 fi
279 echo ""
280 echo "/* WITH_SEM_SWITCH_FAST: non-zero if fast engine is"
281 echo " implemented as a switch(). */"
282 if [ x$fast = xyes ] ; then
283 echo "#define WITH_SEM_SWITCH_FAST 1"
284 else
285 echo "#define WITH_SEM_SWITCH_FAST 0"
286 fi
287fi
288
289# Decls of functions we define.
290
291echo ""
292echo "/* Functions defined in the generated mainloop.c file"
293echo " (which doesn't necessarily have that file name). */"
294echo ""
bb4e03e5
BE
295echo "extern ENGINE_FN ${prefix}_engine_run_full;"
296echo "extern ENGINE_FN ${prefix}_engine_run_fast;"
c906108c
SS
297
298if [ x$pbb = xyes ] ; then
299 echo ""
bb4e03e5
BE
300 echo "extern SEM_PC ${prefix}_pbb_begin (SIM_CPU *, int);"
301 echo "extern SEM_PC ${prefix}_pbb_chain (SIM_CPU *, SEM_ARG);"
302 echo "extern SEM_PC ${prefix}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_BRANCH_TYPE, PCADDR);"
303 echo "extern void ${prefix}_pbb_before (SIM_CPU *, SCACHE *);"
304 echo "extern void ${prefix}_pbb_after (SIM_CPU *, SCACHE *);"
c906108c
SS
305fi
306
307##########################################################################
308
0a129eb1
MF
309rm -f ${outprefix}tmp-mloop-$$.cin ${outprefix}mloop${outsuffix}.cin
310exec 1>${outprefix}tmp-mloop-$$.cin
c906108c
SS
311
312# We use @cpu@ instead of ${cpu} because we still need to run sed to handle
313# transformation of @cpu@ for mainloop.in, so there's no need to use ${cpu}
314# here.
315
316cat << EOF
317/* This file is generated by the genmloop script. DO NOT EDIT! */
318
6df01ab8
MF
319/* This must come before any other includes. */
320#include "defs.h"
321
c906108c
SS
322/* Enable switch() support in cgen headers. */
323#define SEM_IN_SWITCH
324
325#define WANT_CPU @cpu@
326#define WANT_CPU_@CPU@
327
843bf754 328#include "ansidecl.h"
c906108c 329#include "bfd.h"
20a8e078
MF
330
331#include "sim-main.h"
c906108c
SS
332#include "cgen-mem.h"
333#include "cgen-ops.h"
334#include "sim-assert.h"
335
336/* Fill in the administrative ARGBUF fields required by all insns,
337 virtual and real. */
338
339static INLINE void
bb4e03e5 340@prefix@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc,
c906108c
SS
341 PCADDR pc, int fast_p)
342{
343#if WITH_SCACHE
344 SEM_SET_CODE (abuf, idesc, fast_p);
345 ARGBUF_ADDR (abuf) = pc;
346#endif
347 ARGBUF_IDESC (abuf) = idesc;
348}
349
350/* Fill in tracing/profiling fields of an ARGBUF. */
351
352static INLINE void
bb4e03e5 353@prefix@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf,
c906108c
SS
354 int trace_p, int profile_p)
355{
356 ARGBUF_TRACE_P (abuf) = trace_p;
357 ARGBUF_PROFILE_P (abuf) = profile_p;
358}
359
360#if WITH_SCACHE_PBB
361
362/* Emit the "x-before" handler.
363 x-before is emitted before each insn (serial or parallel).
364 This is as opposed to x-after which is only emitted at the end of a group
365 of parallel insns. */
366
3a275541 367ATTRIBUTE_UNUSED static INLINE void
bb4e03e5 368@prefix@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p)
c906108c
SS
369{
370 ARGBUF *abuf = &sc[0].argbuf;
bb4e03e5 371 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEFORE];
c906108c
SS
372
373 abuf->fields.before.first_p = first_p;
bb4e03e5 374 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
c906108c
SS
375 /* no need to set trace_p,profile_p */
376}
377
378/* Emit the "x-after" handler.
379 x-after is emitted after a serial insn or at the end of a group of
380 parallel insns. */
381
3a275541 382ATTRIBUTE_UNUSED static INLINE void
bb4e03e5 383@prefix@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc)
c906108c
SS
384{
385 ARGBUF *abuf = &sc[0].argbuf;
bb4e03e5 386 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_AFTER];
c906108c 387
bb4e03e5 388 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
c906108c
SS
389 /* no need to set trace_p,profile_p */
390}
391
392#endif /* WITH_SCACHE_PBB */
393
394EOF
395
c0e97c85 396load_infile_section support
c906108c
SS
397
398##########################################################################
399
400# Simple engine: fetch an instruction, execute the instruction.
401#
402# Instruction fields are not extracted into ARGBUF, they are extracted in
403# the semantic routines themselves. However, there is still a need to pass
404# and return misc. information to the semantic routines so we still use ARGBUF.
405# [One could certainly implement things differently and remove ARGBUF.
406# It's not clear this is necessarily always a win.]
407# ??? The use of the SCACHE struct is for consistency with the with-scache
408# case though it might be a source of confusion.
409
410if [ x$scache != xyes -a x$pbb != xyes ] ; then
411
412 cat << EOF
413
414#define FAST_P 0
415
416void
bb4e03e5 417@prefix@_engine_run_full (SIM_CPU *current_cpu)
c906108c
SS
418{
419#define FAST_P 0
420 SIM_DESC current_state = CPU_STATE (current_cpu);
421 /* ??? Use of SCACHE is a bit of a hack as we don't actually use the scache.
422 We do however use ARGBUF so for consistency with the other engine flavours
423 the SCACHE type is used. */
424 SCACHE cache[MAX_LIW_INSNS];
425 SCACHE *sc = &cache[0];
426
427EOF
428
53a5351d
JM
429case x$parallel in
430xread | xwrite)
431 cat << EOF
c906108c
SS
432 PAREXEC pbufs[MAX_PARALLEL_INSNS];
433 PAREXEC *par_exec;
434
435EOF
53a5351d
JM
436 ;;
437esac
c906108c
SS
438
439# Any initialization code before looping starts.
440# Note that this code may declare some locals.
c0e97c85 441load_infile_section init
c906108c 442
96baa820 443if [ x$parallel = xread ] ; then
c906108c
SS
444 cat << EOF
445
96baa820 446#if defined (__GNUC__)
c906108c
SS
447 {
448 if (! CPU_IDESC_READ_INIT_P (current_cpu))
449 {
450/* ??? Later maybe paste read.c in when building mainloop.c. */
451#define DEFINE_LABELS
452#include "readx.c"
453 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
454 }
455 }
456#endif
457
458EOF
459fi
460
461cat << EOF
462
96baa820
JM
463 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
464 {
465#if WITH_SEM_SWITCH_FULL
466#if defined (__GNUC__)
c906108c
SS
467/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
468#define DEFINE_LABELS
469#include "$switch"
c906108c 470#endif
96baa820 471#else
bb4e03e5 472 @prefix@_sem_init_idesc_table (current_cpu);
96baa820
JM
473#endif
474 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
475 }
c906108c
SS
476
477 do
478 {
479/* begin full-exec-simple */
480EOF
481
c0e97c85 482load_infile_section full-exec-simple
c906108c
SS
483
484cat << EOF
485/* end full-exec-simple */
486
487 ++ CPU_INSN_COUNT (current_cpu);
488 }
489 while (0 /*CPU_RUNNING_P (current_cpu)*/);
490}
491
492#undef FAST_P
493
494EOF
495
496####################################
497
498# Simple engine: fast version.
499# ??? A somewhat dubious effort, but for completeness' sake.
500
501if [ x$fast = xyes ] ; then
502
503 cat << EOF
504
505#define FAST_P 1
506
507FIXME: "fast simple version unimplemented, delete -fast arg to genmloop.sh."
508
509#undef FAST_P
510
511EOF
512
513fi # -fast
514
515fi # simple engine
516
517##########################################################################
518
96baa820
JM
519# Non-parallel scache engine: lookup insn in scache, fetch if missing,
520# then execute it.
c906108c 521
96baa820 522if [ x$scache = xyes -a x$parallel = xno ] ; then
c906108c
SS
523
524 cat << EOF
525
526static INLINE SCACHE *
bb4e03e5 527@prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
c906108c
SS
528 unsigned int hash_mask, int FAST_P)
529{
530 /* First step: look up current insn in hash table. */
531 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
532
533 /* If the entry isn't the one we want (cache miss),
534 fetch and decode the instruction. */
535 if (sc->argbuf.addr != vpc)
536 {
96baa820 537 if (! FAST_P)
c906108c
SS
538 PROFILE_COUNT_SCACHE_MISS (current_cpu);
539
540/* begin extract-scache */
541EOF
542
c0e97c85 543load_infile_section extract-scache
c906108c
SS
544
545cat << EOF
546/* end extract-scache */
547 }
96baa820 548 else if (! FAST_P)
c906108c
SS
549 {
550 PROFILE_COUNT_SCACHE_HIT (current_cpu);
551 /* Make core access statistics come out right.
552 The size is a guess, but it's currently not used either. */
553 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
554 }
555
556 return sc;
557}
558
559#define FAST_P 0
560
561void
bb4e03e5 562@prefix@_engine_run_full (SIM_CPU *current_cpu)
c906108c
SS
563{
564 SIM_DESC current_state = CPU_STATE (current_cpu);
565 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
566 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
567 SEM_PC vpc;
568
569EOF
570
96baa820
JM
571# Any initialization code before looping starts.
572# Note that this code may declare some locals.
c0e97c85 573load_infile_section init
96baa820
JM
574
575cat << EOF
576
577 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
578 {
579#if ! WITH_SEM_SWITCH_FULL
bb4e03e5 580 @prefix@_sem_init_idesc_table (current_cpu);
96baa820
JM
581#endif
582 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
583 }
584
585 vpc = GET_H_PC ();
586
587 do
588 {
589 SCACHE *sc;
590
bb4e03e5 591 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
96baa820
JM
592
593/* begin full-exec-scache */
594EOF
595
c0e97c85 596load_infile_section full-exec-scache
96baa820
JM
597
598cat << EOF
599/* end full-exec-scache */
600
601 SET_H_PC (vpc);
602
603 ++ CPU_INSN_COUNT (current_cpu);
604 }
605 while (0 /*CPU_RUNNING_P (current_cpu)*/);
606}
607
608#undef FAST_P
609
610EOF
611
612####################################
613
614# Non-parallel scache engine: fast version.
615
616if [ x$fast = xyes ] ; then
617
618 cat << EOF
619
620#define FAST_P 1
621
622void
bb4e03e5 623@prefix@_engine_run_fast (SIM_CPU *current_cpu)
96baa820
JM
624{
625 SIM_DESC current_state = CPU_STATE (current_cpu);
626 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
627 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
628 SEM_PC vpc;
c906108c
SS
629
630EOF
c906108c
SS
631
632# Any initialization code before looping starts.
633# Note that this code may declare some locals.
c0e97c85 634load_infile_section init
c906108c 635
96baa820 636cat << EOF
c906108c 637
96baa820
JM
638 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
639 {
640#if WITH_SEM_SWITCH_FAST
641#if defined (__GNUC__)
642/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
643#define DEFINE_LABELS
644#include "$switch"
645#endif
646#else
bb4e03e5 647 @prefix@_semf_init_idesc_table (current_cpu);
96baa820
JM
648#endif
649 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
650 }
651
652 vpc = GET_H_PC ();
653
654 do
655 {
656 SCACHE *sc;
657
bb4e03e5 658 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
96baa820
JM
659
660/* begin fast-exec-scache */
661EOF
662
c0e97c85 663load_infile_section fast-exec-scache
96baa820
JM
664
665cat << EOF
666/* end fast-exec-scache */
667
668 SET_H_PC (vpc);
669
670 ++ CPU_INSN_COUNT (current_cpu);
671 }
672 while (0 /*CPU_RUNNING_P (current_cpu)*/);
673}
674
675#undef FAST_P
676
677EOF
678
679fi # -fast
680
681fi # -scache && ! parallel
682
683##########################################################################
684
685# Parallel scache engine: lookup insn in scache, fetch if missing,
686# then execute it.
687# For the parallel case we give the target more flexibility.
688
689if [ x$scache = xyes -a x$parallel != xno ] ; then
690
691 cat << EOF
692
693static INLINE SCACHE *
bb4e03e5 694@prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
6426a772 695 unsigned int hash_mask, int FAST_P)
96baa820
JM
696{
697 /* First step: look up current insn in hash table. */
698 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
699
700 /* If the entry isn't the one we want (cache miss),
701 fetch and decode the instruction. */
702 if (sc->argbuf.addr != vpc)
703 {
704 if (! FAST_P)
705 PROFILE_COUNT_SCACHE_MISS (current_cpu);
706
6426a772 707#define SET_LAST_INSN_P(last_p) do { sc->last_insn_p = (last_p); } while (0)
96baa820
JM
708/* begin extract-scache */
709EOF
710
c0e97c85 711load_infile_section extract-scache
96baa820
JM
712
713cat << EOF
714/* end extract-scache */
715#undef SET_LAST_INSN_P
716 }
717 else if (! FAST_P)
718 {
719 PROFILE_COUNT_SCACHE_HIT (current_cpu);
720 /* Make core access statistics come out right.
721 The size is a guess, but it's currently not used either. */
722 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
723 }
724
725 return sc;
726}
727
728#define FAST_P 0
729
730void
bb4e03e5 731@prefix@_engine_run_full (SIM_CPU *current_cpu)
96baa820
JM
732{
733 SIM_DESC current_state = CPU_STATE (current_cpu);
734 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
735 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
736 SEM_PC vpc;
737
738EOF
739
740# Any initialization code before looping starts.
741# Note that this code may declare some locals.
c0e97c85 742load_infile_section init
96baa820
JM
743
744if [ x$parallel = xread ] ; then
745cat << EOF
746#if defined (__GNUC__)
c906108c
SS
747 {
748 if (! CPU_IDESC_READ_INIT_P (current_cpu))
749 {
750/* ??? Later maybe paste read.c in when building mainloop.c. */
751#define DEFINE_LABELS
752#include "readx.c"
753 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
754 }
755 }
756#endif
757
758EOF
759fi
760
761cat << EOF
762
96baa820
JM
763 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
764 {
765#if ! WITH_SEM_SWITCH_FULL
bb4e03e5 766 @prefix@_sem_init_idesc_table (current_cpu);
96baa820
JM
767#endif
768 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
769 }
770
c906108c
SS
771 vpc = GET_H_PC ();
772
773 do
774 {
c906108c
SS
775/* begin full-exec-scache */
776EOF
777
c0e97c85 778load_infile_section full-exec-scache
c906108c
SS
779
780cat << EOF
781/* end full-exec-scache */
c906108c
SS
782 }
783 while (0 /*CPU_RUNNING_P (current_cpu)*/);
784}
785
786#undef FAST_P
787
788EOF
789
790####################################
791
96baa820 792# Parallel scache engine: fast version.
c906108c
SS
793
794if [ x$fast = xyes ] ; then
795
796 cat << EOF
797
798#define FAST_P 1
799
800void
bb4e03e5 801@prefix@_engine_run_fast (SIM_CPU *current_cpu)
c906108c
SS
802{
803 SIM_DESC current_state = CPU_STATE (current_cpu);
804 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
805 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
806 SEM_PC vpc;
c906108c
SS
807 PAREXEC pbufs[MAX_PARALLEL_INSNS];
808 PAREXEC *par_exec;
809
810EOF
c906108c
SS
811
812# Any initialization code before looping starts.
813# Note that this code may declare some locals.
c0e97c85 814load_infile_section init
c906108c 815
96baa820
JM
816if [ x$parallel = xread ] ; then
817cat << EOF
c906108c 818
96baa820 819#if defined (__GNUC__)
c906108c
SS
820 {
821 if (! CPU_IDESC_READ_INIT_P (current_cpu))
822 {
823/* ??? Later maybe paste read.c in when building mainloop.c. */
824#define DEFINE_LABELS
825#include "readx.c"
826 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
827 }
828 }
829#endif
830
831EOF
96baa820 832fi
c906108c
SS
833
834cat << EOF
835
96baa820
JM
836 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
837 {
838#if WITH_SEM_SWITCH_FAST
839#if defined (__GNUC__)
c906108c
SS
840/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
841#define DEFINE_LABELS
842#include "$switch"
c906108c 843#endif
96baa820 844#else
bb4e03e5 845 @prefix@_semf_init_idesc_table (current_cpu);
96baa820
JM
846#endif
847 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
848 }
c906108c
SS
849
850 vpc = GET_H_PC ();
851
852 do
853 {
c906108c
SS
854/* begin fast-exec-scache */
855EOF
856
c0e97c85 857load_infile_section fast-exec-scache
c906108c
SS
858
859cat << EOF
860/* end fast-exec-scache */
c906108c
SS
861 }
862 while (0 /*CPU_RUNNING_P (current_cpu)*/);
863}
864
865#undef FAST_P
866
867EOF
868
869fi # -fast
870
96baa820 871fi # -scache && parallel
c906108c
SS
872
873##########################################################################
874
875# Compilation engine: lookup insn in scache, extract a pbb
876# (pseudo-basic-block) if missing, then execute the pbb.
877# A "pbb" is a sequence of insns up to the next cti insn or until
878# some prespecified maximum.
879# CTI: control transfer instruction.
880
881if [ x$pbb = xyes ] ; then
882
883 cat << EOF
884
885/* Record address of cti terminating a pbb. */
886#define SET_CTI_VPC(sc) do { _cti_sc = (sc); } while (0)
887/* Record number of [real] insns in pbb. */
888#define SET_INSN_COUNT(n) do { _insn_count = (n); } while (0)
889
890/* Fetch and extract a pseudo-basic-block.
891 FAST_P is non-zero if no tracing/profiling/etc. is wanted. */
892
893INLINE SEM_PC
bb4e03e5 894@prefix@_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
c906108c
SS
895{
896 SEM_PC new_vpc;
897 PCADDR pc;
898 SCACHE *sc;
899 int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu);
900
901 pc = GET_H_PC ();
902
903 new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc);
904 if (! new_vpc)
905 {
906 /* Leading '_' to avoid collision with mainloop.in. */
907 int _insn_count = 0;
908 SCACHE *orig_sc = sc;
909 SCACHE *_cti_sc = NULL;
910 int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu);
911
912 /* First figure out how many instructions to compile.
913 MAX_INSNS is the size of the allocated buffer, which includes space
914 for before/after handlers if they're being used.
915 SLICE_INSNS is the maxinum number of real insns that can be
916 executed. Zero means "as many as we want". */
917 /* ??? max_insns is serving two incompatible roles.
918 1) Number of slots available in scache buffer.
919 2) Number of real insns to execute.
920 They're incompatible because there are virtual insns emitted too
921 (chain,cti-chain,before,after handlers). */
922
923 if (slice_insns == 1)
924 {
925 /* No need to worry about extra slots required for virtual insns
926 and parallel exec support because MAX_CHAIN_LENGTH is
927 guaranteed to be big enough to execute at least 1 insn! */
928 max_insns = 1;
929 }
930 else
931 {
932 /* Allow enough slop so that while compiling insns, if max_insns > 0
933 then there's guaranteed to be enough space to emit one real insn.
934 MAX_CHAIN_LENGTH is typically much longer than
935 the normal number of insns between cti's anyway. */
936 max_insns -= (1 /* one for the trailing chain insn */
937 + (FAST_P
938 ? 0
939 : (1 + MAX_PARALLEL_INSNS) /* before+after */)
940 + (MAX_PARALLEL_INSNS > 1
941 ? (MAX_PARALLEL_INSNS * 2)
942 : 0));
943
944 /* Account for before/after handlers. */
945 if (! FAST_P)
946 slice_insns *= 3;
947
948 if (slice_insns > 0
949 && slice_insns < max_insns)
950 max_insns = slice_insns;
951 }
952
953 new_vpc = sc;
954
955 /* SC,PC must be updated to point passed the last entry used.
956 SET_CTI_VPC must be called if pbb is terminated by a cti.
957 SET_INSN_COUNT must be called to record number of real insns in
958 pbb [could be computed by us of course, extra cpu but perhaps
959 negligible enough]. */
960
961/* begin extract-pbb */
962EOF
963
c0e97c85 964load_infile_section extract-pbb
c906108c
SS
965
966cat << EOF
967/* end extract-pbb */
968
969 /* The last one is a pseudo-insn to link to the next chain.
970 It is also used to record the insn count for this chain. */
971 {
972 const IDESC *id;
973
974 /* Was pbb terminated by a cti? */
975 if (_cti_sc)
976 {
bb4e03e5 977 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CTI_CHAIN];
c906108c
SS
978 }
979 else
980 {
bb4e03e5 981 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CHAIN];
c906108c
SS
982 }
983 SEM_SET_CODE (&sc->argbuf, id, FAST_P);
984 sc->argbuf.idesc = id;
985 sc->argbuf.addr = pc;
986 sc->argbuf.fields.chain.insn_count = _insn_count;
987 sc->argbuf.fields.chain.next = 0;
96baa820 988 sc->argbuf.fields.chain.branch_target = 0;
c906108c
SS
989 ++sc;
990 }
991
085dd6e6
JM
992 /* Update the pointer to the next free entry, may not have used as
993 many entries as was asked for. */
c906108c
SS
994 CPU_SCACHE_NEXT_FREE (current_cpu) = sc;
995 /* Record length of chain if profiling.
996 This includes virtual insns since they count against
997 max_insns too. */
998 if (! FAST_P)
999 PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc);
1000 }
1001
1002 return new_vpc;
1003}
1004
1005/* Chain to the next block from a non-cti terminated previous block. */
1006
1007INLINE SEM_PC
bb4e03e5 1008@prefix@_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
c906108c
SS
1009{
1010 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1011
1012 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
1013
1014 SET_H_PC (abuf->addr);
1015
1016 /* If not running forever, exit back to main loop. */
1017 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
1018 /* Also exit back to main loop if there's an event.
1019 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1020 at the "right" time, but then that was what was asked for.
1021 There is no silver bullet for simulator engines.
1022 ??? Clearly this needs a cleaner interface.
1023 At present it's just so Ctrl-C works. */
1024 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1025 CPU_RUNNING_P (current_cpu) = 0;
1026
1027 /* If chained to next block, go straight to it. */
1028 if (abuf->fields.chain.next)
1029 return abuf->fields.chain.next;
1030 /* See if next block has already been compiled. */
1031 abuf->fields.chain.next = scache_lookup (current_cpu, abuf->addr);
1032 if (abuf->fields.chain.next)
1033 return abuf->fields.chain.next;
1034 /* Nope, so next insn is a virtual insn to invoke the compiler
1035 (begin a pbb). */
1036 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1037}
1038
1039/* Chain to the next block from a cti terminated previous block.
96baa820
JM
1040 BR_TYPE indicates whether the branch was taken and whether we can cache
1041 the vpc of the branch target.
c906108c 1042 NEW_PC is the target's branch address, and is only valid if
96baa820 1043 BR_TYPE != SEM_BRANCH_UNTAKEN. */
c906108c
SS
1044
1045INLINE SEM_PC
bb4e03e5 1046@prefix@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
96baa820 1047 SEM_BRANCH_TYPE br_type, PCADDR new_pc)
c906108c 1048{
96baa820
JM
1049 SEM_PC *new_vpc_ptr;
1050
c906108c
SS
1051 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
1052
1053 /* If not running forever, exit back to main loop. */
1054 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
1055 /* Also exit back to main loop if there's an event.
1056 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1057 at the "right" time, but then that was what was asked for.
1058 There is no silver bullet for simulator engines.
1059 ??? Clearly this needs a cleaner interface.
1060 At present it's just so Ctrl-C works. */
1061 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1062 CPU_RUNNING_P (current_cpu) = 0;
1063
1064 /* Restart compiler if we branched to an uncacheable address
1065 (e.g. "j reg"). */
96baa820 1066 if (br_type == SEM_BRANCH_UNCACHEABLE)
c906108c
SS
1067 {
1068 SET_H_PC (new_pc);
1069 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1070 }
1071
1072 /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our
1073 next chain ptr. */
96baa820 1074 if (br_type == SEM_BRANCH_UNTAKEN)
c906108c 1075 {
085dd6e6 1076 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
96baa820
JM
1077 new_pc = abuf->addr;
1078 SET_H_PC (new_pc);
c906108c
SS
1079 new_vpc_ptr = &abuf->fields.chain.next;
1080 }
1081 else
1082 {
96baa820 1083 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
c906108c 1084 SET_H_PC (new_pc);
96baa820 1085 new_vpc_ptr = &abuf->fields.chain.branch_target;
c906108c
SS
1086 }
1087
1088 /* If chained to next block, go straight to it. */
1089 if (*new_vpc_ptr)
1090 return *new_vpc_ptr;
1091 /* See if next block has already been compiled. */
96baa820 1092 *new_vpc_ptr = scache_lookup (current_cpu, new_pc);
c906108c
SS
1093 if (*new_vpc_ptr)
1094 return *new_vpc_ptr;
1095 /* Nope, so next insn is a virtual insn to invoke the compiler
1096 (begin a pbb). */
1097 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1098}
1099
1100/* x-before handler.
1101 This is called before each insn. */
1102
1103void
bb4e03e5 1104@prefix@_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
c906108c
SS
1105{
1106 SEM_ARG sem_arg = sc;
1107 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1108 int first_p = abuf->fields.before.first_p;
1109 const ARGBUF *cur_abuf = SEM_ARGBUF (sc + 1);
1110 const IDESC *cur_idesc = cur_abuf->idesc;
1111 PCADDR pc = cur_abuf->addr;
1112
1113 if (ARGBUF_PROFILE_P (cur_abuf))
1114 PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
1115
1116 /* If this isn't the first insn, finish up the previous one. */
1117
1118 if (! first_p)
1119 {
1120 if (PROFILE_MODEL_P (current_cpu))
1121 {
1122 const SEM_ARG prev_sem_arg = sc - 1;
1123 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1124 const IDESC *prev_idesc = prev_abuf->idesc;
1125 int cycles;
1126
1127 /* ??? May want to measure all insns if doing insn tracing. */
1128 if (ARGBUF_PROFILE_P (prev_abuf))
1129 {
1130 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
bb4e03e5 1131 @prefix@_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
c906108c
SS
1132 }
1133 }
1134
db7858e2 1135 CGEN_TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/);
c906108c
SS
1136 }
1137
1138 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */
1139 if (PROFILE_MODEL_P (current_cpu)
1140 && ARGBUF_PROFILE_P (cur_abuf))
bb4e03e5 1141 @prefix@_model_insn_before (current_cpu, first_p);
c906108c 1142
db7858e2
MF
1143 CGEN_TRACE_INSN_INIT (current_cpu, cur_abuf, first_p);
1144 CGEN_TRACE_INSN (current_cpu, cur_idesc->idata, cur_abuf, pc);
c906108c
SS
1145}
1146
1147/* x-after handler.
1148 This is called after a serial insn or at the end of a group of parallel
1149 insns. */
1150
1151void
bb4e03e5 1152@prefix@_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
c906108c 1153{
c906108c
SS
1154 const SEM_ARG prev_sem_arg = sc - 1;
1155 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1156
1157 /* ??? May want to measure all insns if doing insn tracing. */
1158 if (PROFILE_MODEL_P (current_cpu)
1159 && ARGBUF_PROFILE_P (prev_abuf))
1160 {
1161 const IDESC *prev_idesc = prev_abuf->idesc;
1162 int cycles;
1163
1164 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
bb4e03e5 1165 @prefix@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
c906108c 1166 }
db7858e2 1167 CGEN_TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/);
c906108c
SS
1168}
1169
1170#define FAST_P 0
1171
1172void
bb4e03e5 1173@prefix@_engine_run_full (SIM_CPU *current_cpu)
c906108c 1174{
c906108c
SS
1175 /* virtual program counter */
1176 SEM_PC vpc;
1177#if WITH_SEM_SWITCH_FULL
1178 /* For communication between cti's and cti-chain. */
babcfd75
TO
1179 SEM_BRANCH_TYPE pbb_br_type = SEM_BRANCH_UNTAKEN;
1180 PCADDR pbb_br_npc = 0;
c906108c
SS
1181#endif
1182
1183EOF
1184
53a5351d
JM
1185case x$parallel in
1186xread | xwrite)
1187 cat << EOF
c906108c
SS
1188 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1189 PAREXEC *par_exec = &pbufs[0];
1190
1191EOF
53a5351d
JM
1192 ;;
1193esac
c906108c
SS
1194
1195# Any initialization code before looping starts.
1196# Note that this code may declare some locals.
c0e97c85 1197load_infile_section init
c906108c
SS
1198
1199cat << EOF
1200
1201 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1202 {
1203 /* ??? 'twould be nice to move this up a level and only call it once.
1204 On the other hand, in the "let's go fast" case the test is only done
1205 once per pbb (since we only return to the main loop at the end of
1206 a pbb). And in the "let's run until we're done" case we don't return
1207 until the program exits. */
1208
96baa820
JM
1209#if WITH_SEM_SWITCH_FULL
1210#if defined (__GNUC__)
c906108c
SS
1211/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1212#define DEFINE_LABELS
1213#include "$switch"
96baa820
JM
1214#endif
1215#else
bb4e03e5 1216 @prefix@_sem_init_idesc_table (current_cpu);
c906108c
SS
1217#endif
1218
1219 /* Initialize the "begin (compile) a pbb" virtual insn. */
1220 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1221 SEM_SET_FULL_CODE (SEM_ARGBUF (vpc),
bb4e03e5
BE
1222 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1223 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
c906108c
SS
1224
1225 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1226 }
1227
1228 CPU_RUNNING_P (current_cpu) = 1;
1229 /* ??? In the case where we're returning to the main loop after every
1230 pbb we don't want to call pbb_begin each time (which hashes on the pc
1231 and does a table lookup). A way to speed this up is to save vpc
1232 between calls. */
bb4e03e5 1233 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
c906108c
SS
1234
1235 do
1236 {
1237/* begin full-exec-pbb */
1238EOF
1239
c0e97c85 1240load_infile_section full-exec-pbb
c906108c
SS
1241
1242cat << EOF
1243/* end full-exec-pbb */
1244 }
1245 while (CPU_RUNNING_P (current_cpu));
1246}
1247
1248#undef FAST_P
1249
1250EOF
1251
1252####################################
1253
1254# Compile engine: fast version.
1255
1256if [ x$fast = xyes ] ; then
1257
1258 cat << EOF
1259
1260#define FAST_P 1
1261
1262void
bb4e03e5 1263@prefix@_engine_run_fast (SIM_CPU *current_cpu)
c906108c 1264{
c906108c
SS
1265 /* virtual program counter */
1266 SEM_PC vpc;
1267#if WITH_SEM_SWITCH_FAST
1268 /* For communication between cti's and cti-chain. */
babcfd75
TO
1269 SEM_BRANCH_TYPE pbb_br_type = SEM_BRANCH_UNTAKEN;
1270 PCADDR pbb_br_npc = 0;
c906108c
SS
1271#endif
1272
1273EOF
1274
53a5351d
JM
1275case x$parallel in
1276xread | xwrite)
1277 cat << EOF
c906108c
SS
1278 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1279 PAREXEC *par_exec = &pbufs[0];
1280
1281EOF
53a5351d
JM
1282 ;;
1283esac
c906108c
SS
1284
1285# Any initialization code before looping starts.
1286# Note that this code may declare some locals.
c0e97c85 1287load_infile_section init
c906108c
SS
1288
1289cat << EOF
1290
1291 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1292 {
1293 /* ??? 'twould be nice to move this up a level and only call it once.
1294 On the other hand, in the "let's go fast" case the test is only done
1295 once per pbb (since we only return to the main loop at the end of
1296 a pbb). And in the "let's run until we're done" case we don't return
1297 until the program exits. */
1298
96baa820
JM
1299#if WITH_SEM_SWITCH_FAST
1300#if defined (__GNUC__)
c906108c
SS
1301/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1302#define DEFINE_LABELS
1303#include "$switch"
1304#endif
96baa820 1305#else
bb4e03e5 1306 @prefix@_semf_init_idesc_table (current_cpu);
96baa820 1307#endif
c906108c
SS
1308
1309 /* Initialize the "begin (compile) a pbb" virtual insn. */
1310 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1311 SEM_SET_FAST_CODE (SEM_ARGBUF (vpc),
bb4e03e5
BE
1312 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1313 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
c906108c
SS
1314
1315 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1316 }
1317
1318 CPU_RUNNING_P (current_cpu) = 1;
1319 /* ??? In the case where we're returning to the main loop after every
1320 pbb we don't want to call pbb_begin each time (which hashes on the pc
1321 and does a table lookup). A way to speed this up is to save vpc
1322 between calls. */
bb4e03e5 1323 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
c906108c
SS
1324
1325 do
1326 {
1327/* begin fast-exec-pbb */
1328EOF
1329
c0e97c85 1330load_infile_section fast-exec-pbb
c906108c
SS
1331
1332cat << EOF
1333/* end fast-exec-pbb */
1334 }
1335 while (CPU_RUNNING_P (current_cpu));
1336}
1337
1338#undef FAST_P
1339
1340EOF
1341fi # -fast
1342
1343fi # -pbb
1344
bb4e03e5
BE
1345# Expand @..@ macros appearing in tmp-mloop-{pid}.cin.
1346sed \
1347 -e "s/@cpu@/$cpu/g" -e "s/@CPU@/$CPU/g" \
0a129eb1
MF
1348 -e "s/@prefix@/$prefix/g" -e "s/@PREFIX@/$PREFIX/g" \
1349 < ${outprefix}tmp-mloop-$$.cin > ${outprefix}mloop${outsuffix}.cin
c906108c 1350rc=$?
0a129eb1 1351rm -f ${outprefix}tmp-mloop-$$.cin
c906108c
SS
1352
1353exit $rc