xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/sim-model.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
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
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
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
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
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 *
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 *
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 *
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
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