From patchwork Mon Jan 4 10:32:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Frysinger X-Patchwork-Id: 10210 X-Patchwork-Delegate: vapier@gentoo.org Received: (qmail 31963 invoked by alias); 4 Jan 2016 10:32:52 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 31947 invoked by uid 89); 4 Jan 2016 10:32:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.4 required=5.0 tests=AWL, BAYES_50, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=164, 533, 535, fly X-HELO: smtp.gentoo.org Received: from smtp.gentoo.org (HELO smtp.gentoo.org) (140.211.166.183) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Mon, 04 Jan 2016 10:32:47 +0000 Received: from localhost.localdomain (localhost [127.0.0.1]) by smtp.gentoo.org (Postfix) with ESMTP id 4A97E34067D for ; Mon, 4 Jan 2016 10:32:45 +0000 (UTC) From: Mike Frysinger To: gdb-patches@sourceware.org Subject: [PATCH/RFC] sim: simarch: new runtime framework for target settings (for --enable-targets=all) Date: Mon, 4 Jan 2016 05:32:43 -0500 Message-Id: <1451903563-6188-1-git-send-email-vapier@gentoo.org> X-IsSubscribed: yes This takes a page from gdbarch's framework and brings it to the sim. Rather than setting up defaults via configure flags or having every port provide specific symbol names (e.g. sim_xxx), they define and register a simarch structure. The core code then matches that when it loads and uses that for defaults/further callbacks. This doesn't get us complete arch independence yet as we need to: - redo the build system - invert sim_state definition (e.g. STATE_ARCH_DATA) - invert sim_cpu definition (e.g. CPU_ARCH_DATA) But this gets us much closer and should allow for further unwinding. This isn't ready just yet for merging -- posting as RFC before I get too much further down this rabbit hole. --- sim/bfin/configure | 21 +---- sim/bfin/configure.ac | 3 +- sim/bfin/interp.c | 163 ++++++++++------------------------ sim/bfin/proc_list.def | 3 +- sim/bfin/sim-main.h | 3 + sim/common/Make-common.in | 3 + sim/common/sim-base.h | 8 +- sim/common/sim-config.c | 9 +- sim/common/sim-inferior.c | 64 ++++++++++++++ sim/common/sim-model.c | 216 +++++++++++++++++++++++++++++----------------- sim/common/sim-model.h | 13 ++- sim/common/sim-open.c | 95 ++++++++++++++++++++ sim/common/sim-resume.c | 5 +- sim/common/sim-simarch.c | 120 ++++++++++++++++++++++++++ sim/common/sim-simarch.h | 58 +++++++++++++ 15 files changed, 549 insertions(+), 235 deletions(-) create mode 100644 sim/common/sim-inferior.c create mode 100644 sim/common/sim-open.c create mode 100644 sim/common/sim-simarch.c create mode 100644 sim/common/sim-simarch.h diff --git a/sim/bfin/configure b/sim/bfin/configure index ae49198..10079c6 100755 --- a/sim/bfin/configure +++ b/sim/bfin/configure @@ -765,7 +765,6 @@ with_pkgversion with_bugurl enable_sim_endian enable_sim_alignment -enable_sim_default_model enable_sim_environment enable_sim_inline enable_werror @@ -1427,8 +1426,6 @@ Optional Features: --enable-sim-alignment=align Specify strict, nonstrict or forced alignment of memory accesses - --enable-sim-default-model=model - Specify default model to simulate --enable-sim-environment=environment Specify mixed, user, virtual or operating environment @@ -13132,7 +13129,7 @@ sim_link_links="${sim_link_links} targ-vals.def" -wire_endian="LITTLE" +wire_endian="" default_endian="" # Check whether --enable-sim-endian was given. if test "${enable_sim_endian+set}" = set; then : @@ -13223,22 +13220,6 @@ fi fi -default_sim_default_model="bf537" -# Check whether --enable-sim-default-model was given. -if test "${enable_sim_default_model+set}" = set; then : - enableval=$enable_sim_default_model; case "${enableval}" in - yes|no) as_fn_error "\"Missing argument to --enable-sim-default-model\"" "$LINENO" 5;; - *) sim_default_model="-DWITH_DEFAULT_MODEL='\"${enableval}\"'";; -esac -if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then - echo "Setting default model = $sim_default_model" 6>&1 -fi -else - sim_default_model="-DWITH_DEFAULT_MODEL='\"${default_sim_default_model}\"'" -fi - - - # Check whether --enable-sim-environment was given. if test "${enable_sim_environment+set}" = set; then : enableval=$enable_sim_environment; case "${enableval}" in diff --git a/sim/bfin/configure.ac b/sim/bfin/configure.ac index f0f7396..32598fb 100644 --- a/sim/bfin/configure.ac +++ b/sim/bfin/configure.ac @@ -5,9 +5,8 @@ sinclude(../common/acinclude.m4) SIM_AC_COMMON -SIM_AC_OPTION_ENDIAN(LITTLE) +SIM_AC_OPTION_ENDIAN SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT,STRICT_ALIGNMENT) -SIM_AC_OPTION_DEFAULT_MODEL(bf537) SIM_AC_OPTION_ENVIRONMENT SIM_AC_OPTION_INLINE SIM_AC_OPTION_WARNINGS diff --git a/sim/bfin/interp.c b/sim/bfin/interp.c index ad86500..effcdff 100644 --- a/sim/bfin/interp.c +++ b/sim/bfin/interp.c @@ -657,8 +657,8 @@ step_once (SIM_CPU *cpu) return oldpc; } -void -sim_engine_run (SIM_DESC sd, +static void +bfin_engine_run (SIM_DESC sd, int next_cpu_nr, /* ignore */ int nr_cpus, /* ignore */ int siggnal) /* ignore */ @@ -681,22 +681,11 @@ sim_engine_run (SIM_DESC sd, } } -/* Cover function of sim_state_free to free the cpu buffers as well. */ - static void -free_state (SIM_DESC sd) +bfin_cpu_init (SIM_CPU *cpu) { - if (STATE_MODULES (sd) != NULL) - sim_module_uninstall (sd); - sim_cpu_free_all (sd); - sim_state_free (sd); -} - -/* Create an instance of the simulator. */ + SIM_DESC sd = CPU_STATE (cpu); -static void -bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu) -{ memset (&cpu->state, 0, sizeof (cpu->state)); PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0; @@ -712,56 +701,20 @@ bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu) SET_SYSCFGREG (0x30); } -SIM_DESC -sim_open (SIM_OPEN_KIND kind, host_callback *callback, - struct bfd *abfd, char **argv) +static void +bfin_state_init (SIM_DESC sd) { char c; - int i; - SIM_DESC sd = sim_state_alloc (kind, callback); - - /* The cpu data is kept in a separately allocated chunk of memory. */ - if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK) - { - free_state (sd); - return 0; - } - { - /* XXX: Only first core gets profiled ? */ - SIM_CPU *cpu = STATE_CPU (sd, 0); - STATE_WATCHPOINTS (sd)->pc = &PCREG; - STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PCREG); - } - - if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) - { - free_state (sd); - return 0; - } + /* XXX: Only first core gets profiled ? */ + SIM_CPU *cpu = STATE_CPU (sd, 0); + STATE_WATCHPOINTS (sd)->pc = &PCREG; + STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PCREG); /* XXX: Default to the Virtual environment. */ if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT) STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT; - /* These options override any module options. - Obviously ambiguity should be avoided, however the caller may wish to - augment the meaning of an option. */ -#define e_sim_add_option_table(sd, options) \ - do { \ - extern const OPTION options[]; \ - sim_add_option_table (sd, NULL, options); \ - } while (0) - e_sim_add_option_table (sd, bfin_mmu_options); - e_sim_add_option_table (sd, bfin_mach_options); - - /* The parser will print an error message for us, so we silently return. */ - if (sim_parse_args (sd, argv) != SIM_RC_OK) - { - free_state (sd); - return 0; - } - /* Allocate external memory if none specified by user. Use address 4 here in case the user wanted address 0 unmapped. */ if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0) @@ -770,38 +723,6 @@ sim_open (SIM_OPEN_KIND kind, host_callback *callback, sim_do_commandf (sd, "memory-size 0x%lx", BFIN_DEFAULT_MEM_SIZE); sim_write (sd, 0, (void *)&emuexcpt, 2); } - - /* Check for/establish the a reference program image. */ - if (sim_analyze_program (sd, - (STATE_PROG_ARGV (sd) != NULL - ? *STATE_PROG_ARGV (sd) - : NULL), abfd) != SIM_RC_OK) - { - free_state (sd); - return 0; - } - - /* Establish any remaining configuration options. */ - if (sim_config (sd) != SIM_RC_OK) - { - free_state (sd); - return 0; - } - - if (sim_post_argv_init (sd) != SIM_RC_OK) - { - free_state (sd); - return 0; - } - - /* CPU specific initialization. */ - for (i = 0; i < MAX_NR_PROCESSORS; ++i) - { - SIM_CPU *cpu = STATE_CPU (sd, i); - bfin_initialize_cpu (sd, cpu); - } - - return sd; } /* Some utils don't like having a NULL environ. */ @@ -962,7 +883,7 @@ bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp, } static void -bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, +bfin_user_init (SIM_DESC sd, struct bfd *abfd, const char * const *argv, const char * const *env) { /* XXX: Missing host -> target endian ... */ @@ -998,6 +919,9 @@ bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, host_callback *cb = STATE_CALLBACK (sd); + /* We only set up the first CPU. The others are left unlocked. */ + SIM_CPU *cpu = STATE_CPU (sd, 0); + elf_addrs[0] = elf_addrs[4] = bfd_get_start_address (abfd); elf_addrs[1] = elf_addrs[2] = elf_addrs[3] = elf_addrs[5] = 0; @@ -1145,8 +1069,10 @@ bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, } static void -bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, const char * const *argv) +bfin_os_init (SIM_DESC sd, const char * const *argv) { + /* We only set up the first CPU. The others are left unlocked. */ + SIM_CPU *cpu = STATE_CPU (sd, 0); /* Pass the command line via a string in R0 like Linux expects. */ int i; bu8 byte; @@ -1172,7 +1098,7 @@ bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, const char * const *argv) } static void -bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu) +bfin_virtual_init (SIM_DESC sd) { host_callback *cb = STATE_CALLBACK (sd); @@ -1180,42 +1106,41 @@ bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu) stat_map_64 = NULL; } -SIM_RC -sim_create_inferior (SIM_DESC sd, struct bfd *abfd, - char **argv, char **env) +static void +bfin_inferior_init (SIM_DESC sd, struct bfd *abfd, + const char * const *argv, const char * const *envp) { - SIM_CPU *cpu = STATE_CPU (sd, 0); - SIM_ADDR addr; - - /* Set the PC. */ - if (abfd != NULL) - addr = bfd_get_start_address (abfd); - else - addr = 0; - sim_pc_set (cpu, addr); - - /* Standalone mode (i.e. `run`) will take care of the argv for us in - sim_open() -> sim_parse_args(). But in debug mode (i.e. 'target sim' - with `gdb`), we need to handle it because the user can change the - argv on the fly via gdb's 'run'. */ - if (STATE_PROG_ARGV (sd) != argv) - { - freeargv (STATE_PROG_ARGV (sd)); - STATE_PROG_ARGV (sd) = dupargv (argv); - } - switch (STATE_ENVIRONMENT (sd)) { case USER_ENVIRONMENT: - bfin_user_init (sd, cpu, abfd, (void *)argv, (void *)env); + bfin_user_init (sd, abfd, (void *)argv, (void *)envp); break; case OPERATING_ENVIRONMENT: - bfin_os_init (sd, cpu, (void *)argv); + bfin_os_init (sd, (void *)argv); break; default: - bfin_virtual_init (sd, cpu); + bfin_virtual_init (sd); break; } +} + +static const simarch bfin_simarch = +{ + .engine_run = bfin_engine_run, + .state_init = bfin_state_init, + .cpu_init = bfin_cpu_init, + .inferior_init = bfin_inferior_init, + .default_environment = VIRTUAL_ENVIRONMENT, + .default_endian = BFD_ENDIAN_LITTLE, + .default_alignment = STRICT_ALIGNMENT, + .default_model = "bf537", + .machs = sim_machs, +}; + +extern SIM_SIMARCH_REGISTER_FN sim_simarch_register_bfin; - return SIM_RC_OK; +SIM_RC +sim_simarch_register_bfin (void) +{ + return sim_simarch_register (bfd_arch_bfin, &bfin_simarch); } diff --git a/sim/bfin/proc_list.def b/sim/bfin/proc_list.def index 1fe73ff..a9bb67d 100644 --- a/sim/bfin/proc_list.def +++ b/sim/bfin/proc_list.def @@ -18,8 +18,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* First entry is the default model. */ -P(537) P(504) P(506) P(512) @@ -38,6 +36,7 @@ P(533) P(534) /*P(535)*/ P(536) +P(537) P(538) P(539) P(542) diff --git a/sim/bfin/sim-main.h b/sim/bfin/sim-main.h index 8804a71..65587d3 100644 --- a/sim/bfin/sim-main.h +++ b/sim/bfin/sim-main.h @@ -21,6 +21,9 @@ #ifndef _BFIN_MAIN_SIM_H_ #define _BFIN_MAIN_SIM_H_ +/* We want to use the new simarch logic. */ +#define WITH_SIMARCH 1 + #include "sim-basics.h" #include "sim-signal.h" diff --git a/sim/common/Make-common.in b/sim/common/Make-common.in index 6fdf10f..1ec468d 100644 --- a/sim/common/Make-common.in +++ b/sim/common/Make-common.in @@ -185,17 +185,20 @@ SIM_NEW_COMMON_OBJS = \ sim-fpu.o \ sim-hload.o \ sim-hrw.o \ + sim-inferior.o \ sim-io.o \ sim-info.o \ sim-load.o \ sim-memopt.o \ sim-model.o \ sim-module.o \ + sim-open.o \ sim-options.o \ sim-profile.o \ sim-reason.o \ sim-reg.o \ sim-signal.o \ + sim-simarch.o \ sim-stop.o \ sim-syscall.o \ sim-trace.o \ diff --git a/sim/common/sim-base.h b/sim/common/sim-base.h index 350b352..9d51dbf 100644 --- a/sim/common/sim-base.h +++ b/sim/common/sim-base.h @@ -78,6 +78,7 @@ typedef struct _sim_cpu sim_cpu; #include "sim-module.h" +#include "sim-simarch.h" #include "sim-trace.h" #include "sim-core.h" #include "sim-events.h" @@ -113,6 +114,10 @@ typedef struct { struct host_callback_struct *callback; #define STATE_CALLBACK(sd) ((sd)->base.callback) + /* Target specific data. */ + const simarch *simarch; +#define STATE_SIMARCH(sd) ((sd)->base.simarch) + /* The type of simulation environment (user/operating). */ enum sim_environment environment; #define STATE_ENVIRONMENT(sd) ((sd)->base.environment) @@ -147,8 +152,7 @@ typedef struct { const char *target; #define STATE_TARGET(sd) ((sd)->base.target) - /* In standalone simulator, this is the program's arguments passed - on the command line. */ + /* The program's arguments passed on the command line. */ char **prog_argv; #define STATE_PROG_ARGV(sd) ((sd)->base.prog_argv) diff --git a/sim/common/sim-config.c b/sim/common/sim-config.c index d9036e1..60c6efc 100644 --- a/sim/common/sim-config.c +++ b/sim/common/sim-config.c @@ -169,6 +169,8 @@ sim_config (SIM_DESC sd) current_target_byte_order = WITH_TARGET_BYTE_ORDER; if (current_target_byte_order == BFD_ENDIAN_UNKNOWN) current_target_byte_order = WITH_DEFAULT_TARGET_BYTE_ORDER; + if (current_target_byte_order == BFD_ENDIAN_UNKNOWN && WITH_SIMARCH) + current_target_byte_order = STATE_SIMARCH (sd)->default_endian; /* verify the target byte order */ if (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_UNKNOWN) @@ -237,8 +239,9 @@ sim_config (SIM_DESC sd) } #endif if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT) - STATE_ENVIRONMENT (sd) = DEFAULT_ENVIRONMENT; - + STATE_ENVIRONMENT (sd) = + WITH_SIMARCH ? STATE_SIMARCH (sd)->default_environment + : DEFAULT_ENVIRONMENT; /* set the alignment */ #if (WITH_TREE_PROPERTIES) @@ -252,6 +255,8 @@ sim_config (SIM_DESC sd) current_alignment = WITH_ALIGNMENT; if (current_alignment == 0) current_alignment = WITH_DEFAULT_ALIGNMENT; + if (current_alignment == 0 && WITH_SIMARCH) + current_alignment = STATE_SIMARCH (sd)->default_alignment; /* verify the alignment */ if (CURRENT_ALIGNMENT == 0) diff --git a/sim/common/sim-inferior.c b/sim/common/sim-inferior.c new file mode 100644 index 0000000..d9f601c --- /dev/null +++ b/sim/common/sim-inferior.c @@ -0,0 +1,64 @@ +/* Miscellaneous simulator utilities. + + Copyright (C) 2005-2015 Free Software Foundation, Inc. + Contributed by Analog Devices, Inc. and Stephane Carrez. + + This file is part of simulators. + + 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 3 of the License, 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, see . */ + +#include "sim-main.h" +#include "gdb/remote-sim.h" + +#if WITH_SIMARCH + +SIM_RC +sim_create_inferior (SIM_DESC sd, struct bfd *abfd, + char **argv, char **envp) +{ + size_t i; + sim_cia pc; + const simarch *simarch; + + /* Set the PC. */ + if (abfd != NULL) + pc = bfd_get_start_address (abfd); + else + pc = 0; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); + + sim_pc_set (cpu, pc); + } + + /* Standalone mode (i.e. `run`) will take care of the argv for us in + sim_open() -> sim_parse_args(). But in debug mode (i.e. 'target sim' + with `gdb`), we need to handle it because the user can change the + argv on the fly via gdb's 'run'. */ + if (STATE_PROG_ARGV (sd) != argv) + { + freeargv (STATE_PROG_ARGV (sd)); + STATE_PROG_ARGV (sd) = dupargv (argv); + } + + simarch = STATE_SIMARCH (sd); + if (simarch->inferior_init) + simarch->inferior_init (sd, abfd, (void *)argv, (void *)envp); + + return SIM_RC_OK; +} + +#endif diff --git a/sim/common/sim-model.c b/sim/common/sim-model.c index 80c2d6c..84e140a 100644 --- a/sim/common/sim-model.c +++ b/sim/common/sim-model.c @@ -25,79 +25,39 @@ along with this program. If not, see . */ #include "sim-assert.h" #include "bfd.h" -static void model_set (sim_cpu *, const SIM_MODEL *); +#define MODEL_ACTION_LIST (void *)-1 -static DECLARE_OPTION_HANDLER (model_option_handler); +/* Find where the list of models are maintained. */ -static MODULE_INIT_FN sim_model_init; - -enum { - OPTION_MODEL = OPTION_START, - OPTION_MODEL_INFO, -}; - -static const OPTION model_options[] = { - { {"model", required_argument, NULL, OPTION_MODEL}, - '\0', "MODEL", "Specify model to simulate", - model_option_handler, NULL }, - - { {"model-info", no_argument, NULL, OPTION_MODEL_INFO}, - '\0', NULL, "List selectable models", - model_option_handler, NULL }, - { {"info-model", no_argument, NULL, OPTION_MODEL_INFO}, - '\0', NULL, NULL, - model_option_handler, NULL }, - - { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } -}; - -static SIM_RC -model_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, - char *arg, int is_command) +static const SIM_MACH ** +sim_model_machs (SIM_DESC sd) { - switch (opt) - { - case OPTION_MODEL : - { - const SIM_MODEL *model = sim_model_lookup (arg); - if (! model) - { - sim_io_eprintf (sd, "unknown model `%s'\n", arg); - return SIM_RC_FAIL; - } - sim_model_set (sd, cpu, model); - break; - } - - case OPTION_MODEL_INFO : - { - const SIM_MACH **machp; - const SIM_MODEL *model; - for (machp = & sim_machs[0]; *machp != NULL; ++machp) - { - sim_io_printf (sd, "Models for architecture `%s':\n", - MACH_NAME (*machp)); - for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; - ++model) - sim_io_printf (sd, " %s", MODEL_NAME (model)); - sim_io_printf (sd, "\n"); - } - break; - } - } - - return SIM_RC_OK; +#if WITH_SIMARCH + return STATE_SIMARCH (sd)->machs; +#else +# if !WITH_MODEL_P + /* Set up basic model support. This is a stub for ports that do not define + models. See sim-model.h for more details. */ + static const SIM_MACH *sim_machs[] = { NULL }; +# endif + return &sim_machs[0]; +#endif } -SIM_RC -sim_model_install (SIM_DESC sd) +static void +model_list (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); + const SIM_MACH **machp; + const SIM_MODEL *model; - return SIM_RC_OK; + for (machp = sim_model_machs (sd); *machp != NULL; ++machp) + { + sim_io_printf (sd, "Models for architecture `%s':\n", + MACH_NAME (*machp)); + for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; ++model) + sim_io_printf (sd, " %s", MODEL_NAME (model)); + sim_io_printf (sd, "\n"); + } } /* Subroutine of sim_model_set to set the model for one cpu. */ @@ -135,12 +95,12 @@ sim_model_set (SIM_DESC sd, sim_cpu *cpu, const SIM_MODEL *model) Result is pointer to MODEL entry or NULL if not found. */ const SIM_MODEL * -sim_model_lookup (const char *name) +sim_model_lookup (SIM_DESC sd, const char *name) { const SIM_MACH **machp; const SIM_MODEL *model; - for (machp = & sim_machs[0]; *machp != NULL; ++machp) + for (machp = sim_model_machs (sd); *machp != NULL; ++machp) { for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; ++model) { @@ -151,15 +111,30 @@ sim_model_lookup (const char *name) return NULL; } +static SIM_RC +model_set_name (SIM_DESC sd, sim_cpu *cpu, const char *name) +{ + const SIM_MODEL *model = sim_model_lookup (sd, name); + + if (model == NULL) + { + sim_io_eprintf (sd, "unknown model `%s'\n", name); + return SIM_RC_FAIL; + } + + sim_model_set (sd, cpu, model); + return SIM_RC_OK; +} + /* Look up machine named NAME. Result is pointer to MACH entry or NULL if not found. */ const SIM_MACH * -sim_mach_lookup (const char *name) +sim_mach_lookup (SIM_DESC sd, const char *name) { const SIM_MACH **machp; - for (machp = & sim_machs[0]; *machp != NULL; ++machp) + for (machp = sim_model_machs (sd); *machp != NULL; ++machp) { if (strcmp (MACH_NAME (*machp), name) == 0) return *machp; @@ -171,11 +146,11 @@ sim_mach_lookup (const char *name) Result is pointer to MACH entry or NULL if not found. */ const SIM_MACH * -sim_mach_lookup_bfd_name (const char *name) +sim_mach_lookup_bfd_name (SIM_DESC sd, const char *name) { const SIM_MACH **machp; - for (machp = & sim_machs[0]; *machp != NULL; ++machp) + for (machp = sim_model_machs (sd); *machp != NULL; ++machp) { if (strcmp (MACH_BFD_NAME (*machp), name) == 0) return *machp; @@ -202,11 +177,26 @@ sim_model_init (SIM_DESC sd) /* ??? At present this only supports homogeneous multiprocessors. */ cpu = STATE_CPU (sd, 0); + /* Process any actions requested by the command line. */ + if (CPU_MODEL_DATA (cpu) == MODEL_ACTION_LIST) + model_list (sd); + else if (CPU_MODEL_DATA (cpu) != NULL) + { + const char *model_name = CPU_MODEL_DATA (cpu); + + if (model_set_name (sd, cpu, model_name) != SIM_RC_OK) + return SIM_RC_FAIL; + } + CPU_MODEL_DATA (cpu) = NULL; + if (! STATE_ARCHITECTURE (sd) && ! CPU_MACH (cpu)) { +#if WITH_SIMARCH +# define WITH_DEFAULT_MODEL STATE_SIMARCH (sd)->default_model +#endif /* Set the default model. */ - const SIM_MODEL *model = sim_model_lookup (WITH_DEFAULT_MODEL); + const SIM_MODEL *model = sim_model_lookup (sd, WITH_DEFAULT_MODEL); SIM_ASSERT (model != NULL); sim_model_set (sd, NULL, model); } @@ -227,7 +217,7 @@ sim_model_init (SIM_DESC sd) { /* Use the default model for the selected machine. The default model is the first one in the list. */ - const SIM_MACH *mach = sim_mach_lookup_bfd_name (STATE_ARCHITECTURE (sd)->printable_name); + const SIM_MACH *mach = sim_mach_lookup_bfd_name (sd, STATE_ARCHITECTURE (sd)->printable_name); if (mach == NULL) { @@ -245,11 +235,77 @@ sim_model_init (SIM_DESC sd) return SIM_RC_OK; } -#if !WITH_MODEL_P -/* Set up basic model support. This is a stub for ports that do not define - models. See sim-model.h for more details. */ -const SIM_MACH *sim_machs[] = +/* We need to delay actions from option parsing to the init phase. + This way we can load the simarch properly which provides models. */ +static void +model_queue_action (SIM_DESC sd, sim_cpu *cpu, void *act) { - NULL + if (cpu == NULL) + { + size_t c; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + cpu = STATE_CPU (sd, c); + if (cpu) + CPU_MODEL_DATA (cpu) = act; + } + } + else + CPU_MODEL_DATA (cpu) = act; +} + +enum { + OPTION_MODEL = OPTION_START, + OPTION_MODEL_INFO, }; -#endif + +static SIM_RC +model_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + switch (opt) + { + case OPTION_MODEL : + if (STATE_SIMARCH (sd)) + return model_set_name (sd, cpu, arg); + else + model_queue_action (sd, cpu, arg); + break; + + case OPTION_MODEL_INFO : + if (STATE_SIMARCH (sd)) + model_list (sd); + else + model_queue_action (sd, cpu, MODEL_ACTION_LIST); + break; + } + + return SIM_RC_OK; +} + +static const OPTION model_options[] = { + { {"model", required_argument, NULL, OPTION_MODEL}, + '\0', "MODEL", "Specify model to simulate", + model_option_handler, NULL }, + + { {"model-info", no_argument, NULL, OPTION_MODEL_INFO}, + '\0', NULL, "List selectable models", + model_option_handler, NULL }, + { {"info-model", no_argument, NULL, OPTION_MODEL_INFO}, + '\0', NULL, NULL, + model_option_handler, NULL }, + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } +}; + +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; +} diff --git a/sim/common/sim-model.h b/sim/common/sim-model.h index 534e720..939f83f 100644 --- a/sim/common/sim-model.h +++ b/sim/common/sim-model.h @@ -47,9 +47,8 @@ typedef struct { #define MAX_UNITS 1 #endif -#ifndef WITH_DEFAULT_MODEL +#if !defined(WITH_DEFAULT_MODEL) && !WITH_SIMARCH /* Just a stub for ports that do not define models. */ -enum mach_attr { _MACH_NONE }; # define WITH_DEFAULT_MODEL NULL # define WITH_MODEL_P 0 #else @@ -86,13 +85,13 @@ typedef struct { /* A machine variant. */ -typedef struct { +typedef struct sim_mach { 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) - enum mach_attr num; + int num; #define MACH_NUM(m) ((m)->num) int word_bitsize; @@ -147,8 +146,8 @@ extern MODULE_INSTALL_FN sim_model_install; /* Support routines. */ extern void sim_model_set (SIM_DESC sd_, sim_cpu *cpu_, const SIM_MODEL *model_); -extern const SIM_MODEL *sim_model_lookup (const char *name_); -extern const SIM_MACH *sim_mach_lookup (const char *name_); -extern const SIM_MACH *sim_mach_lookup_bfd_name (const char *bfd_name_); +extern const SIM_MODEL *sim_model_lookup (SIM_DESC, const char *name_); +extern const SIM_MACH *sim_mach_lookup (SIM_DESC, const char *name_); +extern const SIM_MACH *sim_mach_lookup_bfd_name (SIM_DESC, const char *bfd_name_); #endif /* SIM_MODEL_H */ diff --git a/sim/common/sim-open.c b/sim/common/sim-open.c new file mode 100644 index 0000000..73d2401 --- /dev/null +++ b/sim/common/sim-open.c @@ -0,0 +1,95 @@ +/* Create a fully initialized simulator instance. + + Copyright (C) 2005-2016 Free Software Foundation, Inc. + Contributed by Analog Devices, Inc. + + This file is part of simulators. + + 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 3 of the License, 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, see . */ + +#include "sim-main.h" +#include "gdb/remote-sim.h" + +#if WITH_SIMARCH + +#ifndef CGEN_ARCH +# define cgen_cpu_max_extra_bytes() 0 +# define cgen_init(sd) +#endif + +SIM_DESC +sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv) +{ + SIM_DESC sd = sim_state_alloc (kind, cb); + const simarch *simarch; + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* The cpu data is kept in a separately allocated chunk of memory. */ + if (sim_cpu_alloc_all (sd, MAX_NR_PROCESSORS, cgen_cpu_max_extra_bytes ()) + != SIM_RC_OK) + goto error_cpu_alloc; + + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) + goto error_argv_init; + + /* The parser will print an error message for us, so we silently return. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) + goto error; + + /* Check for/establish the reference program image. */ + if (sim_analyze_program (sd, (STATE_PROG_ARGV (sd) != NULL + ? *STATE_PROG_ARGV (sd) : NULL), + abfd) != SIM_RC_OK) + goto error; + + /* With an appropriate prog bfd loaded, try to detect the right sim. */ + if (sim_simarch_lookup (sd) != SIM_RC_OK) + goto error; + simarch = STATE_SIMARCH (sd); + + /* Establish any remaining configuration options. */ + if (sim_config (sd) != SIM_RC_OK) + goto error; + + if (sim_post_argv_init (sd) != SIM_RC_OK) + goto error; + + /* Port specific state finalization. */ + if (simarch->state_init) + simarch->state_init (sd); + + /* Initialize various cgen things not done by common framework. */ + cgen_init (sd); + + /* CPU specific initialization. */ + if (simarch->cpu_init) + { + size_t i; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + simarch->cpu_init (STATE_CPU (sd, i)); + } + + return sd; + + error: + sim_module_uninstall (sd); + error_argv_init: + sim_cpu_free_all (sd); + error_cpu_alloc: + sim_state_free (sd); + return NULL; +} + +#endif diff --git a/sim/common/sim-resume.c b/sim/common/sim-resume.c index e9ec9c9..40ccb4d 100644 --- a/sim/common/sim-resume.c +++ b/sim/common/sim-resume.c @@ -86,7 +86,10 @@ sim_resume (SIM_DESC sd, } #endif - sim_engine_run (sd, next_cpu_nr, nr_cpus, sig_to_deliver); + if (WITH_SIMARCH) + STATE_SIMARCH (sd)->engine_run (sd, next_cpu_nr, nr_cpus, sig_to_deliver); + else + sim_engine_run (sd, next_cpu_nr, nr_cpus, sig_to_deliver); } engine->jmpbuf = NULL; diff --git a/sim/common/sim-simarch.c b/sim/common/sim-simarch.c new file mode 100644 index 0000000..d51a583 --- /dev/null +++ b/sim/common/sim-simarch.c @@ -0,0 +1,120 @@ +/* Simulator arch ops for support multiple targets in a single build. + + Copyright (C) 2016 Free Software Foundation, Inc. + Contributed by Mike Frysinger. + + This file is part of simulators. + + 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 3 of the License, 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, see . */ + +#include "sim-main.h" + +/* Keep a registry of the architectures known by the sim. */ + +struct simarch_registration +{ + const struct bfd_arch_info *bfd_arch_info; + const struct simarch *simarch; +}; + +static size_t registered_count; +static struct simarch_registration **simarch_registery; + +SIM_RC +sim_simarch_register (enum bfd_architecture bfd_architecture, + const struct simarch *simarch) +{ + size_t i; + struct simarch_registration *reg; + const struct bfd_arch_info *bfd_arch_info; + + bfd_arch_info = bfd_lookup_arch (bfd_architecture, 0); + if (bfd_arch_info == NULL) + return SIM_RC_FAIL; + + i = registered_count++; + simarch_registery = XRESIZEVEC (struct simarch_registration *, + simarch_registery, registered_count); + reg = simarch_registery[i] = xmalloc (sizeof (*reg)); + reg->bfd_arch_info = bfd_arch_info; + reg->simarch = simarch; + + + return SIM_RC_OK; +} + +static const struct simarch * +simarch_lookup (const struct bfd_arch_info *architecture) +{ + struct simarch_registration *reg; + size_t i; + + for (i = 0; i < registered_count; ++i) + { + reg = simarch_registery[i]; + if (architecture == reg->bfd_arch_info) + return reg->simarch; + } + + return NULL; +} + +SIM_RC +sim_simarch_lookup (SIM_DESC sd) +{ + const struct simarch *simarch = NULL; + const struct bfd_arch_info *architecture; + struct bfd *abfd; + const char **list, **lp; + +extern SIM_SIMARCH_REGISTER_FN sim_simarch_register_bfin; +sim_simarch_register_bfin (); + + /* The prog bfd has been set, use it. */ + abfd = STATE_PROG_BFD (sd); + if (abfd != NULL) + { + simarch = simarch_lookup (bfd_get_arch_info (abfd)); + goto done; + } + + /* If the state arch has been set, use it. */ + architecture = STATE_ARCHITECTURE (sd); + if (architecture != NULL) + { + simarch = simarch_lookup (STATE_ARCHITECTURE (sd)); + goto done; + } + + /* Scan all available bfds and blindly use the first one that matches. */ + list = bfd_arch_list (); + if (list != NULL) + { + for (lp = list; *lp != NULL; lp++) + { + architecture = bfd_scan_arch (*lp); + if (architecture == NULL) + continue; + + simarch = simarch_lookup (architecture); + if (simarch) + break; + } + free (list); + } + + done: + STATE_SIMARCH (sd) = simarch; + return simarch ? SIM_RC_OK : SIM_RC_FAIL; +} diff --git a/sim/common/sim-simarch.h b/sim/common/sim-simarch.h new file mode 100644 index 0000000..d0de77e --- /dev/null +++ b/sim/common/sim-simarch.h @@ -0,0 +1,58 @@ +/* Simulator arch ops for support multiple targets in a single build. + + Copyright (C) 2016 Free Software Foundation, Inc. + Contributed by Mike Frysinger. + + This file is part of simulators. + + 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 3 of the License, 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, see . */ + +#ifndef SIM_SIMARCH_H +#define SIM_SIMARCH_H + +/* Not all targets have been converted yet. */ +#ifndef WITH_SIMARCH +#define WITH_SIMARCH 0 +#endif + +typedef SIM_RC (SIM_SIMARCH_REGISTER_FN) (void); + +struct sim_mach; + +typedef struct simarch +{ + /* Runtime callbacks. */ + void (*engine_run) (SIM_DESC, int, int, int); + + /* Init callbacks. */ + void (*state_init) (SIM_DESC); + void (*cpu_init) (SIM_CPU *); + void (*inferior_init) (SIM_DESC, struct bfd *, + const char * const *argv, const char * const *envp); + + /* Arch settings. */ + enum sim_environment default_environment; + enum bfd_endian default_endian; + enum sim_alignments default_alignment; + + const char *default_model; + const struct sim_mach **machs; +} simarch; + +SIM_RC sim_simarch_register (enum bfd_architecture bfd_architecture, + const simarch *simarch); + +SIM_RC sim_simarch_lookup (SIM_DESC); + +#endif /* SIM_SIMARCH_H */