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