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