14e98e3e1Schristos /* Model support. 2*88241920Schristos Copyright (C) 1996-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Contributed by Cygnus Support. 44e98e3e1Schristos 54e98e3e1Schristos This file is part of GDB, the GNU debugger. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224b169a6bSchristos 234b169a6bSchristos #include "bfd.h" 244b169a6bSchristos #include "libiberty.h" 254b169a6bSchristos 264e98e3e1Schristos #include "sim-main.h" 274e98e3e1Schristos #include "sim-model.h" 284e98e3e1Schristos #include "sim-options.h" 294e98e3e1Schristos #include "sim-io.h" 304e98e3e1Schristos #include "sim-assert.h" 314e98e3e1Schristos 32ba340e45Schristos static void model_set (sim_cpu *, const SIM_MODEL *); 334e98e3e1Schristos 344e98e3e1Schristos static DECLARE_OPTION_HANDLER (model_option_handler); 354e98e3e1Schristos 364e98e3e1Schristos static MODULE_INIT_FN sim_model_init; 374e98e3e1Schristos 384e98e3e1Schristos enum { 394e98e3e1Schristos OPTION_MODEL = OPTION_START, 404e98e3e1Schristos OPTION_MODEL_INFO, 414e98e3e1Schristos }; 424e98e3e1Schristos 434e98e3e1Schristos static const OPTION model_options[] = { 444e98e3e1Schristos { {"model", required_argument, NULL, OPTION_MODEL}, 454e98e3e1Schristos '\0', "MODEL", "Specify model to simulate", 464e98e3e1Schristos model_option_handler, NULL }, 474e98e3e1Schristos 484e98e3e1Schristos { {"model-info", no_argument, NULL, OPTION_MODEL_INFO}, 494e98e3e1Schristos '\0', NULL, "List selectable models", 504e98e3e1Schristos model_option_handler, NULL }, 514e98e3e1Schristos { {"info-model", no_argument, NULL, OPTION_MODEL_INFO}, 524e98e3e1Schristos '\0', NULL, NULL, 534e98e3e1Schristos model_option_handler, NULL }, 544e98e3e1Schristos 554e98e3e1Schristos { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } 564e98e3e1Schristos }; 574e98e3e1Schristos 584e98e3e1Schristos static SIM_RC 594e98e3e1Schristos model_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, 604e98e3e1Schristos char *arg, int is_command) 614e98e3e1Schristos { 624e98e3e1Schristos switch (opt) 634e98e3e1Schristos { 644e98e3e1Schristos case OPTION_MODEL : 654e98e3e1Schristos { 664b169a6bSchristos const SIM_MODEL *model = sim_model_lookup (sd, arg); 674e98e3e1Schristos if (! model) 684e98e3e1Schristos { 694e98e3e1Schristos sim_io_eprintf (sd, "unknown model `%s'\n", arg); 704e98e3e1Schristos return SIM_RC_FAIL; 714e98e3e1Schristos } 724b169a6bSchristos STATE_MODEL_NAME (sd) = arg; 734e98e3e1Schristos sim_model_set (sd, cpu, model); 744e98e3e1Schristos break; 754e98e3e1Schristos } 764e98e3e1Schristos 774e98e3e1Schristos case OPTION_MODEL_INFO : 784e98e3e1Schristos { 794b169a6bSchristos const SIM_MACH * const *machp; 80ba340e45Schristos const SIM_MODEL *model; 814b169a6bSchristos 824b169a6bSchristos if (STATE_MACHS (sd) == NULL) 834b169a6bSchristos { 844b169a6bSchristos sim_io_printf (sd, "This target does not support any models\n"); 854b169a6bSchristos return SIM_RC_FAIL; 864b169a6bSchristos } 874b169a6bSchristos 884b169a6bSchristos for (machp = STATE_MACHS(sd); *machp != NULL; ++machp) 894e98e3e1Schristos { 904e98e3e1Schristos sim_io_printf (sd, "Models for architecture `%s':\n", 914e98e3e1Schristos MACH_NAME (*machp)); 924e98e3e1Schristos for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; 934e98e3e1Schristos ++model) 944e98e3e1Schristos sim_io_printf (sd, " %s", MODEL_NAME (model)); 954e98e3e1Schristos sim_io_printf (sd, "\n"); 964e98e3e1Schristos } 974e98e3e1Schristos break; 984e98e3e1Schristos } 994e98e3e1Schristos } 1004e98e3e1Schristos 1014e98e3e1Schristos return SIM_RC_OK; 1024e98e3e1Schristos } 1034e98e3e1Schristos 1044e98e3e1Schristos SIM_RC 1054e98e3e1Schristos sim_model_install (SIM_DESC sd) 1064e98e3e1Schristos { 1074e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1084e98e3e1Schristos 1094e98e3e1Schristos sim_add_option_table (sd, NULL, model_options); 1104e98e3e1Schristos sim_module_add_init_fn (sd, sim_model_init); 1114e98e3e1Schristos 1124e98e3e1Schristos return SIM_RC_OK; 1134e98e3e1Schristos } 1144e98e3e1Schristos 1154e98e3e1Schristos /* Subroutine of sim_model_set to set the model for one cpu. */ 1164e98e3e1Schristos 1174e98e3e1Schristos static void 118ba340e45Schristos model_set (sim_cpu *cpu, const SIM_MODEL *model) 1194e98e3e1Schristos { 1204e98e3e1Schristos CPU_MACH (cpu) = MODEL_MACH (model); 1214e98e3e1Schristos CPU_MODEL (cpu) = model; 1224e98e3e1Schristos (* MACH_INIT_CPU (MODEL_MACH (model))) (cpu); 1234e98e3e1Schristos (* MODEL_INIT (model)) (cpu); 1244e98e3e1Schristos } 1254e98e3e1Schristos 1264e98e3e1Schristos /* Set the current model of CPU to MODEL. 1274e98e3e1Schristos If CPU is NULL, all cpus are set to MODEL. */ 1284e98e3e1Schristos 1294e98e3e1Schristos void 130ba340e45Schristos sim_model_set (SIM_DESC sd, sim_cpu *cpu, const SIM_MODEL *model) 1314e98e3e1Schristos { 1324e98e3e1Schristos if (! cpu) 1334e98e3e1Schristos { 1344e98e3e1Schristos int c; 1354e98e3e1Schristos 1364e98e3e1Schristos for (c = 0; c < MAX_NR_PROCESSORS; ++c) 1374e98e3e1Schristos if (STATE_CPU (sd, c)) 1384e98e3e1Schristos model_set (STATE_CPU (sd, c), model); 1394e98e3e1Schristos } 1404e98e3e1Schristos else 1414e98e3e1Schristos { 1424e98e3e1Schristos model_set (cpu, model); 1434e98e3e1Schristos } 1444e98e3e1Schristos } 1454e98e3e1Schristos 1464e98e3e1Schristos /* Look up model named NAME. 1474e98e3e1Schristos Result is pointer to MODEL entry or NULL if not found. */ 1484e98e3e1Schristos 149ba340e45Schristos const SIM_MODEL * 1504b169a6bSchristos sim_model_lookup (SIM_DESC sd, const char *name) 1514e98e3e1Schristos { 1524b169a6bSchristos const SIM_MACH * const *machp; 153ba340e45Schristos const SIM_MODEL *model; 1544e98e3e1Schristos 1554b169a6bSchristos if (STATE_MACHS (sd) == NULL) 1564b169a6bSchristos return NULL; 1574b169a6bSchristos 1584b169a6bSchristos for (machp = STATE_MACHS (sd); *machp != NULL; ++machp) 1594e98e3e1Schristos { 1604e98e3e1Schristos for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; ++model) 1614e98e3e1Schristos { 1624e98e3e1Schristos if (strcmp (MODEL_NAME (model), name) == 0) 1634e98e3e1Schristos return model; 1644e98e3e1Schristos } 1654e98e3e1Schristos } 1664e98e3e1Schristos return NULL; 1674e98e3e1Schristos } 1684e98e3e1Schristos 1694e98e3e1Schristos /* Look up machine named NAME. 1704e98e3e1Schristos Result is pointer to MACH entry or NULL if not found. */ 1714e98e3e1Schristos 172ba340e45Schristos const SIM_MACH * 1734b169a6bSchristos sim_mach_lookup (SIM_DESC sd, const char *name) 1744e98e3e1Schristos { 1754b169a6bSchristos const SIM_MACH * const *machp; 1764e98e3e1Schristos 1774b169a6bSchristos if (STATE_MACHS (sd) == NULL) 1784b169a6bSchristos return NULL; 1794b169a6bSchristos 1804b169a6bSchristos for (machp = STATE_MACHS (sd); *machp != NULL; ++machp) 1814e98e3e1Schristos { 1824e98e3e1Schristos if (strcmp (MACH_NAME (*machp), name) == 0) 1834e98e3e1Schristos return *machp; 1844e98e3e1Schristos } 1854e98e3e1Schristos return NULL; 1864e98e3e1Schristos } 1874e98e3e1Schristos 1884e98e3e1Schristos /* Look up a machine via its bfd name. 1894e98e3e1Schristos Result is pointer to MACH entry or NULL if not found. */ 1904e98e3e1Schristos 191ba340e45Schristos const SIM_MACH * 1924b169a6bSchristos sim_mach_lookup_bfd_name (SIM_DESC sd, const char *name) 1934e98e3e1Schristos { 1944b169a6bSchristos const SIM_MACH * const *machp; 1954e98e3e1Schristos 1964b169a6bSchristos if (STATE_MACHS (sd) == NULL) 1974b169a6bSchristos return NULL; 1984b169a6bSchristos 1994b169a6bSchristos for (machp = STATE_MACHS (sd); *machp != NULL; ++machp) 2004e98e3e1Schristos { 2014e98e3e1Schristos if (strcmp (MACH_BFD_NAME (*machp), name) == 0) 2024e98e3e1Schristos return *machp; 2034e98e3e1Schristos } 2044e98e3e1Schristos return NULL; 2054e98e3e1Schristos } 2064e98e3e1Schristos 2074e98e3e1Schristos /* Initialize model support. */ 2084e98e3e1Schristos 2094e98e3e1Schristos static SIM_RC 2104e98e3e1Schristos sim_model_init (SIM_DESC sd) 2114e98e3e1Schristos { 2124e98e3e1Schristos SIM_CPU *cpu; 2134e98e3e1Schristos 2144e98e3e1Schristos /* If both cpu model and state architecture are set, ensure they're 2154e98e3e1Schristos compatible. If only one is set, set the other. If neither are set, 2164e98e3e1Schristos use the default model. STATE_ARCHITECTURE is the bfd_arch_info data 2174e98e3e1Schristos for the selected "mach" (bfd terminology). */ 2184e98e3e1Schristos 2194e98e3e1Schristos /* Only check cpu 0. STATE_ARCHITECTURE is for that one only. */ 2204e98e3e1Schristos /* ??? At present this only supports homogeneous multiprocessors. */ 2214e98e3e1Schristos cpu = STATE_CPU (sd, 0); 2224e98e3e1Schristos 2234e98e3e1Schristos if (! STATE_ARCHITECTURE (sd) 2244b169a6bSchristos && ! CPU_MACH (cpu) 2254b169a6bSchristos && STATE_MODEL_NAME (sd)) 2264e98e3e1Schristos { 2274e98e3e1Schristos /* Set the default model. */ 2284b169a6bSchristos const SIM_MODEL *model = sim_model_lookup (sd, STATE_MODEL_NAME (sd)); 229212397c6Schristos SIM_ASSERT (model != NULL); 2304e98e3e1Schristos sim_model_set (sd, NULL, model); 2314e98e3e1Schristos } 2324e98e3e1Schristos 2334e98e3e1Schristos if (STATE_ARCHITECTURE (sd) 2344e98e3e1Schristos && CPU_MACH (cpu)) 2354e98e3e1Schristos { 2364e98e3e1Schristos if (strcmp (STATE_ARCHITECTURE (sd)->printable_name, 2374e98e3e1Schristos MACH_BFD_NAME (CPU_MACH (cpu))) != 0) 2384e98e3e1Schristos { 2394e98e3e1Schristos sim_io_eprintf (sd, "invalid model `%s' for `%s'\n", 2404e98e3e1Schristos MODEL_NAME (CPU_MODEL (cpu)), 2414e98e3e1Schristos STATE_ARCHITECTURE (sd)->printable_name); 2424e98e3e1Schristos return SIM_RC_FAIL; 2434e98e3e1Schristos } 2444e98e3e1Schristos } 2454b169a6bSchristos else if (STATE_ARCHITECTURE (sd) && STATE_MACHS (sd)) 2464e98e3e1Schristos { 2474e98e3e1Schristos /* Use the default model for the selected machine. 2484e98e3e1Schristos The default model is the first one in the list. */ 2494b169a6bSchristos const SIM_MACH *mach = 2504b169a6bSchristos sim_mach_lookup_bfd_name (sd, STATE_ARCHITECTURE (sd)->printable_name); 2514e98e3e1Schristos 2524e98e3e1Schristos if (mach == NULL) 2534e98e3e1Schristos { 2544e98e3e1Schristos sim_io_eprintf (sd, "unsupported machine `%s'\n", 2554e98e3e1Schristos STATE_ARCHITECTURE (sd)->printable_name); 2564e98e3e1Schristos return SIM_RC_FAIL; 2574e98e3e1Schristos } 2584e98e3e1Schristos sim_model_set (sd, NULL, MACH_MODELS (mach)); 2594e98e3e1Schristos } 2604b169a6bSchristos else if (CPU_MACH (cpu)) 2614e98e3e1Schristos { 2624e98e3e1Schristos STATE_ARCHITECTURE (sd) = bfd_scan_arch (MACH_BFD_NAME (CPU_MACH (cpu))); 2634e98e3e1Schristos } 2644e98e3e1Schristos 2654e98e3e1Schristos return SIM_RC_OK; 2664e98e3e1Schristos } 267