1 # Generate the main loop of the simulator.
2 # Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3 # Contributed by Cygnus Support.
5 # This file is part of the GNU simulators.
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)
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.
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.
21 # This file creates two files: eng.hin and mloop.cin.
22 # eng.hin defines a few macros that specify what kind of engine was selected
23 # based on the arguments to this script.
24 # mloop.cin contains the engine.
26 # ??? Rename mloop.c to eng.c?
27 # ??? Rename mainloop.in to engine.in?
28 # ??? Rename this file to genengine.sh?
30 # Syntax: genmloop.sh [options]
35 # - specify single cpu or multiple cpus (number specifyable at runtime),
36 # maximum number is a configuration parameter
39 # -fast: include support for fast execution in addition to full featured mode
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
50 # -full-switch: same as -fast but for full featured version of -switch
51 # Only needed if -fast present.
53 # -simple: simple execution engine (the default)
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.
60 # -scache: use the scache to speed things up (not always a win)
62 # This engine caches the extracted instruction before executing it.
63 # When executing instructions they are first looked up in the scache.
65 # -pbb: same as -scache but extract a (pseudo-) basic block at a time
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.
75 # -parallel: cpu can execute multiple instructions parallely
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
83 # -switch file: specify file containing semantics implemented as a switch()
87 # Specify the cpu family name.
89 # -infile <input-file>
91 # Specify the mainloop.in input file.
93 # Only one of -scache/-pbb may be selected.
94 # -simple is the default.
99 # - build mainloop.in from .cpu file
115 -multi) type=multi
;;
118 -full-switch) full_switch
=yes ;;
120 -scache) scache
=yes ;;
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 ;;
132 # Argument validation.
134 if [ x
$scache = xyes
-a x
$pbb = xyes
] ; then
135 echo "only one of -scache and -pbb may be selected" >&2
139 if [ "x$cpu" = xunknown
] ; then
140 echo "cpu family not specified" >&2
144 if [ "x$infile" = x
] ; then
145 echo "mainloop.in not specified" >&2
149 lowercase
='abcdefghijklmnopqrstuvwxyz'
150 uppercase
='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
151 CPU
=`echo ${cpu} | tr "${lowercase}" "${uppercase}"`
153 ##########################################################################
158 echo "/* engine configuration for ${cpu} */"
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"
166 echo "#define WITH_FAST 0"
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"
174 echo "#define WITH_SCACHE_PBB_${CPU} 0"
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"
182 echo "#define HAVE_PARALLEL_INSNS 0"
185 if [ "x$switch" != x
] ; then
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"
192 echo "#define WITH_SEM_SWITCH_FULL 0"
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"
200 echo "#define WITH_SEM_SWITCH_FAST 0"
204 # Decls of functions we define.
207 echo "/* Functions defined in the generated mainloop.c file"
208 echo " (which doesn't necessarily have that file name). */"
210 echo "extern ENGINE_FN ${cpu}_engine_run_full;"
211 echo "extern ENGINE_FN ${cpu}_engine_run_fast;"
213 if [ x
$pbb = xyes
] ; then
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 *);"
222 ##########################################################################
224 rm -f tmp-mloop.cin mloop.cin
227 # We use @cpu@ instead of ${cpu} because we still want to run sed to handle
228 # transformation of @cpu@ for mainloop.in.
231 /* This file is generated by the genmloop script. DO NOT EDIT! */
233 /* Enable switch() support in cgen headers. */
234 #define SEM_IN_SWITCH
237 #define WANT_CPU_@CPU@
239 #include "sim-main.h"
241 #include "cgen-mem.h"
242 #include "cgen-ops.h"
245 #include "sim-assert.h"
247 /* Fill in the administrative ARGBUF fields required by all insns,
251 @cpu@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc,
252 PCADDR pc, int fast_p)
254 SEM_SET_CODE (abuf, idesc, fast_p);
255 ARGBUF_ADDR (abuf) = pc;
256 ARGBUF_IDESC (abuf) = idesc;
259 /* Fill in tracing/profiling fields of an ARGBUF. */
262 @cpu@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf,
263 int trace_p, int profile_p)
265 ARGBUF_TRACE_P (abuf) = trace_p;
266 ARGBUF_PROFILE_P (abuf) = profile_p;
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. */
277 @cpu@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p)
279 ARGBUF *abuf = &sc[0].argbuf;
280 const IDESC *id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEFORE];
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 */
287 /* Emit the "x-after" handler.
288 x-after is emitted after a serial insn or at the end of a group of
292 @cpu@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc)
294 ARGBUF *abuf = &sc[0].argbuf;
295 const IDESC *id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_AFTER];
297 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, 0);
298 /* no need to set trace_p,profile_p */
301 #endif /* WITH_SCACHE_PBB */
305 ${SHELL} $infile support
307 ##########################################################################
309 # Simple engine: fetch an instruction, execute the instruction.
311 if [ x
$scache != xyes
-a x
$pbb != xyes
] ; then
318 @cpu@_engine_run_full (SIM_CPU *current_cpu)
321 SIM_DESC current_state = CPU_STATE (current_cpu);
322 SCACHE cache[MAX_LIW_INSNS];
323 SCACHE *sc = &cache[0];
328 if [ x
$parallel = xyes
] ; then
330 PAREXEC pbufs[MAX_PARALLEL_INSNS];
336 # Any initialization code before looping starts.
337 # Note that this code may declare some locals.
338 ${SHELL} $infile init
340 if [ x
$parallel = xyes
] ; then
343 #if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
345 if (! CPU_IDESC_READ_INIT_P (current_cpu))
347 /* ??? Later maybe paste read.c in when building mainloop.c. */
348 #define DEFINE_LABELS
350 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
360 #if WITH_SEM_SWITCH_FULL && defined (__GNUC__)
362 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
364 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
365 #define DEFINE_LABELS
367 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
376 /* begin full-{extract,exec}-simple */
379 ${SHELL} $infile extract-simple
381 ${SHELL} $infile full-exec-simple
384 /* end full-{extract,exec}-simple */
386 ++ CPU_INSN_COUNT (current_cpu);
388 while (0 /*CPU_RUNNING_P (current_cpu)*/);
396 ####################################
398 # Simple engine: fast version.
399 # ??? A somewhat dubious effort, but for completeness' sake.
401 if [ x
$fast = xyes
] ; then
407 FIXME: "fast simple version unimplemented, delete -fast arg to genmloop.sh."
417 ##########################################################################
419 # Scache engine: lookup insn in scache, fetch if missing, then execute it.
421 if [ x
$scache = xyes
] ; then
425 static INLINE SCACHE *
426 @cpu@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
427 unsigned int hash_mask, int FAST_P)
429 /* First step: look up current insn in hash table. */
430 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
432 /* If the entry isn't the one we want (cache miss),
433 fetch and decode the instruction. */
434 if (sc->argbuf.addr != vpc)
439 PROFILE_COUNT_SCACHE_MISS (current_cpu);
441 /* begin extract-scache */
444 ${SHELL} $infile extract-scache
447 /* end extract-scache */
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);
463 @cpu@_engine_run_full (SIM_CPU *current_cpu)
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);
472 if [ x
$parallel = xyes
] ; then
474 PAREXEC pbufs[MAX_PARALLEL_INSNS];
480 # Any initialization code before looping starts.
481 # Note that this code may declare some locals.
482 ${SHELL} $infile init
484 if [ x
$parallel = xyes
] ; then
487 #if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
489 if (! CPU_IDESC_READ_INIT_P (current_cpu))
491 /* ??? Later maybe paste read.c in when building mainloop.c. */
492 #define DEFINE_LABELS
494 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
510 sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
512 /* begin full-exec-scache */
515 ${SHELL} $infile full-exec-scache
518 /* end full-exec-scache */
522 ++ CPU_INSN_COUNT (current_cpu);
524 while (0 /*CPU_RUNNING_P (current_cpu)*/);
531 ####################################
533 # Scache engine: fast version.
535 if [ x
$fast = xyes
] ; then
542 @cpu@_engine_run_fast (SIM_CPU *current_cpu)
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);
551 if [ x
$parallel = xyes
] ; then
553 PAREXEC pbufs[MAX_PARALLEL_INSNS];
559 # Any initialization code before looping starts.
560 # Note that this code may declare some locals.
561 ${SHELL} $infile init
563 if [ x
$parallel = xyes
] ; then
566 #if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
568 if (! CPU_IDESC_READ_INIT_P (current_cpu))
570 /* ??? Later maybe paste read.c in when building mainloop.c. */
571 #define DEFINE_LABELS
573 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
583 #if WITH_SEM_SWITCH_FAST && defined (__GNUC__)
585 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
587 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
588 #define DEFINE_LABELS
590 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
601 sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
603 /* begin fast-exec-scache */
606 ${SHELL} $infile fast-exec-scache
609 /* end fast-exec-scache */
613 ++ CPU_INSN_COUNT (current_cpu);
615 while (0 /*CPU_RUNNING_P (current_cpu)*/);
626 ##########################################################################
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.
634 if [ x
$pbb = xyes
] ; then
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)
643 /* Fetch and extract a pseudo-basic-block.
644 FAST_P is non-zero if no tracing/profiling/etc. is wanted. */
647 @cpu@_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
652 int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu);
656 new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc);
659 /* Leading '_' to avoid collision with mainloop.in. */
661 SCACHE *orig_sc = sc;
662 SCACHE *_cti_sc = NULL;
663 int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu);
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). */
676 if (slice_insns == 1)
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! */
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 */
692 : (1 + MAX_PARALLEL_INSNS) /* before+after */)
693 + (MAX_PARALLEL_INSNS > 1
694 ? (MAX_PARALLEL_INSNS * 2)
697 /* Account for before/after handlers. */
702 && slice_insns < max_insns)
703 max_insns = slice_insns;
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]. */
714 /* begin extract-pbb */
717 ${SHELL} $infile extract-pbb
720 /* end extract-pbb */
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. */
727 /* Was pbb terminated by a cti? */
730 id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_CTI_CHAIN];
734 id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_CHAIN];
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;
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
750 PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc);
756 /* Chain to the next block from a non-cti terminated previous block. */
759 @cpu@_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
761 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
763 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
765 SET_H_PC (abuf->addr);
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;
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
787 return CPU_SCACHE_PBB_BEGIN (current_cpu);
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. */
797 @cpu@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
798 SEM_PC *new_vpc_ptr, PCADDR new_pc)
802 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
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;
815 /* Restart compiler if we branched to an uncacheable address
817 if (new_vpc_ptr == SEM_BRANCH_UNCACHEABLE)
820 return CPU_SCACHE_PBB_BEGIN (current_cpu);
823 /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our
825 if (new_vpc_ptr == SEM_BRANCH_UNTAKEN)
827 abuf = SEM_ARGBUF (sem_arg);
828 SET_H_PC (abuf->addr);
829 new_vpc_ptr = &abuf->fields.chain.next;
836 /* If chained to next block, go straight to it. */
839 /* See if next block has already been compiled. */
840 *new_vpc_ptr = scache_lookup (current_cpu, GET_H_PC ());
843 /* Nope, so next insn is a virtual insn to invoke the compiler
845 return CPU_SCACHE_PBB_BEGIN (current_cpu);
849 This is called before each insn. */
852 @cpu@_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
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;
861 if (ARGBUF_PROFILE_P (cur_abuf))
862 PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
864 /* If this isn't the first insn, finish up the previous one. */
868 if (PROFILE_MODEL_P (current_cpu))
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;
875 /* ??? May want to measure all insns if doing insn tracing. */
876 if (ARGBUF_PROFILE_P (prev_abuf))
878 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
879 @cpu@_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
883 TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/);
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);
891 TRACE_INSN_INIT (current_cpu, cur_abuf, first_p);
892 TRACE_INSN (current_cpu, cur_idesc->opcode, cur_abuf, cur_abuf->addr);
896 This is called after a serial insn or at the end of a group of parallel
900 @cpu@_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
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);
907 /* ??? May want to measure all insns if doing insn tracing. */
908 if (PROFILE_MODEL_P (current_cpu)
909 && ARGBUF_PROFILE_P (prev_abuf))
911 const IDESC *prev_idesc = prev_abuf->idesc;
914 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
915 @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
917 TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/);
923 @cpu@_engine_run_full (SIM_CPU *current_cpu)
925 SIM_DESC current_state = CPU_STATE (current_cpu);
926 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
927 /* virtual program counter */
929 #if WITH_SEM_SWITCH_FULL
930 /* For communication between cti's and cti-chain. */
932 SEM_PC *pbb_br_npc_ptr;
937 if [ x
$parallel = xyes
] ; then
939 PAREXEC pbufs[MAX_PARALLEL_INSNS];
940 PAREXEC *par_exec = &pbufs[0];
945 # Any initialization code before looping starts.
946 # Note that this code may declare some locals.
947 ${SHELL} $infile init
951 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
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. */
959 #if WITH_SEM_SWITCH_FULL && defined (__GNUC__)
960 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
961 #define DEFINE_LABELS
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];
971 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
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
979 vpc = @cpu@_pbb_begin (current_cpu, FAST_P);
983 /* begin full-exec-pbb */
986 ${SHELL} $infile full-exec-pbb
989 /* end full-exec-pbb */
991 while (CPU_RUNNING_P (current_cpu));
998 ####################################
1000 # Compile engine: fast version.
1002 if [ x
$fast = xyes
] ; then
1009 @cpu@_engine_run_fast (SIM_CPU *current_cpu)
1011 SIM_DESC current_state = CPU_STATE (current_cpu);
1012 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
1013 /* virtual program counter */
1015 #if WITH_SEM_SWITCH_FAST
1016 /* For communication between cti's and cti-chain. */
1018 SEM_PC *pbb_br_npc_ptr;
1023 if [ x
$parallel = xyes
] ; then
1025 PAREXEC pbufs[MAX_PARALLEL_INSNS];
1026 PAREXEC *par_exec = &pbufs[0];
1031 # Any initialization code before looping starts.
1032 # Note that this code may declare some locals.
1033 ${SHELL} $infile init
1037 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
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. */
1045 #if WITH_SEM_SWITCH_FAST && defined (__GNUC__)
1046 /* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
1047 #define DEFINE_LABELS
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];
1057 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
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
1065 vpc = @cpu@_pbb_begin (current_cpu, FAST_P);
1069 /* begin fast-exec-pbb */
1072 ${SHELL} $infile fast-exec-pbb
1075 /* end fast-exec-pbb */
1077 while (CPU_RUNNING_P (current_cpu));
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
This page took 0.053599 seconds and 4 git commands to generate.