* genmloop.sh (@cpu@_engine_run): Delete `current_state'.
(engine_resume): Likewise. Make `engine' volatile. Save copy of cpu pointer in volatile object.
This commit is contained in:
parent
cb5cd5b464
commit
dde54cb845
2 changed files with 360 additions and 69 deletions
|
@ -1,3 +1,9 @@
|
|||
Mon Feb 9 14:48:37 1998 Doug Evans <devans@canuck.cygnus.com>
|
||||
|
||||
* genmloop.sh (@cpu@_engine_run): Delete `current_state'.
|
||||
(engine_resume): Likewise. Make `engine' volatile. Save copy
|
||||
of cpu pointer in volatile object.
|
||||
|
||||
Thu Feb 5 13:27:04 1998 Doug Evans <devans@seba.cygnus.com>
|
||||
|
||||
* cgen-sim.h (EX_FN_NAME): _exc_ -> _ex_.
|
||||
|
|
|
@ -1,11 +1,48 @@
|
|||
# This shell script emits a C file. -*- C -*-
|
||||
# Generate the main loop of the simulator.
|
||||
# Syntax: genmloop.sh mono|multi cpu mainloop.in
|
||||
# Syntax: genmloop.sh /bin/sh [options] cpu mainloop.in
|
||||
# Options: [-mono|-multi] -scache -fast -parallel
|
||||
#
|
||||
# -scache: use the scache
|
||||
# -fast: include support for fast execution in addition to full featured mode
|
||||
# -parallel: cpu can execute multiple instructions parallely
|
||||
#
|
||||
# FIXME: "multi" support is wip.
|
||||
|
||||
type=$1
|
||||
cpu=$2
|
||||
file=$3
|
||||
# TODO
|
||||
# - move this C code to mainloop.in
|
||||
# - keep genmloop.sh
|
||||
# - build exec.in from .cpu file
|
||||
# - have each cpu provide handwritten cycle.in
|
||||
# - integrate with common/sim-engine.[ch]
|
||||
# - for sparc, have two main loops, outer one handles delay slot when npc != 0
|
||||
# - inner loop does not handle delay slots, pc = pc + 4
|
||||
|
||||
type=mono
|
||||
#scache=
|
||||
#fast=
|
||||
#parallel=
|
||||
|
||||
shell=$1 ; shift
|
||||
|
||||
while true
|
||||
do
|
||||
case $1 in
|
||||
-mono) type=mono ;;
|
||||
-multi) type=multi ;;
|
||||
-no-scache) ;;
|
||||
-scache) scache=yes ;;
|
||||
-no-fast) ;;
|
||||
-fast) fast=yes ;;
|
||||
-no-parallel) ;;
|
||||
-parallel) parallel=yes ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
cpu=$1
|
||||
file=$2
|
||||
|
||||
cat <<EOF
|
||||
/* This file is is generated by the genmloop script. DO NOT EDIT! */
|
||||
|
@ -14,7 +51,7 @@ cat <<EOF
|
|||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
This file is part of the GNU simulators.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -30,16 +67,30 @@ You should have received a copy of the GNU General Public License along
|
|||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* We want the simcache version of SEM_ARG. */
|
||||
#define SCACHE_P
|
||||
/* We want the scache version of SEM_ARG.
|
||||
This is used by the switch() version of the semantic code. */
|
||||
EOF
|
||||
|
||||
if [ x$scache = xyes ] ; then
|
||||
echo "#define SCACHE_P"
|
||||
else
|
||||
echo '/*#define SCACHE_P*/'
|
||||
echo '#undef WITH_SCACHE'
|
||||
echo '#define WITH_SCACHE 0'
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
#define WANT_CPU
|
||||
#define WANT_CPU_@CPU@
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "bfd.h"
|
||||
#include "mem-ops.h"
|
||||
#include "sem-ops.h"
|
||||
#include "cgen-scache.h"
|
||||
#include "cgen-mem.h"
|
||||
#include "cgen-ops.h"
|
||||
#include "cpu-opc.h"
|
||||
#include "cpu-sim.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
/* Tell sim_main_loop to use the cache if it's active.
|
||||
Collecting profile data and tracing slow us down so we don't do them in
|
||||
|
@ -48,7 +99,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
- use or don't use the cache
|
||||
- run normally (full featured) or run fast
|
||||
Supporting all four possibilities in one executable is a bit much but
|
||||
supporting normal/fast seems reasonable.
|
||||
supporting full/fast seems reasonable.
|
||||
If the cache is configured in it is always used.
|
||||
??? Need to see whether it speeds up profiling significantly or not.
|
||||
Speeding up tracing doesn't seem worth it.
|
||||
|
@ -70,6 +121,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define SIM_POST_EXEC_HOOK(state)
|
||||
#endif
|
||||
|
||||
#if 0 /* FIXME:experiment */
|
||||
/* "sc" is local to the calling function.
|
||||
It is done this way to keep the internals of the implementation out of
|
||||
the description file. */
|
||||
#define EXTRACT(cpu, pc, insn, sc, num, fast_p) \
|
||||
@cpu@_extract (cpu, pc, insn, sc + num, fast_p)
|
||||
|
||||
#define EXECUTE(cpu, sc, num, fast_p) \
|
||||
@cpu@_execute (cpu, sc + num, fast_p)
|
||||
#endif
|
||||
|
||||
#define GET_ATTR(cpu, num, attr) \
|
||||
CGEN_INSN_ATTR (sc[num].argbuf.opcode, CGEN_INSN_##attr)
|
||||
|
||||
EOF
|
||||
|
||||
${SHELL} $file support
|
||||
|
@ -77,18 +142,25 @@ ${SHELL} $file support
|
|||
cat <<EOF
|
||||
|
||||
static volatile int keep_running;
|
||||
/* Want to measure simulator speed even in fast mode. */
|
||||
static unsigned long insn_count;
|
||||
static SIM_ELAPSED_TIME start_time;
|
||||
|
||||
/* Forward decls of cpu-specific functions. */
|
||||
static void engine_resume (SIM_DESC, int, int);
|
||||
static void engine_resume_full (SIM_DESC);
|
||||
${scache+static void engine_resume_fast (SIM_DESC);}
|
||||
|
||||
int
|
||||
engine_stop (SIM_DESC sd)
|
||||
@cpu@_engine_stop (SIM_DESC sd)
|
||||
{
|
||||
keep_running = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
engine_run (SIM_DESC sd, int step, int siggnal)
|
||||
@cpu@_engine_run (SIM_DESC sd, int step, int siggnal)
|
||||
{
|
||||
current_state = sd;
|
||||
#if WITH_SCACHE
|
||||
if (USING_SCACHE_P (sd))
|
||||
scache_flush (sd);
|
||||
|
@ -96,37 +168,82 @@ engine_run (SIM_DESC sd, int step, int siggnal)
|
|||
engine_resume (sd, step, siggnal);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
engine_resume (SIM_DESC sd, int step, int siggnal)
|
||||
{
|
||||
#ifdef __STDC__
|
||||
/* These are volatile to survive setjmp/longjmp.
|
||||
This will slow down the simulation a teensy bit, but we want to
|
||||
measure simulator speed even in fast mode. */
|
||||
volatile unsigned long insn_count;
|
||||
volatile SIM_ELAPSED_TIME start_time;
|
||||
#else
|
||||
/* ??? Not sure what to do for K&R C. */
|
||||
static unsigned long insn_count;
|
||||
static SIM_ELAPSED_TIME start_time;
|
||||
#endif
|
||||
SIM_DESC current_state = sd;
|
||||
sim_cpu *current_cpu = STATE_CPU (sd, 0);
|
||||
/* These are volatile to survive setjmp. */
|
||||
volatile sim_cpu *cpu = current_cpu;
|
||||
volatile sim_engine *engine = STATE_ENGINE (sd);
|
||||
jmp_buf buf;
|
||||
int jmpval;
|
||||
|
||||
keep_running = 1;
|
||||
keep_running = ! step;
|
||||
start_time = sim_elapsed_time_get ();
|
||||
/* FIXME: Having this global can slow things down a teensy bit.
|
||||
After things are working see about moving engine_resume_{full,fast}
|
||||
back into this function. */
|
||||
insn_count = 0;
|
||||
|
||||
if (setjmp (STATE_HALT_JMP_BUF (sd)))
|
||||
engine->jmpbuf = &buf;
|
||||
if (setjmp (buf))
|
||||
{
|
||||
TRACE_INSN_FINI (current_cpu);
|
||||
PROFILE_EXEC_TIME (CPU_PROFILE_DATA (current_cpu))
|
||||
engine->jmpbuf = NULL;
|
||||
TRACE_INSN_FINI ((sim_cpu *) cpu);
|
||||
PROFILE_EXEC_TIME (CPU_PROFILE_DATA (cpu))
|
||||
+= sim_elapsed_time_since (start_time);
|
||||
PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (current_cpu))
|
||||
PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu))
|
||||
+= insn_count;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ??? Restart support to be added in time. */
|
||||
|
||||
/* The computed goto switch can be used, and while the number of blocks
|
||||
may swamp the relatively few that this function contains, when running
|
||||
with the scache we put the actual semantic code in their own
|
||||
functions. */
|
||||
|
||||
EOF
|
||||
|
||||
if [ x$fast = xyes ] ; then
|
||||
cat <<EOF
|
||||
if (step
|
||||
|| !RUN_FAST_P (current_cpu))
|
||||
engine_resume_full (sd);
|
||||
else
|
||||
engine_resume_fast (sd);
|
||||
EOF
|
||||
else
|
||||
cat <<EOF
|
||||
engine_resume_full (sd);
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
/* If the loop exits, either we single-stepped or engine_stop was called.
|
||||
In either case we need to call engine_halt: to properly exit this
|
||||
function we must go through the setjmp executed above. */
|
||||
if (step)
|
||||
sim_engine_halt (sd, current_cpu, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
|
||||
sim_engine_halt (sd, current_cpu, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
if [ x$scache = xyes ] ; then
|
||||
cat <<EOF
|
||||
|
||||
static void
|
||||
engine_resume_full (SIM_DESC sd)
|
||||
{
|
||||
#define FAST_P 0
|
||||
/* current_{state,cpu} exist for the generated code to use. */
|
||||
SIM_DESC current_state = sd;
|
||||
sim_cpu *current_cpu = STATE_CPU (sd, 0);
|
||||
${parallel+ int icount = 0;}
|
||||
|
||||
EOF
|
||||
|
||||
# Any initialization code before looping starts.
|
||||
|
@ -134,56 +251,224 @@ ${SHELL} $file init
|
|||
|
||||
cat <<EOF
|
||||
|
||||
/* ??? Restart support to be added in time. */
|
||||
|
||||
if (step
|
||||
|| !RUN_FAST_P (current_cpu))
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
#define FAST 0 /* ??? Hopefully this name won't collide with anything. */
|
||||
/* FIXME: Later check every insn for events and such. */
|
||||
/* FIXME: Later check every insn for events and such. */
|
||||
|
||||
SIM_PRE_EXEC_HOOK (current_cpu);
|
||||
SIM_PRE_EXEC_HOOK (current_cpu);
|
||||
|
||||
{
|
||||
unsigned int hash;
|
||||
SCACHE *sc;
|
||||
PCADDR pc = PC;
|
||||
|
||||
/* First step: look up current insn in hash table. */
|
||||
hash = SCACHE_HASH_PC (sd, pc);
|
||||
sc = CPU_SCACHE_CACHE (current_cpu) + hash;
|
||||
|
||||
/* If the entry isn't the one we want (cache miss),
|
||||
fetch and decode the instruction. */
|
||||
if (sc->argbuf.addr != pc)
|
||||
{
|
||||
insn_t insn;
|
||||
|
||||
PROFILE_COUNT_SCACHE_MISS (current_cpu);
|
||||
|
||||
/* begin full-extract-scache */
|
||||
EOF
|
||||
|
||||
# Copy of main loop that uses the various compiled in features.
|
||||
# FIXME: May want more than one copy of this.
|
||||
${SHELL} $file normal
|
||||
${SHELL} $file full-extract-scache
|
||||
|
||||
cat <<EOF
|
||||
/* end full-extract-scache */
|
||||
}
|
||||
else
|
||||
{
|
||||
PROFILE_COUNT_SCACHE_HIT (current_cpu);
|
||||
}
|
||||
|
||||
SIM_POST_EXEC_HOOK (current_cpu);
|
||||
|
||||
++insn_count;
|
||||
if (step)
|
||||
engine_halt (current_cpu, EXEC_STATE_STOPPED, SIM_SIGTRAP);
|
||||
}
|
||||
while (keep_running);
|
||||
/* If the loop exists, engine_stop was called. */
|
||||
engine_halt (current_cpu, EXEC_STATE_STOPPED, SIM_SIGINT);
|
||||
#undef FAST
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
#define FAST 1
|
||||
|
||||
/* begin full-exec-scache */
|
||||
EOF
|
||||
|
||||
# Copy of main loop that is run purely for fast execution.
|
||||
${SHELL} $file fast
|
||||
${SHELL} $file full-exec-scache
|
||||
|
||||
cat <<EOF
|
||||
/* end full-exec-scache */
|
||||
}
|
||||
|
||||
#undef FAST
|
||||
++insn_count;
|
||||
}
|
||||
while (keep_running);
|
||||
/* If the loop exists, engine_stop was called. */
|
||||
engine_halt (current_cpu, EXEC_STATE_STOPPED, SIM_SIGINT);
|
||||
SIM_POST_EXEC_HOOK (current_cpu);
|
||||
|
||||
++insn_count;
|
||||
}
|
||||
while (keep_running);
|
||||
#undef FAST_P
|
||||
}
|
||||
EOF
|
||||
|
||||
else # ! WITH_SCACHE
|
||||
cat <<EOF
|
||||
|
||||
static void
|
||||
engine_resume_full (SIM_DESC sd)
|
||||
{
|
||||
#define FAST_P 0
|
||||
SIM_DESC current_state = sd;
|
||||
sim_cpu *current_cpu = STATE_CPU (sd, 0);
|
||||
SCACHE cache[MAX_LIW_INSNS];
|
||||
SCACHE *sc = &cache[0];
|
||||
${parallel+ int icount = 0;}
|
||||
|
||||
EOF
|
||||
|
||||
# Any initialization code before looping starts.
|
||||
${SHELL} $file init
|
||||
|
||||
cat <<EOF
|
||||
|
||||
do
|
||||
{
|
||||
/* FIXME: Later check every insn for events and such. */
|
||||
|
||||
SIM_PRE_EXEC_HOOK (current_cpu);
|
||||
|
||||
{
|
||||
/* begin full-{extract,exec}-noscache */
|
||||
EOF
|
||||
|
||||
${SHELL} $file full-extract-noscache
|
||||
echo ""
|
||||
${SHELL} $file full-exec-noscache
|
||||
|
||||
cat <<EOF
|
||||
/* end full-{extract,exec}-noscache */
|
||||
}
|
||||
|
||||
SIM_POST_EXEC_HOOK (current_cpu);
|
||||
|
||||
++insn_count;
|
||||
}
|
||||
while (keep_running);
|
||||
#undef FAST_P
|
||||
}
|
||||
|
||||
EOF
|
||||
fi # ! WITH_SCACHE
|
||||
|
||||
if [ x$fast = xyes ] ; then
|
||||
if [ x$scache = xyes ] ; then
|
||||
cat <<EOF
|
||||
|
||||
static void
|
||||
engine_resume_fast (SIM_DESC sd)
|
||||
{
|
||||
#define FAST_P 1
|
||||
SIM_DESC current_state = sd;
|
||||
sim_cpu *current_cpu = STATE_CPU (sd, 0);
|
||||
${parallel+ int icount = 0;}
|
||||
|
||||
EOF
|
||||
|
||||
# Any initialization code before looping starts.
|
||||
${SHELL} $file init
|
||||
|
||||
cat <<EOF
|
||||
|
||||
#if defined (WITH_SEM_SWITCH_FAST) && defined (__GNUC__)
|
||||
{
|
||||
static decode_init_p = 0;
|
||||
if (! decode_init_p)
|
||||
{
|
||||
/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
|
||||
#define DEFINE_LABELS
|
||||
#include "sem-switch.c"
|
||||
decode_init_p = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
{
|
||||
unsigned int hash;
|
||||
SCACHE *sc;
|
||||
PCADDR pc = PC;
|
||||
|
||||
/* First step: look up current insn in hash table. */
|
||||
hash = SCACHE_HASH_PC (sd, pc);
|
||||
sc = CPU_SCACHE_CACHE (current_cpu) + hash;
|
||||
|
||||
/* If the entry isn't the one we want (cache miss),
|
||||
fetch and decode the instruction. */
|
||||
if (sc->argbuf.addr != pc)
|
||||
{
|
||||
insn_t insn;
|
||||
|
||||
/* begin fast-extract-scache */
|
||||
EOF
|
||||
|
||||
${SHELL} $file fast-extract-scache
|
||||
|
||||
cat <<EOF
|
||||
/* end fast-extract-scache */
|
||||
}
|
||||
|
||||
/* begin fast-exec-scache */
|
||||
EOF
|
||||
|
||||
${SHELL} $file fast-exec-scache
|
||||
|
||||
cat <<EOF
|
||||
/* end fast-exec-scache */
|
||||
|
||||
}
|
||||
|
||||
++insn_count;
|
||||
}
|
||||
while (keep_running);
|
||||
#undef FAST_P
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
else # ! WITH_SCACHE
|
||||
cat <<EOF
|
||||
|
||||
static void
|
||||
engine_resume_fast (SIM_DESC sd)
|
||||
{
|
||||
#define FAST_P 1
|
||||
SIM_DESC current_state = sd;
|
||||
sim_cpu *current_cpu = STATE_CPU (sd, 0);
|
||||
SCACHE cache[MAX_LIW_INSNS];
|
||||
SCACHE *sc = &cache[0];
|
||||
${parallel+ int icount = 0;}
|
||||
|
||||
EOF
|
||||
|
||||
# Any initialization code before looping starts.
|
||||
${SHELL} $file init
|
||||
|
||||
cat <<EOF
|
||||
|
||||
do
|
||||
{
|
||||
/* begin fast-{extract,exec}-noscache */
|
||||
EOF
|
||||
|
||||
${SHELL} $file fast-extract-noscache
|
||||
echo ""
|
||||
${SHELL} $file fast-exec-noscache
|
||||
|
||||
cat <<EOF
|
||||
/* end fast-{extract,exec}-noscache */
|
||||
|
||||
++insn_count;
|
||||
}
|
||||
while (keep_running);
|
||||
#undef FAST_P
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
fi # ! WITH_SCACHE
|
||||
fi # -fast
|
||||
|
|
Loading…
Reference in a new issue