xref: /netbsd-src/external/gpl3/gdb/dist/sim/example-synacor/interp.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
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
38    a single instruction.
39 
40    Usually you do not need to change things here.  */
41 
42 void
43 sim_engine_run (SIM_DESC sd,
44 		int next_cpu_nr, /* ignore  */
45 		int nr_cpus, /* ignore  */
46 		int siggnal) /* ignore  */
47 {
48   SIM_CPU *cpu;
49 
50   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
51 
52   cpu = STATE_CPU (sd, 0);
53 
54   while (1)
55     {
56       step_once (cpu);
57       if (sim_events_tick (sd))
58 	sim_events_process (sd);
59     }
60 }
61 
62 /* Initialize the simulator from scratch.  This is called once per lifetime of
63    the simulation.  Think of it as a processor reset.
64 
65    Usually all cpu-specific setup is handled in the initialize_cpu callback.
66    If you want to do cpu-independent stuff, then it should go at the end (see
67    where memory is initialized).  */
68 
69 #define DEFAULT_MEM_SIZE (16 * 1024 * 1024)
70 
71 static void
72 free_state (SIM_DESC sd)
73 {
74   if (STATE_MODULES (sd) != NULL)
75     sim_module_uninstall (sd);
76   sim_cpu_free_all (sd);
77   sim_state_free (sd);
78 }
79 
80 SIM_DESC
81 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
82 	  struct bfd *abfd, char * const *argv)
83 {
84   char c;
85   int i;
86   SIM_DESC sd = sim_state_alloc (kind, callback);
87 
88   /* Set default options before parsing user options.  */
89   current_alignment = STRICT_ALIGNMENT;
90   current_target_byte_order = BFD_ENDIAN_LITTLE;
91 
92   /* The cpu data is kept in a separately allocated chunk of memory.  */
93   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct example_sim_cpu))
94       != SIM_RC_OK)
95     {
96       free_state (sd);
97       return 0;
98     }
99 
100   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
101     {
102       free_state (sd);
103       return 0;
104     }
105 
106   /* XXX: Default to the Virtual environment.  */
107   if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
108     STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
109 
110   /* The parser will print an error message for us, so we silently return.  */
111   if (sim_parse_args (sd, argv) != SIM_RC_OK)
112     {
113       free_state (sd);
114       return 0;
115     }
116 
117   /* Check for/establish the a reference program image.  */
118   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
119     {
120       free_state (sd);
121       return 0;
122     }
123 
124   /* Establish any remaining configuration options.  */
125   if (sim_config (sd) != SIM_RC_OK)
126     {
127       free_state (sd);
128       return 0;
129     }
130 
131   if (sim_post_argv_init (sd) != SIM_RC_OK)
132     {
133       free_state (sd);
134       return 0;
135     }
136 
137   /* CPU specific initialization.  */
138   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
139     {
140       SIM_CPU *cpu = STATE_CPU (sd, i);
141 
142       initialize_cpu (sd, cpu);
143     }
144 
145   /* Allocate external memory if none specified by user.
146      Use address 4 here in case the user wanted address 0 unmapped.  */
147   if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
148     sim_do_commandf (sd, "memory-size %#x", DEFAULT_MEM_SIZE);
149 
150   return sd;
151 }
152 
153 /* Prepare to run a program that has already been loaded into memory.
154 
155    Usually you do not need to change things here.  */
156 
157 SIM_RC
158 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
159 		     char * const *argv, char * const *env)
160 {
161   SIM_CPU *cpu = STATE_CPU (sd, 0);
162   host_callback *cb = STATE_CALLBACK (sd);
163   sim_cia addr;
164 
165   /* Set the PC.  */
166   if (abfd != NULL)
167     addr = bfd_get_start_address (abfd);
168   else
169     addr = 0;
170   sim_pc_set (cpu, addr);
171 
172   /* Standalone mode (i.e. `run`) will take care of the argv for us in
173      sim_open() -> sim_parse_args().  But in debug mode (i.e. 'target sim'
174      with `gdb`), we need to handle it because the user can change the
175      argv on the fly via gdb's 'run'.  */
176   if (STATE_PROG_ARGV (sd) != argv)
177     {
178       freeargv (STATE_PROG_ARGV (sd));
179       STATE_PROG_ARGV (sd) = dupargv (argv);
180     }
181 
182   if (STATE_PROG_ENVP (sd) != env)
183     {
184       freeargv (STATE_PROG_ENVP (sd));
185       STATE_PROG_ENVP (sd) = dupargv (env);
186     }
187 
188   cb->argv = STATE_PROG_ARGV (sd);
189   cb->envp = STATE_PROG_ENVP (sd);
190 
191   return SIM_RC_OK;
192 }
193