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