Home | History | Annotate | Line # | Download | only in example-synacor
      1 /* Example synacor simulator.
      2 
      3    Copyright (C) 2005-2024 Free Software Foundation, Inc.
      4    Contributed by Mike Frysinger.
      5 
      6    This file is part of simulators.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20 
     21 /* This file contains the main glue logic between the sim core and the target
     22    specific simulator.  Normally this file will be kept small and the target
     23    details will live in other files.
     24 
     25    For more specific details on these functions, see the sim/sim.h header
     26    file.  */
     27 
     28 /* This must come before any other includes.  */
     29 #include "defs.h"
     30 
     31 #include "sim/callback.h"
     32 #include "sim-main.h"
     33 #include "sim-options.h"
     34 
     35 #include "example-synacor-sim.h"
     36 
     37 /* This function is the main loop.  It should process ticks and decode+execute
     39    a single instruction.
     40 
     41    Usually you do not need to change things here.  */
     42 
     43 void
     44 sim_engine_run (SIM_DESC sd,
     45 		int next_cpu_nr, /* ignore  */
     46 		int nr_cpus, /* ignore  */
     47 		int siggnal) /* ignore  */
     48 {
     49   SIM_CPU *cpu;
     50 
     51   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
     52 
     53   cpu = STATE_CPU (sd, 0);
     54 
     55   while (1)
     56     {
     57       step_once (cpu);
     58       if (sim_events_tick (sd))
     59 	sim_events_process (sd);
     60     }
     61 }
     62 
     63 /* Initialize the simulator from scratch.  This is called once per lifetime of
     65    the simulation.  Think of it as a processor reset.
     66 
     67    Usually all cpu-specific setup is handled in the initialize_cpu callback.
     68    If you want to do cpu-independent stuff, then it should go at the end (see
     69    where memory is initialized).  */
     70 
     71 #define DEFAULT_MEM_SIZE (16 * 1024 * 1024)
     72 
     73 static void
     74 free_state (SIM_DESC sd)
     75 {
     76   if (STATE_MODULES (sd) != NULL)
     77     sim_module_uninstall (sd);
     78   sim_cpu_free_all (sd);
     79   sim_state_free (sd);
     80 }
     81 
     82 SIM_DESC
     83 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
     84 	  struct bfd *abfd, char * const *argv)
     85 {
     86   char c;
     87   int i;
     88   SIM_DESC sd = sim_state_alloc (kind, callback);
     89 
     90   /* Set default options before parsing user options.  */
     91   current_alignment = STRICT_ALIGNMENT;
     92   current_target_byte_order = BFD_ENDIAN_LITTLE;
     93 
     94   /* The cpu data is kept in a separately allocated chunk of memory.  */
     95   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct example_sim_cpu))
     96       != SIM_RC_OK)
     97     {
     98       free_state (sd);
     99       return 0;
    100     }
    101 
    102   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
    103     {
    104       free_state (sd);
    105       return 0;
    106     }
    107 
    108   /* XXX: Default to the Virtual environment.  */
    109   if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
    110     STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
    111 
    112   /* The parser will print an error message for us, so we silently return.  */
    113   if (sim_parse_args (sd, argv) != SIM_RC_OK)
    114     {
    115       free_state (sd);
    116       return 0;
    117     }
    118 
    119   /* Check for/establish the a reference program image.  */
    120   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
    121     {
    122       free_state (sd);
    123       return 0;
    124     }
    125 
    126   /* Establish any remaining configuration options.  */
    127   if (sim_config (sd) != SIM_RC_OK)
    128     {
    129       free_state (sd);
    130       return 0;
    131     }
    132 
    133   if (sim_post_argv_init (sd) != SIM_RC_OK)
    134     {
    135       free_state (sd);
    136       return 0;
    137     }
    138 
    139   /* CPU specific initialization.  */
    140   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
    141     {
    142       SIM_CPU *cpu = STATE_CPU (sd, i);
    143 
    144       initialize_cpu (sd, cpu);
    145     }
    146 
    147   /* Allocate external memory if none specified by user.
    148      Use address 4 here in case the user wanted address 0 unmapped.  */
    149   if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
    150     sim_do_commandf (sd, "memory-size %#x", DEFAULT_MEM_SIZE);
    151 
    152   return sd;
    153 }
    154 
    155 /* Prepare to run a program that has already been loaded into memory.
    157 
    158    Usually you do not need to change things here.  */
    159 
    160 SIM_RC
    161 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
    162 		     char * const *argv, char * const *env)
    163 {
    164   SIM_CPU *cpu = STATE_CPU (sd, 0);
    165   host_callback *cb = STATE_CALLBACK (sd);
    166   sim_cia addr;
    167 
    168   /* Set the PC.  */
    169   if (abfd != NULL)
    170     addr = bfd_get_start_address (abfd);
    171   else
    172     addr = 0;
    173   sim_pc_set (cpu, addr);
    174 
    175   /* Standalone mode (i.e. `run`) will take care of the argv for us in
    176      sim_open() -> sim_parse_args().  But in debug mode (i.e. 'target sim'
    177      with `gdb`), we need to handle it because the user can change the
    178      argv on the fly via gdb's 'run'.  */
    179   if (STATE_PROG_ARGV (sd) != argv)
    180     {
    181       freeargv (STATE_PROG_ARGV (sd));
    182       STATE_PROG_ARGV (sd) = dupargv (argv);
    183     }
    184 
    185   if (STATE_PROG_ENVP (sd) != env)
    186     {
    187       freeargv (STATE_PROG_ENVP (sd));
    188       STATE_PROG_ENVP (sd) = dupargv (env);
    189     }
    190 
    191   cb->argv = STATE_PROG_ARGV (sd);
    192   cb->envp = STATE_PROG_ENVP (sd);
    193 
    194   return SIM_RC_OK;
    195 }
    196