14e98e3e1Schristos /* Simulator hardware option handling. 2*88241920Schristos Copyright (C) 1998-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Contributed by Cygnus Support and Andrew Cagney. 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 <ctype.h> 244b169a6bSchristos #include <errno.h> 254b169a6bSchristos #include <stdarg.h> 264b169a6bSchristos #include <stdlib.h> 274b169a6bSchristos #include <string.h> 284b169a6bSchristos 294e98e3e1Schristos #include "sim-main.h" 304e98e3e1Schristos #include "sim-assert.h" 314e98e3e1Schristos #include "sim-options.h" 324b169a6bSchristos #include "sim/callback.h" 334e98e3e1Schristos 344e98e3e1Schristos #include "sim-hw.h" 354e98e3e1Schristos 364e98e3e1Schristos #include "hw-tree.h" 374e98e3e1Schristos #include "hw-device.h" 384e98e3e1Schristos #include "hw-main.h" 394e98e3e1Schristos #include "hw-base.h" 404e98e3e1Schristos 414e98e3e1Schristos struct sim_hw { 424e98e3e1Schristos struct hw *tree; 434e98e3e1Schristos int trace_p; 444e98e3e1Schristos int info_p; 454e98e3e1Schristos /* if called from a processor */ 464e98e3e1Schristos sim_cpu *cpu; 474e98e3e1Schristos sim_cia cia; 484e98e3e1Schristos }; 494e98e3e1Schristos 504e98e3e1Schristos 514e98e3e1Schristos struct hw * 524e98e3e1Schristos sim_hw_parse (struct sim_state *sd, 534e98e3e1Schristos const char *fmt, 544e98e3e1Schristos ...) 554e98e3e1Schristos { 564e98e3e1Schristos struct hw *current; 574e98e3e1Schristos va_list ap; 584e98e3e1Schristos va_start (ap, fmt); 594e98e3e1Schristos current = hw_tree_vparse (STATE_HW (sd)->tree, fmt, ap); 604e98e3e1Schristos va_end (ap); 614e98e3e1Schristos return current; 624e98e3e1Schristos } 634e98e3e1Schristos 644e98e3e1Schristos struct printer { 654e98e3e1Schristos struct sim_state *file; 664e98e3e1Schristos void (*print) (struct sim_state *, const char *, va_list ap); 674e98e3e1Schristos }; 684e98e3e1Schristos 694e98e3e1Schristos static void 704e98e3e1Schristos do_print (void *file, const char *fmt, ...) 714e98e3e1Schristos { 724e98e3e1Schristos struct printer *p = file; 734e98e3e1Schristos va_list ap; 744e98e3e1Schristos va_start (ap, fmt); 754e98e3e1Schristos p->print (p->file, fmt, ap); 764e98e3e1Schristos va_end (ap); 774e98e3e1Schristos } 784e98e3e1Schristos 794e98e3e1Schristos void 804e98e3e1Schristos sim_hw_print (struct sim_state *sd, 814e98e3e1Schristos void (*print) (struct sim_state *, const char *, va_list ap)) 824e98e3e1Schristos { 834e98e3e1Schristos struct printer p; 844e98e3e1Schristos p.file = sd; 854e98e3e1Schristos p.print = print; 864e98e3e1Schristos hw_tree_print (STATE_HW (sd)->tree, do_print, &p); 874e98e3e1Schristos } 884e98e3e1Schristos 894e98e3e1Schristos 904e98e3e1Schristos 914e98e3e1Schristos 924e98e3e1Schristos /* command line options. */ 934e98e3e1Schristos 944e98e3e1Schristos enum { 954e98e3e1Schristos OPTION_HW_INFO = OPTION_START, 964e98e3e1Schristos OPTION_HW_TRACE, 974e98e3e1Schristos OPTION_HW_DEVICE, 984e98e3e1Schristos OPTION_HW_LIST, 994e98e3e1Schristos OPTION_HW_FILE, 1004e98e3e1Schristos }; 1014e98e3e1Schristos 1024e98e3e1Schristos static DECLARE_OPTION_HANDLER (hw_option_handler); 1034e98e3e1Schristos 1044e98e3e1Schristos static const OPTION hw_options[] = 1054e98e3e1Schristos { 1064e98e3e1Schristos { {"hw-info", no_argument, NULL, OPTION_HW_INFO }, 1074e98e3e1Schristos '\0', NULL, "List configurable hw regions", 1084e98e3e1Schristos hw_option_handler, NULL }, 1094e98e3e1Schristos { {"info-hw", no_argument, NULL, OPTION_HW_INFO }, 1104e98e3e1Schristos '\0', NULL, NULL, 1114e98e3e1Schristos hw_option_handler, NULL }, 1124e98e3e1Schristos 1134e98e3e1Schristos { {"hw-trace", optional_argument, NULL, OPTION_HW_TRACE }, 1144e98e3e1Schristos '\0', "on|off", "Trace all hardware devices", 1154e98e3e1Schristos hw_option_handler, NULL }, 1164e98e3e1Schristos { {"trace-hw", optional_argument, NULL, OPTION_HW_TRACE }, 1174e98e3e1Schristos '\0', NULL, NULL, 1184e98e3e1Schristos hw_option_handler, NULL }, 1194e98e3e1Schristos 1204e98e3e1Schristos { {"hw-device", required_argument, NULL, OPTION_HW_DEVICE }, 1214e98e3e1Schristos '\0', "DEVICE", "Add the specified device", 1224e98e3e1Schristos hw_option_handler, NULL }, 1234e98e3e1Schristos 1244e98e3e1Schristos { {"hw-list", no_argument, NULL, OPTION_HW_LIST }, 1254e98e3e1Schristos '\0', NULL, "List the device tree", 1264e98e3e1Schristos hw_option_handler, NULL }, 1274e98e3e1Schristos 1284e98e3e1Schristos { {"hw-file", required_argument, NULL, OPTION_HW_FILE }, 1294e98e3e1Schristos '\0', "FILE", "Add the devices listed in the file", 1304e98e3e1Schristos hw_option_handler, NULL }, 1314e98e3e1Schristos 1324e98e3e1Schristos { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } 1334e98e3e1Schristos }; 1344e98e3e1Schristos 1354e98e3e1Schristos 1364e98e3e1Schristos 1374e98e3e1Schristos /* Copied from ../ppc/psim.c:psim_merge_device_file() */ 1384e98e3e1Schristos 1394e98e3e1Schristos static SIM_RC 1404e98e3e1Schristos merge_device_file (struct sim_state *sd, 1414e98e3e1Schristos const char *file_name) 1424e98e3e1Schristos { 1434e98e3e1Schristos FILE *description; 1444e98e3e1Schristos struct hw *current = STATE_HW (sd)->tree; 1454b169a6bSchristos char *device_path = NULL; 1464b169a6bSchristos size_t buf_size = 0; 1474b169a6bSchristos ssize_t device_path_len; 1484e98e3e1Schristos 1494e98e3e1Schristos /* try opening the file */ 1504e98e3e1Schristos description = fopen (file_name, "r"); 1514e98e3e1Schristos if (description == NULL) 1524e98e3e1Schristos { 1534e98e3e1Schristos perror (file_name); 1544e98e3e1Schristos return SIM_RC_FAIL; 1554e98e3e1Schristos } 1564e98e3e1Schristos 1574b169a6bSchristos while ((device_path_len = getline (&device_path, &buf_size, description)) > 0) 1584e98e3e1Schristos { 1594e98e3e1Schristos char *device; 1604b169a6bSchristos char *next_line = NULL; 1614b169a6bSchristos 1624b169a6bSchristos if (device_path[device_path_len - 1] == '\n') 1634b169a6bSchristos device_path[--device_path_len] = '\0'; 1644b169a6bSchristos 1654e98e3e1Schristos /* skip comments ("#" or ";") and blank lines lines */ 1664e98e3e1Schristos for (device = device_path; 1674e98e3e1Schristos *device != '\0' && isspace (*device); 1684e98e3e1Schristos device++); 1694e98e3e1Schristos if (device[0] == '#' 1704e98e3e1Schristos || device[0] == ';' 1714e98e3e1Schristos || device[0] == '\0') 1724e98e3e1Schristos continue; 1734b169a6bSchristos 1744e98e3e1Schristos /* merge any appended lines */ 1754b169a6bSchristos while (device_path[device_path_len - 1] == '\\') 1764e98e3e1Schristos { 1774b169a6bSchristos size_t next_buf_size = 0; 1784b169a6bSchristos ssize_t next_line_len; 1794b169a6bSchristos 1804e98e3e1Schristos /* zap the `\' at the end of the line */ 1814b169a6bSchristos device_path[--device_path_len] = '\0'; 1824b169a6bSchristos 1834b169a6bSchristos /* get the next line */ 1844b169a6bSchristos next_line_len = getline (&next_line, &next_buf_size, description); 1854b169a6bSchristos if (next_line_len <= 0) 1864b169a6bSchristos break; 1874b169a6bSchristos 1884b169a6bSchristos if (next_line[next_line_len - 1] == '\n') 1894b169a6bSchristos next_line[--next_line_len] = '\0'; 1904b169a6bSchristos 1914e98e3e1Schristos /* append the next line */ 1924b169a6bSchristos if (buf_size - device_path_len <= next_line_len) 1934e98e3e1Schristos { 1944b169a6bSchristos ptrdiff_t offset = device - device_path; 1954b169a6bSchristos 1964b169a6bSchristos buf_size += next_buf_size; 1974b169a6bSchristos device_path = xrealloc (device_path, buf_size); 1984b169a6bSchristos device = device_path + offset; 1994e98e3e1Schristos } 2004b169a6bSchristos memcpy (device_path + device_path_len, next_line, 2014b169a6bSchristos next_line_len + 1); 2024b169a6bSchristos device_path_len += next_line_len; 2034e98e3e1Schristos } 2044b169a6bSchristos free (next_line); 2054b169a6bSchristos 2064e98e3e1Schristos /* parse this line */ 2074e98e3e1Schristos current = hw_tree_parse (current, "%s", device); 2084e98e3e1Schristos } 2094b169a6bSchristos 2104b169a6bSchristos free (device_path); 2114e98e3e1Schristos fclose (description); 2124e98e3e1Schristos return SIM_RC_OK; 2134e98e3e1Schristos } 2144e98e3e1Schristos 2154e98e3e1Schristos 2164e98e3e1Schristos static SIM_RC 2174e98e3e1Schristos hw_option_handler (struct sim_state *sd, sim_cpu *cpu, int opt, 2184e98e3e1Schristos char *arg, int is_command) 2194e98e3e1Schristos { 2204e98e3e1Schristos switch (opt) 2214e98e3e1Schristos { 2224e98e3e1Schristos 2234e98e3e1Schristos case OPTION_HW_INFO: 2244e98e3e1Schristos { 2254e98e3e1Schristos /* delay info until after the tree is finished */ 2264e98e3e1Schristos STATE_HW (sd)->info_p = 1; 2274e98e3e1Schristos return SIM_RC_OK; 2284e98e3e1Schristos break; 2294e98e3e1Schristos } 2304e98e3e1Schristos 2314e98e3e1Schristos case OPTION_HW_TRACE: 2324e98e3e1Schristos { 2334e98e3e1Schristos if (arg == NULL) 2344e98e3e1Schristos { 2354e98e3e1Schristos STATE_HW (sd)->trace_p = 1; 2364e98e3e1Schristos } 2374e98e3e1Schristos else if (strcmp (arg, "yes") == 0 2384e98e3e1Schristos || strcmp (arg, "on") == 0) 2394e98e3e1Schristos { 2404e98e3e1Schristos STATE_HW (sd)->trace_p = 1; 2414e98e3e1Schristos } 2424e98e3e1Schristos else if (strcmp (arg, "no") == 0 2434e98e3e1Schristos || strcmp (arg, "off") == 0) 2444e98e3e1Schristos { 2454e98e3e1Schristos STATE_HW (sd)->trace_p = 0; 2464e98e3e1Schristos } 2474e98e3e1Schristos else 2484e98e3e1Schristos { 2494e98e3e1Schristos sim_io_eprintf (sd, "Option --hw-trace ignored\n"); 2504e98e3e1Schristos /* set tracing on all devices */ 2514e98e3e1Schristos return SIM_RC_FAIL; 2524e98e3e1Schristos } 2534e98e3e1Schristos /* FIXME: Not very nice - see also hw-base.c */ 2544e98e3e1Schristos if (STATE_HW (sd)->trace_p) 2554e98e3e1Schristos hw_tree_parse (STATE_HW (sd)->tree, "/global-trace? true"); 2564e98e3e1Schristos return SIM_RC_OK; 2574e98e3e1Schristos break; 2584e98e3e1Schristos } 2594e98e3e1Schristos 2604e98e3e1Schristos case OPTION_HW_DEVICE: 2614e98e3e1Schristos { 2624e98e3e1Schristos hw_tree_parse (STATE_HW (sd)->tree, "%s", arg); 2634e98e3e1Schristos return SIM_RC_OK; 2644e98e3e1Schristos } 2654e98e3e1Schristos 2664e98e3e1Schristos case OPTION_HW_LIST: 2674e98e3e1Schristos { 2684e98e3e1Schristos sim_hw_print (sd, sim_io_vprintf); 2694e98e3e1Schristos return SIM_RC_OK; 2704e98e3e1Schristos } 2714e98e3e1Schristos 2724e98e3e1Schristos case OPTION_HW_FILE: 2734e98e3e1Schristos { 2744e98e3e1Schristos return merge_device_file (sd, arg); 2754e98e3e1Schristos } 2764e98e3e1Schristos 2774e98e3e1Schristos default: 2784e98e3e1Schristos sim_io_eprintf (sd, "Unknown hw option %d\n", opt); 2794e98e3e1Schristos return SIM_RC_FAIL; 2804e98e3e1Schristos 2814e98e3e1Schristos } 2824e98e3e1Schristos 2834e98e3e1Schristos return SIM_RC_FAIL; 2844e98e3e1Schristos } 2854e98e3e1Schristos 2864e98e3e1Schristos 2874e98e3e1Schristos /* "hw" module install handler. 2884e98e3e1Schristos 2894e98e3e1Schristos This is called via sim_module_install to install the "hw" subsystem 2904e98e3e1Schristos into the simulator. */ 2914e98e3e1Schristos 2924e98e3e1Schristos static MODULE_INIT_FN sim_hw_init; 2934e98e3e1Schristos static MODULE_UNINSTALL_FN sim_hw_uninstall; 2944e98e3e1Schristos 2954b169a6bSchristos /* Provide a prototype to silence -Wmissing-prototypes. */ 2964b169a6bSchristos SIM_RC sim_install_hw (struct sim_state *sd); 2974b169a6bSchristos 2984b169a6bSchristos /* Establish this object. */ 2994e98e3e1Schristos SIM_RC 3004b169a6bSchristos sim_install_hw (struct sim_state *sd) 3014e98e3e1Schristos { 3024e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 3034e98e3e1Schristos sim_add_option_table (sd, NULL, hw_options); 3044e98e3e1Schristos sim_module_add_uninstall_fn (sd, sim_hw_uninstall); 3054e98e3e1Schristos sim_module_add_init_fn (sd, sim_hw_init); 3064e98e3e1Schristos STATE_HW (sd) = ZALLOC (struct sim_hw); 3074e98e3e1Schristos STATE_HW (sd)->tree = hw_tree_create (sd, "core"); 3084e98e3e1Schristos return SIM_RC_OK; 3094e98e3e1Schristos } 3104e98e3e1Schristos 3114e98e3e1Schristos 3124e98e3e1Schristos static SIM_RC 3134e98e3e1Schristos sim_hw_init (struct sim_state *sd) 3144e98e3e1Schristos { 3154e98e3e1Schristos /* FIXME: anything needed? */ 3164e98e3e1Schristos hw_tree_finish (STATE_HW (sd)->tree); 3174e98e3e1Schristos if (STATE_HW (sd)->info_p) 3184e98e3e1Schristos sim_hw_print (sd, sim_io_vprintf); 3194e98e3e1Schristos return SIM_RC_OK; 3204e98e3e1Schristos } 3214e98e3e1Schristos 3224e98e3e1Schristos /* Uninstall the "hw" subsystem from the simulator. */ 3234e98e3e1Schristos 3244e98e3e1Schristos static void 3254e98e3e1Schristos sim_hw_uninstall (struct sim_state *sd) 3264e98e3e1Schristos { 3274e98e3e1Schristos hw_tree_delete (STATE_HW (sd)->tree); 3284e98e3e1Schristos free (STATE_HW (sd)); 3294e98e3e1Schristos STATE_HW (sd) = NULL; 3304e98e3e1Schristos } 3314e98e3e1Schristos 3324e98e3e1Schristos 3334e98e3e1Schristos 3344e98e3e1Schristos /* Data transfers to/from the hardware device tree. There are several 3354e98e3e1Schristos cases. */ 3364e98e3e1Schristos 3374e98e3e1Schristos 3384e98e3e1Schristos /* CPU: The simulation is running and the current CPU/CIA 3394e98e3e1Schristos initiates a data transfer. */ 3404e98e3e1Schristos 3414e98e3e1Schristos void 3424e98e3e1Schristos sim_cpu_hw_io_read_buffer (sim_cpu *cpu, 3434e98e3e1Schristos sim_cia cia, 3444e98e3e1Schristos struct hw *hw, 3454e98e3e1Schristos void *dest, 3464e98e3e1Schristos int space, 3474e98e3e1Schristos unsigned_word addr, 3484e98e3e1Schristos unsigned nr_bytes) 3494e98e3e1Schristos { 3504e98e3e1Schristos SIM_DESC sd = CPU_STATE (cpu); 3514e98e3e1Schristos STATE_HW (sd)->cpu = cpu; 3524e98e3e1Schristos STATE_HW (sd)->cia = cia; 3534e98e3e1Schristos if (hw_io_read_buffer (hw, dest, space, addr, nr_bytes) != nr_bytes) 3544e98e3e1Schristos sim_engine_abort (sd, cpu, cia, "broken CPU read"); 3554e98e3e1Schristos } 3564e98e3e1Schristos 3574e98e3e1Schristos void 3584e98e3e1Schristos sim_cpu_hw_io_write_buffer (sim_cpu *cpu, 3594e98e3e1Schristos sim_cia cia, 3604e98e3e1Schristos struct hw *hw, 3614e98e3e1Schristos const void *source, 3624e98e3e1Schristos int space, 3634e98e3e1Schristos unsigned_word addr, 3644e98e3e1Schristos unsigned nr_bytes) 3654e98e3e1Schristos { 3664e98e3e1Schristos SIM_DESC sd = CPU_STATE (cpu); 3674e98e3e1Schristos STATE_HW (sd)->cpu = cpu; 3684e98e3e1Schristos STATE_HW (sd)->cia = cia; 3694e98e3e1Schristos if (hw_io_write_buffer (hw, source, space, addr, nr_bytes) != nr_bytes) 3704e98e3e1Schristos sim_engine_abort (sd, cpu, cia, "broken CPU write"); 3714e98e3e1Schristos } 3724e98e3e1Schristos 3734e98e3e1Schristos 3744e98e3e1Schristos 3754e98e3e1Schristos 3764e98e3e1Schristos /* SYSTEM: A data transfer is being initiated by the system. */ 3774e98e3e1Schristos 3784e98e3e1Schristos unsigned 3794e98e3e1Schristos sim_hw_io_read_buffer (struct sim_state *sd, 3804e98e3e1Schristos struct hw *hw, 3814e98e3e1Schristos void *dest, 3824e98e3e1Schristos int space, 3834e98e3e1Schristos unsigned_word addr, 3844e98e3e1Schristos unsigned nr_bytes) 3854e98e3e1Schristos { 3864e98e3e1Schristos STATE_HW (sd)->cpu = NULL; 3874e98e3e1Schristos return hw_io_read_buffer (hw, dest, space, addr, nr_bytes); 3884e98e3e1Schristos } 3894e98e3e1Schristos 3904e98e3e1Schristos unsigned 3914e98e3e1Schristos sim_hw_io_write_buffer (struct sim_state *sd, 3924e98e3e1Schristos struct hw *hw, 3934e98e3e1Schristos const void *source, 3944e98e3e1Schristos int space, 3954e98e3e1Schristos unsigned_word addr, 3964e98e3e1Schristos unsigned nr_bytes) 3974e98e3e1Schristos { 3984e98e3e1Schristos STATE_HW (sd)->cpu = NULL; 3994e98e3e1Schristos return hw_io_write_buffer (hw, source, space, addr, nr_bytes); 4004e98e3e1Schristos } 4014e98e3e1Schristos 4024e98e3e1Schristos 4034e98e3e1Schristos 4044e98e3e1Schristos /* Abort the simulation specifying HW as the reason */ 4054e98e3e1Schristos 4064e98e3e1Schristos void 4074e98e3e1Schristos hw_vabort (struct hw *me, 4084e98e3e1Schristos const char *fmt, 4094e98e3e1Schristos va_list ap) 4104e98e3e1Schristos { 4114b169a6bSchristos int len; 4124e98e3e1Schristos const char *name; 4134e98e3e1Schristos char *msg; 4144b169a6bSchristos va_list cpy; 4154b169a6bSchristos 4164e98e3e1Schristos /* find an identity */ 4174e98e3e1Schristos if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0') 4184e98e3e1Schristos name = hw_path (me); 4194e98e3e1Schristos else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0') 4204e98e3e1Schristos name = hw_name (me); 4214e98e3e1Schristos else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0') 4224e98e3e1Schristos name = hw_family (me); 4234e98e3e1Schristos else 4244e98e3e1Schristos name = "device"; 4254b169a6bSchristos 4264b169a6bSchristos /* Expand FMT and AP into MSG buffer. */ 4274b169a6bSchristos va_copy (cpy, ap); 4284b169a6bSchristos len = vsnprintf (NULL, 0, fmt, cpy) + 1; 4294b169a6bSchristos va_end (cpy); 4304b169a6bSchristos msg = alloca (len); 4314b169a6bSchristos vsnprintf (msg, len, fmt, ap); 4324b169a6bSchristos 4334e98e3e1Schristos /* report the problem */ 4344b169a6bSchristos sim_engine_abort (hw_system (me), 4354e98e3e1Schristos STATE_HW (hw_system (me))->cpu, 4364e98e3e1Schristos STATE_HW (hw_system (me))->cia, 4374b169a6bSchristos "%s: %s", name, msg); 4384e98e3e1Schristos } 4394e98e3e1Schristos 4404e98e3e1Schristos void 4414e98e3e1Schristos hw_abort (struct hw *me, 4424e98e3e1Schristos const char *fmt, 4434e98e3e1Schristos ...) 4444e98e3e1Schristos { 4454e98e3e1Schristos va_list ap; 4464e98e3e1Schristos /* report the problem */ 4474e98e3e1Schristos va_start (ap, fmt); 4484e98e3e1Schristos hw_vabort (me, fmt, ap); 4494e98e3e1Schristos va_end (ap); 4504e98e3e1Schristos } 4514e98e3e1Schristos 4524e98e3e1Schristos void 4534e98e3e1Schristos sim_hw_abort (struct sim_state *sd, 4544e98e3e1Schristos struct hw *me, 4554e98e3e1Schristos const char *fmt, 4564e98e3e1Schristos ...) 4574e98e3e1Schristos { 4584e98e3e1Schristos va_list ap; 4594e98e3e1Schristos va_start (ap, fmt); 4604e98e3e1Schristos if (me == NULL) 4614e98e3e1Schristos sim_engine_vabort (sd, NULL, NULL_CIA, fmt, ap); 4624e98e3e1Schristos else 4634e98e3e1Schristos hw_vabort (me, fmt, ap); 4644e98e3e1Schristos va_end (ap); 4654e98e3e1Schristos } 4664e98e3e1Schristos 4674e98e3e1Schristos 4684e98e3e1Schristos /* MISC routines to tie HW into the rest of the system */ 4694e98e3e1Schristos 4704e98e3e1Schristos void 4714e98e3e1Schristos hw_halt (struct hw *me, 4724e98e3e1Schristos int reason, 4734e98e3e1Schristos int status) 4744e98e3e1Schristos { 4754e98e3e1Schristos struct sim_state *sd = hw_system (me); 4764e98e3e1Schristos struct sim_hw *sim = STATE_HW (sd); 4774e98e3e1Schristos sim_engine_halt (sd, sim->cpu, NULL, sim->cia, reason, status); 4784e98e3e1Schristos } 4794e98e3e1Schristos 4804e98e3e1Schristos struct _sim_cpu * 4814e98e3e1Schristos hw_system_cpu (struct hw *me) 4824e98e3e1Schristos { 4834e98e3e1Schristos return STATE_HW (hw_system (me))->cpu; 4844e98e3e1Schristos } 4854e98e3e1Schristos 4864e98e3e1Schristos void 4874e98e3e1Schristos hw_trace (struct hw *me, 4884e98e3e1Schristos const char *fmt, 4894e98e3e1Schristos ...) 4904e98e3e1Schristos { 4914e98e3e1Schristos if (hw_trace_p (me)) /* to be sure, to be sure */ 4924e98e3e1Schristos { 4934e98e3e1Schristos va_list ap; 4944e98e3e1Schristos va_start (ap, fmt); 4954e98e3e1Schristos sim_io_eprintf (hw_system (me), "%s: ", hw_path (me)); 4964e98e3e1Schristos sim_io_evprintf (hw_system (me), fmt, ap); 4974e98e3e1Schristos sim_io_eprintf (hw_system (me), "\n"); 4984e98e3e1Schristos va_end (ap); 4994e98e3e1Schristos } 5004e98e3e1Schristos } 5014e98e3e1Schristos 5024e98e3e1Schristos 5034e98e3e1Schristos /* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin() */ 5044e98e3e1Schristos 5054e98e3e1Schristos int 5064e98e3e1Schristos do_hw_poll_read (struct hw *me, 5074e98e3e1Schristos do_hw_poll_read_method *read, 5084e98e3e1Schristos int sim_io_fd, 5094e98e3e1Schristos void *buf, 5104e98e3e1Schristos unsigned sizeof_buf) 5114e98e3e1Schristos { 5124e98e3e1Schristos int status = read (hw_system (me), sim_io_fd, buf, sizeof_buf); 5134e98e3e1Schristos if (status > 0) 5144e98e3e1Schristos return status; 5154e98e3e1Schristos else if (status == 0 && sizeof_buf == 0) 5164e98e3e1Schristos return 0; 5174e98e3e1Schristos else if (status == 0) 5184e98e3e1Schristos return HW_IO_EOF; 5194e98e3e1Schristos else /* status < 0 */ 5204e98e3e1Schristos { 5214e98e3e1Schristos #ifdef EAGAIN 5224e98e3e1Schristos if (STATE_CALLBACK (hw_system (me))->last_errno == EAGAIN) 5234e98e3e1Schristos return HW_IO_NOT_READY; 5244e98e3e1Schristos else 5254e98e3e1Schristos return HW_IO_EOF; 5264e98e3e1Schristos #else 5274e98e3e1Schristos return HW_IO_EOF; 5284e98e3e1Schristos #endif 5294e98e3e1Schristos } 5304e98e3e1Schristos } 531