1 /* Model support.
2    Copyright (C) 1996-2024 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.
4 
5 This file is part of GDB, the GNU debugger.
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 /* This must come before any other includes.  */
21 #include "defs.h"
22 
23 #include "bfd.h"
24 #include "libiberty.h"
25 
26 #include "sim-main.h"
27 #include "sim-model.h"
28 #include "sim-options.h"
29 #include "sim-io.h"
30 #include "sim-assert.h"
31 
32 static void model_set (sim_cpu *, const SIM_MODEL *);
33 
34 static DECLARE_OPTION_HANDLER (model_option_handler);
35 
36 static MODULE_INIT_FN sim_model_init;
37 
38 enum {
39   OPTION_MODEL = OPTION_START,
40   OPTION_MODEL_INFO,
41 };
42 
43 static const OPTION model_options[] = {
44   { {"model", required_argument, NULL, OPTION_MODEL},
45       '\0', "MODEL", "Specify model to simulate",
46       model_option_handler, NULL },
47 
48   { {"model-info", no_argument, NULL, OPTION_MODEL_INFO},
49       '\0', NULL, "List selectable models",
50       model_option_handler, NULL },
51   { {"info-model", no_argument, NULL, OPTION_MODEL_INFO},
52       '\0', NULL, NULL,
53       model_option_handler, NULL },
54 
55   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
56 };
57 
58 static SIM_RC
model_option_handler(SIM_DESC sd,sim_cpu * cpu,int opt,char * arg,int is_command)59 model_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
60                           char *arg, int is_command)
61 {
62   switch (opt)
63     {
64     case OPTION_MODEL :
65       {
66           const SIM_MODEL *model = sim_model_lookup (sd, arg);
67           if (! model)
68             {
69               sim_io_eprintf (sd, "unknown model `%s'\n", arg);
70               return SIM_RC_FAIL;
71             }
72           STATE_MODEL_NAME (sd) = arg;
73           sim_model_set (sd, cpu, model);
74           break;
75       }
76 
77     case OPTION_MODEL_INFO :
78       {
79           const SIM_MACH * const *machp;
80           const SIM_MODEL *model;
81 
82           if (STATE_MACHS (sd) == NULL)
83             {
84               sim_io_printf (sd, "This target does not support any models\n");
85               return SIM_RC_FAIL;
86             }
87 
88           for (machp = STATE_MACHS(sd); *machp != NULL; ++machp)
89             {
90               sim_io_printf (sd, "Models for architecture `%s':\n",
91                                  MACH_NAME (*machp));
92               for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL;
93                      ++model)
94                 sim_io_printf (sd, " %s", MODEL_NAME (model));
95               sim_io_printf (sd, "\n");
96             }
97           break;
98       }
99     }
100 
101   return SIM_RC_OK;
102 }
103 
104 SIM_RC
sim_model_install(SIM_DESC sd)105 sim_model_install (SIM_DESC sd)
106 {
107   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
108 
109   sim_add_option_table (sd, NULL, model_options);
110   sim_module_add_init_fn (sd, sim_model_init);
111 
112   return SIM_RC_OK;
113 }
114 
115 /* Subroutine of sim_model_set to set the model for one cpu.  */
116 
117 static void
model_set(sim_cpu * cpu,const SIM_MODEL * model)118 model_set (sim_cpu *cpu, const SIM_MODEL *model)
119 {
120   CPU_MACH (cpu) = MODEL_MACH (model);
121   CPU_MODEL (cpu) = model;
122   (* MACH_INIT_CPU (MODEL_MACH (model))) (cpu);
123   (* MODEL_INIT (model)) (cpu);
124 }
125 
126 /* Set the current model of CPU to MODEL.
127    If CPU is NULL, all cpus are set to MODEL.  */
128 
129 void
sim_model_set(SIM_DESC sd,sim_cpu * cpu,const SIM_MODEL * model)130 sim_model_set (SIM_DESC sd, sim_cpu *cpu, const SIM_MODEL *model)
131 {
132   if (! cpu)
133     {
134       int c;
135 
136       for (c = 0; c < MAX_NR_PROCESSORS; ++c)
137           if (STATE_CPU (sd, c))
138             model_set (STATE_CPU (sd, c), model);
139     }
140   else
141     {
142       model_set (cpu, model);
143     }
144 }
145 
146 /* Look up model named NAME.
147    Result is pointer to MODEL entry or NULL if not found.  */
148 
149 const SIM_MODEL *
sim_model_lookup(SIM_DESC sd,const char * name)150 sim_model_lookup (SIM_DESC sd, const char *name)
151 {
152   const SIM_MACH * const *machp;
153   const SIM_MODEL *model;
154 
155   if (STATE_MACHS (sd) == NULL)
156     return NULL;
157 
158   for (machp = STATE_MACHS (sd); *machp != NULL; ++machp)
159     {
160       for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; ++model)
161           {
162             if (strcmp (MODEL_NAME (model), name) == 0)
163               return model;
164           }
165     }
166   return NULL;
167 }
168 
169 /* Look up machine named NAME.
170    Result is pointer to MACH entry or NULL if not found.  */
171 
172 const SIM_MACH *
sim_mach_lookup(SIM_DESC sd,const char * name)173 sim_mach_lookup (SIM_DESC sd, const char *name)
174 {
175   const SIM_MACH * const *machp;
176 
177   if (STATE_MACHS (sd) == NULL)
178     return NULL;
179 
180   for (machp = STATE_MACHS (sd); *machp != NULL; ++machp)
181     {
182       if (strcmp (MACH_NAME (*machp), name) == 0)
183           return *machp;
184     }
185   return NULL;
186 }
187 
188 /* Look up a machine via its bfd name.
189    Result is pointer to MACH entry or NULL if not found.  */
190 
191 const SIM_MACH *
sim_mach_lookup_bfd_name(SIM_DESC sd,const char * name)192 sim_mach_lookup_bfd_name (SIM_DESC sd, const char *name)
193 {
194   const SIM_MACH * const *machp;
195 
196   if (STATE_MACHS (sd) == NULL)
197     return NULL;
198 
199   for (machp = STATE_MACHS (sd); *machp != NULL; ++machp)
200     {
201       if (strcmp (MACH_BFD_NAME (*machp), name) == 0)
202           return *machp;
203     }
204   return NULL;
205 }
206 
207 /* Initialize model support.  */
208 
209 static SIM_RC
sim_model_init(SIM_DESC sd)210 sim_model_init (SIM_DESC sd)
211 {
212   SIM_CPU *cpu;
213 
214   /* If both cpu model and state architecture are set, ensure they're
215      compatible.  If only one is set, set the other.  If neither are set,
216      use the default model.  STATE_ARCHITECTURE is the bfd_arch_info data
217      for the selected "mach" (bfd terminology).  */
218 
219   /* Only check cpu 0.  STATE_ARCHITECTURE is for that one only.  */
220   /* ??? At present this only supports homogeneous multiprocessors.  */
221   cpu = STATE_CPU (sd, 0);
222 
223   if (! STATE_ARCHITECTURE (sd)
224       && ! CPU_MACH (cpu)
225       && STATE_MODEL_NAME (sd))
226     {
227       /* Set the default model.  */
228       const SIM_MODEL *model = sim_model_lookup (sd, STATE_MODEL_NAME (sd));
229       SIM_ASSERT (model != NULL);
230       sim_model_set (sd, NULL, model);
231     }
232 
233   if (STATE_ARCHITECTURE (sd)
234       && CPU_MACH (cpu))
235     {
236       if (strcmp (STATE_ARCHITECTURE (sd)->printable_name,
237                       MACH_BFD_NAME (CPU_MACH (cpu))) != 0)
238           {
239             sim_io_eprintf (sd, "invalid model `%s' for `%s'\n",
240                                 MODEL_NAME (CPU_MODEL (cpu)),
241                                 STATE_ARCHITECTURE (sd)->printable_name);
242             return SIM_RC_FAIL;
243           }
244     }
245   else if (STATE_ARCHITECTURE (sd) && STATE_MACHS (sd))
246     {
247       /* Use the default model for the selected machine.
248            The default model is the first one in the list.  */
249       const SIM_MACH *mach =
250           sim_mach_lookup_bfd_name (sd, STATE_ARCHITECTURE (sd)->printable_name);
251 
252       if (mach == NULL)
253           {
254             sim_io_eprintf (sd, "unsupported machine `%s'\n",
255                                 STATE_ARCHITECTURE (sd)->printable_name);
256             return SIM_RC_FAIL;
257           }
258       sim_model_set (sd, NULL, MACH_MODELS (mach));
259     }
260   else if (CPU_MACH (cpu))
261     {
262       STATE_ARCHITECTURE (sd) = bfd_scan_arch (MACH_BFD_NAME (CPU_MACH (cpu)));
263     }
264 
265   return SIM_RC_OK;
266 }
267