aboutsummaryrefslogtreecommitdiff
path: root/sim/common
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>1999-08-09 21:36:23 +0000
committerJason Molenda <jmolenda@apple.com>1999-08-09 21:36:23 +0000
commit96baa820df8126165bd3c4a33c561556b21203af (patch)
tree60cf1938a2c0aaae5d3aab73b553f031138ec99c /sim/common
parent10e80b41455f1a386485631b7c170cafe341dcd6 (diff)
downloadgdb-96baa820df8126165bd3c4a33c561556b21203af.zip
gdb-96baa820df8126165bd3c4a33c561556b21203af.tar.gz
gdb-96baa820df8126165bd3c4a33c561556b21203af.tar.bz2
import gdb-1999-08-09 snapshot
Diffstat (limited to 'sim/common')
-rw-r--r--sim/common/ChangeLog32
-rw-r--r--sim/common/cgen-cpu.h4
-rw-r--r--sim/common/cgen-defs.h9
-rw-r--r--sim/common/cgen-engine.h132
-rw-r--r--sim/common/cgen-scache.c7
-rw-r--r--sim/common/cgen-scache.h8
-rw-r--r--sim/common/genmloop.sh303
7 files changed, 340 insertions, 155 deletions
diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog
index bc2bb01..26dcb3c 100644
--- a/sim/common/ChangeLog
+++ b/sim/common/ChangeLog
@@ -1,3 +1,35 @@
+1999-08-08 Doug Evans <devans@casey.cygnus.com>
+
+ * cgen-engine.h (SEM_FN_NAME,SEMF_FN_NAME): Delete.
+ (insn_sem): Rewrite.
+ (sem_fn_desc): New struct.
+ (idesc): Rewrite.
+ * genmloop.sh (scache case,@cpu@_scache_lookup): Profile scache hit,
+ misses if ! FAST_P.
+ (scache case): Split into non-parallel/parallel versions.
+ (@cpu@_engine_run_{full,fast}): Call @cpu@_{sem,semf}_init_idesc_table
+ if not use semantic switch version.
+
+1999-08-04 Doug Evans <devans@casey.cygnus.com>
+
+ * cgen-defs.h (SEM_BRANCH_TYPE): New enum.
+ * cgen-engine.h (SEM_BRANCH_UNTAKEN,SEM_BRANCH_UNCACHEABLE): Delete.
+ (SEM_BRANCH_INIT_EXTRACT): Delete.
+ (SEM_BRANCH_INIT): Replace npc_ptr with br_type.
+ (SEM_BRANCH_FINI): Ditto.
+ (SEM_BRANCH_VIA_ADDR): Ditto.
+ (SEM_BRANCH_VIA_CACHE): Ditto. Delete cachvarptr arg.
+ (SEM_BRANCH_ADDR_CACHE): Delete.
+ (SEM_SKIP_COMPILE,SEM_SKIP_INSN): New macros.
+ * cgen-scache.h (cpu_scache): Replace member pbb_pr_npc_ptr with
+ pbb_br_type.
+ * genmloop.sh (eng.hin): Update prototype of ${cpu}_pbb_cti_chain.
+ (@cpu@_pbb_begin): Initialize branch_target.
+ (@cpu@_pbb_cti_chain): Replace arg new_vpc_ptr with br_type.
+ (@cpu@_engine_run_full): Replace local pbb_br_npc_ptr with
+ pbb_br_type.
+ (@cpu@_engine_run_fast): Ditto.
+
Fri Jul 16 14:47:53 1999 Dave Brolley <brolley@cygnus.com>
* cgen-utils.c (RORSI): New function.
diff --git a/sim/common/cgen-cpu.h b/sim/common/cgen-cpu.h
index c807182..914fb45 100644
--- a/sim/common/cgen-cpu.h
+++ b/sim/common/cgen-cpu.h
@@ -63,8 +63,8 @@ typedef struct {
IDESC *idesc;
#define CPU_IDESC(cpu) ((cpu)->cgen_cpu.idesc)
- /* Whether the read,write,semantic entries (computed goto labels) have been
- initialized or not. */
+ /* Whether the read,write,semantic entries (function pointers or computed
+ goto labels) have been initialized or not. */
int idesc_read_init_p;
#define CPU_IDESC_READ_INIT_P(cpu) ((cpu)->cgen_cpu.idesc_read_init_p)
int idesc_write_init_p;
diff --git a/sim/common/cgen-defs.h b/sim/common/cgen-defs.h
index d3c9a8a..1faa2ee 100644
--- a/sim/common/cgen-defs.h
+++ b/sim/common/cgen-defs.h
@@ -92,6 +92,15 @@ typedef SCACHE *SEM_PC;
#else
typedef IADDR SEM_PC;
#endif
+
+/* Kinds of branches. */
+typedef enum {
+ SEM_BRANCH_UNTAKEN,
+ /* Branch to an uncacheable address (e.g. j reg). */
+ SEM_BRANCH_UNCACHEABLE,
+ /* Branch to a cacheable (fixed) address. */
+ SEM_BRANCH_CACHEABLE
+} SEM_BRANCH_TYPE;
/* Virtual insn support. */
diff --git a/sim/common/cgen-engine.h b/sim/common/cgen-engine.h
index e7d27e0..fbcf3e5 100644
--- a/sim/common/cgen-engine.h
+++ b/sim/common/cgen-engine.h
@@ -180,11 +180,6 @@ do { \
& CGEN_ATTR_MASK (CGEN_INSN_SKIP_CTI)) \
!= 0)
-/* These are used so that we can compile two copies of the semantic code,
- one with full feature support and one without that runs fast(er). */
-#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
-#define SEMF_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn)
-
/* Return pointer to ARGBUF given ptr to SCACHE. */
#define SEM_ARGBUF(sem_arg) (& (sem_arg) -> argbuf)
@@ -217,22 +212,11 @@ do { \
#define PBB_UPDATE_INSN_COUNT(cpu,sc) \
(CPU_INSN_COUNT (cpu) += SEM_ARGBUF (sc) -> fields.chain.insn_count)
-/* Value for br_addr_ptr indicating branch wasn't taken. */
-#define SEM_BRANCH_UNTAKEN ((SEM_PC *) 0)
-
-/* Value for br_addr_ptr indicating branch was taken to uncacheable
- address (e.g. j reg). */
-#define SEM_BRANCH_UNCACHEABLE ((SEM_PC *) 1)
-
-/* Initialize next-pbb link for SEM_BRANCH_VIA_CACHE. */
-#define SEM_BRANCH_INIT_EXTRACT(abuf) \
-do { (abuf)->fields.cti.addr_cache = 0; } while (0)
-
/* Do not append a `;' to invocations of this.
- npc,npc_ptr are for communication between the cti insn and cti-chain. */
+ npc,br_type are for communication between the cti insn and cti-chain. */
#define SEM_BRANCH_INIT \
IADDR npc = 0; /* assign a value for -Wall */ \
- SEM_PC *npc_ptr = SEM_BRANCH_UNTAKEN;
+ SEM_BRANCH_TYPE br_type = SEM_BRANCH_UNTAKEN;
/* SEM_IN_SWITCH is defined at the top of the mainloop.c files
generated by genmloop.sh. It exists so generated semantic code needn't
@@ -241,30 +225,36 @@ do { (abuf)->fields.cti.addr_cache = 0; } while (0)
#define SEM_BRANCH_FINI(pcvar) \
do { \
pbb_br_npc = npc; \
- pbb_br_npc_ptr = npc_ptr; \
+ pbb_br_type = br_type; \
} while (0)
#else /* 1 semantic function per instruction */
#define SEM_BRANCH_FINI(pcvar) \
do { \
CPU_PBB_BR_NPC (current_cpu) = npc; \
- CPU_PBB_BR_NPC_PTR (current_cpu) = npc_ptr; \
+ CPU_PBB_BR_TYPE (current_cpu) = br_type; \
} while (0)
#endif
-/* Return address of cached branch address value. */
-#define SEM_BRANCH_ADDR_CACHE(sem_arg) \
- (& SEM_ARGBUF (sem_arg)->fields.cti.addr_cache)
-
-#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevarptr) \
+#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \
do { \
npc = (newval); \
- npc_ptr = (cachevarptr); \
+ br_type = SEM_BRANCH_CACHEABLE; \
} while (0)
#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
do { \
npc = (newval); \
- npc_ptr = SEM_BRANCH_UNCACHEABLE; \
+ br_type = SEM_BRANCH_UNCACHEABLE; \
+} while (0)
+
+#define SEM_SKIP_COMPILE(cpu, sc, skip) \
+do { \
+ SEM_ARGBUF (sc) -> skip_count = (skip); \
+} while (0)
+
+#define SEM_SKIP_INSN(cpu, sc, vpcvar) \
+do { \
+ (vpcvar) += SEM_ARGBUF (sc) -> skip_count; \
} while (0)
#else /* ! WITH_SCACHE_PBB */
@@ -273,8 +263,6 @@ do { \
#define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len))
-#define SEM_BRANCH_INIT_EXTRACT(abuf) do { } while (0)
-
/* ??? May wish to move taken_p out of here and make it explicit. */
#define SEM_BRANCH_INIT \
int taken_p = 0;
@@ -285,9 +273,7 @@ do { \
#define SEM_BRANCH_FINI(pcvar) \
do { TARGET_SEM_BRANCH_FINI (pcvar, taken_p); } while (0)
-#define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used
-
-#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevar) \
+#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \
do { \
(pcvar) = (newval); \
taken_p = 1; \
@@ -314,9 +300,7 @@ do { \
#define SEM_BRANCH_INIT \
int taken_p = 0;
-#define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used
-
-#define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar, cachevar) \
+#define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar) \
do { \
(pcvar) = (newval); \
taken_p = 1; \
@@ -344,10 +328,12 @@ do { \
/* Instruction information. */
-/* Compile time computable instruction data.
+/* Sanity check, at most one of these may be true. */
+#if WITH_PARALLEL_READ && WITH_PARALLEL_WRITE
+#error "Both WITH_PARALLEL_READ && WITH_PARALLEL_WRITE can't be true."
+#endif
- ??? May wish to move parallel execution support into its own struct.
- It's a fair bit of "clutter" for the "normal" case. */
+/* Compile time computable instruction data. */
struct insn_sem {
/* The instruction type (a number that identifies each insn over the
@@ -357,10 +343,8 @@ struct insn_sem {
/* Index in IDESC table. */
int index;
- /* Sanity check, at most one of these may be true. */
-#if WITH_PARALLEL_READ && WITH_PARALLEL_WRITE
-#error "Both WITH_PARALLEL_READ && WITH_PARALLEL_WRITE can't be true."
-#endif
+ /* Semantic format number. */
+ int sfmt;
#if WITH_PARALLEL_READ || WITH_PARALLEL_WRITE
/* Index in IDESC table of parallel handler. */
@@ -368,50 +352,38 @@ struct insn_sem {
#endif
#if WITH_PARALLEL_READ
-#ifndef __GNUC__
- /* Semantic format number of pre-read handler.
- Only used by chips that support parallel execution of several insns.
- It is always implemented as a `switch'. In the case of GNUC we use
- computed gotos. When not GNUC, this is the argument to `switch'. */
- int fmt;
-#endif
+ /* Index in IDESC table of read handler. */
+ int read_index;
#endif
#if WITH_PARALLEL_WRITE
- /* Index in IDESC table of writeback handler.
- Only used by chips that support parallel execution of several insns. */
+ /* Index in IDESC table of writeback handler. */
int write_index;
#endif
+};
- /* Routines to execute the insn.
- The full version has all features (profiling,tracing) compiled in.
- The fast version has none of that. */
-#if ! WITH_SEM_SWITCH_FULL
- SEMANTIC_FN *sem_full;
-#endif
-#if WITH_FAST && ! WITH_SEM_SWITCH_FAST
- SEMANTIC_FN *sem_fast;
-#endif
+/* Entry in semantic function table.
+ This information is copied to the insn descriptor table at run-time. */
+
+struct sem_fn_desc {
+ /* Index in IDESC table. */
+ int index;
+
+ /* Function to perform the semantics of the insn. */
+ SEMANTIC_FN *fn;
};
/* Run-time computed instruction descriptor. */
struct idesc {
- /* Parallel read-before-exec support. */
-#if WITH_PARALLEL_READ
- struct idesc *par_idesc;
+#if WITH_SEM_SWITCH_FAST
#ifdef __GNUC__
- void *read;
+ void *sem_fast_lab;
#else
- int fmt;
-#endif
+ /* nothing needed, switch's on `num' member */
#endif
-
- /* Parallel write-after-exec support. */
-#if WITH_PARALLEL_WRITE
- /* Pointer to parallel handler if serial insn.
- Pointer to writeback handler if parallel insn. */
- struct idesc *par_idesc;
+#else
+ SEMANTIC_FN *sem_fast;
#endif
#if WITH_SEM_SWITCH_FULL
@@ -424,20 +396,20 @@ struct idesc {
SEMANTIC_FN *sem_full;
#endif
-#if WITH_SEM_SWITCH_FAST
-#ifdef __GNUC__
- void *sem_fast_lab;
-#else
- /* nothing needed, switch's on `num' member */
-#endif
-#else
- SEMANTIC_FN *sem_fast;
+ /* Parallel support. */
+#if WITH_PARALLEL_READ || WITH_PARALLEL_WRITE
+ /* Pointer to parallel handler if serial insn.
+ Pointer to readahead/writeback handler if parallel insn. */
+ struct idesc *par_idesc;
#endif
/* Instruction number (index in IDESC table, profile table).
Also used to switch on in non-gcc semantic switches. */
int num;
+ /* Semantic format id. */
+ int sfmt;
+
/* instruction data (name, attributes, size, etc.) */
const CGEN_INSN *idata;
diff --git a/sim/common/cgen-scache.c b/sim/common/cgen-scache.c
index c5ea075..890afc8 100644
--- a/sim/common/cgen-scache.c
+++ b/sim/common/cgen-scache.c
@@ -313,6 +313,8 @@ scache_flush_cpu (SIM_CPU *cpu)
SCACHE *
scache_lookup (SIM_CPU *cpu, IADDR pc)
{
+ /* FIXME: hash computation is wrong, doesn't take into account
+ NUM_HASH_CHAIN_ENTRIES. A lot of the hash table will be unused! */
unsigned int slot = HASH_PC (pc) & (CPU_SCACHE_NUM_HASH_CHAINS (cpu) - 1);
int i, max_i = CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu);
SCACHE_MAP *scm;
@@ -343,6 +345,8 @@ scache_lookup (SIM_CPU *cpu, IADDR pc)
SCACHE *
scache_lookup_or_alloc (SIM_CPU *cpu, IADDR pc, int n, SCACHE **bufp)
{
+ /* FIXME: hash computation is wrong, doesn't take into account
+ NUM_HASH_CHAIN_ENTRIES. A lot of the hash table will be unused! */
unsigned int slot = HASH_PC (pc) & (CPU_SCACHE_NUM_HASH_CHAINS (cpu) - 1);
int i, max_i = CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu);
SCACHE_MAP *scm;
@@ -372,6 +376,7 @@ scache_lookup_or_alloc (SIM_CPU *cpu, IADDR pc, int n, SCACHE **bufp)
static int next_free = 0;
scm = & CPU_SCACHE_HASH_TABLE (cpu) [slot];
+ /* FIXME: This seems rather clumsy. */
for (i = 0; i < next_free; ++i, ++scm)
continue;
++next_free;
@@ -381,6 +386,8 @@ scache_lookup_or_alloc (SIM_CPU *cpu, IADDR pc, int n, SCACHE **bufp)
/* At this point SCM points to the hash table entry to use.
Now make sure there's room in the cache. */
+ /* FIXME: Kinda weird to use a next_free adjusted scm when cache is
+ flushed. */
{
int elm_size = IMP_PROPS_SCACHE_ELM_SIZE (MACH_IMP_PROPS (CPU_MACH (cpu)));
diff --git a/sim/common/cgen-scache.h b/sim/common/cgen-scache.h
index 7ca4e65..b7a20de 100644
--- a/sim/common/cgen-scache.h
+++ b/sim/common/cgen-scache.h
@@ -69,10 +69,10 @@ typedef struct cpu_scache {
SCACHE *next_free;
#define CPU_SCACHE_NEXT_FREE(cpu) ((cpu) -> cgen_cpu.scache.next_free)
- /* Address of cti-chain insn, only used by functional semantics,
- not switch form. */
- SCACHE **pbb_br_npc_ptr;
-#define CPU_PBB_BR_NPC_PTR(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_npc_ptr)
+ /* Kind of branch being taken.
+ Only used by functional semantics, not switch form. */
+ SEM_BRANCH_TYPE pbb_br_type;
+#define CPU_PBB_BR_TYPE(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_type)
/* Target's branch address. */
IADDR pbb_br_npc;
#define CPU_PBB_BR_NPC(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_npc)
diff --git a/sim/common/genmloop.sh b/sim/common/genmloop.sh
index 6720799..8a1b8d6 100644
--- a/sim/common/genmloop.sh
+++ b/sim/common/genmloop.sh
@@ -238,7 +238,7 @@ if [ x$pbb = xyes ] ; then
echo ""
echo "extern SEM_PC ${cpu}_pbb_begin (SIM_CPU *, int);"
echo "extern SEM_PC ${cpu}_pbb_chain (SIM_CPU *, SEM_ARG);"
- echo "extern SEM_PC ${cpu}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_PC *, PCADDR);"
+ echo "extern SEM_PC ${cpu}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_BRANCH_TYPE, PCADDR);"
echo "extern void ${cpu}_pbb_before (SIM_CPU *, SCACHE *);"
echo "extern void ${cpu}_pbb_after (SIM_CPU *, SCACHE *);"
fi
@@ -372,10 +372,10 @@ fi
# Note that this code may declare some locals.
${SHELL} $infile init
-if [ x$parallel != xno ] ; then
+if [ x$parallel = xread ] ; then
cat << EOF
-#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
+#if defined (__GNUC__)
{
if (! CPU_IDESC_READ_INIT_P (current_cpu))
{
@@ -392,17 +392,19 @@ fi
cat << EOF
-#if WITH_SEM_SWITCH_FULL && defined (__GNUC__)
- {
- if (! CPU_IDESC_SEM_INIT_P (current_cpu))
- {
+ if (! CPU_IDESC_SEM_INIT_P (current_cpu))
+ {
+#if WITH_SEM_SWITCH_FULL
+#if defined (__GNUC__)
/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
#define DEFINE_LABELS
#include "$switch"
- CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
- }
- }
#endif
+#else
+ @cpu@_sem_init_idesc_table (current_cpu);
+#endif
+ CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
+ }
do
{
@@ -446,9 +448,10 @@ fi # simple engine
##########################################################################
-# Scache engine: lookup insn in scache, fetch if missing, then execute it.
+# Non-parallel scache engine: lookup insn in scache, fetch if missing,
+# then execute it.
-if [ x$scache = xyes ] ; then
+if [ x$scache = xyes -a x$parallel = xno ] ; then
cat << EOF
@@ -463,7 +466,7 @@ static INLINE SCACHE *
fetch and decode the instruction. */
if (sc->argbuf.addr != vpc)
{
- if (FAST_P)
+ if (! FAST_P)
PROFILE_COUNT_SCACHE_MISS (current_cpu);
/* begin extract-scache */
@@ -474,7 +477,7 @@ ${SHELL} $infile extract-scache
cat << EOF
/* end extract-scache */
}
- else if (FAST_P)
+ else if (! FAST_P)
{
PROFILE_COUNT_SCACHE_HIT (current_cpu);
/* Make core access statistics come out right.
@@ -497,22 +500,182 @@ void
EOF
-if [ x$parallel != xno ] ; then
- cat << EOF
- PAREXEC pbufs[MAX_PARALLEL_INSNS];
- PAREXEC *par_exec;
+# Any initialization code before looping starts.
+# Note that this code may declare some locals.
+${SHELL} $infile init
+
+cat << EOF
+
+ if (! CPU_IDESC_SEM_INIT_P (current_cpu))
+ {
+#if ! WITH_SEM_SWITCH_FULL
+ @cpu@_sem_init_idesc_table (current_cpu);
+#endif
+ CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
+ }
+
+ vpc = GET_H_PC ();
+
+ do
+ {
+ SCACHE *sc;
+
+ sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
+
+/* begin full-exec-scache */
+EOF
+
+${SHELL} $infile full-exec-scache
+
+cat << EOF
+/* end full-exec-scache */
+
+ SET_H_PC (vpc);
+
+ ++ CPU_INSN_COUNT (current_cpu);
+ }
+ while (0 /*CPU_RUNNING_P (current_cpu)*/);
+}
+
+#undef FAST_P
+
+EOF
+
+####################################
+
+# Non-parallel scache engine: fast version.
+
+if [ x$fast = xyes ] ; then
+
+ cat << EOF
+
+#define FAST_P 1
+
+void
+@cpu@_engine_run_fast (SIM_CPU *current_cpu)
+{
+ SIM_DESC current_state = CPU_STATE (current_cpu);
+ SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
+ unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
+ SEM_PC vpc;
EOF
-fi
# Any initialization code before looping starts.
# Note that this code may declare some locals.
${SHELL} $infile init
-if [ x$parallel != xno ] ; then
- cat << EOF
+cat << EOF
-#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
+ if (! CPU_IDESC_SEM_INIT_P (current_cpu))
+ {
+#if WITH_SEM_SWITCH_FAST
+#if defined (__GNUC__)
+/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
+#define DEFINE_LABELS
+#include "$switch"
+#endif
+#else
+ @cpu@_semf_init_idesc_table (current_cpu);
+#endif
+ CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
+ }
+
+ vpc = GET_H_PC ();
+
+ do
+ {
+ SCACHE *sc;
+
+ sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
+
+/* begin fast-exec-scache */
+EOF
+
+${SHELL} $infile fast-exec-scache
+
+cat << EOF
+/* end fast-exec-scache */
+
+ SET_H_PC (vpc);
+
+ ++ CPU_INSN_COUNT (current_cpu);
+ }
+ while (0 /*CPU_RUNNING_P (current_cpu)*/);
+}
+
+#undef FAST_P
+
+EOF
+
+fi # -fast
+
+fi # -scache && ! parallel
+
+##########################################################################
+
+# Parallel scache engine: lookup insn in scache, fetch if missing,
+# then execute it.
+# For the parallel case we give the target more flexibility.
+
+if [ x$scache = xyes -a x$parallel != xno ] ; then
+
+ cat << EOF
+
+static INLINE SCACHE *
+@cpu@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
+ unsigned int hash_mask, int *last_insn_p, int FAST_P)
+{
+ /* First step: look up current insn in hash table. */
+ SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask);
+
+ /* If the entry isn't the one we want (cache miss),
+ fetch and decode the instruction. */
+ if (sc->argbuf.addr != vpc)
+ {
+ if (! FAST_P)
+ PROFILE_COUNT_SCACHE_MISS (current_cpu);
+
+#define SET_LAST_INSN_P(last_p) do { *last_insn_p = (last_p); } while (0)
+/* begin extract-scache */
+EOF
+
+${SHELL} $infile extract-scache
+
+cat << EOF
+/* end extract-scache */
+#undef SET_LAST_INSN_P
+ }
+ else if (! FAST_P)
+ {
+ PROFILE_COUNT_SCACHE_HIT (current_cpu);
+ /* Make core access statistics come out right.
+ The size is a guess, but it's currently not used either. */
+ PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map);
+ }
+
+ return sc;
+}
+
+#define FAST_P 0
+
+void
+@cpu@_engine_run_full (SIM_CPU *current_cpu)
+{
+ SIM_DESC current_state = CPU_STATE (current_cpu);
+ SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
+ unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
+ SEM_PC vpc;
+
+EOF
+
+# Any initialization code before looping starts.
+# Note that this code may declare some locals.
+${SHELL} $infile init
+
+if [ x$parallel = xread ] ; then
+cat << EOF
+#if defined (__GNUC__)
{
if (! CPU_IDESC_READ_INIT_P (current_cpu))
{
@@ -529,14 +692,18 @@ fi
cat << EOF
+ if (! CPU_IDESC_SEM_INIT_P (current_cpu))
+ {
+#if ! WITH_SEM_SWITCH_FULL
+ @cpu@_sem_init_idesc_table (current_cpu);
+#endif
+ CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
+ }
+
vpc = GET_H_PC ();
do
{
- SCACHE *sc;
-
- sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
-
/* begin full-exec-scache */
EOF
@@ -544,10 +711,6 @@ ${SHELL} $infile full-exec-scache
cat << EOF
/* end full-exec-scache */
-
- SET_H_PC (vpc);
-
- ++ CPU_INSN_COUNT (current_cpu);
}
while (0 /*CPU_RUNNING_P (current_cpu)*/);
}
@@ -558,7 +721,7 @@ EOF
####################################
-# Scache engine: fast version.
+# Parallel scache engine: fast version.
if [ x$fast = xyes ] ; then
@@ -573,25 +736,19 @@ void
SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu);
SEM_PC vpc;
-
-EOF
-
-if [ x$parallel != xno ] ; then
- cat << EOF
PAREXEC pbufs[MAX_PARALLEL_INSNS];
PAREXEC *par_exec;
EOF
-fi
# Any initialization code before looping starts.
# Note that this code may declare some locals.
${SHELL} $infile init
-if [ x$parallel != xno ] ; then
- cat << EOF
+if [ x$parallel = xread ] ; then
+cat << EOF
-#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__)
+#if defined (__GNUC__)
{
if (! CPU_IDESC_READ_INIT_P (current_cpu))
{
@@ -604,30 +761,28 @@ if [ x$parallel != xno ] ; then
#endif
EOF
-fi # parallel != no
+fi
cat << EOF
-#if WITH_SEM_SWITCH_FAST && defined (__GNUC__)
- {
- if (! CPU_IDESC_SEM_INIT_P (current_cpu))
- {
+ if (! CPU_IDESC_SEM_INIT_P (current_cpu))
+ {
+#if WITH_SEM_SWITCH_FAST
+#if defined (__GNUC__)
/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
#define DEFINE_LABELS
#include "$switch"
- CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
- }
- }
#endif
+#else
+ @cpu@_semf_init_idesc_table (current_cpu);
+#endif
+ CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
+ }
vpc = GET_H_PC ();
do
{
- SCACHE *sc;
-
- sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
-
/* begin fast-exec-scache */
EOF
@@ -635,10 +790,6 @@ ${SHELL} $infile fast-exec-scache
cat << EOF
/* end fast-exec-scache */
-
- SET_H_PC (vpc);
-
- ++ CPU_INSN_COUNT (current_cpu);
}
while (0 /*CPU_RUNNING_P (current_cpu)*/);
}
@@ -649,7 +800,7 @@ EOF
fi # -fast
-fi # -scache
+fi # -scache && parallel
##########################################################################
@@ -766,6 +917,7 @@ cat << EOF
sc->argbuf.addr = pc;
sc->argbuf.fields.chain.insn_count = _insn_count;
sc->argbuf.fields.chain.next = 0;
+ sc->argbuf.fields.chain.branch_target = 0;
++sc;
}
@@ -817,15 +969,17 @@ INLINE SEM_PC
}
/* Chain to the next block from a cti terminated previous block.
- NEW_VPC_PTR is one of SEM_BRANCH_UNTAKEN, SEM_BRANCH_UNCACHEABLE, or
- a pointer to a location containing the SEM_PC of the branch's address.
+ BR_TYPE indicates whether the branch was taken and whether we can cache
+ the vpc of the branch target.
NEW_PC is the target's branch address, and is only valid if
- NEW_VPC_PTR != SEM_BRANCH_UNTAKEN. */
+ BR_TYPE != SEM_BRANCH_UNTAKEN. */
INLINE SEM_PC
@cpu@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
- SEM_PC *new_vpc_ptr, PCADDR new_pc)
+ SEM_BRANCH_TYPE br_type, PCADDR new_pc)
{
+ SEM_PC *new_vpc_ptr;
+
PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
/* If not running forever, exit back to main loop. */
@@ -841,7 +995,7 @@ INLINE SEM_PC
/* Restart compiler if we branched to an uncacheable address
(e.g. "j reg"). */
- if (new_vpc_ptr == SEM_BRANCH_UNCACHEABLE)
+ if (br_type == SEM_BRANCH_UNCACHEABLE)
{
SET_H_PC (new_pc);
return CPU_SCACHE_PBB_BEGIN (current_cpu);
@@ -849,22 +1003,25 @@ INLINE SEM_PC
/* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our
next chain ptr. */
- if (new_vpc_ptr == SEM_BRANCH_UNTAKEN)
+ if (br_type == SEM_BRANCH_UNTAKEN)
{
ARGBUF *abuf = SEM_ARGBUF (sem_arg);
- SET_H_PC (abuf->addr);
+ new_pc = abuf->addr;
+ SET_H_PC (new_pc);
new_vpc_ptr = &abuf->fields.chain.next;
}
else
{
+ ARGBUF *abuf = SEM_ARGBUF (sem_arg);
SET_H_PC (new_pc);
+ new_vpc_ptr = &abuf->fields.chain.branch_target;
}
/* If chained to next block, go straight to it. */
if (*new_vpc_ptr)
return *new_vpc_ptr;
/* See if next block has already been compiled. */
- *new_vpc_ptr = scache_lookup (current_cpu, GET_H_PC ());
+ *new_vpc_ptr = scache_lookup (current_cpu, new_pc);
if (*new_vpc_ptr)
return *new_vpc_ptr;
/* Nope, so next insn is a virtual insn to invoke the compiler
@@ -955,8 +1112,8 @@ void
SEM_PC vpc;
#if WITH_SEM_SWITCH_FULL
/* For communication between cti's and cti-chain. */
+ SEM_BRANCH_TYPE pbb_br_type;
PCADDR pbb_br_npc;
- SEM_PC *pbb_br_npc_ptr;
#endif
EOF
@@ -983,11 +1140,15 @@ cat << EOF
a pbb). And in the "let's run until we're done" case we don't return
until the program exits. */
-#if WITH_SEM_SWITCH_FULL && defined (__GNUC__)
+#if WITH_SEM_SWITCH_FULL
+#if defined (__GNUC__)
/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
#define DEFINE_LABELS
#include "$switch"
#endif
+#else
+ @cpu@_sem_init_idesc_table (current_cpu);
+#endif
/* Initialize the "begin (compile) a pbb" virtual insn. */
vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
@@ -1041,8 +1202,8 @@ void
SEM_PC vpc;
#if WITH_SEM_SWITCH_FAST
/* For communication between cti's and cti-chain. */
+ SEM_BRANCH_TYPE pbb_br_type;
PCADDR pbb_br_npc;
- SEM_PC *pbb_br_npc_ptr;
#endif
EOF
@@ -1069,11 +1230,15 @@ cat << EOF
a pbb). And in the "let's run until we're done" case we don't return
until the program exits. */
-#if WITH_SEM_SWITCH_FAST && defined (__GNUC__)
+#if WITH_SEM_SWITCH_FAST
+#if defined (__GNUC__)
/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
#define DEFINE_LABELS
#include "$switch"
#endif
+#else
+ @cpu@_semf_init_idesc_table (current_cpu);
+#endif
/* Initialize the "begin (compile) a pbb" virtual insn. */
vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);