1 # Generate the main loop of the simulator.
2 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007, 2008, 2009, 2010
3 # Free Software Foundation, Inc.
4 # Contributed by Cygnus Support.
6 # This file is part of the GNU simulators.
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 3 of the License, or
11 # (at your option) any later version.
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.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 # This file creates two files: eng.hin and mloop.cin.
22 # eng.hin defines a few macros that specify what kind of engine was selected
23 # based on the arguments to this script.
24 # mloop.cin contains the engine.
26 # ??? Rename mloop.c to eng.c?
27 # ??? Rename mainloop.in to engine.in?
28 # ??? Add options to specify output file names?
29 # ??? Rename this file to genengine.sh?
31 # Syntax: genmloop.sh [options]
36 # - specify single cpu or multiple cpus (number specifyable at runtime),
37 # maximum number is a configuration parameter
40 # -fast: include support for fast execution in addition to full featured mode
42 # Full featured mode is for tracing, profiling, etc. and is always
43 # provided. Fast mode contains no frills, except speed.
44 # A target need only provide a "full" version of one of
45 # simple,scache,pbb. If the target wants it can also provide a fast
46 # version of same. It can't provide more than this.
47 # ??? Later add ability to have another set of full/fast semantics
48 # for use in with-devices/with-smp situations (pbb can be inappropriate
51 # -full-switch: same as -fast but for full featured version of -switch
52 # Only needed if -fast present.
54 # -simple: simple execution engine (the default)
56 # This engine fetches and executes one instruction at a time.
57 # Field extraction is done in the semantic routines.
59 # ??? There are two possible flavours of -simple. One that extracts
60 # fields in the semantic routine (which is what is implemented here),
61 # and one that stores the extracted fields in ARGBUF before calling the
62 # semantic routine. The latter is essentially the -scache case with a
63 # cache size of one (and the scache lookup code removed). There are no
64 # current uses of this and it's not clear when doing this would be a win.
65 # More complicated ISA's that want to use -simple may find this a win.
66 # Should this ever be desirable, implement a new engine style here and
67 # call it -extract (or some such). It's believed that the CGEN-generated
68 # code for the -scache case would be usable here, so no new code
69 # generation option would be needed for CGEN.
71 # -scache: use the scache to speed things up (not always a win)
73 # This engine caches the extracted instruction before executing it.
74 # When executing instructions they are first looked up in the scache.
76 # -pbb: same as -scache but extract a (pseudo-) basic block at a time
78 # This engine is basically identical to the scache version except that
79 # extraction is done a pseudo-basic-block at a time and the address of
80 # the scache entry of a branch target is recorded as well.
81 # Additional speedups are then possible by defering Ctrl-C checking
82 # to the end of basic blocks and by threading the insns together.
83 # We call them pseudo-basic-block's instead of just basic-blocks because
84 # they're not necessarily basic-blocks, though normally are.
86 # -parallel-read: support parallel execution with read-before-exec support.
87 # -parallel-write: support parallel execution with write-after-exec support.
88 # -parallel-generic-write: support parallel execution with generic queued
91 # One of these options is specified in addition to -simple, -scache,
92 # -pbb. Note that while the code can determine if the cpu supports
93 # parallel execution with HAVE_PARALLEL_INSNS [and thus this option is
94 # technically unnecessary], having this option cuts down on the clutter
97 # -parallel-only: semantic code only supports parallel version of insn
99 # Semantic code only supports parallel versions of each insn.
100 # Things can be sped up by generating both serial and parallel versions
101 # and is better suited to mixed parallel architectures like the m32r.
103 # -prefix: string to prepend to function names in mloop.c/eng.h.
105 # If no prefix is specified, the cpu type is used.
107 # -switch file: specify file containing semantics implemented as a switch()
111 # Specify the cpu family name.
113 # -infile <input-file>
115 # Specify the mainloop.in input file.
117 # -outfile-suffix <output-file-suffix>
119 # Specify the suffix to append to output files.
123 # Specify the shell to use to execute <input-file>
125 # Only one of -scache/-pbb may be selected.
126 # -simple is the default.
131 # - build mainloop.in from .cpu file
150 -multi) type=multi
;;
153 -full-switch) full_switch
=yes ;;
155 -scache) scache
=yes ;;
158 -outfile-suffix) shift ; outsuffix
=$1 ;;
159 -parallel-read) parallel
=read ;;
160 -parallel-write) parallel
=write ;;
161 -parallel-generic-write) parallel
=genwrite
;;
162 -parallel-only) parallel_only
=yes ;;
163 -prefix) shift ; prefix
=$1 ;;
164 -switch) shift ; switch
=$1 ;;
165 -cpu) shift ; cpu
=$1 ;;
166 -infile) shift ; infile
=$1 ;;
167 -shell) shift ; SHELL
=$1 ;;
168 *) echo "unknown option: $1" >&2 ; exit 1 ;;
173 # Argument validation.
175 if [ x
$scache = xyes
-a x
$pbb = xyes
] ; then
176 echo "only one of -scache and -pbb may be selected" >&2
180 if [ "x$cpu" = xunknown
] ; then
181 echo "cpu family not specified" >&2
185 if [ "x$infile" = x
] ; then
186 echo "mainloop.in not specified" >&2
190 if [ "x$prefix" = xunknown
] ; then
194 lowercase
='abcdefghijklmnopqrstuvwxyz'
195 uppercase
='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
196 CPU
=`echo ${cpu} | tr "${lowercase}" "${uppercase}"`
197 PREFIX
=`echo ${prefix} | tr "${lowercase}" "${uppercase}"`
199 ##########################################################################
201 rm -f eng
${outsuffix}.hin
202 exec 1>eng
${outsuffix}.hin
204 echo "/* engine configuration for ${cpu} */"
207 echo "/* WITH_FAST: non-zero if a fast version of the engine is available"
208 echo " in addition to the full-featured version. */"
209 if [ x
$fast = xyes
] ; then
210 echo "#define WITH_FAST 1"
212 echo "#define WITH_FAST 0"
216 echo "/* WITH_SCACHE_PBB_${PREFIX}: non-zero if the pbb engine was selected. */"
217 if [ x
$pbb = xyes
] ; then
218 echo "#define WITH_SCACHE_PBB_${PREFIX} 1"
220 echo "#define WITH_SCACHE_PBB_${PREFIX} 0"
224 echo "/* HAVE_PARALLEL_INSNS: non-zero if cpu can parallelly execute > 1 insn. */"
225 # blah blah blah, other ways to do this, blah blah blah
228 echo "#define HAVE_PARALLEL_INSNS 0"
229 echo "#define WITH_PARALLEL_READ 0"
230 echo "#define WITH_PARALLEL_WRITE 0"
231 echo "#define WITH_PARALLEL_GENWRITE 0"
234 echo "#define HAVE_PARALLEL_INSNS 1"
235 echo "/* Parallel execution is supported by read-before-exec. */"
236 echo "#define WITH_PARALLEL_READ 1"
237 echo "#define WITH_PARALLEL_WRITE 0"
238 echo "#define WITH_PARALLEL_GENWRITE 0"
241 echo "#define HAVE_PARALLEL_INSNS 1"
242 echo "/* Parallel execution is supported by write-after-exec. */"
243 echo "#define WITH_PARALLEL_READ 0"
244 echo "#define WITH_PARALLEL_WRITE 1"
245 echo "#define WITH_PARALLEL_GENWRITE 0"
248 echo "#define HAVE_PARALLEL_INSNS 1"
249 echo "/* Parallel execution is supported by generic write-after-exec. */"
250 echo "#define WITH_PARALLEL_READ 0"
251 echo "#define WITH_PARALLEL_WRITE 0"
252 echo "#define WITH_PARALLEL_GENWRITE 1"
256 if [ "x$switch" != x
] ; then
258 echo "/* WITH_SEM_SWITCH_FULL: non-zero if full-featured engine is"
259 echo " implemented as a switch(). */"
260 if [ x
$fast != xyes
-o x
$full_switch = xyes
] ; then
261 echo "#define WITH_SEM_SWITCH_FULL 1"
263 echo "#define WITH_SEM_SWITCH_FULL 0"
266 echo "/* WITH_SEM_SWITCH_FAST: non-zero if fast engine is"
267 echo " implemented as a switch(). */"
268 if [ x
$fast = xyes
] ; then
269 echo "#define WITH_SEM_SWITCH_FAST 1"
271 echo "#define WITH_SEM_SWITCH_FAST 0"
275 # Decls of functions we define.
278 echo "/* Functions defined in the generated mainloop.c file"
279 echo " (which doesn't necessarily have that file name). */"
281 echo "extern ENGINE_FN ${prefix}_engine_run_full;"
282 echo "extern ENGINE_FN ${prefix}_engine_run_fast;"
284 if [ x
$pbb = xyes
] ; then
286 echo "extern SEM_PC ${prefix}_pbb_begin (SIM_CPU *, int);"
287 echo "extern SEM_PC ${prefix}_pbb_chain (SIM_CPU *, SEM_ARG);"
288 echo "extern SEM_PC ${prefix}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_BRANCH_TYPE, PCADDR);"
289 echo "extern void ${prefix}_pbb_before (SIM_CPU *, SCACHE *);"
290 echo "extern void ${prefix}_pbb_after (SIM_CPU *, SCACHE *);"
293 ##########################################################################
295 rm -f tmp-mloop-$$.cin mloop
${outsuffix}.cin
296 exec 1>tmp-mloop-$$.cin
298 # We use @cpu@ instead of ${cpu} because we still need to run sed to handle
299 # transformation of @cpu@ for mainloop.in, so there's no need to use ${cpu}
303 /* This file is generated by the genmloop script. DO NOT EDIT! */
305 /* Enable switch() support in cgen headers. */
306 #define SEM_IN_SWITCH
308 #define WANT_CPU @cpu@
309 #define WANT_CPU_@CPU@
311 #include "sim-main.h"
313 #include "cgen-mem.h"
314 #include "cgen-ops.h"
315 #include "sim-assert.h"
317 /* Fill in the administrative ARGBUF fields required by all insns,
321 @prefix@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc,
322 PCADDR pc, int fast_p)
325 SEM_SET_CODE (abuf, idesc, fast_p);
326 ARGBUF_ADDR (abuf) = pc;
328 ARGBUF_IDESC (abuf) = idesc;
331 /* Fill in tracing/profiling fields of an ARGBUF. */
334 @prefix@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf,
335 int trace_p, int profile_p)
337 ARGBUF_TRACE_P (abuf) = trace_p;
338 ARGBUF_PROFILE_P (abuf) = profile_p;
343 /* Emit the "x-before" handler.
344 x-before is emitted before each insn (serial or parallel).
345 This is as opposed to x-after which is only emitted at the end of a group
346 of parallel insns. */
349 @prefix@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p)
351 ARGBUF *abuf = &sc[0].argbuf;
352 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEFORE];
354 abuf->fields.before.first_p = first_p;
355 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
356 /* no need to set trace_p,profile_p */
359 /* Emit the "x-after" handler.
360 x-after is emitted after a serial insn or at the end of a group of
364 @prefix@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc)
366 ARGBUF *abuf = &sc[0].argbuf;
367 const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_AFTER];
369 @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0);
370 /* no need to set trace_p,profile_p */
373 #endif /* WITH_SCACHE_PBB */
377 ${SHELL} $infile support
379 ##########################################################################
381 # Simple engine: fetch an instruction, execute the instruction.
383 # Instruction fields are not extracted into ARGBUF, they are extracted in
384 # the semantic routines themselves. However, there is still a need to pass
385 # and return misc. information to the semantic routines so we still use ARGBUF.
386 # [One could certainly implement things differently and remove ARGBUF.
387 # It's not clear this is necessarily always a win.]
388 # ??? The use of the SCACHE struct is for consistency with the with-scache
389 # case though it might be a source of confusion.
391 if [ x
$scache != xyes
-a x
$pbb != xyes
] ; then
398 @prefix@_engine_run_full (SIM_CPU *current_cpu)
401 SIM_DESC current_state = CPU_STATE (current_cpu);
402 /* ??? Use of SCACHE is a bit of a hack as we don't actually use the scache.
403 We do however use ARGBUF so for consistency with the other engine flavours
404 the SCACHE type is used. */
405 SCACHE cache[MAX_LIW_INSNS];
406 SCACHE *sc = &cache[0];
413 PAREXEC pbufs[MAX_PARALLEL_INSNS];
420 # Any initialization code before looping starts.
421 # Note that this code may declare some locals.
422 ${SHELL} $infile init
424 if [ x
$parallel = xread
] ; then
427 #if defined (__GNUC__)
429 if (! CPU_IDESC_READ_INIT_P (current_cpu))
431 /* ??? Later maybe paste read.c in when building mainloop.c. */
432 #define DEFINE_LABELS
434 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
444 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
446 #if WITH_SEM_SWITCH_FULL
447 #if defined (__GNUC__)
448 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
449 #define DEFINE_LABELS
453 @prefix@_sem_init_idesc_table (current_cpu);
455 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
460 /* begin full-exec-simple */
463 ${SHELL} $infile full-exec-simple
466 /* end full-exec-simple */
468 ++ CPU_INSN_COUNT (current_cpu);
470 while (0 /*CPU_RUNNING_P (current_cpu)*/);
477 ####################################
479 # Simple engine: fast version.
480 # ??? A somewhat dubious effort, but for completeness' sake.
482 if [ x
$fast = xyes
] ; then
488 FIXME: "fast simple version unimplemented, delete -fast arg to genmloop.sh."
498 ##########################################################################
500 # Non-parallel scache engine: lookup insn in scache, fetch if missing,
503 if [ x
$scache = xyes
-a x
$parallel = xno
] ; then
507 static INLINE SCACHE *
508 @prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
509 unsigned int hash_mask, int FAST_P)
511 /* First step: look up current insn in hash table. */
512 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
514 /* If the entry isn't the one we want (cache miss),
515 fetch and decode the instruction. */
516 if (sc->argbuf.addr != vpc)
519 PROFILE_COUNT_SCACHE_MISS (current_cpu);
521 /* begin extract-scache */
524 ${SHELL} $infile extract-scache
527 /* end extract-scache */
531 PROFILE_COUNT_SCACHE_HIT (current_cpu);
532 /* Make core access statistics come out right.
533 The size is a guess, but it's currently not used either. */
534 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
543 @prefix@_engine_run_full (SIM_CPU *current_cpu)
545 SIM_DESC current_state = CPU_STATE (current_cpu);
546 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
547 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
552 # Any initialization code before looping starts.
553 # Note that this code may declare some locals.
554 ${SHELL} $infile init
558 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
560 #if ! WITH_SEM_SWITCH_FULL
561 @prefix@_sem_init_idesc_table (current_cpu);
563 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
572 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
574 /* begin full-exec-scache */
577 ${SHELL} $infile full-exec-scache
580 /* end full-exec-scache */
584 ++ CPU_INSN_COUNT (current_cpu);
586 while (0 /*CPU_RUNNING_P (current_cpu)*/);
593 ####################################
595 # Non-parallel scache engine: fast version.
597 if [ x
$fast = xyes
] ; then
604 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
606 SIM_DESC current_state = CPU_STATE (current_cpu);
607 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
608 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
613 # Any initialization code before looping starts.
614 # Note that this code may declare some locals.
615 ${SHELL} $infile init
619 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
621 #if WITH_SEM_SWITCH_FAST
622 #if defined (__GNUC__)
623 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
624 #define DEFINE_LABELS
628 @prefix@_semf_init_idesc_table (current_cpu);
630 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
639 sc = @prefix@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
641 /* begin fast-exec-scache */
644 ${SHELL} $infile fast-exec-scache
647 /* end fast-exec-scache */
651 ++ CPU_INSN_COUNT (current_cpu);
653 while (0 /*CPU_RUNNING_P (current_cpu)*/);
662 fi # -scache && ! parallel
664 ##########################################################################
666 # Parallel scache engine: lookup insn in scache, fetch if missing,
668 # For the parallel case we give the target more flexibility.
670 if [ x
$scache = xyes
-a x
$parallel != xno
] ; then
674 static INLINE SCACHE *
675 @prefix@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
676 unsigned int hash_mask, int FAST_P)
678 /* First step: look up current insn in hash table. */
679 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
681 /* If the entry isn't the one we want (cache miss),
682 fetch and decode the instruction. */
683 if (sc->argbuf.addr != vpc)
686 PROFILE_COUNT_SCACHE_MISS (current_cpu);
688 #define SET_LAST_INSN_P(last_p) do { sc->last_insn_p = (last_p); } while (0)
689 /* begin extract-scache */
692 ${SHELL} $infile extract-scache
695 /* end extract-scache */
696 #undef SET_LAST_INSN_P
700 PROFILE_COUNT_SCACHE_HIT (current_cpu);
701 /* Make core access statistics come out right.
702 The size is a guess, but it's currently not used either. */
703 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
712 @prefix@_engine_run_full (SIM_CPU *current_cpu)
714 SIM_DESC current_state = CPU_STATE (current_cpu);
715 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
716 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
721 # Any initialization code before looping starts.
722 # Note that this code may declare some locals.
723 ${SHELL} $infile init
725 if [ x
$parallel = xread
] ; then
727 #if defined (__GNUC__)
729 if (! CPU_IDESC_READ_INIT_P (current_cpu))
731 /* ??? Later maybe paste read.c in when building mainloop.c. */
732 #define DEFINE_LABELS
734 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
744 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
746 #if ! WITH_SEM_SWITCH_FULL
747 @prefix@_sem_init_idesc_table (current_cpu);
749 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
756 /* begin full-exec-scache */
759 ${SHELL} $infile full-exec-scache
762 /* end full-exec-scache */
764 while (0 /*CPU_RUNNING_P (current_cpu)*/);
771 ####################################
773 # Parallel scache engine: fast version.
775 if [ x
$fast = xyes
] ; then
782 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
784 SIM_DESC current_state = CPU_STATE (current_cpu);
785 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
786 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
788 PAREXEC pbufs[MAX_PARALLEL_INSNS];
793 # Any initialization code before looping starts.
794 # Note that this code may declare some locals.
795 ${SHELL} $infile init
797 if [ x
$parallel = xread
] ; then
800 #if defined (__GNUC__)
802 if (! CPU_IDESC_READ_INIT_P (current_cpu))
804 /* ??? Later maybe paste read.c in when building mainloop.c. */
805 #define DEFINE_LABELS
807 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
817 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
819 #if WITH_SEM_SWITCH_FAST
820 #if defined (__GNUC__)
821 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
822 #define DEFINE_LABELS
826 @prefix@_semf_init_idesc_table (current_cpu);
828 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
835 /* begin fast-exec-scache */
838 ${SHELL} $infile fast-exec-scache
841 /* end fast-exec-scache */
843 while (0 /*CPU_RUNNING_P (current_cpu)*/);
852 fi # -scache && parallel
854 ##########################################################################
856 # Compilation engine: lookup insn in scache, extract a pbb
857 # (pseudo-basic-block) if missing, then execute the pbb.
858 # A "pbb" is a sequence of insns up to the next cti insn or until
859 # some prespecified maximum.
860 # CTI: control transfer instruction.
862 if [ x
$pbb = xyes
] ; then
866 /* Record address of cti terminating a pbb. */
867 #define SET_CTI_VPC(sc) do { _cti_sc = (sc); } while (0)
868 /* Record number of [real] insns in pbb. */
869 #define SET_INSN_COUNT(n) do { _insn_count = (n); } while (0)
871 /* Fetch and extract a pseudo-basic-block.
872 FAST_P is non-zero if no tracing/profiling/etc. is wanted. */
875 @prefix@_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
880 int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu);
884 new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc);
887 /* Leading '_' to avoid collision with mainloop.in. */
889 SCACHE *orig_sc = sc;
890 SCACHE *_cti_sc = NULL;
891 int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu);
893 /* First figure out how many instructions to compile.
894 MAX_INSNS is the size of the allocated buffer, which includes space
895 for before/after handlers if they're being used.
896 SLICE_INSNS is the maxinum number of real insns that can be
897 executed. Zero means "as many as we want". */
898 /* ??? max_insns is serving two incompatible roles.
899 1) Number of slots available in scache buffer.
900 2) Number of real insns to execute.
901 They're incompatible because there are virtual insns emitted too
902 (chain,cti-chain,before,after handlers). */
904 if (slice_insns == 1)
906 /* No need to worry about extra slots required for virtual insns
907 and parallel exec support because MAX_CHAIN_LENGTH is
908 guaranteed to be big enough to execute at least 1 insn! */
913 /* Allow enough slop so that while compiling insns, if max_insns > 0
914 then there's guaranteed to be enough space to emit one real insn.
915 MAX_CHAIN_LENGTH is typically much longer than
916 the normal number of insns between cti's anyway. */
917 max_insns -= (1 /* one for the trailing chain insn */
920 : (1 + MAX_PARALLEL_INSNS) /* before+after */)
921 + (MAX_PARALLEL_INSNS > 1
922 ? (MAX_PARALLEL_INSNS * 2)
925 /* Account for before/after handlers. */
930 && slice_insns < max_insns)
931 max_insns = slice_insns;
936 /* SC,PC must be updated to point passed the last entry used.
937 SET_CTI_VPC must be called if pbb is terminated by a cti.
938 SET_INSN_COUNT must be called to record number of real insns in
939 pbb [could be computed by us of course, extra cpu but perhaps
940 negligible enough]. */
942 /* begin extract-pbb */
945 ${SHELL} $infile extract-pbb
948 /* end extract-pbb */
950 /* The last one is a pseudo-insn to link to the next chain.
951 It is also used to record the insn count for this chain. */
955 /* Was pbb terminated by a cti? */
958 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CTI_CHAIN];
962 id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_CHAIN];
964 SEM_SET_CODE (&sc->argbuf, id, FAST_P);
965 sc->argbuf.idesc = id;
966 sc->argbuf.addr = pc;
967 sc->argbuf.fields.chain.insn_count = _insn_count;
968 sc->argbuf.fields.chain.next = 0;
969 sc->argbuf.fields.chain.branch_target = 0;
973 /* Update the pointer to the next free entry, may not have used as
974 many entries as was asked for. */
975 CPU_SCACHE_NEXT_FREE (current_cpu) = sc;
976 /* Record length of chain if profiling.
977 This includes virtual insns since they count against
980 PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc);
986 /* Chain to the next block from a non-cti terminated previous block. */
989 @prefix@_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
991 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
993 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
995 SET_H_PC (abuf->addr);
997 /* If not running forever, exit back to main loop. */
998 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
999 /* Also exit back to main loop if there's an event.
1000 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1001 at the "right" time, but then that was what was asked for.
1002 There is no silver bullet for simulator engines.
1003 ??? Clearly this needs a cleaner interface.
1004 At present it's just so Ctrl-C works. */
1005 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1006 CPU_RUNNING_P (current_cpu) = 0;
1008 /* If chained to next block, go straight to it. */
1009 if (abuf->fields.chain.next)
1010 return abuf->fields.chain.next;
1011 /* See if next block has already been compiled. */
1012 abuf->fields.chain.next = scache_lookup (current_cpu, abuf->addr);
1013 if (abuf->fields.chain.next)
1014 return abuf->fields.chain.next;
1015 /* Nope, so next insn is a virtual insn to invoke the compiler
1017 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1020 /* Chain to the next block from a cti terminated previous block.
1021 BR_TYPE indicates whether the branch was taken and whether we can cache
1022 the vpc of the branch target.
1023 NEW_PC is the target's branch address, and is only valid if
1024 BR_TYPE != SEM_BRANCH_UNTAKEN. */
1027 @prefix@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
1028 SEM_BRANCH_TYPE br_type, PCADDR new_pc)
1030 SEM_PC *new_vpc_ptr;
1032 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
1034 /* If not running forever, exit back to main loop. */
1035 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
1036 /* Also exit back to main loop if there's an event.
1037 Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
1038 at the "right" time, but then that was what was asked for.
1039 There is no silver bullet for simulator engines.
1040 ??? Clearly this needs a cleaner interface.
1041 At present it's just so Ctrl-C works. */
1042 || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
1043 CPU_RUNNING_P (current_cpu) = 0;
1045 /* Restart compiler if we branched to an uncacheable address
1047 if (br_type == SEM_BRANCH_UNCACHEABLE)
1050 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1053 /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our
1055 if (br_type == SEM_BRANCH_UNTAKEN)
1057 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1058 new_pc = abuf->addr;
1060 new_vpc_ptr = &abuf->fields.chain.next;
1064 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1066 new_vpc_ptr = &abuf->fields.chain.branch_target;
1069 /* If chained to next block, go straight to it. */
1071 return *new_vpc_ptr;
1072 /* See if next block has already been compiled. */
1073 *new_vpc_ptr = scache_lookup (current_cpu, new_pc);
1075 return *new_vpc_ptr;
1076 /* Nope, so next insn is a virtual insn to invoke the compiler
1078 return CPU_SCACHE_PBB_BEGIN (current_cpu);
1081 /* x-before handler.
1082 This is called before each insn. */
1085 @prefix@_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
1087 SEM_ARG sem_arg = sc;
1088 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1089 int first_p = abuf->fields.before.first_p;
1090 const ARGBUF *cur_abuf = SEM_ARGBUF (sc + 1);
1091 const IDESC *cur_idesc = cur_abuf->idesc;
1092 PCADDR pc = cur_abuf->addr;
1094 if (ARGBUF_PROFILE_P (cur_abuf))
1095 PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
1097 /* If this isn't the first insn, finish up the previous one. */
1101 if (PROFILE_MODEL_P (current_cpu))
1103 const SEM_ARG prev_sem_arg = sc - 1;
1104 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1105 const IDESC *prev_idesc = prev_abuf->idesc;
1108 /* ??? May want to measure all insns if doing insn tracing. */
1109 if (ARGBUF_PROFILE_P (prev_abuf))
1111 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
1112 @prefix@_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
1116 TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/);
1119 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */
1120 if (PROFILE_MODEL_P (current_cpu)
1121 && ARGBUF_PROFILE_P (cur_abuf))
1122 @prefix@_model_insn_before (current_cpu, first_p);
1124 TRACE_INSN_INIT (current_cpu, cur_abuf, first_p);
1125 TRACE_INSN (current_cpu, cur_idesc->idata, cur_abuf, pc);
1129 This is called after a serial insn or at the end of a group of parallel
1133 @prefix@_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
1135 SEM_ARG sem_arg = sc;
1136 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
1137 const SEM_ARG prev_sem_arg = sc - 1;
1138 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
1140 /* ??? May want to measure all insns if doing insn tracing. */
1141 if (PROFILE_MODEL_P (current_cpu)
1142 && ARGBUF_PROFILE_P (prev_abuf))
1144 const IDESC *prev_idesc = prev_abuf->idesc;
1147 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
1148 @prefix@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
1150 TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/);
1156 @prefix@_engine_run_full (SIM_CPU *current_cpu)
1158 SIM_DESC current_state = CPU_STATE (current_cpu);
1159 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
1160 /* virtual program counter */
1162 #if WITH_SEM_SWITCH_FULL
1163 /* For communication between cti's and cti-chain. */
1164 SEM_BRANCH_TYPE pbb_br_type;
1173 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1174 PAREXEC *par_exec = &pbufs[0];
1180 # Any initialization code before looping starts.
1181 # Note that this code may declare some locals.
1182 ${SHELL} $infile init
1186 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1188 /* ??? 'twould be nice to move this up a level and only call it once.
1189 On the other hand, in the "let's go fast" case the test is only done
1190 once per pbb (since we only return to the main loop at the end of
1191 a pbb). And in the "let's run until we're done" case we don't return
1192 until the program exits. */
1194 #if WITH_SEM_SWITCH_FULL
1195 #if defined (__GNUC__)
1196 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1197 #define DEFINE_LABELS
1201 @prefix@_sem_init_idesc_table (current_cpu);
1204 /* Initialize the "begin (compile) a pbb" virtual insn. */
1205 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1206 SEM_SET_FULL_CODE (SEM_ARGBUF (vpc),
1207 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1208 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
1210 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1213 CPU_RUNNING_P (current_cpu) = 1;
1214 /* ??? In the case where we're returning to the main loop after every
1215 pbb we don't want to call pbb_begin each time (which hashes on the pc
1216 and does a table lookup). A way to speed this up is to save vpc
1218 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1222 /* begin full-exec-pbb */
1225 ${SHELL} $infile full-exec-pbb
1228 /* end full-exec-pbb */
1230 while (CPU_RUNNING_P (current_cpu));
1237 ####################################
1239 # Compile engine: fast version.
1241 if [ x
$fast = xyes
] ; then
1248 @prefix@_engine_run_fast (SIM_CPU *current_cpu)
1250 SIM_DESC current_state = CPU_STATE (current_cpu);
1251 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
1252 /* virtual program counter */
1254 #if WITH_SEM_SWITCH_FAST
1255 /* For communication between cti's and cti-chain. */
1256 SEM_BRANCH_TYPE pbb_br_type;
1265 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1266 PAREXEC *par_exec = &pbufs[0];
1272 # Any initialization code before looping starts.
1273 # Note that this code may declare some locals.
1274 ${SHELL} $infile init
1278 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
1280 /* ??? 'twould be nice to move this up a level and only call it once.
1281 On the other hand, in the "let's go fast" case the test is only done
1282 once per pbb (since we only return to the main loop at the end of
1283 a pbb). And in the "let's run until we're done" case we don't return
1284 until the program exits. */
1286 #if WITH_SEM_SWITCH_FAST
1287 #if defined (__GNUC__)
1288 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1289 #define DEFINE_LABELS
1293 @prefix@_semf_init_idesc_table (current_cpu);
1296 /* Initialize the "begin (compile) a pbb" virtual insn. */
1297 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
1298 SEM_SET_FAST_CODE (SEM_ARGBUF (vpc),
1299 & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN]);
1300 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEGIN];
1302 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
1305 CPU_RUNNING_P (current_cpu) = 1;
1306 /* ??? In the case where we're returning to the main loop after every
1307 pbb we don't want to call pbb_begin each time (which hashes on the pc
1308 and does a table lookup). A way to speed this up is to save vpc
1310 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1314 /* begin fast-exec-pbb */
1317 ${SHELL} $infile fast-exec-pbb
1320 /* end fast-exec-pbb */
1322 while (CPU_RUNNING_P (current_cpu));
1332 # Expand @..@ macros appearing in tmp-mloop-{pid}.cin.
1334 -e "s/@cpu@/$cpu/g" -e "s/@CPU@/$CPU/g" \
1335 -e "s/@prefix@/$prefix/g" -e "s/@PREFIX@/$PREFIX/g" < tmp-mloop-$$.cin
> mloop
${outsuffix}.cin
1337 rm -f tmp-mloop-$$.cin
This page took 0.056906 seconds and 4 git commands to generate.