cgen-run.c: new mainloop for cgen
authorDoug Evans <dje@google.com>
Wed, 7 Oct 1998 23:55:42 +0000 (23:55 +0000)
committerDoug Evans <dje@google.com>
Wed, 7 Oct 1998 23:55:42 +0000 (23:55 +0000)
sim-reg.c: generic sim_fetch/store_register interface fns

sim/common/.Sanitize
sim/common/cgen-run.c [new file with mode: 0644]
sim/common/sim-reg.c [new file with mode: 0644]

index 0b708c4..cc1af22 100644 (file)
@@ -38,6 +38,7 @@ aclocal.m4
 callback.c
 cgen-mem.h
 cgen-ops.h
+cgen-run.c
 cgen-scache.c
 cgen-sim.h
 cgen-trace.c
@@ -127,6 +128,7 @@ sim-options.h
 sim-profile.c
 sim-profile.h
 sim-reason.c
+sim-reg.c
 sim-resume.c
 sim-run.c
 sim-signal.c
diff --git a/sim/common/cgen-run.c b/sim/common/cgen-run.c
new file mode 100644 (file)
index 0000000..d4e83b0
--- /dev/null
@@ -0,0 +1,202 @@
+/* Main simulator loop for CGEN-based simulators.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   Contributed by Cygnus Solutions.
+
+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.  */
+
+/* ??? These are old notes, kept around for now.
+   Collecting profile data and tracing slow us down so we don't do them in
+   "fast mode".
+   There are 6 possibilities on 2 axes:
+   - no-scaching, insn-scaching, basic-block-scaching
+   - run with full features or run fast
+   Supporting all six possibilities in one executable is a bit much but
+   supporting full/fast seems reasonable.
+   If the scache is configured in it is always used.
+   If pbb-scaching is configured in it is always used.
+   ??? Sometimes supporting more than one set of semantic functions will make
+   the simulator too large - this should be configurable.  Blah blah blah.
+   ??? Supporting full/fast can be more modular, blah blah blah.
+   When the framework is more modular, this can be.
+*/
+
+#include "sim-main.h"
+#include "sim-assert.h"
+
+#ifndef SIM_ENGINE_PREFIX_HOOK
+#define SIM_ENGINE_PREFIX_HOOK(sd)
+#endif
+#ifndef SIM_ENGINE_POSTFIX_HOOK
+#define SIM_ENGINE_POSTFIX_HOOK(sd)
+#endif
+
+static void has_stepped (SIM_DESC, void *);
+static void engine_run_1 (SIM_DESC, int, int);
+static void engine_run_n (SIM_DESC, int, int, int, int);
+
+/* sim_resume for cgen */
+
+void
+sim_resume (SIM_DESC sd, int step, int siggnal)
+{
+  sim_engine *engine = STATE_ENGINE (sd);
+  jmp_buf buf;
+  int jmpval;
+
+  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+
+  /* we only want to be single stepping the simulator once */
+  if (engine->stepper != NULL)
+    {
+      sim_events_deschedule (sd, engine->stepper);
+      engine->stepper = NULL;
+    }
+  if (step)
+    engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);
+
+  sim_module_resume (sd);
+
+#if WITH_SCACHE
+  if (USING_SCACHE_P (sd))
+    scache_flush (sd);
+#endif
+
+  /* run/resume the simulator */
+
+  sim_engine_set_run_state (sd, sim_running, 0);
+
+  engine->jmpbuf = &buf;
+  jmpval = setjmp (buf);
+  if (jmpval == sim_engine_start_jmpval
+      || jmpval == sim_engine_restart_jmpval)
+    {
+      int last_cpu_nr = sim_engine_last_cpu_nr (sd);
+      int next_cpu_nr = sim_engine_next_cpu_nr (sd);
+      int nr_cpus = sim_engine_nr_cpus (sd);
+      int max_insns = step ? 1 : 0 /*pbb*/;
+      int fast_p = STATE_RUN_FAST_P (sd);
+
+      sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
+      if (next_cpu_nr >= nr_cpus)
+       next_cpu_nr = 0;
+      if (nr_cpus == 1)
+       engine_run_1 (sd, max_insns, fast_p);
+      else
+       engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p);
+    }
+#if 0 /*wip*/
+  else
+    {
+      /* Account for the last insn executed.  */
+      ++ CPU_INSN_COUNT (cpu);
+      TRACE_INSN_FINI ((sim_cpu *) cpu, 1);
+    }
+#endif
+
+  engine->jmpbuf = NULL;
+
+  {
+    int i;
+    int nr_cpus = sim_engine_nr_cpus (sd);
+
+#if 0 /*wip*/
+    /* If the loop exits, either we single-stepped or @cpu@_engine_stop
+       was called.  */
+    if (step)
+      sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
+    else
+      sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
+#endif
+
+    for (i = 0; i < nr_cpus; ++i)
+      {
+       SIM_CPU *cpu = STATE_CPU (sd, i);
+
+       PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu);
+      }
+  }
+
+  sim_module_suspend (sd);
+}
+
+/* Halt the simulator after just one instruction.  */
+
+static void
+has_stepped (SIM_DESC sd, void *data)
+{
+  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+  sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
+}
+
+static void
+engine_run_1 (SIM_DESC sd, int max_insns, int fast_p)
+{
+  sim_cpu *cpu = STATE_CPU (sd, 0);
+  ENGINE_FN *fn = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
+
+  CPU_MAX_SLICE_INSNS (cpu) = max_insns;
+  CPU_INSN_COUNT (cpu) = 0;
+
+  while (1)
+    {
+      SIM_ENGINE_PREFIX_HOOK (sd);
+
+      (*fn) (cpu);
+
+      SIM_ENGINE_POSTFIX_HOOK (sd);
+
+      /* process any events */
+      if (sim_events_tick (sd))
+       sim_events_process (sd);
+    }
+}
+
+static void
+engine_run_n (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int max_insns, int fast_p)
+{
+  int i;
+  ENGINE_FN *engine_fns[MAX_NR_PROCESSORS];
+
+  for (i = 0; i < nr_cpus; ++i)
+    {
+      SIM_CPU *cpu = STATE_CPU (sd, i);
+
+      engine_fns[i] = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
+      CPU_MAX_SLICE_INSNS (cpu) = max_insns;
+      CPU_INSN_COUNT (cpu) = 0;
+    }
+
+  while (1)
+    {
+      SIM_ENGINE_PREFIX_HOOK (sd);
+
+      /* FIXME: proper cycling of all of them, blah blah blah.  */
+      while (next_cpu_nr != nr_cpus)
+       {
+         SIM_CPU *cpu = STATE_CPU (sd, next_cpu_nr);
+
+         (* engine_fns[next_cpu_nr]) (cpu);
+         ++next_cpu_nr;
+       }
+
+      SIM_ENGINE_POSTFIX_HOOK (sd);
+
+      /* process any events */
+      if (sim_events_tick (sd))
+       sim_events_process (sd);
+    }
+}
diff --git a/sim/common/sim-reg.c b/sim/common/sim-reg.c
new file mode 100644 (file)
index 0000000..3f3dc41
--- /dev/null
@@ -0,0 +1,52 @@
+/* Generic register read/write.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   Contributed by Cygnus Solutions.
+
+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 "sim-assert.h"
+
+/* Generic implementation of sim_fetch_register for simulators using
+   CPU_REG_FETCH.
+   The contents of BUF are in target byte order.  */
+/* ??? Obviously the interface needs to be extended to handle multiple
+   cpus.  */
+
+int
+sim_fetch_register (SIM_DESC sd, int rn, unsigned char *buf, int length)
+{
+  SIM_CPU *cpu = STATE_CPU (sd, 0);
+
+  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+  return (* CPU_REG_FETCH (cpu)) (cpu, rn, buf, length);
+}
+
+/* Generic implementation of sim_fetch_register for simulators using
+   CPU_REG_FETCH.
+   The contents of BUF are in target byte order.  */
+/* ??? Obviously the interface needs to be extended to handle multiple
+   cpus.  */
+
+int
+sim_store_register (SIM_DESC sd, int rn, unsigned char *buf, int length)
+{
+  SIM_CPU *cpu = STATE_CPU (sd, 0);
+
+  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+  return (* CPU_REG_STORE (cpu)) (cpu, rn, buf, length);
+}