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