* A few more improvements to gx jit prototype.
[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;"
916b1152
DE
212
213if [ x$pbb = xyes ] ; then
214 echo ""
215 echo "extern SEM_PC ${cpu}_pbb_begin (SIM_CPU *, int);"
216 echo "extern SEM_PC ${cpu}_pbb_chain (SIM_CPU *, SEM_ARG);"
217 echo "extern SEM_PC ${cpu}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_PC *, PCADDR);"
218 echo "extern void ${cpu}_pbb_before (SIM_CPU *, SCACHE *);"
219 echo "extern void ${cpu}_pbb_after (SIM_CPU *, SCACHE *);"
220fi
8c7dc9ff 221
d4df1e30
DE
222##########################################################################
223
224rm -f tmp-mloop.cin mloop.cin
225exec 1>tmp-mloop.cin
226
227# We use @cpu@ instead of ${cpu} because we still want to run sed to handle
228# transformation of @cpu@ for mainloop.in.
229
230cat << EOF
231/* This file is generated by the genmloop script. DO NOT EDIT! */
232
233/* Enable switch() support in cgen headers. */
234#define SEM_IN_SWITCH
dde54cb8
DE
235
236#define WANT_CPU
d4df1e30 237#define WANT_CPU_${CPU}
b9c8cd10
DE
238
239#include "sim-main.h"
240#include "bfd.h"
dde54cb8
DE
241#include "cgen-mem.h"
242#include "cgen-ops.h"
b9c8cd10
DE
243#include "cpu-opc.h"
244#include "cpu-sim.h"
dde54cb8 245#include "sim-assert.h"
b9c8cd10 246
b9c8cd10
DE
247EOF
248
d4df1e30 249${SHELL} $infile support
b9c8cd10 250
d4df1e30 251##########################################################################
ebd58f4d 252
d4df1e30 253# Simple engine: fetch an instruction, execute the instruction.
dde54cb8 254
d4df1e30 255if [ x$scache != xyes -a x$pbb != xyes ] ; then
b9c8cd10 256
d4df1e30 257 cat << EOF
ebd58f4d 258
d4df1e30 259#define FAST_P 0
b9c8cd10
DE
260
261void
d4df1e30 262${cpu}_engine_run_full (SIM_CPU *current_cpu)
b9c8cd10 263{
d4df1e30
DE
264#define FAST_P 0
265 SIM_DESC current_state = CPU_STATE (current_cpu);
266 SCACHE cache[MAX_LIW_INSNS];
267 SCACHE *sc = &cache[0];
dde54cb8
DE
268
269EOF
270
d4df1e30
DE
271if [ x$parallel = xyes ] ; then
272 cat << EOF
273 PAREXEC pbufs[MAX_PARALLEL_INSNS];
274 PAREXEC *par_exec;
dde54cb8 275
b9c8cd10 276EOF
d4df1e30 277fi
b9c8cd10
DE
278
279# Any initialization code before looping starts.
b500809f 280# Note that this code may declare some locals.
d4df1e30 281${SHELL} $infile init
b9c8cd10 282
b500809f 283if [ x$parallel = xyes ] ; then
d4df1e30 284 cat << EOF
b500809f
DE
285
286#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
287 {
6de2add2 288 if (! CPU_IDESC_READ_INIT_P (current_cpu))
b500809f
DE
289 {
290/* ??? Later maybe paste read.c in when building mainloop.c. */
291#define DEFINE_LABELS
292#include "readx.c"
6de2add2 293 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
b500809f
DE
294 }
295 }
296#endif
297
298EOF
299fi
300
d4df1e30 301cat << EOF
b9c8cd10 302
dde54cb8
DE
303 do
304 {
d4df1e30
DE
305/* begin full-{extract,exec}-simple */
306EOF
dde54cb8 307
d4df1e30
DE
308${SHELL} $infile extract-simple
309echo ""
310${SHELL} $infile full-exec-simple
dde54cb8 311
d4df1e30
DE
312cat << EOF
313/* end full-{extract,exec}-simple */
dde54cb8 314
d4df1e30
DE
315 ++ CPU_INSN_COUNT (current_cpu);
316 }
317 while (0 /*CPU_RUNNING_P (current_cpu)*/);
318#undef FAST_P
319}
dde54cb8 320
d4df1e30 321#undef FAST_P
dde54cb8 322
dde54cb8
DE
323EOF
324
d4df1e30 325####################################
dde54cb8 326
d4df1e30
DE
327# Simple engine: fast version.
328# ??? A somewhat dubious effort, but for completeness' sake.
dde54cb8 329
d4df1e30 330if [ x$fast = xyes ] ; then
dde54cb8 331
d4df1e30 332 cat << EOF
dde54cb8 333
d4df1e30 334#define FAST_P 1
dde54cb8 335
d4df1e30 336FIXME
dde54cb8 337
dde54cb8 338#undef FAST_P
d4df1e30 339
dde54cb8
DE
340EOF
341
d4df1e30
DE
342fi # -fast
343
344fi # simple engine
345
b500809f
DE
346##########################################################################
347
d4df1e30
DE
348# Scache engine: lookup insn in scache, fetch if missing, then execute it.
349
350if [ x$scache = xyes ] ; then
351
352 cat << EOF
dde54cb8 353
d4df1e30 354static INLINE SCACHE *
916b1152 355${cpu}_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
d4df1e30 356 unsigned int hash_mask, int FAST_P)
dde54cb8 357{
d4df1e30 358 /* First step: look up current insn in hash table. */
916b1152 359 SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
d4df1e30
DE
360
361 /* If the entry isn't the one we want (cache miss),
362 fetch and decode the instruction. */
916b1152 363 if (sc->argbuf.addr != vpc)
d4df1e30
DE
364 {
365 insn_t insn;
366
367 if (FAST_P)
368 PROFILE_COUNT_SCACHE_MISS (current_cpu);
369
370/* begin extract-scache */
371EOF
372
373${SHELL} $infile extract-scache
374
375cat << EOF
376/* end extract-scache */
377 }
378 else if (FAST_P)
379 {
380 PROFILE_COUNT_SCACHE_HIT (current_cpu);
381 /* Make core access statistics come out right.
382 The size is a guess, but it's currently not used either. */
916b1152 383 PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
d4df1e30 384 }
916b1152
DE
385
386 return sc;
d4df1e30
DE
387}
388
dde54cb8 389#define FAST_P 0
d4df1e30
DE
390
391void
392${cpu}_engine_run_full (SIM_CPU *current_cpu)
393{
394 SIM_DESC current_state = CPU_STATE (current_cpu);
395 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
396 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
916b1152 397 SEM_PC vpc;
dde54cb8
DE
398
399EOF
400
d4df1e30
DE
401if [ x$parallel = xyes ] ; then
402 cat << EOF
403 PAREXEC pbufs[MAX_PARALLEL_INSNS];
404 PAREXEC *par_exec;
405
406EOF
407fi
408
dde54cb8 409# Any initialization code before looping starts.
b500809f 410# Note that this code may declare some locals.
d4df1e30 411${SHELL} $infile init
dde54cb8 412
b500809f 413if [ x$parallel = xyes ] ; then
d4df1e30 414 cat << EOF
b500809f
DE
415
416#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
417 {
6de2add2 418 if (! CPU_IDESC_READ_INIT_P (current_cpu))
b500809f
DE
419 {
420/* ??? Later maybe paste read.c in when building mainloop.c. */
421#define DEFINE_LABELS
422#include "readx.c"
6de2add2 423 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
b500809f
DE
424 }
425 }
426#endif
427
428EOF
429fi
430
d4df1e30 431cat << EOF
dde54cb8 432
916b1152
DE
433 vpc = GET_H_PC ();
434
dde54cb8 435 do
b9c8cd10 436 {
d4df1e30 437 SCACHE *sc;
b9c8cd10 438
916b1152 439 sc = ${cpu}_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
b9c8cd10 440
d4df1e30 441/* begin full-exec-scache */
b9c8cd10
DE
442EOF
443
d4df1e30 444${SHELL} $infile full-exec-scache
b9c8cd10 445
d4df1e30
DE
446cat << EOF
447/* end full-exec-scache */
b9c8cd10 448
916b1152 449 SET_H_PC (vpc);
b9c8cd10 450
d4df1e30 451 ++ CPU_INSN_COUNT (current_cpu);
b9c8cd10 452 }
d4df1e30 453 while (0 /*CPU_RUNNING_P (current_cpu)*/);
dde54cb8
DE
454}
455
d4df1e30
DE
456#undef FAST_P
457
dde54cb8 458EOF
dde54cb8 459
d4df1e30
DE
460####################################
461
462# Scache engine: fast version.
b500809f 463
dde54cb8 464if [ x$fast = xyes ] ; then
dde54cb8 465
d4df1e30
DE
466 cat << EOF
467
dde54cb8 468#define FAST_P 1
d4df1e30
DE
469
470void
471${cpu}_engine_run_fast (SIM_CPU *current_cpu)
472{
473 SIM_DESC current_state = CPU_STATE (current_cpu);
474 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
475 unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
916b1152 476 SEM_PC vpc;
dde54cb8
DE
477
478EOF
479
d4df1e30
DE
480if [ x$parallel = xyes ] ; then
481 cat << EOF
482 PAREXEC pbufs[MAX_PARALLEL_INSNS];
483 PAREXEC *par_exec;
484
485EOF
486fi
487
dde54cb8 488# Any initialization code before looping starts.
b500809f 489# Note that this code may declare some locals.
d4df1e30 490${SHELL} $infile init
dde54cb8 491
b500809f 492if [ x$parallel = xyes ] ; then
d4df1e30 493 cat << EOF
b500809f
DE
494
495#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
496 {
6de2add2 497 if (! CPU_IDESC_READ_INIT_P (current_cpu))
b500809f
DE
498 {
499/* ??? Later maybe paste read.c in when building mainloop.c. */
500#define DEFINE_LABELS
501#include "readx.c"
6de2add2 502 CPU_IDESC_READ_INIT_P (current_cpu) = 1;
b500809f
DE
503 }
504 }
505#endif
506
507EOF
d4df1e30 508fi # parallel = yes
b500809f 509
d4df1e30 510cat << EOF
dde54cb8 511
d4df1e30 512#if WITH_SEM_SWITCH_FAST && defined (__GNUC__)
dde54cb8 513 {
6de2add2 514 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
dde54cb8
DE
515 {
516/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
517#define DEFINE_LABELS
d4df1e30 518#include "$switch"
6de2add2 519 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
dde54cb8
DE
520 }
521 }
522#endif
523
916b1152
DE
524 vpc = GET_H_PC ();
525
dde54cb8 526 do
b9c8cd10 527 {
d4df1e30 528 SCACHE *sc;
dde54cb8 529
916b1152 530 sc = ${cpu}_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
dde54cb8 531
d4df1e30
DE
532/* begin fast-exec-scache */
533EOF
534
535${SHELL} $infile fast-exec-scache
536
537cat << EOF
538/* end fast-exec-scache */
539
916b1152 540 SET_H_PC (vpc);
d4df1e30
DE
541
542 ++ CPU_INSN_COUNT (current_cpu);
543 }
544 while (0 /*CPU_RUNNING_P (current_cpu)*/);
545}
546
547#undef FAST_P
dde54cb8 548
dde54cb8
DE
549EOF
550
d4df1e30 551fi # -fast
dde54cb8 552
d4df1e30 553fi # -scache
dde54cb8 554
d4df1e30
DE
555##########################################################################
556
557# Compilation engine: lookup insn in scache, extract a pbb
558# (pseudo-basic-block) if missing, then execute the pbb.
559# A "pbb" is a sequence of insns up to the next cti insn or until
560# some prespecified maximum.
561# CTI: control transfer instruction.
562
563if [ x$pbb = xyes ] ; then
564
565 cat << EOF
566
567/* Record address of cti terminating a pbb. */
568#define SET_CTI_VPC(sc) do { cti_sc = (sc); } while (0)
569/* Record number of [real] insns in pbb. */
570#define SET_INSN_COUNT(n) do { insn_count = (n); } while (0)
571
572/* Fetch and extract a pseudo-basic-block.
573 FAST_P is non-zero if no tracing/profiling/etc. is wanted. */
574
575INLINE SEM_PC
576${cpu}_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
577{
578 SEM_PC new_vpc;
579 PCADDR pc;
580 SCACHE *sc;
581 int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu);
582
583 pc = GET_H_PC ();
584
585 new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc);
586 if (! new_vpc)
587 {
588 int insn_count = 0;
589 SCACHE *orig_sc = sc;
590 SCACHE *cti_sc = NULL;
591 int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu);
592
593 /* First figure out how many instructions to compile.
594 MAX_INSNS is the size of the allocated buffer, which includes space
595 for before/after handlers if they're being used.
596 SLICE_INSNS is the maxinum number of real insns that can be
597 executed. Zero means "as many as we want". */
598 /* ??? max_insns is serving two incompatible roles.
599 1) Number of slots available in scache buffer.
600 2) Number of real insns to execute.
601 They're incompatible because there are virtual insns emitted too
602 (chain,cti-chain,before,after handlers). */
603
604 if (slice_insns == 1)
605 {
606 /* No need to worry about extra slots required for virtual insns
607 and parallel exec support because MAX_CHAIN_LENGTH is
608 guaranteed to be big enough to execute at least 1 insn! */
609 max_insns = 1;
610 }
611 else
612 {
613 /* Allow enough slop so that while compiling insns, if max_insns > 0
614 then there's guaranteed to be enough space to emit one real insn.
615 MAX_CHAIN_LENGTH is typically much longer than
616 the normal number of insns between cti's anyway. */
617 max_insns -= (1 /* one for the trailing chain insn */
618 + (FAST_P
619 ? 0
620 : (1 + MAX_PARALLEL_INSNS) /* before+after */)
621 + (MAX_PARALLEL_INSNS > 1
622 ? (MAX_PARALLEL_INSNS * 2)
623 : 0));
624
625 /* Account for before/after handlers. */
626 if (! FAST_P)
627 slice_insns *= 3;
628
629 if (slice_insns > 0
630 && slice_insns < max_insns)
631 max_insns = slice_insns;
632 }
633
634 new_vpc = sc;
635
636 /* SC,PC must be updated to point passed the last entry used.
637 SET_CTI_VPC must be called if pbb is terminated by a cti.
638 SET_INSN_COUNT must be called to record number of real insns in
639 pbb [could be computed by us of course, extra cpu but perhaps
640 negligible enough]. */
641
642/* begin extract-pbb */
dde54cb8
DE
643EOF
644
d4df1e30 645${SHELL} $infile extract-pbb
dde54cb8 646
d4df1e30
DE
647cat << EOF
648/* end extract-pbb */
dde54cb8 649
d4df1e30
DE
650 /* The last one is a pseudo-insn to link to the next chain.
651 It is also used to record the insn count for this chain. */
652 {
653 const IDESC *id;
654
655 /* Was pbb terminated by a cti? */
656 if (cti_sc)
657 {
658 id = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_CTI_CHAIN];
659 }
660 else
661 {
662 id = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_CHAIN];
663 }
664 SEM_SET_CODE (&sc->argbuf, id, FAST_P);
665 sc->argbuf.idesc = id;
666 sc->argbuf.addr = pc;
667 sc->argbuf.fields.chain.insn_count = insn_count;
668 sc->argbuf.fields.chain.next = 0;
669 ++sc;
dde54cb8
DE
670 }
671
d4df1e30
DE
672 /* Update the pointer to the next free entry. */
673 CPU_SCACHE_NEXT_FREE (current_cpu) = sc;
674 /* Record length of chain if profiling.
675 This includes virtual insns since they count against
676 max_insns too. */
677 if (! FAST_P)
678 PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc);
dde54cb8 679 }
d4df1e30
DE
680
681 return new_vpc;
dde54cb8
DE
682}
683
d4df1e30 684/* Chain to the next block from a non-cti terminated previous block. */
dde54cb8 685
d4df1e30
DE
686INLINE SEM_PC
687${cpu}_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
688{
689 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
690
691 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
692
693 SET_H_PC (abuf->addr);
694
695 /* If not running forever, exit back to main loop. */
696 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0)
697 CPU_RUNNING_P (current_cpu) = 0;
698
699 /* If chained to next block, go straight to it. */
700 if (abuf->fields.chain.next)
701 return abuf->fields.chain.next;
702 /* See if next block has already been compiled. */
703 abuf->fields.chain.next = scache_lookup (current_cpu, abuf->addr);
704 if (abuf->fields.chain.next)
705 return abuf->fields.chain.next;
706 /* Nope, so next insn is a virtual insn to invoke the compiler
707 (begin a pbb). */
708 return CPU_SCACHE_PBB_BEGIN (current_cpu);
709}
b500809f 710
d4df1e30
DE
711/* Chain to the next block from a cti terminated previous block.
712 NEW_VPC_PTR is one of SEM_BRANCH_UNTAKEN, SEM_BRANCH_UNCACHEABLE, or
713 a pointer to a location containing the SEM_PC of the branch's address.
714 NEW_PC is the target's branch address, and is only valid if
715 NEW_VPC_PTR != SEM_BRANCH_UNTAKEN. */
dde54cb8 716
d4df1e30
DE
717INLINE SEM_PC
718${cpu}_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
719 SEM_PC *new_vpc_ptr, PCADDR new_pc)
dde54cb8 720{
d4df1e30
DE
721 ARGBUF *abuf;
722
723 PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
724
725 /* If not running forever, exit back to main loop. */
726 if (CPU_MAX_SLICE_INSNS (current_cpu) != 0)
727 CPU_RUNNING_P (current_cpu) = 0;
728
729 /* Restart compiler if we branched to an uncacheable address
730 (e.g. "j reg"). */
731 if (new_vpc_ptr == SEM_BRANCH_UNCACHEABLE)
732 {
733 SET_H_PC (new_pc);
734 return CPU_SCACHE_PBB_BEGIN (current_cpu);
735 }
736
737 /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our
738 next chain ptr. */
739 if (new_vpc_ptr == SEM_BRANCH_UNTAKEN)
740 {
741 abuf = SEM_ARGBUF (sem_arg);
742 SET_H_PC (abuf->addr);
743 new_vpc_ptr = &abuf->fields.chain.next;
744 }
745 else
746 {
747 SET_H_PC (new_pc);
748 }
749
750 /* If chained to next block, go straight to it. */
751 if (*new_vpc_ptr)
752 return *new_vpc_ptr;
753 /* See if next block has already been compiled. */
754 *new_vpc_ptr = scache_lookup (current_cpu, GET_H_PC ());
755 if (*new_vpc_ptr)
756 return *new_vpc_ptr;
757 /* Nope, so next insn is a virtual insn to invoke the compiler
758 (begin a pbb). */
759 return CPU_SCACHE_PBB_BEGIN (current_cpu);
760}
761
762/* x-before handler.
763 This is called before each insn. */
764
765void
766${cpu}_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
767{
768 SEM_ARG sem_arg = sc;
769 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
770 int first_p = abuf->fields.before.first_p;
771 const ARGBUF *cur_abuf = SEM_ARGBUF (sc + 1);
772 const IDESC *cur_idesc = cur_abuf->idesc;
773 PCADDR pc = cur_abuf->addr;
774
775 PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
776
777 /* If this isn't the first insn, finish up the previous one. */
778
779 if (! first_p)
780 {
781 if (PROFILE_MODEL_P (current_cpu))
782 {
783 const SEM_ARG prev_sem_arg = sc - 1;
784 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
785 const IDESC *prev_idesc = prev_abuf->idesc;
786 int cycles;
787
788 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
789 ${cpu}_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
790 }
791
792 TRACE_INSN_FINI (current_cpu, 0 /*last_p*/);
793 }
794
795 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */
796 if (PROFILE_MODEL_P (current_cpu))
797 ${cpu}_model_insn_before (current_cpu, first_p);
798
799 TRACE_INSN_INIT (current_cpu, first_p);
800 TRACE_INSN (current_cpu, cur_idesc->opcode, cur_abuf, cur_abuf->addr);
801}
802
803/* x-after handler.
804 This is called after a serial insn or at the end of a group of parallel
805 insns. */
806
807void
808${cpu}_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
809{
810 SEM_ARG sem_arg = sc;
811 const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
812
813 if (PROFILE_MODEL_P (current_cpu))
814 {
815 const SEM_ARG prev_sem_arg = sc - 1;
816 const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
817 const IDESC *prev_idesc = prev_abuf->idesc;
818 int cycles;
819
820 cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
821 ${cpu}_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
822 }
823 TRACE_INSN_FINI (current_cpu, 1 /*last_p*/);
824}
825
826#define FAST_P 0
827
828void
829${cpu}_engine_run_full (SIM_CPU *current_cpu)
830{
831 SIM_DESC current_state = CPU_STATE (current_cpu);
832 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
833 /* virtual program counter */
834 SEM_PC vpc;
835#if WITH_SEM_SWITCH_FULL
836 /* For communication between cti's and cti-chain. */
837 PCADDR pbb_br_npc;
838 SEM_PC *pbb_br_npc_ptr;
839#endif
840
841EOF
842
843if [ x$parallel = xyes ] ; then
844 cat << EOF
845 PAREXEC pbufs[MAX_PARALLEL_INSNS];
846 PAREXEC *par_exec = &pbufs[0];
b9c8cd10
DE
847
848EOF
d4df1e30 849fi
b9c8cd10 850
dde54cb8 851# Any initialization code before looping starts.
b500809f 852# Note that this code may declare some locals.
d4df1e30 853${SHELL} $infile init
b9c8cd10 854
b500809f
DE
855cat << EOF
856
d4df1e30
DE
857 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
858 {
859 /* ??? 'twould be nice to move this up a level and only call it once.
860 On the other hand, in the "let's go fast" case the test is only done
861 once per pbb (since we only return to the main loop at the end of
862 a pbb). And in the "let's run until we're done" case we don't return
863 until the program exits. */
864
865#if WITH_SEM_SWITCH_FULL && defined (__GNUC__)
866/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
b500809f 867#define DEFINE_LABELS
d4df1e30
DE
868#include "$switch"
869#endif
870
871 /* Initialize the "begin (compile) a pbb" virtual insn. */
872 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
873 SEM_SET_FULL_CODE (SEM_ARGBUF (vpc),
874 & CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN]);
875 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN];
876
877 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
878 }
879
880 CPU_RUNNING_P (current_cpu) = 1;
881 /* ??? In the case where we're returning to the main loop after every
882 pbb we don't want to call pbb_begin each time (which hashes on the pc
883 and does a table lookup). A way to speed this up is to save vpc
884 between calls. */
885 vpc = ${cpu}_pbb_begin (current_cpu, FAST_P);
886
887 do
888 {
889/* begin full-exec-pbb */
890EOF
891
892${SHELL} $infile full-exec-pbb
893
894cat << EOF
895/* end full-exec-pbb */
896 }
897 while (CPU_RUNNING_P (current_cpu));
898}
899
900#undef FAST_P
901
902EOF
903
904####################################
905
906# Compile engine: fast version.
907
908if [ x$fast = xyes ] ; then
909
910 cat << EOF
911
912#define FAST_P 1
913
914void
915${cpu}_engine_run_fast (SIM_CPU *current_cpu)
916{
917 SIM_DESC current_state = CPU_STATE (current_cpu);
918 SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
919 /* virtual program counter */
920 SEM_PC vpc;
921#if WITH_SEM_SWITCH_FAST
922 /* For communication between cti's and cti-chain. */
923 PCADDR pbb_br_npc;
924 SEM_PC *pbb_br_npc_ptr;
b500809f
DE
925#endif
926
d4df1e30
DE
927EOF
928
929if [ x$parallel = xyes ] ; then
930 cat << EOF
931 PAREXEC pbufs[MAX_PARALLEL_INSNS];
932 PAREXEC *par_exec = &pbufs[0];
933
b500809f
DE
934EOF
935fi
936
d4df1e30
DE
937# Any initialization code before looping starts.
938# Note that this code may declare some locals.
939${SHELL} $infile init
940
941cat << EOF
942
943 if (! CPU_IDESC_SEM_INIT_P (current_cpu))
944 {
945 /* ??? 'twould be nice to move this up a level and only call it once.
946 On the other hand, in the "let's go fast" case the test is only done
947 once per pbb (since we only return to the main loop at the end of
948 a pbb). And in the "let's run until we're done" case we don't return
949 until the program exits. */
950
951#if WITH_SEM_SWITCH_FAST && defined (__GNUC__)
952/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
953#define DEFINE_LABELS
954#include "$switch"
955#endif
956
957 /* Initialize the "begin (compile) a pbb" virtual insn. */
958 vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
959 SEM_SET_FAST_CODE (SEM_ARGBUF (vpc),
960 & CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN]);
961 vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN];
962
963 CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
964 }
965
966 CPU_RUNNING_P (current_cpu) = 1;
967 /* ??? In the case where we're returning to the main loop after every
968 pbb we don't want to call pbb_begin each time (which hashes on the pc
969 and does a table lookup). A way to speed this up is to save vpc
970 between calls. */
971 vpc = ${cpu}_pbb_begin (current_cpu, FAST_P);
b9c8cd10 972
dde54cb8
DE
973 do
974 {
d4df1e30 975/* begin fast-exec-pbb */
dde54cb8
DE
976EOF
977
d4df1e30 978${SHELL} $infile fast-exec-pbb
dde54cb8 979
d4df1e30
DE
980cat << EOF
981/* end fast-exec-pbb */
b9c8cd10 982 }
d4df1e30 983 while (CPU_RUNNING_P (current_cpu));
b9c8cd10 984}
dde54cb8 985
d4df1e30 986#undef FAST_P
dde54cb8 987
d4df1e30 988EOF
dde54cb8 989fi # -fast
d4df1e30
DE
990
991fi # -pbb
992
993sed -e "s/@cpu@/$cpu/g" -e "s/@CPU@/$CPU/g" < tmp-mloop.cin > mloop.cin
994rc=$?
995rm -f tmp-mloop.cin
996
997exit $rc
This page took 0.113039 seconds and 4 git commands to generate.