diff options
author | Jason Molenda <jmolenda@apple.com> | 1999-08-09 21:36:23 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 1999-08-09 21:36:23 +0000 |
commit | 96baa820df8126165bd3c4a33c561556b21203af (patch) | |
tree | 60cf1938a2c0aaae5d3aab73b553f031138ec99c /sim/common | |
parent | 10e80b41455f1a386485631b7c170cafe341dcd6 (diff) | |
download | gdb-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/ChangeLog | 32 | ||||
-rw-r--r-- | sim/common/cgen-cpu.h | 4 | ||||
-rw-r--r-- | sim/common/cgen-defs.h | 9 | ||||
-rw-r--r-- | sim/common/cgen-engine.h | 132 | ||||
-rw-r--r-- | sim/common/cgen-scache.c | 7 | ||||
-rw-r--r-- | sim/common/cgen-scache.h | 8 | ||||
-rw-r--r-- | sim/common/genmloop.sh | 303 |
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); |