1 /* Model support. 2 Copyright (C) 1996-2020 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 #include "sim-main.h" 21 #include "sim-model.h" 22 #include "libiberty.h" 23 #include "sim-options.h" 24 #include "sim-io.h" 25 #include "sim-assert.h" 26 #include "bfd.h" 27 28 static void model_set (sim_cpu *, const SIM_MODEL *); 29 30 static DECLARE_OPTION_HANDLER (model_option_handler); 31 32 static MODULE_INIT_FN sim_model_init; 33 34 enum { 35 OPTION_MODEL = OPTION_START, 36 OPTION_MODEL_INFO, 37 }; 38 39 static const OPTION model_options[] = { 40 { {"model", required_argument, NULL, OPTION_MODEL}, 41 '\0', "MODEL", "Specify model to simulate", 42 model_option_handler, NULL }, 43 44 { {"model-info", no_argument, NULL, OPTION_MODEL_INFO}, 45 '\0', NULL, "List selectable models", 46 model_option_handler, NULL }, 47 { {"info-model", no_argument, NULL, OPTION_MODEL_INFO}, 48 '\0', NULL, NULL, 49 model_option_handler, NULL }, 50 51 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } 52 }; 53 54 static SIM_RC 55 model_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, 56 char *arg, int is_command) 57 { 58 switch (opt) 59 { 60 case OPTION_MODEL : 61 { 62 const SIM_MODEL *model = sim_model_lookup (arg); 63 if (! model) 64 { 65 sim_io_eprintf (sd, "unknown model `%s'\n", arg); 66 return SIM_RC_FAIL; 67 } 68 sim_model_set (sd, cpu, model); 69 break; 70 } 71 72 case OPTION_MODEL_INFO : 73 { 74 const SIM_MACH **machp; 75 const SIM_MODEL *model; 76 for (machp = & sim_machs[0]; *machp != NULL; ++machp) 77 { 78 sim_io_printf (sd, "Models for architecture `%s':\n", 79 MACH_NAME (*machp)); 80 for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; 81 ++model) 82 sim_io_printf (sd, " %s", MODEL_NAME (model)); 83 sim_io_printf (sd, "\n"); 84 } 85 break; 86 } 87 } 88 89 return SIM_RC_OK; 90 } 91 92 SIM_RC 93 sim_model_install (SIM_DESC sd) 94 { 95 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 96 97 sim_add_option_table (sd, NULL, model_options); 98 sim_module_add_init_fn (sd, sim_model_init); 99 100 return SIM_RC_OK; 101 } 102 103 /* Subroutine of sim_model_set to set the model for one cpu. */ 104 105 static void 106 model_set (sim_cpu *cpu, const SIM_MODEL *model) 107 { 108 CPU_MACH (cpu) = MODEL_MACH (model); 109 CPU_MODEL (cpu) = model; 110 (* MACH_INIT_CPU (MODEL_MACH (model))) (cpu); 111 (* MODEL_INIT (model)) (cpu); 112 } 113 114 /* Set the current model of CPU to MODEL. 115 If CPU is NULL, all cpus are set to MODEL. */ 116 117 void 118 sim_model_set (SIM_DESC sd, sim_cpu *cpu, const SIM_MODEL *model) 119 { 120 if (! cpu) 121 { 122 int c; 123 124 for (c = 0; c < MAX_NR_PROCESSORS; ++c) 125 if (STATE_CPU (sd, c)) 126 model_set (STATE_CPU (sd, c), model); 127 } 128 else 129 { 130 model_set (cpu, model); 131 } 132 } 133 134 /* Look up model named NAME. 135 Result is pointer to MODEL entry or NULL if not found. */ 136 137 const SIM_MODEL * 138 sim_model_lookup (const char *name) 139 { 140 const SIM_MACH **machp; 141 const SIM_MODEL *model; 142 143 for (machp = & sim_machs[0]; *machp != NULL; ++machp) 144 { 145 for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; ++model) 146 { 147 if (strcmp (MODEL_NAME (model), name) == 0) 148 return model; 149 } 150 } 151 return NULL; 152 } 153 154 /* Look up machine named NAME. 155 Result is pointer to MACH entry or NULL if not found. */ 156 157 const SIM_MACH * 158 sim_mach_lookup (const char *name) 159 { 160 const SIM_MACH **machp; 161 162 for (machp = & sim_machs[0]; *machp != NULL; ++machp) 163 { 164 if (strcmp (MACH_NAME (*machp), name) == 0) 165 return *machp; 166 } 167 return NULL; 168 } 169 170 /* Look up a machine via its bfd name. 171 Result is pointer to MACH entry or NULL if not found. */ 172 173 const SIM_MACH * 174 sim_mach_lookup_bfd_name (const char *name) 175 { 176 const SIM_MACH **machp; 177 178 for (machp = & sim_machs[0]; *machp != NULL; ++machp) 179 { 180 if (strcmp (MACH_BFD_NAME (*machp), name) == 0) 181 return *machp; 182 } 183 return NULL; 184 } 185 186 /* Initialize model support. */ 187 188 static SIM_RC 189 sim_model_init (SIM_DESC sd) 190 { 191 SIM_CPU *cpu; 192 193 if (!WITH_MODEL_P) 194 return SIM_RC_OK; 195 196 /* If both cpu model and state architecture are set, ensure they're 197 compatible. If only one is set, set the other. If neither are set, 198 use the default model. STATE_ARCHITECTURE is the bfd_arch_info data 199 for the selected "mach" (bfd terminology). */ 200 201 /* Only check cpu 0. STATE_ARCHITECTURE is for that one only. */ 202 /* ??? At present this only supports homogeneous multiprocessors. */ 203 cpu = STATE_CPU (sd, 0); 204 205 if (! STATE_ARCHITECTURE (sd) 206 && ! CPU_MACH (cpu)) 207 { 208 /* Set the default model. */ 209 const SIM_MODEL *model = sim_model_lookup (WITH_DEFAULT_MODEL); 210 SIM_ASSERT (model != NULL); 211 sim_model_set (sd, NULL, model); 212 } 213 214 if (STATE_ARCHITECTURE (sd) 215 && CPU_MACH (cpu)) 216 { 217 if (strcmp (STATE_ARCHITECTURE (sd)->printable_name, 218 MACH_BFD_NAME (CPU_MACH (cpu))) != 0) 219 { 220 sim_io_eprintf (sd, "invalid model `%s' for `%s'\n", 221 MODEL_NAME (CPU_MODEL (cpu)), 222 STATE_ARCHITECTURE (sd)->printable_name); 223 return SIM_RC_FAIL; 224 } 225 } 226 else if (STATE_ARCHITECTURE (sd)) 227 { 228 /* Use the default model for the selected machine. 229 The default model is the first one in the list. */ 230 const SIM_MACH *mach = sim_mach_lookup_bfd_name (STATE_ARCHITECTURE (sd)->printable_name); 231 232 if (mach == NULL) 233 { 234 sim_io_eprintf (sd, "unsupported machine `%s'\n", 235 STATE_ARCHITECTURE (sd)->printable_name); 236 return SIM_RC_FAIL; 237 } 238 sim_model_set (sd, NULL, MACH_MODELS (mach)); 239 } 240 else 241 { 242 STATE_ARCHITECTURE (sd) = bfd_scan_arch (MACH_BFD_NAME (CPU_MACH (cpu))); 243 } 244 245 return SIM_RC_OK; 246 } 247 248 #if !WITH_MODEL_P 249 /* Set up basic model support. This is a stub for ports that do not define 250 models. See sim-model.h for more details. */ 251 const SIM_MACH *sim_machs[] = 252 { 253 NULL 254 }; 255 #endif 256