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