* cgen-sim.h (EX_FN_NAME): _exc_ -> _ex_.
authorDoug Evans <dje@google.com>
Thu, 5 Feb 1998 21:29:18 +0000 (21:29 +0000)
committerDoug Evans <dje@google.com>
Thu, 5 Feb 1998 21:29:18 +0000 (21:29 +0000)
(SEM_INSN): New macro.

sim/common/ChangeLog
sim/common/cgen-sim.h

index 765cc69..cdddbfa 100644 (file)
@@ -1,3 +1,8 @@
+Thu Feb  5 13:27:04 1998  Doug Evans  <devans@seba.cygnus.com>
+
+       * cgen-sim.h (EX_FN_NAME): _exc_ -> _ex_.
+       (SEM_INSN): New macro.
+
 Tue Feb  3 16:31:56 1998  Andrew Cagney  <cagney@b1.cygnus.com>
 
        * sim-run.c (sim_engine_run): Assume IMEM is 32 bit.
index 7df7d3f..71e41df 100644 (file)
@@ -1,5 +1,5 @@
 /* Simulator header for Cpu tools GENerated 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.
@@ -21,26 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef CGEN_SIM_H
 #define CGEN_SIM_H
 
-#define PC (STATE_CPU_CPU (current_state, 0)->pc)
-
-/* Execution state.  */
-enum exec_state {
-  EXEC_STATE_RUNNING, EXEC_STATE_EXITED,
-  EXEC_STATE_STOPPED, EXEC_STATE_SIGNALLED
-};
-
-/* Signals we use.  */
-enum sim_signal_type {
-  SIM_SIGNONE,
-  SIM_SIGILL,    /* illegal insn */
-  SIM_SIGTRAP,
-  SIM_SIGALIGN,  /* misaligned memory access */
-  SIM_SIGACCESS, /* tried to read/write memory that's not readable/writable */
-  SIM_SIGXCPU    /* cpu limit exceeded */
-};
-
-void engine_halt PARAMS ((struct _sim_cpu *, enum exec_state, int));
-void engine_signal PARAMS ((struct _sim_cpu *, enum sim_signal_type));
+#include "sim-xcat.h"
+
+#define PC CPU (h_pc)
 \f
 /* Instruction field support macros.  */
 
@@ -56,63 +39,258 @@ void engine_signal PARAMS ((struct _sim_cpu *, enum sim_signal_type));
 #define HOST_LONGS_FOR_BITS(n) \
   (((n) + sizeof (long) * 8 - 1) / sizeof (long) * 8)
 \f
-/* Decode,extract,semantics.  */
+/* Execution support.  */
+
+/* Forward decls.  Defined in the machine generated arch.h and cpu.h files.  */
+typedef struct argbuf ARGBUF;
+typedef struct scache SCACHE;
+typedef struct parallel_exec PARALLEL_EXEC;
 
-typedef void (EXTRACT_FN) PARAMS ((SIM_CPU *, PCADDR, insn_t, struct argbuf *));
-/*typedef CIA (SEMANTIC_FN) PARAMS ((SEM_ARG));*/
-typedef PCADDR (SEMANTIC_FN) PARAMS ((SIM_CPU *, struct argbuf *));
+/* Types of the machine generated extract and semantic fns.  */
+typedef void (EXTRACT_FN) (SIM_CPU *, PCADDR, insn_t, ARGBUF *);
+typedef void (READ_FN) (SIM_CPU *, PCADDR, insn_t, PARALLEL_EXEC *);
+/*typedef CIA (SEMANTIC_FN) (SEM_ARG);*/
+typedef PCADDR (SEMANTIC_FN) (SIM_CPU *, ARGBUF *);
 #if 0 /* wip */
-typedef void (EXTRACT_CACHE_FN) PARAMS ((SIM_CPU *, PCADDR, insn_t, struct argbuf *));
+typedef void (EXTRACT_CACHE_FN) (SIM_CPU *, PCADDR, insn_t, ARGBUF *);
 #endif
-typedef PCADDR (SEMANTIC_CACHE_FN) PARAMS ((SIM_CPU *, struct scache *));
+typedef PCADDR (SEMANTIC_CACHE_FN) (SIM_CPU *, SCACHE *);
 
 typedef struct {
   /* Using cgen_insn_type requires <cpu>-opc.h.  */
   int /*enum cgen_insn_type*/ insn_type;
   const struct cgen_insn *opcode;
-  /* FIXME: Perhaps rename these to normal/fast versions to associate them
-     with the normal/fast args to genmloop.sh.  */
   EXTRACT_FN *extract;
+#ifdef HAVE_PARALLEL_EXEC
+#ifdef USE_READ_SWITCH
+#ifdef __GNUC__
+  void *read;
+#else
+  int read;
+#endif
+#else
+  READ_FN *read;
+#endif
+#endif
   SEMANTIC_FN *semantic;
 #if 0 /* wip */
   EXTRACT_CACHE_FN *extract_fast;
 #endif
   SEMANTIC_CACHE_FN *semantic_fast;
-#if defined (USE_SEM_SWITCH) && defined (__GNUC__)
-  void *semantic_lab;
+#if WITH_SEM_SWITCH_FULL && defined (__GNUC__)
+  /* Set at runtime.  */
+  void *sem_full_lab;
+#endif
+#if WITH_SEM_SWITCH_FAST && defined (__GNUC__)
+  /* Set at runtime.  */
+  void *semantic_lab; /* FIXME: Rename to sem_fast_lab.  */
 #endif
 } DECODE;
 
-/* FIXME: length parm to decode() is currently unneeded.  */
-extern DECODE *decode PARAMS ((insn_t /*, int*/));
+/* Execution support.
+
+   Semantic functions come in two versions.
+   One that uses the cache, and one that doesn't.
+   ??? The one that doesn't may eventually be thrown away or replaced with
+   something else.  */
+
+#ifdef SCACHE_P
+
+/* instruction address */
+typedef PCADDR IADDR;
+/* current instruction address */
+typedef PCADDR CIA;
+/* argument to semantic functions */
+typedef SCACHE *SEM_ARG;
+
+#else /* ! SCACHE_P */
+
+/* instruction address */
+typedef PCADDR IADDR;
+/* current instruction address */
+typedef PCADDR CIA;
+/* argument to semantic functions */
+typedef ARGBUF *SEM_ARG;
+
+#endif /* ! SCACHE_P */
+
+/* Scache data for each cpu.  */
+
+typedef struct cpu_scache {
+  /* Simulator cache size.  */
+  int size;
+#define CPU_SCACHE_SIZE(cpu) ((cpu) -> cgen_cpu.scache.size)
+  /* 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
+
+#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)
+#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))
+
+/* Non-zero if cache is in use.  */
+#define USING_SCACHE_P(sd) (STATE_SCACHE_SIZE (sd) > 0)
+
+/* Install the simulator cache into the simulator.  */
+MODULE_INSTALL_FN scache_install;
+
+/* Flush all cpu's caches.  */
+void scache_flush (SIM_DESC);
 \f
-/* Simulator state.  */
+/* Scache profiling support.  */
 
-#if WITH_SCACHE
-#include "cgen-scache.h"
+/* Print summary scache usage information.  */
+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]) \
+    ++ CPU_SCACHE_HITS (cpu); \
+} while (0)
+#define PROFILE_COUNT_SCACHE_MISS(cpu) \
+do { \
+  if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \
+    ++ CPU_SCACHE_MISSES (cpu); \
+} while (0)
+#else
+#define PROFILE_COUNT_SCACHE_HIT(cpu)
+#define PROFILE_COUNT_SCACHE_MISS(cpu)
+#endif
+\f
+/* Engine support.  */
+
+/* Values to denote parallel/sequential execution.  */
+#define EXEC_SEQUENCE 0
+#define EXEC_PARALLEL 1
+
+#ifdef SCACHE_P
+
+#define CIA_ADDR(cia) (cia)
+
+/* These are used so that we can compile two copies of the semantic code,
+   one with scache support and one without.  */
+/* FIXME: Do we want _ex_ or _exc_?  */
+/*#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_exc_,fn)*/
+#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_ex_,fn)
+#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semc_,fn)
+
+/* extract.c support */
+/* scache_unset is a cache entry that is never used.
+   It's raison d'etre is so BRANCH_VIA_CACHE doesn't have to test for
+   newval.cache == NULL.  */
+extern struct scache scache_unset;
+#define RECORD_IADDR(fld, val) \
+do { (fld) = (val); } while (0)
+
+/* semantics.c support */
+#define SEM_ARGBUF(sem_arg) (&(sem_arg) -> argbuf)
+#define SEM_INSN(sem_arg) shouldnt_be_used
+#define SEM_NEXT_PC(sc) ((sc) -> next)
+#define SEM_BRANCH_VIA_CACHE(sc, newval) (newval)
+#define SEM_BRANCH_VIA_ADDR(sc, newval) (newval)
+/* Return address a branch insn will branch to.
+   This is only used during tracing.  */
+#define SEM_NEW_PC_ADDR(new_pc) (new_pc)
+
+#else /* ! SCACHE_P */
+
+#define CIA_ADDR(cia) (cia)
+
+/* These are used so that we can compile two copies of the semantic code,
+   one with scache support and one without.  */
+#define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_ex_,fn)
+#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
+
+/* extract.c support */
+#define RECORD_IADDR(fld, val) \
+do { (fld) = (val); } while (0)
+
+/* semantics.c support */
+#define SEM_ARGBUF(sem_arg) (sem_arg)
+#define SEM_INSN(sem_arg) (SEM_ARGBUF (sem_arg) -> insn)
+#define SEM_NEXT_PC(abuf) (abuf -> addr + abuf -> length)
+#define SEM_BRANCH_VIA_CACHE(abuf, newval) (newval)
+#define SEM_BRANCH_VIA_ADDR(abuf, newval) (newval)
+#define SEM_NEW_PC_ADDR(new_pc) (new_pc)
+
+#endif /* ! SCACHE_P */
+
+/* GNU C's "computed goto" facility is used to speed things up where
+   possible.  These macros provide a portable way to use them.
+   Nesting of these switch statements is done by providing an extra argument
+   that distinguishes them.  `N' can be a number or symbol.
+   Variable `labels_##N' must be initialized with the labels of each case.  */
+#ifdef __GNUC__
+#define SWITCH(N, X) goto *X;
+#define CASE(N, X) case_##N##_##X
+#define BREAK(N) goto end_switch_##N
+#define DEFAULT(N) default_##N
+#define ENDSWITCH(N) end_switch_##N:
+#else
+#define SWITCH(N, X) switch (X)
+#define CASE(N, X) case X /* FIXME: old sem-switch had (@arch@_,X) here */
+#define BREAK(N) break
+#define DEFAULT(N) default
+#define ENDSWITCH(N)
 #endif
 
-/* ??? Do we *need* to pass state to the semantic routines?  */
-extern SIM_DESC current_state;
+/* Engine control (FIXME).  */
+int engine_stop (SIM_DESC);
+void engine_run (SIM_DESC, int, int);
+/*void engine_resume (SIM_DESC, int, int);*/
+\f
+/* Simulator state.  */
 
-/* FIXME: Until sim_open creates one.  */
-extern struct sim_state sim_global_state;
+/* Records simulator descriptor so utilities like @cpu@_dump_regs can be
+   called from gdb.  */
+extern SIM_DESC current_state;
 
 /* Simulator state.  */
 
-/* Main state struct.
-   CGEN_STATE contains addition state information not present in
+/* CGEN_STATE contains additional state information not present in
    sim_state_base.  */
 
 typedef struct cgen_state {
+  /* FIXME: Moved to sim_state_base.  */
   /* argv, env */
   char **argv;
-#define STATE_ARGV(s) ((s)->cgen_state.argv)
+#define STATE_ARGV(s) ((s) -> cgen_state.argv)
+  /* FIXME: Move to sim_state_base.  */
   char **envp;
-#define STATE_ENVP(s) ((s)->cgen_state.envp)
+#define STATE_ENVP(s) ((s) -> cgen_state.envp)
+
+  /* Non-zero if no tracing or profiling is selected.  */
+  int run_fast_p;
+#define STATE_RUN_FAST_P(sd) ((sd) -> cgen_state.run_fast_p)
 } CGEN_STATE;
 
-/* Additional per-cpu data.  */
+/* Additional non-machine generated per-cpu data to go in SIM_CPU.
+   The member's name must be `cgen_cpu'.  */
 
 typedef struct {
   /* Simulator's execution cache.  */
@@ -120,33 +298,18 @@ typedef struct {
   CPU_SCACHE scache;
 #endif /* WITH_SCACHE */
 
-  enum exec_state exec_state;
-#define CPU_EXEC_STATE(cpu) ((cpu)->cgen_cpu.exec_state)
-
-  int halt_sigrc;
-#define CPU_HALT_SIGRC(cpu) ((cpu)->cgen_cpu.halt_sigrc)
-
-  jmp_buf halt_jmp_buf;
-#define CPU_HALT_JMP_BUF(cpu) ((cpu)->cgen_cpu.halt_jmp_buf)
-
-  CPU_DATA cpu;
-#define CPU_CPU(c) (& (c)->cgen_cpu.cpu)
-  CPU_PROFILE profile_state;
-#define CPU_PROFILE_STATE(cpu) (& (cpu)->cgen_cpu.profile_state)
+  /* Allow slop in size calcs for case where multiple cpu types are supported
+     and space for the specified cpu is malloc'd at run time.  */
+  double slop;
 } CGEN_CPU;
 \f
 /* Various utilities.  */
 
-int engine_stop (SIM_DESC);
-void engine_run (SIM_DESC, int, int);
-void engine_resume (SIM_DESC, int, int);
-void engine_halt (SIM_CPU *, enum exec_state, int);
-void engine_signal (SIM_CPU *, enum sim_signal_type);
-
-int sim_signal_to_host (int);
+/* Called after sim_post_argv_init to do any cgen initialization.  */
+void cgen_init (SIM_DESC);
 
 void
-sim_disassemble_insn (const struct cgen_insn *, const struct argbuf *,
-                     PCADDR, char *);
+sim_disassemble_insn (SIM_CPU *, const struct cgen_insn *,
+                     const struct argbuf *, PCADDR, char *);
 
 #endif /* CGEN_SIM_H */