1 # Generate the main loop of the simulator.
2 # Copyright (C) 1996-2022 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@
315 #include "ansidecl.h"
318 #include "sim-main.h"
319 #include "cgen-mem.h"
320 #include "cgen-ops.h"
321 #include "sim-assert.h"
323 /* Fill in the administrative ARGBUF fields required by all insns,
327 @prefix@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc,
328 PCADDR pc, int fast_p)
331 SEM_SET_CODE (abuf, idesc, fast_p);
332 ARGBUF_ADDR (abuf) = pc;
334 ARGBUF_IDESC (abuf) = idesc;
337 /* Fill in tracing/profiling fields of an ARGBUF. */
340 @prefix@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf,
341 int trace_p, int profile_p)
343 ARGBUF_TRACE_P (abuf) = trace_p;
344 ARGBUF_PROFILE_P (abuf) = profile_p;
349 /* Emit the "x-before" handler.
350 x-before is emitted before each insn (serial or parallel).
351 This is as opposed to x-after which is only emitted at the end of a group
352 of parallel insns. */
354 ATTRIBUTE_UNUSED static INLINE void
355 @prefix@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p)
357 ARGBUF *abuf = &sc[0].argbuf;
358 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEFORE];
360 abuf->fields.before.first_p = first_p;
361 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
362 /* no need to set trace_p,profile_p */
365 /* Emit the "x-after" handler.
366 x-after is emitted after a serial insn or at the end of a group of
369 ATTRIBUTE_UNUSED static INLINE void
370 @prefix@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc)
372 ARGBUF *abuf = &sc[0].argbuf;
373 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_AFTER];
375 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
376 /* no need to set trace_p,profile_p */
379 #endif /* WITH_SCACHE_PBB */
383 ${SHELL} $infile support
385 ##########################################################################
387 # Simple engine: fetch an instruction, execute the instruction.
389 # Instruction fields are not extracted into ARGBUF, they are extracted in
390 # the semantic routines themselves. However, there is still a need to pass
391 # and return misc. information to the semantic routines so we still use ARGBUF.
392 # [One could certainly implement things differently and remove ARGBUF.
393 # It's not clear this is necessarily always a win.]
394 # ??? The use of the SCACHE struct is for consistency with the with-scache
395 # case though it might be a source of confusion.
397 if [ x
$scache != xyes
-a x
$pbb != xyes
] ; then
404 @prefix@_engine_run_full (SIM_CPU *current_cpu)
407 SIM_DESC current_state = CPU_STATE (current_cpu);
408 /* ??? Use of SCACHE is a bit of a hack as we don't actually use the scache.
409 We do however use ARGBUF so for consistency with the other engine flavours
410 the SCACHE type is used. */
411 SCACHE cache[MAX_LIW_INSNS];
412 SCACHE *sc = &cache[0];
419 PAREXEC pbufs[MAX_PARALLEL_INSNS];
426 # Any initialization code before looping starts.
427 # Note that this code may declare some locals.
428 ${SHELL} $infile init
430 if [ x
$parallel = xread
] ; then
433 #if defined (__GNUC__)
435 if (! CPU_IDESC_READ_INIT_P (current_cpu))
437 /* ??? Later maybe paste read.c in when building mainloop.c. */
438 #define DEFINE_LABELS
440 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
450 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
452 #if WITH_SEM_SWITCH_FULL
453 #if defined (__GNUC__)
454 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
455 #define DEFINE_LABELS
459 @prefix@_sem_init_idesc_table (current_cpu);
461 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
466 /* begin full-exec-simple */
469 ${SHELL} $infile full-exec-simple
472 /* end full-exec-simple */
474 ++ CPU_INSN_COUNT (current_cpu);
476 while (0 /*CPU_RUNNING_P (current_cpu)*/);
483 ####################################
485 # Simple engine: fast version.
486 # ??? A somewhat dubious effort, but for completeness' sake.
488 if [ x
$fast = xyes
] ; then
494 FIXME: "fast simple version unimplemented, delete -fast arg to genmloop.sh."
504 ##########################################################################
506 # Non-parallel scache engine: lookup insn in scache, fetch if missing,
509 if [ x
$scache = xyes
-a x
$parallel = xno
] ; then
513 static INLINE SCACHE *
514 @prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
515 unsigned int hash_mask, int FAST_P)
517 /* First step: look up current insn in hash table. */
518 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
520 /* If the entry isn't the one we want (cache miss),
521 fetch and decode the instruction. */
522 if (sc->argbuf.addr != vpc)
525 PROFILE_COUNT_SCACHE_MISS (current_cpu);
527 /* begin extract-scache */
530 ${SHELL} $infile extract-scache
533 /* end extract-scache */
537 PROFILE_COUNT_SCACHE_HIT (current_cpu);
538 /* Make core access statistics come out right.
539 The size is a guess, but it's currently not used either. */
540 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
549 @prefix@_engine_run_full (SIM_CPU *current_cpu)
551 SIM_DESC current_state = CPU_STATE (current_cpu);
552 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
553 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
558 # Any initialization code before looping starts.
559 # Note that this code may declare some locals.
560 ${SHELL} $infile init
564 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
566 #if ! WITH_SEM_SWITCH_FULL
567 @prefix@_sem_init_idesc_table (current_cpu);
569 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
578 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
580 /* begin full-exec-scache */
583 ${SHELL} $infile full-exec-scache
586 /* end full-exec-scache */
590 ++ CPU_INSN_COUNT (current_cpu);
592 while (0 /*CPU_RUNNING_P (current_cpu)*/);
599 ####################################
601 # Non-parallel scache engine: fast version.
603 if [ x
$fast = xyes
] ; then
610 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
612 SIM_DESC current_state = CPU_STATE (current_cpu);
613 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
614 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
619 # Any initialization code before looping starts.
620 # Note that this code may declare some locals.
621 ${SHELL} $infile init
625 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
627 #if WITH_SEM_SWITCH_FAST
628 #if defined (__GNUC__)
629 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
630 #define DEFINE_LABELS
634 @prefix@_semf_init_idesc_table (current_cpu);
636 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
645 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
647 /* begin fast-exec-scache */
650 ${SHELL} $infile fast-exec-scache
653 /* end fast-exec-scache */
657 ++ CPU_INSN_COUNT (current_cpu);
659 while (0 /*CPU_RUNNING_P (current_cpu)*/);
668 fi # -scache && ! parallel
670 ##########################################################################
672 # Parallel scache engine: lookup insn in scache, fetch if missing,
674 # For the parallel case we give the target more flexibility.
676 if [ x
$scache = xyes
-a x
$parallel != xno
] ; then
680 static INLINE SCACHE *
681 @prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
682 unsigned int hash_mask, int FAST_P)
684 /* First step: look up current insn in hash table. */
685 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
687 /* If the entry isn't the one we want (cache miss),
688 fetch and decode the instruction. */
689 if (sc->argbuf.addr != vpc)
692 PROFILE_COUNT_SCACHE_MISS (current_cpu);
694 #define SET_LAST_INSN_P(last_p) do { sc->last_insn_p = (last_p); } while (0)
695 /* begin extract-scache */
698 ${SHELL} $infile extract-scache
701 /* end extract-scache */
702 #undef SET_LAST_INSN_P
706 PROFILE_COUNT_SCACHE_HIT (current_cpu);
707 /* Make core access statistics come out right.
708 The size is a guess, but it's currently not used either. */
709 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
718 @prefix@_engine_run_full (SIM_CPU *current_cpu)
720 SIM_DESC current_state = CPU_STATE (current_cpu);
721 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
722 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
727 # Any initialization code before looping starts.
728 # Note that this code may declare some locals.
729 ${SHELL} $infile init
731 if [ x
$parallel = xread
] ; then
733 #if defined (__GNUC__)
735 if (! CPU_IDESC_READ_INIT_P (current_cpu))
737 /* ??? Later maybe paste read.c in when building mainloop.c. */
738 #define DEFINE_LABELS
740 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
750 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
752 #if ! WITH_SEM_SWITCH_FULL
753 @prefix@_sem_init_idesc_table (current_cpu);
755 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
762 /* begin full-exec-scache */
765 ${SHELL} $infile full-exec-scache
768 /* end full-exec-scache */
770 while (0 /*CPU_RUNNING_P (current_cpu)*/);
777 ####################################
779 # Parallel scache engine: fast version.
781 if [ x
$fast = xyes
] ; then
788 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
790 SIM_DESC current_state = CPU_STATE (current_cpu);
791 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
792 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
794 PAREXEC pbufs[MAX_PARALLEL_INSNS];
799 # Any initialization code before looping starts.
800 # Note that this code may declare some locals.
801 ${SHELL} $infile init
803 if [ x
$parallel = xread
] ; then
806 #if defined (__GNUC__)
808 if (! CPU_IDESC_READ_INIT_P (current_cpu))
810 /* ??? Later maybe paste read.c in when building mainloop.c. */
811 #define DEFINE_LABELS
813 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
823 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
825 #if WITH_SEM_SWITCH_FAST
826 #if defined (__GNUC__)
827 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
828 #define DEFINE_LABELS
832 @prefix@_semf_init_idesc_table (current_cpu);
834 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
841 /* begin fast-exec-scache */
844 ${SHELL} $infile fast-exec-scache
847 /* end fast-exec-scache */
849 while (0 /*CPU_RUNNING_P (current_cpu)*/);
858 fi # -scache && parallel
860 ##########################################################################
862 # Compilation engine: lookup insn in scache, extract a pbb
863 # (pseudo-basic-block) if missing, then execute the pbb.
864 # A "pbb" is a sequence of insns up to the next cti insn or until
865 # some prespecified maximum.
866 # CTI: control transfer instruction.
868 if [ x
$pbb = xyes
] ; then
872 /* Record address of cti terminating a pbb. */
873 #define SET_CTI_VPC(sc) do { _cti_sc = (sc); } while (0)
874 /* Record number of [real] insns in pbb. */
875 #define SET_INSN_COUNT(n) do { _insn_count = (n); } while (0)
877 /* Fetch and extract a pseudo-basic-block.
878 FAST_P is non-zero if no tracing/profiling/etc. is wanted. */
881 @prefix@_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
886 int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu);
890 new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc);
893 /* Leading '_' to avoid collision with mainloop.in. */
895 SCACHE *orig_sc = sc;
896 SCACHE *_cti_sc = NULL;
897 int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu);
899 /* First figure out how many instructions to compile.
900 MAX_INSNS is the size of the allocated buffer, which includes space
901 for before/after handlers if they're being used.
902 SLICE_INSNS is the maxinum number of real insns that can be
903 executed. Zero means "as many as we want". */
904 /* ??? max_insns is serving two incompatible roles.
905 1) Number of slots available in scache buffer.
906 2) Number of real insns to execute.
907 They're incompatible because there are virtual insns emitted too
908 (chain,cti-chain,before,after handlers). */
910 if (slice_insns == 1)
912 /* No need to worry about extra slots required for virtual insns
913 and parallel exec support because MAX_CHAIN_LENGTH is
914 guaranteed to be big enough to execute at least 1 insn! */
919 /* Allow enough slop so that while compiling insns, if max_insns > 0
920 then there's guaranteed to be enough space to emit one real insn.
921 MAX_CHAIN_LENGTH is typically much longer than
922 the normal number of insns between cti's anyway. */
923 max_insns -= (1 /* one for the trailing chain insn */
926 : (1 + MAX_PARALLEL_INSNS) /* before+after */)
927 + (MAX_PARALLEL_INSNS > 1
928 ? (MAX_PARALLEL_INSNS * 2)
931 /* Account for before/after handlers. */
936 && slice_insns < max_insns)
937 max_insns = slice_insns;
942 /* SC,PC must be updated to point passed the last entry used.
943 SET_CTI_VPC must be called if pbb is terminated by a cti.
944 SET_INSN_COUNT must be called to record number of real insns in
945 pbb [could be computed by us of course, extra cpu but perhaps
946 negligible enough]. */
948 /* begin extract-pbb */
951 ${SHELL} $infile extract-pbb
954 /* end extract-pbb */
956 /* The last one is a pseudo-insn to link to the next chain.
957 It is also used to record the insn count for this chain. */
961 /* Was pbb terminated by a cti? */
964 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CTI_CHAIN];
968 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CHAIN];
970 SEM_SET_CODE (&sc->argbuf, id, FAST_P);
971 sc->argbuf.idesc = id;
972 sc->argbuf.addr = pc;
973 sc->argbuf.fields.chain.insn_count = _insn_count;
974 sc->argbuf.fields.chain.next = 0;
975 sc->argbuf.fields.chain.branch_target = 0;
979 /* Update the pointer to the next free entry, may not have used as
980 many entries as was asked for. */
981 CPU_SCACHE_NEXT_FREE (current_cpu) = sc;
982 /* Record length of chain if profiling.
983 This includes virtual insns since they count against
986 PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc);
992 /* Chain to the next block from a non-cti terminated previous block. */
995 @prefix@_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
997 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
999 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
1001 SET_H_PC (abuf->addr);
1003 /* If not running forever, exit back to main loop. */
1004 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
1005 /* Also exit back to main loop if there's an event.
1006 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1007 at the "right" time, but then that was what was asked for.
1008 There is no silver bullet for simulator engines.
1009 ??? Clearly this needs a cleaner interface.
1010 At present it's just so Ctrl-C works. */
1011 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1012 CPU_RUNNING_P (current_cpu) = 0;
1014 /* If chained to next block, go straight to it. */
1015 if (abuf->fields.chain.next)
1016 return abuf->fields.chain.next;
1017 /* See if next block has already been compiled. */
1018 abuf->fields.chain.next = scache_lookup (current_cpu, abuf->addr);
1019 if (abuf->fields.chain.next)
1020 return abuf->fields.chain.next;
1021 /* Nope, so next insn is a virtual insn to invoke the compiler
1023 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1026 /* Chain to the next block from a cti terminated previous block.
1027 BR_TYPE indicates whether the branch was taken and whether we can cache
1028 the vpc of the branch target.
1029 NEW_PC is the target's branch address, and is only valid if
1030 BR_TYPE != SEM_BRANCH_UNTAKEN. */
1033 @prefix@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
1034 SEM_BRANCH_TYPE br_type, PCADDR new_pc)
1036 SEM_PC *new_vpc_ptr;
1038 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
1040 /* If not running forever, exit back to main loop. */
1041 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
1042 /* Also exit back to main loop if there's an event.
1043 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1044 at the "right" time, but then that was what was asked for.
1045 There is no silver bullet for simulator engines.
1046 ??? Clearly this needs a cleaner interface.
1047 At present it's just so Ctrl-C works. */
1048 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1049 CPU_RUNNING_P (current_cpu) = 0;
1051 /* Restart compiler if we branched to an uncacheable address
1053 if (br_type == SEM_BRANCH_UNCACHEABLE)
1056 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1059 /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our
1061 if (br_type == SEM_BRANCH_UNTAKEN)
1063 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1064 new_pc = abuf->addr;
1066 new_vpc_ptr = &abuf->fields.chain.next;
1070 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1072 new_vpc_ptr = &abuf->fields.chain.branch_target;
1075 /* If chained to next block, go straight to it. */
1077 return *new_vpc_ptr;
1078 /* See if next block has already been compiled. */
1079 *new_vpc_ptr = scache_lookup (current_cpu, new_pc);
1081 return *new_vpc_ptr;
1082 /* Nope, so next insn is a virtual insn to invoke the compiler
1084 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1087 /* x-before handler.
1088 This is called before each insn. */
1091 @prefix@_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
1093 SEM_ARG sem_arg = sc;
1094 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1095 int first_p = abuf->fields.before.first_p;
1096 const ARGBUF *cur_abuf = SEM_ARGBUF (sc + 1);
1097 const IDESC *cur_idesc = cur_abuf->idesc;
1098 PCADDR pc = cur_abuf->addr;
1100 if (ARGBUF_PROFILE_P (cur_abuf))
1101 PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
1103 /* If this isn't the first insn, finish up the previous one. */
1107 if (PROFILE_MODEL_P (current_cpu))
1109 const SEM_ARG prev_sem_arg = sc - 1;
1110 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1111 const IDESC *prev_idesc = prev_abuf->idesc;
1114 /* ??? May want to measure all insns if doing insn tracing. */
1115 if (ARGBUF_PROFILE_P (prev_abuf))
1117 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
1118 @prefix@_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
1122 CGEN_TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/);
1125 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */
1126 if (PROFILE_MODEL_P (current_cpu)
1127 && ARGBUF_PROFILE_P (cur_abuf))
1128 @prefix@_model_insn_before (current_cpu, first_p);
1130 CGEN_TRACE_INSN_INIT (current_cpu, cur_abuf, first_p);
1131 CGEN_TRACE_INSN (current_cpu, cur_idesc->idata, cur_abuf, pc);
1135 This is called after a serial insn or at the end of a group of parallel
1139 @prefix@_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
1141 SEM_ARG sem_arg = sc;
1142 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1143 const SEM_ARG prev_sem_arg = sc - 1;
1144 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1146 /* ??? May want to measure all insns if doing insn tracing. */
1147 if (PROFILE_MODEL_P (current_cpu)
1148 && ARGBUF_PROFILE_P (prev_abuf))
1150 const IDESC *prev_idesc = prev_abuf->idesc;
1153 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
1154 @prefix@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
1156 CGEN_TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/);
1162 @prefix@_engine_run_full (SIM_CPU *current_cpu)
1164 SIM_DESC current_state = CPU_STATE (current_cpu);
1165 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
1166 /* virtual program counter */
1168 #if WITH_SEM_SWITCH_FULL
1169 /* For communication between cti's and cti-chain. */
1170 SEM_BRANCH_TYPE pbb_br_type;
1179 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1180 PAREXEC *par_exec = &pbufs[0];
1186 # Any initialization code before looping starts.
1187 # Note that this code may declare some locals.
1188 ${SHELL} $infile init
1192 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1194 /* ??? 'twould be nice to move this up a level and only call it once.
1195 On the other hand, in the "let's go fast" case the test is only done
1196 once per pbb (since we only return to the main loop at the end of
1197 a pbb). And in the "let's run until we're done" case we don't return
1198 until the program exits. */
1200 #if WITH_SEM_SWITCH_FULL
1201 #if defined (__GNUC__)
1202 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1203 #define DEFINE_LABELS
1207 @prefix@_sem_init_idesc_table (current_cpu);
1210 /* Initialize the "begin (compile) a pbb" virtual insn. */
1211 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1212 SEM_SET_FULL_CODE (SEM_ARGBUF (vpc),
1213 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1214 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
1216 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1219 CPU_RUNNING_P (current_cpu) = 1;
1220 /* ??? In the case where we're returning to the main loop after every
1221 pbb we don't want to call pbb_begin each time (which hashes on the pc
1222 and does a table lookup). A way to speed this up is to save vpc
1224 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1228 /* begin full-exec-pbb */
1231 ${SHELL} $infile full-exec-pbb
1234 /* end full-exec-pbb */
1236 while (CPU_RUNNING_P (current_cpu));
1243 ####################################
1245 # Compile engine: fast version.
1247 if [ x
$fast = xyes
] ; then
1254 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
1256 SIM_DESC current_state = CPU_STATE (current_cpu);
1257 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
1258 /* virtual program counter */
1260 #if WITH_SEM_SWITCH_FAST
1261 /* For communication between cti's and cti-chain. */
1262 SEM_BRANCH_TYPE pbb_br_type;
1271 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1272 PAREXEC *par_exec = &pbufs[0];
1278 # Any initialization code before looping starts.
1279 # Note that this code may declare some locals.
1280 ${SHELL} $infile init
1284 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1286 /* ??? 'twould be nice to move this up a level and only call it once.
1287 On the other hand, in the "let's go fast" case the test is only done
1288 once per pbb (since we only return to the main loop at the end of
1289 a pbb). And in the "let's run until we're done" case we don't return
1290 until the program exits. */
1292 #if WITH_SEM_SWITCH_FAST
1293 #if defined (__GNUC__)
1294 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1295 #define DEFINE_LABELS
1299 @prefix@_semf_init_idesc_table (current_cpu);
1302 /* Initialize the "begin (compile) a pbb" virtual insn. */
1303 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1304 SEM_SET_FAST_CODE (SEM_ARGBUF (vpc),
1305 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1306 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
1308 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1311 CPU_RUNNING_P (current_cpu) = 1;
1312 /* ??? In the case where we're returning to the main loop after every
1313 pbb we don't want to call pbb_begin each time (which hashes on the pc
1314 and does a table lookup). A way to speed this up is to save vpc
1316 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1320 /* begin fast-exec-pbb */
1323 ${SHELL} $infile fast-exec-pbb
1326 /* end fast-exec-pbb */
1328 while (CPU_RUNNING_P (current_cpu));
1338 # Expand @..@ macros appearing in tmp-mloop-{pid}.cin.
1340 -e "s/@cpu@/$cpu/g" -e "s/@CPU@/$CPU/g" \
1341 -e "s/@prefix@/$prefix/g" -e "s/@PREFIX@/$PREFIX/g" \
1342 < ${outprefix}tmp-mloop-$$.cin > ${outprefix}mloop${outsuffix}.cin
1344 rm -f ${outprefix}tmp-mloop-$$.cin