diff --git a/sim/common/.Sanitize b/sim/common/.Sanitize index 0b708c42f8..cc1af2266c 100644 --- a/sim/common/.Sanitize +++ b/sim/common/.Sanitize @@ -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 index 0000000000..d4e83b0273 --- /dev/null +++ b/sim/common/cgen-run.c @@ -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 index 0000000000..3f3dc41cd4 --- /dev/null +++ b/sim/common/sim-reg.c @@ -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); +}