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