* Make-common.in (CGEN_INCLUDE_DEPS): Add cgen-defs.h, cgen-engine.h.
(CGEN_MAIN_SCM): Add rtx-funcs.scm. (cgen-arch): Pass $(mach) to cgen.sh. * cgen-engine.h (SEM_BRANCH_FINI): New arg pcvar, all uses updated. (SEM_BRANCH_INIT_EXTRACT): New macro. (SEM_BRANCH_INIT): Add taken_p. (TARGET_SEM_BRANCH_FINI): Provide default definition. (SEM_BRANCH_FINI): Use it. (SEM_INSN): Update. * cgen-run.c (sim_resume): Handle tracing of last insn. * cgen-scache.h (WITH_SCACHE): Define as 0 if not defined. * cgen-trace.c (current_abuf): New static global. (trace_insn_init): Initialize it. (trace_insn_fini): Use it. (trace_insn): Set it. * cgen.sh (arch case): Pass -m ${mach} to cgen. * genmloop.sh (@cpu@_emit_before): Only define if WITH_SCACHE_PBB. (@cpu@_emit_after): Ditto. (simple @cpu@_engine_run_full): New local `pc'. Initialize semantic labels if WITH_SEM_SWITCH_FULL. * sim-model.c: Include bfd.h. (sim_model_init): New function. (sim_model_install): Record init fn. * sim-model.h (MACH): New member bfd_name. * sim-module.c (modules): Initialize model before scache.
This commit is contained in:
parent
5730d39d2c
commit
f5cd4d758c
8 changed files with 810 additions and 224 deletions
|
@ -1,3 +1,31 @@
|
|||
1999-01-05 Doug Evans <devans@casey.cygnus.com>
|
||||
|
||||
* Make-common.in (CGEN_INCLUDE_DEPS): Add cgen-defs.h, cgen-engine.h.
|
||||
(CGEN_MAIN_SCM): Add rtx-funcs.scm.
|
||||
(cgen-arch): Pass $(mach) to cgen.sh.
|
||||
* cgen-engine.h (SEM_BRANCH_FINI): New arg pcvar, all uses updated.
|
||||
(SEM_BRANCH_INIT_EXTRACT): New macro.
|
||||
(SEM_BRANCH_INIT): Add taken_p.
|
||||
(TARGET_SEM_BRANCH_FINI): Provide default definition.
|
||||
(SEM_BRANCH_FINI): Use it.
|
||||
(SEM_INSN): Update.
|
||||
* cgen-run.c (sim_resume): Handle tracing of last insn.
|
||||
* cgen-scache.h (WITH_SCACHE): Define as 0 if not defined.
|
||||
* cgen-trace.c (current_abuf): New static global.
|
||||
(trace_insn_init): Initialize it.
|
||||
(trace_insn_fini): Use it.
|
||||
(trace_insn): Set it.
|
||||
* cgen.sh (arch case): Pass -m ${mach} to cgen.
|
||||
* genmloop.sh (@cpu@_emit_before): Only define if WITH_SCACHE_PBB.
|
||||
(@cpu@_emit_after): Ditto.
|
||||
(simple @cpu@_engine_run_full): New local `pc'. Initialize semantic
|
||||
labels if WITH_SEM_SWITCH_FULL.
|
||||
* sim-model.c: Include bfd.h.
|
||||
(sim_model_init): New function.
|
||||
(sim_model_install): Record init fn.
|
||||
* sim-model.h (MACH): New member bfd_name.
|
||||
* sim-module.c (modules): Initialize model before scache.
|
||||
|
||||
1998-12-24 Frank Ch. Eigler <fche@cygnus.com>
|
||||
|
||||
* dv-sockser.c (DEFAULT_TIMEOUT): Increase to 1 ms.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Simulator header for the cgen engine.
|
||||
/* Engine header for Cpu tools GENerated simulators.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
|
@ -18,10 +18,7 @@ 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. */
|
||||
|
||||
/* This file must be included after eng.h and ${cpu}.h have been included. */
|
||||
|
||||
#ifndef CGEN_ENGINE_H
|
||||
#define CGEN_ENGINE_H
|
||||
/* This file must be included after eng.h and before ${cpu}.h. */
|
||||
|
||||
/* Semantic functions come in six versions on two axes:
|
||||
fast/full-featured, and using one of the simple/scache/compilation engines.
|
||||
|
@ -32,6 +29,43 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
/* FIXME: --enable-sim-fast not implemented yet. */
|
||||
/* FIXME: undecided how to handle WITH_SCACHE_PBB. */
|
||||
|
||||
#ifndef CGEN_ENGINE_H
|
||||
#define CGEN_ENGINE_H
|
||||
|
||||
/* Instruction field support macros. */
|
||||
|
||||
#define EXTRACT_MSB0_INT(val, total, start, length) \
|
||||
(((INT) (val) << ((sizeof (INT) * 8) - (total) + (start))) \
|
||||
>> ((sizeof (INT) * 8) - (length)))
|
||||
#define EXTRACT_MSB0_UINT(val, total, start, length) \
|
||||
(((UINT) (val) << ((sizeof (UINT) * 8) - (total) + (start))) \
|
||||
>> ((sizeof (UINT) * 8) - (length)))
|
||||
|
||||
#define EXTRACT_LSB0_INT(val, total, start, length) \
|
||||
(((INT) (val) << ((sizeof (INT) * 8) - (start) - (length))) \
|
||||
>> ((sizeof (INT) * 8) - (length)))
|
||||
#define EXTRACT_LSB0_UINT(val, total, start, length) \
|
||||
(((UINT) (val) << ((sizeof (UINT) * 8) - (start) - (length))) \
|
||||
>> ((sizeof (UINT) * 8) - (length)))
|
||||
|
||||
#if CGEN_INSN_LSB0_P
|
||||
|
||||
#define EXTRACT_INT(val, total, start, length) \
|
||||
EXTRACT_LSB0_INT ((val), (total), (start), (length))
|
||||
#define EXTRACT_UINT(val, total, start, length) \
|
||||
EXTRACT_LSB0_UINT ((val), (total), (start), (length))
|
||||
|
||||
#else
|
||||
|
||||
#define EXTRACT_INT(val, total, start, length) \
|
||||
EXTRACT_MSB0_INT ((val), (total), (start), (length))
|
||||
#define EXTRACT_UINT(val, total, start, length) \
|
||||
EXTRACT_MSB0_UINT ((val), (total), (start), (length))
|
||||
|
||||
#endif
|
||||
|
||||
/* union sem */
|
||||
|
||||
/* Types of the machine generated extract and semantic fns. */
|
||||
typedef void (EXTRACT_FN) (SIM_CPU *, PCADDR, insn_t, ARGBUF *);
|
||||
#if HAVE_PARALLEL_INSNS
|
||||
|
@ -91,7 +125,7 @@ do { \
|
|||
else \
|
||||
SEM_SET_FULL_CODE ((abuf), (idesc)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define IDESC_CTI_P(idesc) \
|
||||
((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->opcode)) \
|
||||
& (CGEN_ATTR_MASK (CGEN_INSN_COND_CTI) \
|
||||
|
@ -104,8 +138,6 @@ do { \
|
|||
|
||||
/* 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). */
|
||||
/* FIXME: Eventually delete extraction if not using scache. */
|
||||
#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_ex_,fn)
|
||||
#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
|
||||
#define SEMF_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn)
|
||||
|
||||
|
@ -116,10 +148,15 @@ do { \
|
|||
/* semantics.c support */
|
||||
#define SEM_ARGBUF(sem_arg) (& (sem_arg) -> argbuf)
|
||||
#define SEM_INSN(sem_arg) shouldnt_be_used
|
||||
#define SEM_NEXT_VPC(sc, len) ((sc) + 1)
|
||||
|
||||
#if WITH_SCACHE_PBB
|
||||
|
||||
/* Return the scache pointer of the current insn. */
|
||||
#define SEM_SEM_ARG(vpc, sc) (vpc)
|
||||
/* Return the virtual pc of the next insn to execute
|
||||
(assuming this isn't a cti). */
|
||||
#define SEM_NEXT_VPC(sem_arg, pc, len) ((sem_arg) + 1)
|
||||
|
||||
/* Update the instruction counter. */
|
||||
#define PBB_UPDATE_INSN_COUNT(cpu,sc) \
|
||||
(CPU_INSN_COUNT (cpu) += SEM_ARGBUF (sc) -> fields.chain.insn_count)
|
||||
|
@ -130,8 +167,7 @@ do { \
|
|||
address (e.g. j reg). */
|
||||
#define SEM_BRANCH_UNCACHEABLE ((SEM_PC *) 1)
|
||||
|
||||
/* ??? Only necessary if SEM_BRANCH_VIA_CACHE will be used,
|
||||
but for simplicity it's done this way. */
|
||||
/* Initialize next-pbb link for SEM_BRANCH_VIA_CACHE. */
|
||||
#define SEM_BRANCH_INIT_EXTRACT(abuf) \
|
||||
do { (abuf)->fields.cti.addr_cache = 0; } while (0)
|
||||
|
||||
|
@ -144,21 +180,17 @@ do { (abuf)->fields.cti.addr_cache = 0; } while (0)
|
|||
generated by genmloop.sh. It exists so generated semantic code needn't
|
||||
care whether it's being put in a switch or in a function. */
|
||||
#ifdef SEM_IN_SWITCH
|
||||
/* Do not append a `;' to invocations of this.
|
||||
??? Unnecessary here, but for consistency with ..._INIT. */
|
||||
#define SEM_BRANCH_FINI \
|
||||
{ \
|
||||
#define SEM_BRANCH_FINI(pcvar) \
|
||||
do { \
|
||||
pbb_br_npc = npc; \
|
||||
pbb_br_npc_ptr = npc_ptr; \
|
||||
}
|
||||
} while (0)
|
||||
#else /* 1 semantic function per instruction */
|
||||
/* Do not append a `;' to invocations of this.
|
||||
??? Unnecessary here, but for consistency with ..._INIT. */
|
||||
#define SEM_BRANCH_FINI \
|
||||
{ \
|
||||
#define SEM_BRANCH_FINI(pcvar) \
|
||||
do { \
|
||||
CPU_PBB_BR_NPC (current_cpu) = npc; \
|
||||
CPU_PBB_BR_NPC_PTR (current_cpu) = npc_ptr; \
|
||||
}
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Return address of cached branch address value. */
|
||||
|
@ -177,50 +209,83 @@ do { \
|
|||
|
||||
#else /* ! WITH_SCACHE_PBB */
|
||||
|
||||
#define SEM_BRANCH_INIT
|
||||
#define SEM_BRANCH_FINI
|
||||
#define SEM_SEM_ARG(vpc, sc) (sc)
|
||||
#define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len))
|
||||
|
||||
#define SEM_BRANCH_INIT_EXTRACT(abuf) do { } while (0)
|
||||
|
||||
#define SEM_BRANCH_INIT \
|
||||
int taken_p = 0;
|
||||
#ifndef TARGET_SEM_BRANCH_FINI(pcvar, taken_p)
|
||||
#define TARGET_SEM_BRANCH_FINI(pcvar, taken_p)
|
||||
#endif
|
||||
#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) \
|
||||
do { \
|
||||
(pcvar) = (newval); \
|
||||
taken_p = 1; \
|
||||
} while (0)
|
||||
#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
|
||||
do { \
|
||||
(pcvar) = (newval); \
|
||||
taken_p = 1; \
|
||||
} while (0)
|
||||
|
||||
#endif /* ! WITH_SCACHE_PBB */
|
||||
|
||||
/* Return address a branch insn will branch to.
|
||||
This is only used during tracing. */
|
||||
#define SEM_NEW_PC_ADDR(new_pc) (new_pc)
|
||||
|
||||
#else /* ! WITH_SCACHE */
|
||||
|
||||
#define CIA_ADDR(cia) (cia)
|
||||
|
||||
/* semantics.c support */
|
||||
#define SEM_ARGBUF(sem_arg) (sem_arg)
|
||||
#define SEM_INSN(sem_arg) (SEM_ARGBUF (sem_arg) -> insn)
|
||||
/* FIXME:wip */
|
||||
#define SEM_NEXT_VPC(abuf, len) ((abuf) -> addr + (abuf) -> length)
|
||||
#define SEM_INSN(sem_arg) (SEM_ARGBUF (sem_arg) -> base_insn)
|
||||
|
||||
#define SEM_BRANCH_INIT
|
||||
#define SEM_BRANCH_FINI
|
||||
#define SEM_SEM_ARG(vpc, sc) (sc)
|
||||
#define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len))
|
||||
|
||||
#define SEM_BRANCH_INIT \
|
||||
int taken_p = 0;
|
||||
#ifndef TARGET_SEM_BRANCH_FINI
|
||||
#define TARGET_SEM_BRANCH_FINI(pcvar, taken_p)
|
||||
#endif
|
||||
#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, abuf, newval, pcvar, cachevar) \
|
||||
do { \
|
||||
(pcvar) = (newval); \
|
||||
taken_p = 1; \
|
||||
} while (0)
|
||||
#define SEM_BRANCH_VIA_ADDR(cpu, abuf, newval, pcvar) \
|
||||
do { \
|
||||
(pcvar) = (newval); \
|
||||
taken_p = 1; \
|
||||
} while (0)
|
||||
|
||||
#define SEM_NEW_PC_ADDR(new_pc) (new_pc)
|
||||
|
||||
#endif /* ! WITH_SCACHE */
|
||||
|
||||
/* Tracing/profiling. */
|
||||
|
||||
/* Return non-zero if a before/after handler is needed.
|
||||
When tracing/profiling a selected range there's no need to slow
|
||||
down simulation of the other insns (except to get more accurate data!).
|
||||
|
||||
??? May wish to profile all insns if doing insn tracing, or to
|
||||
get more accurate cycle data.
|
||||
|
||||
First test ANY_P so we avoid a potentially expensive HIT_P call
|
||||
[if there are lots of address ranges]. */
|
||||
|
||||
#define PC_IN_TRACE_RANGE_P(cpu, pc) \
|
||||
(TRACE_ANY_P (cpu) \
|
||||
&& ADDR_RANGE_HIT_P (TRACE_RANGE (CPU_TRACE_DATA (cpu)), (pc)))
|
||||
#define PC_IN_PROFILE_RANGE_P(cpu, pc) \
|
||||
(PROFILE_ANY_P (cpu) \
|
||||
&& ADDR_RANGE_HIT_P (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), (pc)))
|
||||
|
||||
#endif /* CGEN_ENGINE_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Simulator cache definitions for CGEN simulators (and maybe others).
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
/* Simulator header for cgen scache support.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Solutions.
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
||||
|
@ -18,62 +18,94 @@ 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. */
|
||||
|
||||
#ifndef SCACHE_H
|
||||
#define SCACHE_H
|
||||
#ifndef CGEN_SCACHE_H
|
||||
#define CGEN_SCACHE_H
|
||||
|
||||
/* A cached insn. */
|
||||
typedef struct scache {
|
||||
IADDR next;
|
||||
union {
|
||||
#ifdef USE_SEM_SWITCH
|
||||
#ifdef __GNUC__
|
||||
void *sem_case;
|
||||
#else
|
||||
int sem_case;
|
||||
#ifndef WITH_SCACHE
|
||||
#define WITH_SCACHE 0
|
||||
#endif
|
||||
#endif
|
||||
SEMANTIC_CACHE_FN *sem_fn;
|
||||
} semantic;
|
||||
ARGBUF argbuf;
|
||||
} SCACHE;
|
||||
|
||||
/* Scache data for each cpu. */
|
||||
/* When caching bb's, instructions are extracted into "chains".
|
||||
SCACHE_MAP is a hash table into these chains. */
|
||||
|
||||
typedef struct {
|
||||
PCADDR pc;
|
||||
SCACHE *sc;
|
||||
} SCACHE_MAP;
|
||||
|
||||
typedef struct cpu_scache {
|
||||
/* Simulator cache size. */
|
||||
int size;
|
||||
#define CPU_SCACHE_SIZE(cpu) ((cpu)->cgen_cpu.scache.size)
|
||||
/* Cache. */
|
||||
/* Simulator cache size. Must be a power of 2.
|
||||
This is the number of elements in the `cache' member. */
|
||||
unsigned int size;
|
||||
#define CPU_SCACHE_SIZE(cpu) ((cpu) -> cgen_cpu.scache.size)
|
||||
/* The cache. */
|
||||
SCACHE *cache;
|
||||
#define CPU_SCACHE_CACHE(cpu) ((cpu)->cgen_cpu.scache.cache)
|
||||
#if 0 /* FIXME: wip */
|
||||
/* Free list. */
|
||||
SCACHE *free;
|
||||
#define CPU_SCACHE_FREE(cpu) ((cpu)->cgen_cpu.scache.free)
|
||||
/* Hash table. */
|
||||
SCACHE **hash_table;
|
||||
#define CPU_SCACHE_HASH_TABLE(cpu) ((cpu)->cgen_cpu.scache.hash_table)
|
||||
#endif
|
||||
#define CPU_SCACHE_CACHE(cpu) ((cpu) -> cgen_cpu.scache.cache)
|
||||
|
||||
#if WITH_SCACHE_PBB
|
||||
/* Number of hash chains. Must be a power of 2. */
|
||||
unsigned int num_hash_chains;
|
||||
#define CPU_SCACHE_NUM_HASH_CHAINS(cpu) ((cpu) -> cgen_cpu.scache.num_hash_chains)
|
||||
/* Number of entries in each hash chain.
|
||||
The hash table is a statically allocated NxM array where
|
||||
N = num_hash_chains
|
||||
M = num_hash_chain_entries. */
|
||||
unsigned int num_hash_chain_entries;
|
||||
#define CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES(cpu) ((cpu) -> cgen_cpu.scache.num_hash_chain_entries)
|
||||
/* Maximum number of instructions in a chain.
|
||||
??? This just let's us set a static size of chain_lengths table.
|
||||
In a simulation that handles more than just the cpu, this might also be
|
||||
used to keep too many instructions from being executed before checking
|
||||
for events (or some such). */
|
||||
unsigned int max_chain_length;
|
||||
#define CPU_SCACHE_MAX_CHAIN_LENGTH(cpu) ((cpu) -> cgen_cpu.scache.max_chain_length)
|
||||
/* Special scache entry for (re)starting bb extraction. */
|
||||
SCACHE *pbb_begin;
|
||||
#define CPU_SCACHE_PBB_BEGIN(cpu) ((cpu) -> cgen_cpu.scache.pbb_begin)
|
||||
/* Hash table into cached chains. */
|
||||
SCACHE_MAP *hash_table;
|
||||
#define CPU_SCACHE_HASH_TABLE(cpu) ((cpu) -> cgen_cpu.scache.hash_table)
|
||||
/* Next free entry in cache. */
|
||||
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)
|
||||
/* Target's branch address. */
|
||||
PCADDR pbb_br_npc;
|
||||
#define CPU_PBB_BR_NPC(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_npc)
|
||||
#endif /* WITH_SCACHE_PBB */
|
||||
|
||||
#if WITH_PROFILE_SCACHE_P
|
||||
/* Cache hits, misses. */
|
||||
unsigned long hits, misses;
|
||||
#define CPU_SCACHE_HITS(cpu) ((cpu)->cgen_cpu.scache.hits)
|
||||
#define CPU_SCACHE_MISSES(cpu) ((cpu)->cgen_cpu.scache.misses)
|
||||
#define CPU_SCACHE_HITS(cpu) ((cpu) -> cgen_cpu.scache.hits)
|
||||
#define CPU_SCACHE_MISSES(cpu) ((cpu) -> cgen_cpu.scache.misses)
|
||||
|
||||
#if WITH_SCACHE_PBB
|
||||
/* Chain length counts.
|
||||
Each element is a count of the number of chains created with that
|
||||
length. */
|
||||
unsigned long *chain_lengths;
|
||||
#define CPU_SCACHE_CHAIN_LENGTHS(cpu) ((cpu) -> cgen_cpu.scache.chain_lengths)
|
||||
/* Number of times cache was flushed due to its being full. */
|
||||
unsigned long full_flushes;
|
||||
#define CPU_SCACHE_FULL_FLUSHES(cpu) ((cpu) -> cgen_cpu.scache.full_flushes)
|
||||
#endif
|
||||
#endif
|
||||
} CPU_SCACHE;
|
||||
|
||||
/* Default number of cached blocks. */
|
||||
#ifdef CONFIG_SIM_CACHE_SIZE
|
||||
#define SCACHE_DEFAULT_CACHE_SIZE CONFIG_SIM_CACHE_SIZE
|
||||
#else
|
||||
#define SCACHE_DEFAULT_CACHE_SIZE 1024
|
||||
#endif
|
||||
|
||||
/* Hash a PC value. */
|
||||
/* FIXME: cpu specific */
|
||||
#define SCACHE_HASH_PC(state, pc) \
|
||||
(((pc) >> 1) & (STATE_SCACHE_SIZE (sd) - 1))
|
||||
/* Hash a PC value.
|
||||
This is split into two parts to help with moving as much of the
|
||||
computation out of the main loop. */
|
||||
#define CPU_SCACHE_HASH_MASK(cpu) (CPU_SCACHE_SIZE (cpu) - 1)
|
||||
#define SCACHE_HASH_PC(pc, mask) \
|
||||
((CGEN_MIN_INSN_SIZE == 2 ? ((pc) >> 1) \
|
||||
: CGEN_MIN_INSN_SIZE == 4 ? ((pc) >> 2) \
|
||||
: (pc)) \
|
||||
& (mask))
|
||||
|
||||
/* Non-zero if cache is in use. */
|
||||
#define USING_SCACHE_P(sd) (STATE_SCACHE_SIZE (sd) > 0)
|
||||
|
@ -81,15 +113,22 @@ typedef struct cpu_scache {
|
|||
/* Install the simulator cache into the simulator. */
|
||||
MODULE_INSTALL_FN scache_install;
|
||||
|
||||
/* Flush all cpu's caches. */
|
||||
void scache_flush (SIM_DESC);
|
||||
/* Lookup a PC value in the scache [compilation only]. */
|
||||
extern SCACHE * scache_lookup (SIM_CPU *, PCADDR);
|
||||
/* Return a pointer to at least N buffers. */
|
||||
extern SCACHE *scache_lookup_or_alloc (SIM_CPU *, PCADDR, int, SCACHE **);
|
||||
/* Flush all cpu's scaches. */
|
||||
extern void scache_flush (SIM_DESC);
|
||||
/* Flush a cpu's scache. */
|
||||
extern void scache_flush_cpu (SIM_CPU *);
|
||||
|
||||
/* Profiling support. */
|
||||
/* Scache profiling support. */
|
||||
|
||||
/* Print summary scache usage information. */
|
||||
void scache_print_profile (SIM_DESC sd, int verbose);
|
||||
extern void scache_print_profile (SIM_CPU *cpu, int verbose);
|
||||
|
||||
#if WITH_PROFILE_SCACHE_P
|
||||
|
||||
#define PROFILE_COUNT_SCACHE_HIT(cpu) \
|
||||
do { \
|
||||
if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \
|
||||
|
@ -100,9 +139,24 @@ do { \
|
|||
if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \
|
||||
++ CPU_SCACHE_MISSES (cpu); \
|
||||
} while (0)
|
||||
#define PROFILE_COUNT_SCACHE_CHAIN_LENGTH(cpu,length) \
|
||||
do { \
|
||||
if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \
|
||||
++ CPU_SCACHE_CHAIN_LENGTHS (cpu) [length]; \
|
||||
} while (0)
|
||||
#define PROFILE_COUNT_SCACHE_FULL_FLUSH(cpu) \
|
||||
do { \
|
||||
if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \
|
||||
++ CPU_SCACHE_FULL_FLUSHES (cpu); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define PROFILE_COUNT_SCACHE_HIT(cpu)
|
||||
#define PROFILE_COUNT_SCACHE_MISS(cpu)
|
||||
#define PROFILE_COUNT_SCACHE_CHAIN_LENGTH(cpu,length)
|
||||
#define PROFILE_COUNT_SCACHE_FULL_FLUSH(cpu)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SCACHE_H */
|
||||
#endif /* CGEN_SCACHE_H */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Tracing support for CGEN-based simulators.
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
@ -46,118 +46,136 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define SIZE_TOTAL_CYCLE_COUNT 9
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_TRACE_BUF
|
||||
#define SIZE_TRACE_BUF 256
|
||||
#endif
|
||||
|
||||
/* Text is queued in TRACE_BUF because we want to output the insn's cycle
|
||||
count first but that isn't known until after the insn has executed. */
|
||||
static char trace_buf[1024];
|
||||
count first but that isn't known until after the insn has executed.
|
||||
This also handles the queueing of trace results, TRACE_RESULT may be
|
||||
called multiple times for one insn. */
|
||||
static char trace_buf[SIZE_TRACE_BUF];
|
||||
/* If NULL, output to stdout directly. */
|
||||
static char *bufptr;
|
||||
|
||||
/* For computing an instruction's cycle count.
|
||||
FIXME: Need to move into cpu struct for smp case. */
|
||||
static unsigned long last_cycle_count;
|
||||
/* Non-zero if this is the first insn in a set of parallel insns. */
|
||||
static int first_insn_p;
|
||||
|
||||
/* For communication between trace_insn and trace_result. */
|
||||
static int printed_result_p;
|
||||
|
||||
/* Insn and its extracted fields.
|
||||
Set by trace_insn, used by trace_insn_fini.
|
||||
??? Move to SIM_CPU to support heterogeneous multi-cpu case. */
|
||||
static const struct cgen_insn *current_insn;
|
||||
static CGEN_FIELDS insn_fields;
|
||||
static const struct argbuf *current_abuf;
|
||||
|
||||
void
|
||||
trace_insn_init (SIM_CPU *cpu, int first_p)
|
||||
{
|
||||
bufptr = trace_buf;
|
||||
*bufptr = 0;
|
||||
first_insn_p = first_p;
|
||||
|
||||
/* Set to NULL so trace_insn_fini can know if trace_insn was called. */
|
||||
current_insn = NULL;
|
||||
current_abuf = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
trace_insn_fini (SIM_CPU *cpu, int last_p)
|
||||
trace_insn_fini (SIM_CPU *cpu, const struct argbuf *abuf, int last_p)
|
||||
{
|
||||
if (CPU_PROFILE_FLAGS (cpu) [PROFILE_MODEL_IDX])
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
|
||||
/* Was insn traced? It might not be if trace ranges are in effect. */
|
||||
if (current_insn == NULL)
|
||||
return;
|
||||
|
||||
/* The first thing printed is current and total cycle counts. */
|
||||
|
||||
if (PROFILE_MODEL_P (cpu)
|
||||
&& ARGBUF_PROFILE_P (current_abuf))
|
||||
{
|
||||
unsigned long total = PROFILE_TOTAL_CYCLE_COUNT (CPU_PROFILE_DATA (cpu));
|
||||
trace_printf (CPU_STATE (cpu), cpu, "%-*ld %-*ld ",
|
||||
SIZE_CYCLE_COUNT, total - last_cycle_count,
|
||||
SIZE_TOTAL_CYCLE_COUNT, total);
|
||||
last_cycle_count = total;
|
||||
unsigned long total = PROFILE_MODEL_TOTAL_CYCLES (CPU_PROFILE_DATA (cpu));
|
||||
unsigned long this_insn = PROFILE_MODEL_CUR_INSN_CYCLES (CPU_PROFILE_DATA (cpu));
|
||||
|
||||
if (last_p)
|
||||
{
|
||||
trace_printf (sd, cpu, "%-*ld %-*ld ",
|
||||
SIZE_CYCLE_COUNT, this_insn,
|
||||
SIZE_TOTAL_CYCLE_COUNT, total);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace_printf (sd, cpu, "%-*ld %-*s ",
|
||||
SIZE_CYCLE_COUNT, this_insn,
|
||||
SIZE_TOTAL_CYCLE_COUNT, "---");
|
||||
}
|
||||
}
|
||||
|
||||
trace_printf (CPU_STATE (cpu), cpu, "%s\n", trace_buf);
|
||||
}
|
||||
/* Print the disassembled insn. */
|
||||
|
||||
/* For communication between trace_insn and trace_result. */
|
||||
static int printed_result_p;
|
||||
trace_printf (sd, cpu, "%s", TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
|
||||
|
||||
#if 0
|
||||
/* Print insn results. */
|
||||
{
|
||||
const CGEN_OPERAND_INSTANCE *opinst = CGEN_INSN_OPERANDS (current_insn);
|
||||
|
||||
if (opinst)
|
||||
{
|
||||
int i;
|
||||
int indices[MAX_OPERAND_INSTANCES];
|
||||
|
||||
/* Fetch the operands used by the insn. */
|
||||
/* FIXME: Add fn ptr to CGEN_OPCODE_DESC. */
|
||||
CGEN_SYM (get_insn_operands) (STATE_OPCODE_TABLE (sd), current_insn,
|
||||
0, CGEN_FIELDS_BITSIZE (&insn_fields),
|
||||
indices);
|
||||
|
||||
for (i = 0;
|
||||
CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
|
||||
++i, ++opinst)
|
||||
{
|
||||
if (CGEN_OPERAND_INSTANCE_TYPE (opinst) == CGEN_OPERAND_INSTANCE_OUTPUT)
|
||||
trace_result (cpu, current_insn, opinst, indices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print anything else requested. */
|
||||
|
||||
if (*trace_buf)
|
||||
trace_printf (sd, cpu, " %s\n", trace_buf);
|
||||
else
|
||||
trace_printf (sd, cpu, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
|
||||
const struct argbuf *abuf, PCADDR pc)
|
||||
{
|
||||
const char *filename;
|
||||
const char *functionname;
|
||||
unsigned int linenumber;
|
||||
char *p, buf[256], disasm_buf[50];
|
||||
char disasm_buf[50];
|
||||
|
||||
if (! TRACE_P (cpu, TRACE_LINENUM_IDX))
|
||||
printed_result_p = 0;
|
||||
current_insn = opcode;
|
||||
current_abuf = abuf;
|
||||
|
||||
if (CGEN_INSN_VIRTUAL_P (opcode))
|
||||
{
|
||||
cgen_trace_printf (cpu, "0x%.*x %-*s ",
|
||||
SIZE_PC, (unsigned) pc,
|
||||
SIZE_INSTRUCTION,
|
||||
CGEN_INSN_MNEMONIC (opcode));
|
||||
printed_result_p = 0;
|
||||
trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, (address_word) 0, 0,
|
||||
NULL, 0, CGEN_INSN_NAME (opcode));
|
||||
return;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
if (STATE_TEXT_SECTION (CPU_STATE (cpu))
|
||||
&& pc >= STATE_TEXT_START (CPU_STATE (cpu))
|
||||
&& pc < STATE_TEXT_END (CPU_STATE (cpu)))
|
||||
{
|
||||
filename = (const char *) 0;
|
||||
functionname = (const char *) 0;
|
||||
linenumber = 0;
|
||||
if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
|
||||
STATE_TEXT_SECTION (CPU_STATE (cpu)),
|
||||
(struct symbol_cache_entry **) 0,
|
||||
pc - STATE_TEXT_START (CPU_STATE (cpu)),
|
||||
&filename, &functionname, &linenumber))
|
||||
{
|
||||
p = buf;
|
||||
if (linenumber)
|
||||
{
|
||||
sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber);
|
||||
p += strlen (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
|
||||
p += SIZE_LINE_NUMBER+2;
|
||||
}
|
||||
|
||||
if (functionname)
|
||||
{
|
||||
sprintf (p, "%s ", functionname);
|
||||
p += strlen (p);
|
||||
}
|
||||
else if (filename)
|
||||
{
|
||||
char *q = (char *) strrchr (filename, '/');
|
||||
sprintf (p, "%s ", (q) ? q+1 : filename);
|
||||
p += strlen (p);
|
||||
}
|
||||
|
||||
if (*p == ' ')
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf);
|
||||
|
||||
cgen_trace_printf (cpu, "0x%.*x %-*.*s %-*s ",
|
||||
SIZE_PC, (unsigned) pc,
|
||||
SIZE_LOCATION, SIZE_LOCATION, buf,
|
||||
SIZE_INSTRUCTION,
|
||||
#if 0
|
||||
CGEN_INSN_NAME (opcode)
|
||||
#else
|
||||
disasm_buf
|
||||
#endif
|
||||
);
|
||||
|
||||
printed_result_p = 0;
|
||||
sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf, &insn_fields);
|
||||
trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
|
||||
NULL, 0,
|
||||
"%s%-*s",
|
||||
first_insn_p ? " " : "|",
|
||||
SIZE_INSTRUCTION, disasm_buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -169,7 +187,8 @@ trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
|
|||
|
||||
va_start (args, name);
|
||||
|
||||
trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*x: %s ", SIZE_PC, pc, name);
|
||||
trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*lx: %s ",
|
||||
SIZE_PC, pc, name);
|
||||
|
||||
do {
|
||||
int type,ival;
|
||||
|
@ -206,6 +225,7 @@ trace_result (SIM_CPU *cpu, char *name, int type, ...)
|
|||
va_start (args, type);
|
||||
if (printed_result_p)
|
||||
cgen_trace_printf (cpu, ", ");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 'x' :
|
||||
|
@ -222,6 +242,7 @@ trace_result (SIM_CPU *cpu, char *name, int type, ...)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printed_result_p = 1;
|
||||
va_end (args);
|
||||
}
|
||||
|
@ -248,6 +269,9 @@ cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...)
|
|||
{
|
||||
vsprintf (bufptr, fmt, args);
|
||||
bufptr += strlen (bufptr);
|
||||
/* ??? Need version of SIM_ASSERT that is always enabled. */
|
||||
if (bufptr - trace_buf > SIZE_TRACE_BUF)
|
||||
abort ();
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
|
|
|
@ -234,7 +234,7 @@ cat << EOF
|
|||
#define SEM_IN_SWITCH
|
||||
|
||||
#define WANT_CPU
|
||||
#define WANT_CPU_${CPU}
|
||||
#define WANT_CPU_@CPU@
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "bfd.h"
|
||||
|
@ -244,6 +244,62 @@ cat << EOF
|
|||
#include "cpu-sim.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
/* Fill in the administrative ARGBUF fields required by all insns,
|
||||
virtual and real. */
|
||||
|
||||
static INLINE void
|
||||
@cpu@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc,
|
||||
PCADDR pc, int fast_p)
|
||||
{
|
||||
SEM_SET_CODE (abuf, idesc, fast_p);
|
||||
ARGBUF_ADDR (abuf) = pc;
|
||||
ARGBUF_IDESC (abuf) = idesc;
|
||||
}
|
||||
|
||||
/* Fill in tracing/profiling fields of an ARGBUF. */
|
||||
|
||||
static INLINE void
|
||||
@cpu@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf,
|
||||
int trace_p, int profile_p)
|
||||
{
|
||||
ARGBUF_TRACE_P (abuf) = trace_p;
|
||||
ARGBUF_PROFILE_P (abuf) = profile_p;
|
||||
}
|
||||
|
||||
#if WITH_SCACHE_PBB
|
||||
|
||||
/* Emit the "x-before" handler.
|
||||
x-before is emitted before each insn (serial or parallel).
|
||||
This is as opposed to x-after which is only emitted at the end of a group
|
||||
of parallel insns. */
|
||||
|
||||
static INLINE void
|
||||
@cpu@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p)
|
||||
{
|
||||
ARGBUF *abuf = &sc[0].argbuf;
|
||||
const IDESC *id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEFORE];
|
||||
|
||||
abuf->fields.before.first_p = first_p;
|
||||
@cpu@_fill_argbuf (current_cpu, abuf, id, pc, 0);
|
||||
/* no need to set trace_p,profile_p */
|
||||
}
|
||||
|
||||
/* Emit the "x-after" handler.
|
||||
x-after is emitted after a serial insn or at the end of a group of
|
||||
parallel insns. */
|
||||
|
||||
static INLINE void
|
||||
@cpu@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc)
|
||||
{
|
||||
ARGBUF *abuf = &sc[0].argbuf;
|
||||
const IDESC *id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_AFTER];
|
||||
|
||||
@cpu@_fill_argbuf (current_cpu, abuf, id, pc, 0);
|
||||
/* no need to set trace_p,profile_p */
|
||||
}
|
||||
|
||||
#endif /* WITH_SCACHE_PBB */
|
||||
|
||||
EOF
|
||||
|
||||
${SHELL} $infile support
|
||||
|
@ -259,12 +315,13 @@ if [ x$scache != xyes -a x$pbb != xyes ] ; then
|
|||
#define FAST_P 0
|
||||
|
||||
void
|
||||
${cpu}_engine_run_full (SIM_CPU *current_cpu)
|
||||
@cpu@_engine_run_full (SIM_CPU *current_cpu)
|
||||
{
|
||||
#define FAST_P 0
|
||||
SIM_DESC current_state = CPU_STATE (current_cpu);
|
||||
SCACHE cache[MAX_LIW_INSNS];
|
||||
SCACHE *sc = &cache[0];
|
||||
IADDR pc;
|
||||
|
||||
EOF
|
||||
|
||||
|
@ -300,6 +357,20 @@ fi
|
|||
|
||||
cat << EOF
|
||||
|
||||
#if WITH_SEM_SWITCH_FULL && defined (__GNUC__)
|
||||
{
|
||||
if (! CPU_IDESC_SEM_INIT_P (current_cpu))
|
||||
{
|
||||
/* ??? 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
|
||||
|
||||
pc = GET_H_PC ();
|
||||
|
||||
do
|
||||
{
|
||||
/* begin full-{extract,exec}-simple */
|
||||
|
@ -333,7 +404,7 @@ if [ x$fast = xyes ] ; then
|
|||
|
||||
#define FAST_P 1
|
||||
|
||||
FIXME
|
||||
FIXME: "fast simple version unimplemented, delete -fast arg to genmloop.sh."
|
||||
|
||||
#undef FAST_P
|
||||
|
||||
|
@ -352,7 +423,7 @@ if [ x$scache = xyes ] ; then
|
|||
cat << EOF
|
||||
|
||||
static INLINE SCACHE *
|
||||
${cpu}_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
|
||||
@cpu@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache,
|
||||
unsigned int hash_mask, int FAST_P)
|
||||
{
|
||||
/* First step: look up current insn in hash table. */
|
||||
|
@ -389,7 +460,7 @@ cat << EOF
|
|||
#define FAST_P 0
|
||||
|
||||
void
|
||||
${cpu}_engine_run_full (SIM_CPU *current_cpu)
|
||||
@cpu@_engine_run_full (SIM_CPU *current_cpu)
|
||||
{
|
||||
SIM_DESC current_state = CPU_STATE (current_cpu);
|
||||
SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
|
||||
|
@ -436,7 +507,7 @@ cat << EOF
|
|||
{
|
||||
SCACHE *sc;
|
||||
|
||||
sc = ${cpu}_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
|
||||
sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
|
||||
|
||||
/* begin full-exec-scache */
|
||||
EOF
|
||||
|
@ -468,7 +539,7 @@ if [ x$fast = xyes ] ; then
|
|||
#define FAST_P 1
|
||||
|
||||
void
|
||||
${cpu}_engine_run_fast (SIM_CPU *current_cpu)
|
||||
@cpu@_engine_run_fast (SIM_CPU *current_cpu)
|
||||
{
|
||||
SIM_DESC current_state = CPU_STATE (current_cpu);
|
||||
SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
|
||||
|
@ -527,7 +598,7 @@ cat << EOF
|
|||
{
|
||||
SCACHE *sc;
|
||||
|
||||
sc = ${cpu}_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
|
||||
sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P);
|
||||
|
||||
/* begin fast-exec-scache */
|
||||
EOF
|
||||
|
@ -565,15 +636,15 @@ if [ x$pbb = xyes ] ; then
|
|||
cat << EOF
|
||||
|
||||
/* Record address of cti terminating a pbb. */
|
||||
#define SET_CTI_VPC(sc) do { cti_sc = (sc); } while (0)
|
||||
#define SET_CTI_VPC(sc) do { _cti_sc = (sc); } while (0)
|
||||
/* Record number of [real] insns in pbb. */
|
||||
#define SET_INSN_COUNT(n) do { insn_count = (n); } while (0)
|
||||
#define SET_INSN_COUNT(n) do { _insn_count = (n); } while (0)
|
||||
|
||||
/* Fetch and extract a pseudo-basic-block.
|
||||
FAST_P is non-zero if no tracing/profiling/etc. is wanted. */
|
||||
|
||||
INLINE SEM_PC
|
||||
${cpu}_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
|
||||
@cpu@_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
|
||||
{
|
||||
SEM_PC new_vpc;
|
||||
PCADDR pc;
|
||||
|
@ -585,9 +656,10 @@ ${cpu}_pbb_begin (SIM_CPU *current_cpu, int FAST_P)
|
|||
new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc);
|
||||
if (! new_vpc)
|
||||
{
|
||||
int insn_count = 0;
|
||||
/* Leading '_' to avoid collision with mainloop.in. */
|
||||
int _insn_count = 0;
|
||||
SCACHE *orig_sc = sc;
|
||||
SCACHE *cti_sc = NULL;
|
||||
SCACHE *_cti_sc = NULL;
|
||||
int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu);
|
||||
|
||||
/* First figure out how many instructions to compile.
|
||||
|
@ -653,18 +725,18 @@ cat << EOF
|
|||
const IDESC *id;
|
||||
|
||||
/* Was pbb terminated by a cti? */
|
||||
if (cti_sc)
|
||||
if (_cti_sc)
|
||||
{
|
||||
id = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_CTI_CHAIN];
|
||||
id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_CTI_CHAIN];
|
||||
}
|
||||
else
|
||||
{
|
||||
id = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_CHAIN];
|
||||
id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_CHAIN];
|
||||
}
|
||||
SEM_SET_CODE (&sc->argbuf, id, FAST_P);
|
||||
sc->argbuf.idesc = id;
|
||||
sc->argbuf.addr = pc;
|
||||
sc->argbuf.fields.chain.insn_count = insn_count;
|
||||
sc->argbuf.fields.chain.insn_count = _insn_count;
|
||||
sc->argbuf.fields.chain.next = 0;
|
||||
++sc;
|
||||
}
|
||||
|
@ -684,7 +756,7 @@ cat << EOF
|
|||
/* Chain to the next block from a non-cti terminated previous block. */
|
||||
|
||||
INLINE SEM_PC
|
||||
${cpu}_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
|
||||
@cpu@_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
|
||||
{
|
||||
ARGBUF *abuf = SEM_ARGBUF (sem_arg);
|
||||
|
||||
|
@ -693,7 +765,14 @@ ${cpu}_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
|
|||
SET_H_PC (abuf->addr);
|
||||
|
||||
/* If not running forever, exit back to main loop. */
|
||||
if (CPU_MAX_SLICE_INSNS (current_cpu) != 0)
|
||||
if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
|
||||
/* Also exit back to main loop if there's an event.
|
||||
Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
|
||||
at the "right" time, but then that was what was asked for.
|
||||
There is no silver bullet for simulator engines.
|
||||
??? Clearly this needs a cleaner interface.
|
||||
At present it's just so Ctrl-C works. */
|
||||
|| STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
|
||||
CPU_RUNNING_P (current_cpu) = 0;
|
||||
|
||||
/* If chained to next block, go straight to it. */
|
||||
|
@ -715,7 +794,7 @@ ${cpu}_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg)
|
|||
NEW_VPC_PTR != SEM_BRANCH_UNTAKEN. */
|
||||
|
||||
INLINE SEM_PC
|
||||
${cpu}_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
|
||||
@cpu@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
|
||||
SEM_PC *new_vpc_ptr, PCADDR new_pc)
|
||||
{
|
||||
ARGBUF *abuf;
|
||||
|
@ -723,7 +802,14 @@ ${cpu}_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
|
|||
PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg);
|
||||
|
||||
/* If not running forever, exit back to main loop. */
|
||||
if (CPU_MAX_SLICE_INSNS (current_cpu) != 0)
|
||||
if (CPU_MAX_SLICE_INSNS (current_cpu) != 0
|
||||
/* Also exit back to main loop if there's an event.
|
||||
Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed
|
||||
at the "right" time, but then that was what was asked for.
|
||||
There is no silver bullet for simulator engines.
|
||||
??? Clearly this needs a cleaner interface.
|
||||
At present it's just so Ctrl-C works. */
|
||||
|| STATE_EVENTS (CPU_STATE (current_cpu))->work_pending)
|
||||
CPU_RUNNING_P (current_cpu) = 0;
|
||||
|
||||
/* Restart compiler if we branched to an uncacheable address
|
||||
|
@ -763,7 +849,7 @@ ${cpu}_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg,
|
|||
This is called before each insn. */
|
||||
|
||||
void
|
||||
${cpu}_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
|
||||
@cpu@_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
|
||||
{
|
||||
SEM_ARG sem_arg = sc;
|
||||
const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
|
||||
|
@ -772,7 +858,8 @@ ${cpu}_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
|
|||
const IDESC *cur_idesc = cur_abuf->idesc;
|
||||
PCADDR pc = cur_abuf->addr;
|
||||
|
||||
PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
|
||||
if (ARGBUF_PROFILE_P (cur_abuf))
|
||||
PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num);
|
||||
|
||||
/* If this isn't the first insn, finish up the previous one. */
|
||||
|
||||
|
@ -785,18 +872,23 @@ ${cpu}_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
|
|||
const IDESC *prev_idesc = prev_abuf->idesc;
|
||||
int cycles;
|
||||
|
||||
cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
|
||||
${cpu}_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
|
||||
/* ??? May want to measure all insns if doing insn tracing. */
|
||||
if (ARGBUF_PROFILE_P (prev_abuf))
|
||||
{
|
||||
cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
|
||||
@cpu@_model_insn_after (current_cpu, 0 /*last_p*/, cycles);
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_INSN_FINI (current_cpu, 0 /*last_p*/);
|
||||
TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/);
|
||||
}
|
||||
|
||||
/* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */
|
||||
if (PROFILE_MODEL_P (current_cpu))
|
||||
${cpu}_model_insn_before (current_cpu, first_p);
|
||||
if (PROFILE_MODEL_P (current_cpu)
|
||||
&& ARGBUF_PROFILE_P (cur_abuf))
|
||||
@cpu@_model_insn_before (current_cpu, first_p);
|
||||
|
||||
TRACE_INSN_INIT (current_cpu, first_p);
|
||||
TRACE_INSN_INIT (current_cpu, cur_abuf, first_p);
|
||||
TRACE_INSN (current_cpu, cur_idesc->opcode, cur_abuf, cur_abuf->addr);
|
||||
}
|
||||
|
||||
|
@ -805,28 +897,30 @@ ${cpu}_pbb_before (SIM_CPU *current_cpu, SCACHE *sc)
|
|||
insns. */
|
||||
|
||||
void
|
||||
${cpu}_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
|
||||
@cpu@_pbb_after (SIM_CPU *current_cpu, SCACHE *sc)
|
||||
{
|
||||
SEM_ARG sem_arg = sc;
|
||||
const ARGBUF *abuf = SEM_ARGBUF (sem_arg);
|
||||
const SEM_ARG prev_sem_arg = sc - 1;
|
||||
const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
|
||||
|
||||
if (PROFILE_MODEL_P (current_cpu))
|
||||
/* ??? May want to measure all insns if doing insn tracing. */
|
||||
if (PROFILE_MODEL_P (current_cpu)
|
||||
&& ARGBUF_PROFILE_P (prev_abuf))
|
||||
{
|
||||
const SEM_ARG prev_sem_arg = sc - 1;
|
||||
const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg);
|
||||
const IDESC *prev_idesc = prev_abuf->idesc;
|
||||
int cycles;
|
||||
|
||||
cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg);
|
||||
${cpu}_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
|
||||
@cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
|
||||
}
|
||||
TRACE_INSN_FINI (current_cpu, 1 /*last_p*/);
|
||||
TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/);
|
||||
}
|
||||
|
||||
#define FAST_P 0
|
||||
|
||||
void
|
||||
${cpu}_engine_run_full (SIM_CPU *current_cpu)
|
||||
@cpu@_engine_run_full (SIM_CPU *current_cpu)
|
||||
{
|
||||
SIM_DESC current_state = CPU_STATE (current_cpu);
|
||||
SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
|
||||
|
@ -871,8 +965,8 @@ cat << EOF
|
|||
/* Initialize the "begin (compile) a pbb" virtual insn. */
|
||||
vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
|
||||
SEM_SET_FULL_CODE (SEM_ARGBUF (vpc),
|
||||
& CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN]);
|
||||
vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN];
|
||||
& CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN]);
|
||||
vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN];
|
||||
|
||||
CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
|
||||
}
|
||||
|
@ -882,7 +976,7 @@ cat << EOF
|
|||
pbb we don't want to call pbb_begin each time (which hashes on the pc
|
||||
and does a table lookup). A way to speed this up is to save vpc
|
||||
between calls. */
|
||||
vpc = ${cpu}_pbb_begin (current_cpu, FAST_P);
|
||||
vpc = @cpu@_pbb_begin (current_cpu, FAST_P);
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -912,7 +1006,7 @@ if [ x$fast = xyes ] ; then
|
|||
#define FAST_P 1
|
||||
|
||||
void
|
||||
${cpu}_engine_run_fast (SIM_CPU *current_cpu)
|
||||
@cpu@_engine_run_fast (SIM_CPU *current_cpu)
|
||||
{
|
||||
SIM_DESC current_state = CPU_STATE (current_cpu);
|
||||
SCACHE *scache = CPU_SCACHE_CACHE (current_cpu);
|
||||
|
@ -957,8 +1051,8 @@ cat << EOF
|
|||
/* Initialize the "begin (compile) a pbb" virtual insn. */
|
||||
vpc = CPU_SCACHE_PBB_BEGIN (current_cpu);
|
||||
SEM_SET_FAST_CODE (SEM_ARGBUF (vpc),
|
||||
& CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN]);
|
||||
vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [${CPU}_INSN_X_BEGIN];
|
||||
& CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN]);
|
||||
vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN];
|
||||
|
||||
CPU_IDESC_SEM_INIT_P (current_cpu) = 1;
|
||||
}
|
||||
|
@ -968,7 +1062,7 @@ cat << EOF
|
|||
pbb we don't want to call pbb_begin each time (which hashes on the pc
|
||||
and does a table lookup). A way to speed this up is to save vpc
|
||||
between calls. */
|
||||
vpc = ${cpu}_pbb_begin (current_cpu, FAST_P);
|
||||
vpc = @cpu@_pbb_begin (current_cpu, FAST_P);
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -990,6 +1084,7 @@ fi # -fast
|
|||
|
||||
fi # -pbb
|
||||
|
||||
# Process @cpu@,@CPU@ appearing in mainloop.in.
|
||||
sed -e "s/@cpu@/$cpu/g" -e "s/@CPU@/$CPU/g" < tmp-mloop.cin > mloop.cin
|
||||
rc=$?
|
||||
rm -f tmp-mloop.cin
|
||||
|
|
192
sim/common/sim-model.c
Normal file
192
sim/common/sim-model.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/* Model support.
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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. */
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "libiberty.h"
|
||||
#include "sim-options.h"
|
||||
#include "sim-io.h"
|
||||
#include "sim-assert.h"
|
||||
#include "bfd.h"
|
||||
|
||||
static void model_set (SIM_DESC, sim_cpu *, const MODEL *);
|
||||
|
||||
static DECLARE_OPTION_HANDLER (model_option_handler);
|
||||
|
||||
static MODULE_INIT_FN sim_model_init;
|
||||
|
||||
#define OPTION_MODEL (OPTION_START + 0)
|
||||
|
||||
static const OPTION model_options[] = {
|
||||
{ {"model", required_argument, NULL, OPTION_MODEL},
|
||||
'\0', "MODEL", "Specify model to simulate",
|
||||
model_option_handler },
|
||||
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static SIM_RC
|
||||
model_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
|
||||
char *arg, int is_command)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case OPTION_MODEL :
|
||||
{
|
||||
const MODEL *model = sim_model_lookup (arg);
|
||||
if (! model)
|
||||
{
|
||||
sim_io_eprintf (sd, "unknown model `%s'", arg);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
sim_model_set (sd, cpu, model);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
SIM_RC
|
||||
sim_model_install (SIM_DESC sd)
|
||||
{
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
|
||||
sim_add_option_table (sd, NULL, model_options);
|
||||
sim_module_add_init_fn (sd, sim_model_init);
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Subroutine of sim_model_set to set the model for one cpu. */
|
||||
|
||||
static void
|
||||
model_set (SIM_DESC sd, sim_cpu *cpu, const MODEL *model)
|
||||
{
|
||||
CPU_MACH (cpu) = MODEL_MACH (model);
|
||||
CPU_MODEL (cpu) = model;
|
||||
(* MACH_INIT_CPU (MODEL_MACH (model))) (cpu);
|
||||
(* MODEL_INIT (model)) (cpu);
|
||||
}
|
||||
|
||||
/* Set the current model of CPU to MODEL.
|
||||
If CPU is NULL, all cpus are set to MODEL. */
|
||||
|
||||
void
|
||||
sim_model_set (SIM_DESC sd, sim_cpu *cpu, const MODEL *model)
|
||||
{
|
||||
if (! cpu)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < MAX_NR_PROCESSORS; ++c)
|
||||
if (STATE_CPU (sd, c))
|
||||
model_set (sd, STATE_CPU (sd, c), model);
|
||||
}
|
||||
else
|
||||
{
|
||||
model_set (sd, cpu, model);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up model named NAME.
|
||||
Result is pointer to MODEL entry or NULL if not found. */
|
||||
|
||||
const MODEL *
|
||||
sim_model_lookup (const char *name)
|
||||
{
|
||||
const MACH **machp;
|
||||
const MODEL *model;
|
||||
|
||||
for (machp = & sim_machs[0]; *machp != NULL; ++machp)
|
||||
{
|
||||
for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; ++model)
|
||||
{
|
||||
if (strcmp (MODEL_NAME (model), name) == 0)
|
||||
return model;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Look up machine named NAME.
|
||||
Result is pointer to MACH entry or NULL if not found. */
|
||||
|
||||
const MACH *
|
||||
sim_mach_lookup (const char *name)
|
||||
{
|
||||
const MACH **machp;
|
||||
|
||||
for (machp = & sim_machs[0]; *machp != NULL; ++machp)
|
||||
{
|
||||
if (strcmp (MACH_NAME (*machp), name) == 0)
|
||||
return *machp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize model support. */
|
||||
|
||||
static SIM_RC
|
||||
sim_model_init (SIM_DESC sd)
|
||||
{
|
||||
SIM_CPU *cpu;
|
||||
|
||||
/* If both cpu model and state architecture are set, ensure they're
|
||||
compatible. If only one is set, set the other. If neither are set,
|
||||
use the default model. STATE_ARCHITECTURE is the bfd_arch_info data
|
||||
for the selected "mach" (bfd terminology). */
|
||||
|
||||
/* Only check cpu 0. STATE_ARCHITECTURE is for that one only. */
|
||||
/* ??? At present this only supports homogeneous multiprocessors. */
|
||||
cpu = STATE_CPU (sd, 0);
|
||||
|
||||
if (! STATE_ARCHITECTURE (sd)
|
||||
&& ! CPU_MACH (cpu))
|
||||
{
|
||||
/* Set the default model. */
|
||||
const MODEL *model = sim_model_lookup (WITH_DEFAULT_MODEL);
|
||||
sim_model_set (sd, NULL, model);
|
||||
}
|
||||
|
||||
if (STATE_ARCHITECTURE (sd)
|
||||
&& CPU_MACH (cpu))
|
||||
{
|
||||
if (strcmp (STATE_ARCHITECTURE (sd)->printable_name,
|
||||
MACH_BFD_NAME (CPU_MACH (cpu))) != 0)
|
||||
{
|
||||
sim_io_eprintf (sd, "invalid model `%s' for `%s'\n",
|
||||
MODEL_NAME (CPU_MODEL (cpu)),
|
||||
STATE_ARCHITECTURE (sd)->printable_name);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
}
|
||||
else if (STATE_ARCHITECTURE (sd))
|
||||
{
|
||||
/* Use the default model for the selected machine.
|
||||
The default model is the first one in the list. */
|
||||
const MACH *mach = sim_mach_lookup (STATE_ARCHITECTURE (sd)->printable_name);
|
||||
sim_model_set (sd, NULL, MACH_MODELS (mach));
|
||||
}
|
||||
else
|
||||
{
|
||||
STATE_ARCHITECTURE (sd) = bfd_scan_arch (MACH_BFD_NAME (CPU_MACH (cpu)));
|
||||
}
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
132
sim/common/sim-model.h
Normal file
132
sim/common/sim-model.h
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* Architecture, machine, and model support.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
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. */
|
||||
|
||||
/* Nomenclature:
|
||||
architecture = one of sparc, mips, sh, etc.
|
||||
in the sparc architecture, mach = one of v6, v7, v8, sparclite, etc.
|
||||
in the v8 mach, model = one of supersparc, etc.
|
||||
*/
|
||||
|
||||
/* This file is intended to be included by sim-basics.h. */
|
||||
|
||||
#ifndef SIM_MODEL_H
|
||||
#define SIM_MODEL_H
|
||||
|
||||
/* Function unit and instruction timing support.
|
||||
??? This is obviously insufficiently general.
|
||||
It's useful but it needs elaborating upon. */
|
||||
|
||||
typedef struct {
|
||||
unsigned char name; /* actually a UNIT_TYPE enum */
|
||||
unsigned char issue;
|
||||
unsigned char done;
|
||||
} UNIT;
|
||||
|
||||
#ifndef MAX_UNITS
|
||||
#define MAX_UNITS 1
|
||||
#endif
|
||||
|
||||
typedef int (MODEL_FN) (sim_cpu *, void *);
|
||||
|
||||
typedef struct {
|
||||
/* This is an integer that identifies this insn.
|
||||
How this works is up to the target. */
|
||||
int num;
|
||||
|
||||
/* Function to handle insn-specific profiling. */
|
||||
MODEL_FN *model_fn;
|
||||
|
||||
/* Array of function units used by this insn. */
|
||||
UNIT units[MAX_UNITS];
|
||||
} INSN_TIMING;
|
||||
|
||||
/* Struct to describe various implementation properties of a cpu.
|
||||
When multiple cpu variants are supported, the sizes of some structs
|
||||
can vary. */
|
||||
|
||||
typedef struct {
|
||||
/* The size of the SIM_CPU struct. */
|
||||
int sim_cpu_size;
|
||||
#define IMP_PROPS_SIM_CPU_SIZE(cpu_props) ((cpu_props)->sim_cpu_size)
|
||||
/* An SCACHE element can vary in size, depending on the selected cpu.
|
||||
This is zero if the SCACHE isn't in use for this variant. */
|
||||
int scache_elm_size;
|
||||
#define IMP_PROPS_SCACHE_ELM_SIZE(cpu_props) ((cpu_props)->scache_elm_size)
|
||||
} MACH_IMP_PROPERTIES;
|
||||
|
||||
/* A machine variant. */
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
#define MACH_NAME(m) ((m)->name)
|
||||
/* This is the argument to bfd_scan_arch. */
|
||||
const char *bfd_name;
|
||||
#define MACH_BFD_NAME(m) ((m)->bfd_name)
|
||||
int word_bitsize;
|
||||
#define MACH_WORD_BITSIZE(m) ((m)->word_bitsize)
|
||||
int addr_bitsize;
|
||||
#define MACH_ADDR_BITSIZE(m) ((m)->addr_bitsize)
|
||||
|
||||
/* Pointer to null-entry terminated table of models of this mach.
|
||||
The default is the first one. */
|
||||
const struct model *models;
|
||||
#define MACH_MODELS(m) ((m)->models)
|
||||
|
||||
/* Pointer to the implementation properties of this mach. */
|
||||
const MACH_IMP_PROPERTIES *imp_props;
|
||||
#define MACH_IMP_PROPS(m) ((m)->imp_props)
|
||||
|
||||
/* Called by sim_model_set when the model of a cpu is set. */
|
||||
void (* init_cpu) (sim_cpu *);
|
||||
#define MACH_INIT_CPU(m) ((m)->init_cpu)
|
||||
} MACH;
|
||||
|
||||
/* A model (implementation) of a machine. */
|
||||
|
||||
typedef struct model {
|
||||
const char *name;
|
||||
#define MODEL_NAME(m) ((m)->name)
|
||||
const MACH *mach;
|
||||
#define MODEL_MACH(m) ((m)->mach)
|
||||
/* An enum that distinguished the model. */
|
||||
int num;
|
||||
#define MODEL_NUM(m) ((m)->num)
|
||||
/* Pointer to timing table for this model. */
|
||||
const INSN_TIMING *timing;
|
||||
#define MODEL_TIMING(m) ((m)->timing)
|
||||
void (* init) (sim_cpu *);
|
||||
#define MODEL_INIT(m) ((m)->init)
|
||||
} MODEL;
|
||||
|
||||
/* Tables of supported machines. */
|
||||
/* ??? In a simulator of multiple architectures, will need multiple copies of
|
||||
this. Have an `archs' array that contains a pointer to the machs array
|
||||
for each (which in turn has a pointer to the models array for each). */
|
||||
extern const MACH *sim_machs[];
|
||||
|
||||
/* Model module handlers. */
|
||||
extern MODULE_INSTALL_FN sim_model_install;
|
||||
|
||||
/* Support routines. */
|
||||
extern void sim_model_set (SIM_DESC sd, sim_cpu *cpu, const MODEL *model);
|
||||
extern const MODEL * sim_model_lookup (const char *name);
|
||||
extern const MACH * sim_mach_lookup (const char *name);
|
||||
|
||||
#endif /* SIM_MODEL_H */
|
|
@ -23,11 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "sim-options.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
/* start-sanitize-am30 */
|
||||
#if WITH_HW
|
||||
#include "sim-hw.h"
|
||||
#endif
|
||||
/* end-sanitize-am30 */
|
||||
|
||||
#include "libiberty.h"
|
||||
|
||||
|
@ -52,20 +50,18 @@ static MODULE_INSTALL_FN * const modules[] = {
|
|||
#if WITH_WATCHPOINTS
|
||||
sim_watchpoint_install,
|
||||
#endif
|
||||
#if WITH_SCACHE
|
||||
scache_install,
|
||||
#endif
|
||||
#ifdef SIM_HAVE_MODEL
|
||||
sim_model_install,
|
||||
#endif
|
||||
#if WITH_SCACHE
|
||||
scache_install,
|
||||
#endif
|
||||
#ifdef SIM_HAVE_BREAKPOINTS
|
||||
sim_break_install,
|
||||
#endif
|
||||
/* start-sanitize-am30 */
|
||||
#if WITH_HW
|
||||
sim_hw_install,
|
||||
#endif
|
||||
/* end-sanitize-am30 */
|
||||
/* Configured in [simulator specific] additional modules. */
|
||||
#ifdef MODULE_LIST
|
||||
MODULE_LIST
|
||||
|
@ -116,9 +112,6 @@ sim_post_argv_init (SIM_DESC sd)
|
|||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
SIM_ASSERT (STATE_MODULES (sd) != NULL);
|
||||
|
||||
if (sim_module_init (sd) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
/* Set the cpu->state backlinks for each cpu. */
|
||||
for (i = 0; i < MAX_NR_PROCESSORS; ++i)
|
||||
{
|
||||
|
@ -126,6 +119,9 @@ sim_post_argv_init (SIM_DESC sd)
|
|||
CPU_INDEX (STATE_CPU (sd, i)) = i;
|
||||
}
|
||||
|
||||
if (sim_module_init (sd) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue