OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [common/] [genmloop.sh] - Blame information for rev 1181

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.