1 # Generate the main loop of the simulator.
2 # Copyright (C) 1996-2021 Free Software Foundation, Inc.
3 # Contributed by Cygnus Support.
5 # This file is part of the GNU simulators.
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
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
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.
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/>.
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.
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?
30 # Syntax: genmloop.sh [options]
35 # - specify single cpu or multiple cpus (number specifyable at runtime),
36 # maximum number is a configuration parameter
39 # -fast: include support for fast execution in addition to full featured mode
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
50 # -full-switch: same as -fast but for full featured version of -switch
51 # Only needed if -fast present.
53 # -simple: simple execution engine (the default)
55 # This engine fetches and executes one instruction at a time.
56 # Field extraction is done in the semantic routines.
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.
70 # -scache: use the scache to speed things up (not always a win)
72 # This engine caches the extracted instruction before executing it.
73 # When executing instructions they are first looked up in the scache.
75 # -pbb: same as -scache but extract a (pseudo-) basic block at a time
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.
85 # -parallel-read: support parallel execution with read-before-exec support.
86 # -parallel-write: support parallel execution with write-after-exec support.
87 # -parallel-generic-write: support parallel execution with generic queued
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
96 # -parallel-only: semantic code only supports parallel version of insn
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.
102 # -prefix: string to prepend to function names in mloop.c/eng.h.
104 # If no prefix is specified, the cpu type is used.
106 # -switch file: specify file containing semantics implemented as a switch()
110 # Specify the cpu family name.
112 # -infile <input-file>
114 # Specify the mainloop.in input file.
116 # -outfile-suffix <output-file-suffix>
118 # Specify the suffix to append to output files.
122 # Specify the shell to use to execute <input-file>
124 # Only one of -scache/-pbb may be selected.
125 # -simple is the default.
130 # - build mainloop.in from .cpu file
150 -multi) type=multi
;;
153 -full-switch) full_switch
=yes ;;
155 -scache) scache
=yes ;;
158 -outfile-prefix) shift ; outprefix
=$1 ;;
159 -outfile-suffix) shift ; outsuffix
=$1 ;;
160 -parallel-read) parallel
=read ;;
161 -parallel-write) parallel
=write ;;
162 -parallel-generic-write) parallel
=genwrite
;;
163 -parallel-only) parallel_only
=yes ;;
164 -prefix) shift ; prefix
=$1 ;;
165 -switch) shift ; switch
=$1 ;;
166 -cpu) shift ; cpu
=$1 ;;
167 -infile) shift ; infile
=$1 ;;
168 -shell) shift ; SHELL
=$1 ;;
169 *) echo "unknown option: $1" >&2 ; exit 1 ;;
174 # Argument validation.
176 if [ x
$scache = xyes
-a x
$pbb = xyes
] ; then
177 echo "only one of -scache and -pbb may be selected" >&2
181 if [ "x$cpu" = xunknown
] ; then
182 echo "cpu family not specified" >&2
186 if [ "x$infile" = x
] ; then
187 echo "mainloop.in not specified" >&2
191 if [ "x$prefix" = xunknown
] ; then
195 lowercase
='abcdefghijklmnopqrstuvwxyz'
196 uppercase
='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
197 CPU
=`echo ${cpu} | tr "${lowercase}" "${uppercase}"`
198 PREFIX
=`echo ${prefix} | tr "${lowercase}" "${uppercase}"`
200 ##########################################################################
202 rm -f ${outprefix}eng
${outsuffix}.hin
203 exec 1>${outprefix}eng
${outsuffix}.hin
205 echo "/* engine configuration for ${cpu} */"
208 echo "/* WITH_FAST: non-zero if a fast version of the engine is available"
209 echo " in addition to the full-featured version. */"
210 if [ x
$fast = xyes
] ; then
211 echo "#define WITH_FAST 1"
213 echo "#define WITH_FAST 0"
217 echo "/* WITH_SCACHE_PBB_${PREFIX}: non-zero if the pbb engine was selected. */"
218 if [ x
$pbb = xyes
] ; then
219 echo "#define WITH_SCACHE_PBB_${PREFIX} 1"
221 echo "#define WITH_SCACHE_PBB_${PREFIX} 0"
225 echo "/* HAVE_PARALLEL_INSNS: non-zero if cpu can parallelly execute > 1 insn. */"
226 # blah blah blah, other ways to do this, blah blah blah
229 echo "#define HAVE_PARALLEL_INSNS 0"
230 echo "#define WITH_PARALLEL_READ 0"
231 echo "#define WITH_PARALLEL_WRITE 0"
232 echo "#define WITH_PARALLEL_GENWRITE 0"
235 echo "#define HAVE_PARALLEL_INSNS 1"
236 echo "/* Parallel execution is supported by read-before-exec. */"
237 echo "#define WITH_PARALLEL_READ 1"
238 echo "#define WITH_PARALLEL_WRITE 0"
239 echo "#define WITH_PARALLEL_GENWRITE 0"
242 echo "#define HAVE_PARALLEL_INSNS 1"
243 echo "/* Parallel execution is supported by write-after-exec. */"
244 echo "#define WITH_PARALLEL_READ 0"
245 echo "#define WITH_PARALLEL_WRITE 1"
246 echo "#define WITH_PARALLEL_GENWRITE 0"
249 echo "#define HAVE_PARALLEL_INSNS 1"
250 echo "/* Parallel execution is supported by generic write-after-exec. */"
251 echo "#define WITH_PARALLEL_READ 0"
252 echo "#define WITH_PARALLEL_WRITE 0"
253 echo "#define WITH_PARALLEL_GENWRITE 1"
257 if [ "x$switch" != x
] ; then
259 echo "/* WITH_SEM_SWITCH_FULL: non-zero if full-featured engine is"
260 echo " implemented as a switch(). */"
261 if [ x
$fast != xyes
-o x
$full_switch = xyes
] ; then
262 echo "#define WITH_SEM_SWITCH_FULL 1"
264 echo "#define WITH_SEM_SWITCH_FULL 0"
267 echo "/* WITH_SEM_SWITCH_FAST: non-zero if fast engine is"
268 echo " implemented as a switch(). */"
269 if [ x
$fast = xyes
] ; then
270 echo "#define WITH_SEM_SWITCH_FAST 1"
272 echo "#define WITH_SEM_SWITCH_FAST 0"
276 # Decls of functions we define.
279 echo "/* Functions defined in the generated mainloop.c file"
280 echo " (which doesn't necessarily have that file name). */"
282 echo "extern ENGINE_FN ${prefix}_engine_run_full;"
283 echo "extern ENGINE_FN ${prefix}_engine_run_fast;"
285 if [ x
$pbb = xyes
] ; then
287 echo "extern SEM_PC ${prefix}_pbb_begin (SIM_CPU *, int);"
288 echo "extern SEM_PC ${prefix}_pbb_chain (SIM_CPU *, SEM_ARG);"
289 echo "extern SEM_PC ${prefix}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_BRANCH_TYPE, PCADDR);"
290 echo "extern void ${prefix}_pbb_before (SIM_CPU *, SCACHE *);"
291 echo "extern void ${prefix}_pbb_after (SIM_CPU *, SCACHE *);"
294 ##########################################################################
296 rm -f ${outprefix}tmp-mloop-$$.cin ${outprefix}mloop${outsuffix}.cin
297 exec 1>${outprefix}tmp-mloop-$$.cin
299 # We use @cpu@ instead of ${cpu} because we still need to run sed to handle
300 # transformation of @cpu@ for mainloop.in, so there's no need to use ${cpu}
304 /* This file is generated by the genmloop script. DO NOT EDIT! */
306 /* This must come before any other includes. */
309 /* Enable switch() support in cgen headers. */
310 #define SEM_IN_SWITCH
312 #define WANT_CPU @cpu@
313 #define WANT_CPU_@CPU@
317 #include "sim-main.h"
318 #include "cgen-mem.h"
319 #include "cgen-ops.h"
320 #include "sim-assert.h"
322 /* Fill in the administrative ARGBUF fields required by all insns,
326 @prefix@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc,
327 PCADDR pc, int fast_p)
330 SEM_SET_CODE (abuf, idesc, fast_p);
331 ARGBUF_ADDR (abuf) = pc;
333 ARGBUF_IDESC (abuf) = idesc;
336 /* Fill in tracing/profiling fields of an ARGBUF. */
339 @prefix@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf,
340 int trace_p, int profile_p)
342 ARGBUF_TRACE_P (abuf) = trace_p;
343 ARGBUF_PROFILE_P (abuf) = profile_p;
348 /* Emit the "x-before" handler.
349 x-before is emitted before each insn (serial or parallel).
350 This is as opposed to x-after which is only emitted at the end of a group
351 of parallel insns. */
353 ATTRIBUTE_UNUSED static INLINE void
354 @prefix@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p)
356 ARGBUF *abuf = &sc[0].argbuf;
357 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEFORE];
359 abuf->fields.before.first_p = first_p;
360 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
361 /* no need to set trace_p,profile_p */
364 /* Emit the "x-after" handler.
365 x-after is emitted after a serial insn or at the end of a group of
368 ATTRIBUTE_UNUSED static INLINE void
369 @prefix@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc)
371 ARGBUF *abuf = &sc[0].argbuf;
372 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_AFTER];
374 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
375 /* no need to set trace_p,profile_p */
378 #endif /* WITH_SCACHE_PBB */
382 ${SHELL} $infile support
384 ##########################################################################
386 # Simple engine: fetch an instruction, execute the instruction.
388 # Instruction fields are not extracted into ARGBUF, they are extracted in
389 # the semantic routines themselves. However, there is still a need to pass
390 # and return misc. information to the semantic routines so we still use ARGBUF.
391 # [One could certainly implement things differently and remove ARGBUF.
392 # It's not clear this is necessarily always a win.]
393 # ??? The use of the SCACHE struct is for consistency with the with-scache
394 # case though it might be a source of confusion.
396 if [ x
$scache != xyes
-a x
$pbb != xyes
] ; then
403 @prefix@_engine_run_full (SIM_CPU *current_cpu)
406 SIM_DESC current_state = CPU_STATE (current_cpu);
407 /* ??? Use of SCACHE is a bit of a hack as we don't actually use the scache.
408 We do however use ARGBUF so for consistency with the other engine flavours
409 the SCACHE type is used. */
410 SCACHE cache[MAX_LIW_INSNS];
411 SCACHE *sc = &cache[0];
418 PAREXEC pbufs[MAX_PARALLEL_INSNS];
425 # Any initialization code before looping starts.
426 # Note that this code may declare some locals.
427 ${SHELL} $infile init
429 if [ x
$parallel = xread
] ; then
432 #if defined (__GNUC__)
434 if (! CPU_IDESC_READ_INIT_P (current_cpu))
436 /* ??? Later maybe paste read.c in when building mainloop.c. */
437 #define DEFINE_LABELS
439 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
449 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
451 #if WITH_SEM_SWITCH_FULL
452 #if defined (__GNUC__)
453 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
454 #define DEFINE_LABELS
458 @prefix@_sem_init_idesc_table (current_cpu);
460 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
465 /* begin full-exec-simple */
468 ${SHELL} $infile full-exec-simple
471 /* end full-exec-simple */
473 ++ CPU_INSN_COUNT (current_cpu);
475 while (0 /*CPU_RUNNING_P (current_cpu)*/);
482 ####################################
484 # Simple engine: fast version.
485 # ??? A somewhat dubious effort, but for completeness' sake.
487 if [ x
$fast = xyes
] ; then
493 FIXME: "fast simple version unimplemented, delete -fast arg to genmloop.sh."
503 ##########################################################################
505 # Non-parallel scache engine: lookup insn in scache, fetch if missing,
508 if [ x
$scache = xyes
-a x
$parallel = xno
] ; then
512 static INLINE SCACHE *
513 @prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
514 unsigned int hash_mask, int FAST_P)
516 /* First step: look up current insn in hash table. */
517 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
519 /* If the entry isn't the one we want (cache miss),
520 fetch and decode the instruction. */
521 if (sc->argbuf.addr != vpc)
524 PROFILE_COUNT_SCACHE_MISS (current_cpu);
526 /* begin extract-scache */
529 ${SHELL} $infile extract-scache
532 /* end extract-scache */
536 PROFILE_COUNT_SCACHE_HIT (current_cpu);
537 /* Make core access statistics come out right.
538 The size is a guess, but it's currently not used either. */
539 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
548 @prefix@_engine_run_full (SIM_CPU *current_cpu)
550 SIM_DESC current_state = CPU_STATE (current_cpu);
551 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
552 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
557 # Any initialization code before looping starts.
558 # Note that this code may declare some locals.
559 ${SHELL} $infile init
563 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
565 #if ! WITH_SEM_SWITCH_FULL
566 @prefix@_sem_init_idesc_table (current_cpu);
568 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
577 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
579 /* begin full-exec-scache */
582 ${SHELL} $infile full-exec-scache
585 /* end full-exec-scache */
589 ++ CPU_INSN_COUNT (current_cpu);
591 while (0 /*CPU_RUNNING_P (current_cpu)*/);
598 ####################################
600 # Non-parallel scache engine: fast version.
602 if [ x
$fast = xyes
] ; then
609 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
611 SIM_DESC current_state = CPU_STATE (current_cpu);
612 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
613 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
618 # Any initialization code before looping starts.
619 # Note that this code may declare some locals.
620 ${SHELL} $infile init
624 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
626 #if WITH_SEM_SWITCH_FAST
627 #if defined (__GNUC__)
628 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
629 #define DEFINE_LABELS
633 @prefix@_semf_init_idesc_table (current_cpu);
635 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
644 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
646 /* begin fast-exec-scache */
649 ${SHELL} $infile fast-exec-scache
652 /* end fast-exec-scache */
656 ++ CPU_INSN_COUNT (current_cpu);
658 while (0 /*CPU_RUNNING_P (current_cpu)*/);
667 fi # -scache && ! parallel
669 ##########################################################################
671 # Parallel scache engine: lookup insn in scache, fetch if missing,
673 # For the parallel case we give the target more flexibility.
675 if [ x
$scache = xyes
-a x
$parallel != xno
] ; then
679 static INLINE SCACHE *
680 @prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
681 unsigned int hash_mask, int FAST_P)
683 /* First step: look up current insn in hash table. */
684 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
686 /* If the entry isn't the one we want (cache miss),
687 fetch and decode the instruction. */
688 if (sc->argbuf.addr != vpc)
691 PROFILE_COUNT_SCACHE_MISS (current_cpu);
693 #define SET_LAST_INSN_P(last_p) do { sc->last_insn_p = (last_p); } while (0)
694 /* begin extract-scache */
697 ${SHELL} $infile extract-scache
700 /* end extract-scache */
701 #undef SET_LAST_INSN_P
705 PROFILE_COUNT_SCACHE_HIT (current_cpu);
706 /* Make core access statistics come out right.
707 The size is a guess, but it's currently not used either. */
708 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
717 @prefix@_engine_run_full (SIM_CPU *current_cpu)
719 SIM_DESC current_state = CPU_STATE (current_cpu);
720 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
721 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
726 # Any initialization code before looping starts.
727 # Note that this code may declare some locals.
728 ${SHELL} $infile init
730 if [ x
$parallel = xread
] ; then
732 #if defined (__GNUC__)
734 if (! CPU_IDESC_READ_INIT_P (current_cpu))
736 /* ??? Later maybe paste read.c in when building mainloop.c. */
737 #define DEFINE_LABELS
739 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
749 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
751 #if ! WITH_SEM_SWITCH_FULL
752 @prefix@_sem_init_idesc_table (current_cpu);
754 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
761 /* begin full-exec-scache */
764 ${SHELL} $infile full-exec-scache
767 /* end full-exec-scache */
769 while (0 /*CPU_RUNNING_P (current_cpu)*/);
776 ####################################
778 # Parallel scache engine: fast version.
780 if [ x
$fast = xyes
] ; then
787 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
789 SIM_DESC current_state = CPU_STATE (current_cpu);
790 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
791 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
793 PAREXEC pbufs[MAX_PARALLEL_INSNS];
798 # Any initialization code before looping starts.
799 # Note that this code may declare some locals.
800 ${SHELL} $infile init
802 if [ x
$parallel = xread
] ; then
805 #if defined (__GNUC__)
807 if (! CPU_IDESC_READ_INIT_P (current_cpu))
809 /* ??? Later maybe paste read.c in when building mainloop.c. */
810 #define DEFINE_LABELS
812 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
822 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
824 #if WITH_SEM_SWITCH_FAST
825 #if defined (__GNUC__)
826 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
827 #define DEFINE_LABELS
831 @prefix@_semf_init_idesc_table (current_cpu);
833 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
840 /* begin fast-exec-scache */
843 ${SHELL} $infile fast-exec-scache
846 /* end fast-exec-scache */
848 while (0 /*CPU_RUNNING_P (current_cpu)*/);
857 fi # -scache && parallel
859 ##########################################################################
861 # Compilation engine: lookup insn in scache, extract a pbb
862 # (pseudo-basic-block) if missing, then execute the pbb.
863 # A "pbb" is a sequence of insns up to the next cti insn or until
864 # some prespecified maximum.
865 # CTI: control transfer instruction.
867 if [ x
$pbb = xyes
] ; then
871 /* Record address of cti terminating a pbb. */
872 #define SET_CTI_VPC(sc) do { _cti_sc = (sc); } while (0)
873 /* Record number of [real] insns in pbb. */
874 #define SET_INSN_COUNT(n) do { _insn_count = (n); } while (0)
876 /* Fetch and extract a pseudo-basic-block.
877 FAST_P is non-zero if no tracing/profiling/etc. is wanted. */
880 @prefix@_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
885 int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu);
889 new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc);
892 /* Leading '_' to avoid collision with mainloop.in. */
894 SCACHE *orig_sc = sc;
895 SCACHE *_cti_sc = NULL;
896 int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu);
898 /* First figure out how many instructions to compile.
899 MAX_INSNS is the size of the allocated buffer, which includes space
900 for before/after handlers if they're being used.
901 SLICE_INSNS is the maxinum number of real insns that can be
902 executed. Zero means "as many as we want". */
903 /* ??? max_insns is serving two incompatible roles.
904 1) Number of slots available in scache buffer.
905 2) Number of real insns to execute.
906 They're incompatible because there are virtual insns emitted too
907 (chain,cti-chain,before,after handlers). */
909 if (slice_insns == 1)
911 /* No need to worry about extra slots required for virtual insns
912 and parallel exec support because MAX_CHAIN_LENGTH is
913 guaranteed to be big enough to execute at least 1 insn! */
918 /* Allow enough slop so that while compiling insns, if max_insns > 0
919 then there's guaranteed to be enough space to emit one real insn.
920 MAX_CHAIN_LENGTH is typically much longer than
921 the normal number of insns between cti's anyway. */
922 max_insns -= (1 /* one for the trailing chain insn */
925 : (1 + MAX_PARALLEL_INSNS) /* before+after */)
926 + (MAX_PARALLEL_INSNS > 1
927 ? (MAX_PARALLEL_INSNS * 2)
930 /* Account for before/after handlers. */
935 && slice_insns < max_insns)
936 max_insns = slice_insns;
941 /* SC,PC must be updated to point passed the last entry used.
942 SET_CTI_VPC must be called if pbb is terminated by a cti.
943 SET_INSN_COUNT must be called to record number of real insns in
944 pbb [could be computed by us of course, extra cpu but perhaps
945 negligible enough]. */
947 /* begin extract-pbb */
950 ${SHELL} $infile extract-pbb
953 /* end extract-pbb */
955 /* The last one is a pseudo-insn to link to the next chain.
956 It is also used to record the insn count for this chain. */
960 /* Was pbb terminated by a cti? */
963 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CTI_CHAIN];
967 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CHAIN];
969 SEM_SET_CODE (&sc->argbuf, id, FAST_P);
970 sc->argbuf.idesc = id;
971 sc->argbuf.addr = pc;
972 sc->argbuf.fields.chain.insn_count = _insn_count;
973 sc->argbuf.fields.chain.next = 0;
974 sc->argbuf.fields.chain.branch_target = 0;
978 /* Update the pointer to the next free entry, may not have used as
979 many entries as was asked for. */
980 CPU_SCACHE_NEXT_FREE (current_cpu) = sc;
981 /* Record length of chain if profiling.
982 This includes virtual insns since they count against
985 PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc);
991 /* Chain to the next block from a non-cti terminated previous block. */
994 @prefix@_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
996 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
998 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
1000 SET_H_PC (abuf->addr);
1002 /* If not running forever, exit back to main loop. */
1003 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
1004 /* Also exit back to main loop if there's an event.
1005 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1006 at the "right" time, but then that was what was asked for.
1007 There is no silver bullet for simulator engines.
1008 ??? Clearly this needs a cleaner interface.
1009 At present it's just so Ctrl-C works. */
1010 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1011 CPU_RUNNING_P (current_cpu) = 0;
1013 /* If chained to next block, go straight to it. */
1014 if (abuf->fields.chain.next)
1015 return abuf->fields.chain.next;
1016 /* See if next block has already been compiled. */
1017 abuf->fields.chain.next = scache_lookup (current_cpu, abuf->addr);
1018 if (abuf->fields.chain.next)
1019 return abuf->fields.chain.next;
1020 /* Nope, so next insn is a virtual insn to invoke the compiler
1022 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1025 /* Chain to the next block from a cti terminated previous block.
1026 BR_TYPE indicates whether the branch was taken and whether we can cache
1027 the vpc of the branch target.
1028 NEW_PC is the target's branch address, and is only valid if
1029 BR_TYPE != SEM_BRANCH_UNTAKEN. */
1032 @prefix@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
1033 SEM_BRANCH_TYPE br_type, PCADDR new_pc)
1035 SEM_PC *new_vpc_ptr;
1037 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
1039 /* If not running forever, exit back to main loop. */
1040 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
1041 /* Also exit back to main loop if there's an event.
1042 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1043 at the "right" time, but then that was what was asked for.
1044 There is no silver bullet for simulator engines.
1045 ??? Clearly this needs a cleaner interface.
1046 At present it's just so Ctrl-C works. */
1047 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1048 CPU_RUNNING_P (current_cpu) = 0;
1050 /* Restart compiler if we branched to an uncacheable address
1052 if (br_type == SEM_BRANCH_UNCACHEABLE)
1055 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1058 /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our
1060 if (br_type == SEM_BRANCH_UNTAKEN)
1062 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1063 new_pc = abuf->addr;
1065 new_vpc_ptr = &abuf->fields.chain.next;
1069 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1071 new_vpc_ptr = &abuf->fields.chain.branch_target;
1074 /* If chained to next block, go straight to it. */
1076 return *new_vpc_ptr;
1077 /* See if next block has already been compiled. */
1078 *new_vpc_ptr = scache_lookup (current_cpu, new_pc);
1080 return *new_vpc_ptr;
1081 /* Nope, so next insn is a virtual insn to invoke the compiler
1083 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1086 /* x-before handler.
1087 This is called before each insn. */
1090 @prefix@_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
1092 SEM_ARG sem_arg = sc;
1093 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1094 int first_p = abuf->fields.before.first_p;
1095 const ARGBUF *cur_abuf = SEM_ARGBUF (sc + 1);
1096 const IDESC *cur_idesc = cur_abuf->idesc;
1097 PCADDR pc = cur_abuf->addr;
1099 if (ARGBUF_PROFILE_P (cur_abuf))
1100 PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
1102 /* If this isn't the first insn, finish up the previous one. */
1106 if (PROFILE_MODEL_P (current_cpu))
1108 const SEM_ARG prev_sem_arg = sc - 1;
1109 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1110 const IDESC *prev_idesc = prev_abuf->idesc;
1113 /* ??? May want to measure all insns if doing insn tracing. */
1114 if (ARGBUF_PROFILE_P (prev_abuf))
1116 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
1117 @prefix@_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
1121 CGEN_TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/);
1124 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */
1125 if (PROFILE_MODEL_P (current_cpu)
1126 && ARGBUF_PROFILE_P (cur_abuf))
1127 @prefix@_model_insn_before (current_cpu, first_p);
1129 CGEN_TRACE_INSN_INIT (current_cpu, cur_abuf, first_p);
1130 CGEN_TRACE_INSN (current_cpu, cur_idesc->idata, cur_abuf, pc);
1134 This is called after a serial insn or at the end of a group of parallel
1138 @prefix@_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
1140 SEM_ARG sem_arg = sc;
1141 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1142 const SEM_ARG prev_sem_arg = sc - 1;
1143 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1145 /* ??? May want to measure all insns if doing insn tracing. */
1146 if (PROFILE_MODEL_P (current_cpu)
1147 && ARGBUF_PROFILE_P (prev_abuf))
1149 const IDESC *prev_idesc = prev_abuf->idesc;
1152 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
1153 @prefix@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
1155 CGEN_TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/);
1161 @prefix@_engine_run_full (SIM_CPU *current_cpu)
1163 SIM_DESC current_state = CPU_STATE (current_cpu);
1164 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
1165 /* virtual program counter */
1167 #if WITH_SEM_SWITCH_FULL
1168 /* For communication between cti's and cti-chain. */
1169 SEM_BRANCH_TYPE pbb_br_type;
1178 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1179 PAREXEC *par_exec = &pbufs[0];
1185 # Any initialization code before looping starts.
1186 # Note that this code may declare some locals.
1187 ${SHELL} $infile init
1191 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1193 /* ??? 'twould be nice to move this up a level and only call it once.
1194 On the other hand, in the "let's go fast" case the test is only done
1195 once per pbb (since we only return to the main loop at the end of
1196 a pbb). And in the "let's run until we're done" case we don't return
1197 until the program exits. */
1199 #if WITH_SEM_SWITCH_FULL
1200 #if defined (__GNUC__)
1201 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1202 #define DEFINE_LABELS
1206 @prefix@_sem_init_idesc_table (current_cpu);
1209 /* Initialize the "begin (compile) a pbb" virtual insn. */
1210 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1211 SEM_SET_FULL_CODE (SEM_ARGBUF (vpc),
1212 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1213 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
1215 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1218 CPU_RUNNING_P (current_cpu) = 1;
1219 /* ??? In the case where we're returning to the main loop after every
1220 pbb we don't want to call pbb_begin each time (which hashes on the pc
1221 and does a table lookup). A way to speed this up is to save vpc
1223 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1227 /* begin full-exec-pbb */
1230 ${SHELL} $infile full-exec-pbb
1233 /* end full-exec-pbb */
1235 while (CPU_RUNNING_P (current_cpu));
1242 ####################################
1244 # Compile engine: fast version.
1246 if [ x
$fast = xyes
] ; then
1253 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
1255 SIM_DESC current_state = CPU_STATE (current_cpu);
1256 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
1257 /* virtual program counter */
1259 #if WITH_SEM_SWITCH_FAST
1260 /* For communication between cti's and cti-chain. */
1261 SEM_BRANCH_TYPE pbb_br_type;
1270 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1271 PAREXEC *par_exec = &pbufs[0];
1277 # Any initialization code before looping starts.
1278 # Note that this code may declare some locals.
1279 ${SHELL} $infile init
1283 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1285 /* ??? 'twould be nice to move this up a level and only call it once.
1286 On the other hand, in the "let's go fast" case the test is only done
1287 once per pbb (since we only return to the main loop at the end of
1288 a pbb). And in the "let's run until we're done" case we don't return
1289 until the program exits. */
1291 #if WITH_SEM_SWITCH_FAST
1292 #if defined (__GNUC__)
1293 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1294 #define DEFINE_LABELS
1298 @prefix@_semf_init_idesc_table (current_cpu);
1301 /* Initialize the "begin (compile) a pbb" virtual insn. */
1302 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1303 SEM_SET_FAST_CODE (SEM_ARGBUF (vpc),
1304 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1305 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
1307 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1310 CPU_RUNNING_P (current_cpu) = 1;
1311 /* ??? In the case where we're returning to the main loop after every
1312 pbb we don't want to call pbb_begin each time (which hashes on the pc
1313 and does a table lookup). A way to speed this up is to save vpc
1315 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1319 /* begin fast-exec-pbb */
1322 ${SHELL} $infile fast-exec-pbb
1325 /* end fast-exec-pbb */
1327 while (CPU_RUNNING_P (current_cpu));
1337 # Expand @..@ macros appearing in tmp-mloop-{pid}.cin.
1339 -e "s/@cpu@/$cpu/g" -e "s/@CPU@/$CPU/g" \
1340 -e "s/@prefix@/$prefix/g" -e "s/@PREFIX@/$PREFIX/g" \
1341 < ${outprefix}tmp-mloop-$$.cin > ${outprefix}mloop${outsuffix}.cin
1343 rm -f ${outprefix}tmp-mloop-$$.cin