summaryrefslogtreecommitdiff
path: root/sim/common/cgen-run.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/common/cgen-run.c')
-rw-r--r--sim/common/cgen-run.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/sim/common/cgen-run.c b/sim/common/cgen-run.c
new file mode 100644
index 00000000000..07ee19197d7
--- /dev/null
+++ b/sim/common/cgen-run.c
@@ -0,0 +1,233 @@
+/* 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 sim_event_handler has_stepped;
+static void prime_cpu (SIM_CPU *, int);
+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);
+ /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is
+ useful if all one wants to do is run a benchmark. Need some better
+ way to identify this case. */
+ int max_insns = (step
+ ? 1
+ : (nr_cpus == 1 /*&& wip:no-events*/)
+ ? 0
+ : 4); /*FIXME: magic number*/
+ 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 1 /*wip*/
+ else
+ {
+ /* Account for the last insn executed. */
+ SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd));
+ ++ CPU_INSN_COUNT (cpu);
+ TRACE_INSN_FINI (cpu, NULL, 1);
+ }
+#endif
+
+ engine->jmpbuf = NULL;
+
+ {
+ int i;
+ int nr_cpus = sim_engine_nr_cpus (sd);
+
+#if 0 /*wip,ignore*/
+ /* 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);
+}
+
+/* Prepare a cpu for running.
+ MAX_INSNS is the number of insns to execute per time slice.
+ If 0 it means the cpu can run as long as it wants (e.g. until the
+ program completes).
+ ??? Perhaps this should be an argument to the engine_fn. */
+
+static void
+prime_cpu (SIM_CPU *cpu, int max_insns)
+{
+ CPU_MAX_SLICE_INSNS (cpu) = max_insns;
+ CPU_INSN_COUNT (cpu) = 0;
+
+ /* Initialize the insn descriptor table.
+ This has to be done after all initialization so we just defer it to
+ here. */
+
+ if (MACH_PREPARE_RUN (CPU_MACH (cpu)))
+ (* MACH_PREPARE_RUN (CPU_MACH (cpu))) (cpu);
+}
+
+/* Main loop, for 1 cpu. */
+
+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);
+
+ prime_cpu (cpu, max_insns);
+
+ 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);
+ }
+}
+
+/* Main loop, for multiple cpus. */
+
+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);
+ prime_cpu (cpu, max_insns);
+ }
+
+ 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);
+ }
+}