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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [common/] [genmloop.sh] - Blame information for rev 855

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

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

powered by: WebSVN 2.1.0

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