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