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