mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-14 11:25:52 +08:00
* sim-hw.c: Include ctype.h.
(do_hw_poll_read): Do not assume EAGAIN.
This commit is contained in:
@ -1,3 +1,10 @@
|
||||
start-sanitize-am30
|
||||
Thu May 21 17:57:16 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* sim-hw.c: Include ctype.h.
|
||||
(do_hw_poll_read): Do not assume EAGAIN.
|
||||
|
||||
end-sanitize-am30
|
||||
Wed May 20 04:37:57 1998 Doug Evans <devans@seba.cygnus.com>
|
||||
|
||||
* cgen-trace.c (first_insn_p): New static local.
|
||||
|
564
sim/common/sim-hw.c
Normal file
564
sim/common/sim-hw.c
Normal file
@ -0,0 +1,564 @@
|
||||
/* Simulator hardware option handling.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support and Andrew Cagney.
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "sim-assert.h"
|
||||
#include "sim-options.h"
|
||||
|
||||
#include "sim-hw.h"
|
||||
|
||||
#include "hw-tree.h"
|
||||
#include "hw-device.h"
|
||||
#include "hw-base.h"
|
||||
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
|
||||
struct sim_hw {
|
||||
struct hw *tree;
|
||||
int trace_p;
|
||||
int info_p;
|
||||
/* if called from a processor */
|
||||
sim_cpu *cpu;
|
||||
sim_cia cia;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
sim_hw_parse (struct sim_state *sd,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
hw_tree_vparse (STATE_HW (sd)->tree, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
struct printer {
|
||||
struct sim_state *file;
|
||||
void (*print) (struct sim_state *, const char *, va_list ap);
|
||||
};
|
||||
|
||||
static void
|
||||
do_print (void *file, const char *fmt, ...)
|
||||
{
|
||||
struct printer *p = file;
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
p->print (p->file, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
void
|
||||
sim_hw_print (struct sim_state *sd,
|
||||
void (*print) (struct sim_state *, const char *, va_list ap))
|
||||
{
|
||||
struct printer p;
|
||||
p.file = sd;
|
||||
p.print = print;
|
||||
hw_tree_print (STATE_HW (sd)->tree, do_print, &p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* command line options. */
|
||||
|
||||
enum {
|
||||
OPTION_HW_INFO = OPTION_START,
|
||||
OPTION_HW_TRACE,
|
||||
OPTION_HW_DEVICE,
|
||||
OPTION_HW_FILE,
|
||||
};
|
||||
|
||||
static DECLARE_OPTION_HANDLER (hw_option_handler);
|
||||
|
||||
static const OPTION hw_options[] =
|
||||
{
|
||||
{ {"hw-info", no_argument, NULL, OPTION_HW_INFO },
|
||||
'\0', NULL, "List configurable hw regions",
|
||||
hw_option_handler },
|
||||
{ {"info-hw", no_argument, NULL, OPTION_HW_INFO },
|
||||
'\0', NULL, NULL,
|
||||
hw_option_handler },
|
||||
|
||||
{ {"hw-trace", optional_argument, NULL, OPTION_HW_TRACE },
|
||||
'\0', "on|off", "Trace all hardware devices",
|
||||
hw_option_handler },
|
||||
{ {"trace-hw", optional_argument, NULL, OPTION_HW_TRACE },
|
||||
'\0', NULL, NULL,
|
||||
hw_option_handler },
|
||||
|
||||
{ {"hw-device", required_argument, NULL, OPTION_HW_DEVICE },
|
||||
'\0', "DEVICE", "Add the specified device",
|
||||
hw_option_handler },
|
||||
|
||||
{ {"hw-file", required_argument, NULL, OPTION_HW_FILE },
|
||||
'\0', "FILE", "Add the devices listed in the file",
|
||||
hw_option_handler },
|
||||
|
||||
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Copied from ../ppc/psim.c:psim_merge_device_file() */
|
||||
|
||||
static SIM_RC
|
||||
merge_device_file (struct sim_state *sd,
|
||||
const char *file_name)
|
||||
{
|
||||
FILE *description;
|
||||
struct hw *current = STATE_HW (sd)->tree;
|
||||
int line_nr;
|
||||
char device_path[1000];
|
||||
|
||||
/* try opening the file */
|
||||
description = fopen (file_name, "r");
|
||||
if (description == NULL)
|
||||
{
|
||||
perror (file_name);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
|
||||
line_nr = 0;
|
||||
while (fgets (device_path, sizeof(device_path), description))
|
||||
{
|
||||
char *device;
|
||||
/* check that a complete line was read */
|
||||
if (strchr (device_path, '\n') == NULL)
|
||||
{
|
||||
fclose (description);
|
||||
sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
*strchr (device_path, '\n') = '\0';
|
||||
line_nr++;
|
||||
/* skip comments ("#" or ";") and blank lines lines */
|
||||
for (device = device_path;
|
||||
*device != '\0' && isspace (*device);
|
||||
device++);
|
||||
if (device[0] == '#'
|
||||
|| device[0] == ';'
|
||||
|| device[0] == '\0')
|
||||
continue;
|
||||
/* merge any appended lines */
|
||||
while (device_path[strlen (device_path) - 1] == '\\')
|
||||
{
|
||||
int curlen = strlen (device_path) - 1;
|
||||
/* zap the `\' at the end of the line */
|
||||
device_path[curlen] = '\0';
|
||||
/* append the next line */
|
||||
if (!fgets (device_path + curlen,
|
||||
sizeof (device_path) - curlen,
|
||||
description))
|
||||
{
|
||||
fclose (description);
|
||||
sim_io_eprintf (sd, "%s:%d: unexpected eof", file_name, line_nr);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
if (strchr(device_path, '\n') == NULL)
|
||||
{
|
||||
fclose(description);
|
||||
sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
*strchr(device_path, '\n') = '\0';
|
||||
line_nr++;
|
||||
}
|
||||
/* parse this line */
|
||||
current = hw_tree_parse (current, "%s", device);
|
||||
}
|
||||
fclose (description);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
static SIM_RC
|
||||
hw_option_handler (struct sim_state *sd, sim_cpu *cpu, int opt,
|
||||
char *arg, int is_command)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
||||
case OPTION_HW_INFO:
|
||||
{
|
||||
/* delay info until after the tree is finished */
|
||||
STATE_HW (sd)->info_p = 1;
|
||||
return SIM_RC_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPTION_HW_TRACE:
|
||||
{
|
||||
if (arg == NULL)
|
||||
{
|
||||
STATE_HW (sd)->trace_p = 1;
|
||||
}
|
||||
else if (strcmp (arg, "yes") == 0
|
||||
|| strcmp (arg, "on") == 0)
|
||||
{
|
||||
STATE_HW (sd)->trace_p = 1;
|
||||
}
|
||||
else if (strcmp (arg, "no") == 0
|
||||
|| strcmp (arg, "off") == 0)
|
||||
{
|
||||
STATE_HW (sd)->trace_p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_io_eprintf (sd, "Option --hw-trace ignored\n");
|
||||
/* set tracing on all devices */
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
/* FIXME: Not very nice - see also hw-base.c */
|
||||
if (STATE_HW (sd)->trace_p)
|
||||
hw_tree_parse (STATE_HW (sd)->tree, "/global-trace? true");
|
||||
return SIM_RC_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPTION_HW_DEVICE:
|
||||
{
|
||||
hw_tree_parse (STATE_HW (sd)->tree, arg);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
case OPTION_HW_FILE:
|
||||
{
|
||||
return merge_device_file (sd, arg);
|
||||
}
|
||||
|
||||
default:
|
||||
sim_io_eprintf (sd, "Unknown hw option %d\n", opt);
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
}
|
||||
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
|
||||
|
||||
/* "hw" module install handler.
|
||||
|
||||
This is called via sim_module_install to install the "hw" subsystem
|
||||
into the simulator. */
|
||||
|
||||
static MODULE_INIT_FN sim_hw_init;
|
||||
static MODULE_UNINSTALL_FN sim_hw_uninstall;
|
||||
|
||||
SIM_RC
|
||||
sim_hw_install (struct sim_state *sd)
|
||||
{
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
sim_add_option_table (sd, NULL, hw_options);
|
||||
sim_module_add_uninstall_fn (sd, sim_hw_uninstall);
|
||||
sim_module_add_init_fn (sd, sim_hw_init);
|
||||
STATE_HW (sd) = ZALLOC (struct sim_hw);
|
||||
STATE_HW (sd)->tree = hw_tree_create (sd, "core");
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
static SIM_RC
|
||||
sim_hw_init (struct sim_state *sd)
|
||||
{
|
||||
/* FIXME: anything needed? */
|
||||
hw_tree_finish (STATE_HW (sd)->tree);
|
||||
if (STATE_HW (sd)->info_p)
|
||||
sim_hw_print (sd, sim_io_vprintf);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Uninstall the "hw" subsystem from the simulator. */
|
||||
|
||||
static void
|
||||
sim_hw_uninstall (struct sim_state *sd)
|
||||
{
|
||||
/* hw_tree_delete (STATE_HW (sd)->tree); */
|
||||
zfree (STATE_HW (sd));
|
||||
STATE_HW (sd) = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Data transfers to/from the hardware device tree. There are several
|
||||
cases. */
|
||||
|
||||
|
||||
/* CPU: The simulation is running and the current CPU/CIA
|
||||
initiates a data transfer. */
|
||||
|
||||
void
|
||||
sim_cpu_hw_io_read_buffer (sim_cpu *cpu,
|
||||
sim_cia cia,
|
||||
struct hw *hw,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes)
|
||||
{
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
STATE_HW (sd)->cpu = cpu;
|
||||
STATE_HW (sd)->cia = cia;
|
||||
if (hw_io_read_buffer (hw, dest, space, addr, nr_bytes) != nr_bytes)
|
||||
sim_engine_abort (sd, cpu, cia, "broken CPU read");
|
||||
}
|
||||
|
||||
void
|
||||
sim_cpu_hw_io_write_buffer (sim_cpu *cpu,
|
||||
sim_cia cia,
|
||||
struct hw *hw,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes)
|
||||
{
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
STATE_HW (sd)->cpu = cpu;
|
||||
STATE_HW (sd)->cia = cia;
|
||||
if (hw_io_write_buffer (hw, source, space, addr, nr_bytes) != nr_bytes)
|
||||
sim_engine_abort (sd, cpu, cia, "broken CPU write");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* SYSTEM: A data transfer is being initiated by the system. */
|
||||
|
||||
unsigned
|
||||
sim_hw_io_read_buffer (struct sim_state *sd,
|
||||
struct hw *hw,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes)
|
||||
{
|
||||
STATE_HW (sd)->cpu = NULL;
|
||||
return hw_io_read_buffer (hw, dest, space, addr, nr_bytes);
|
||||
}
|
||||
|
||||
unsigned
|
||||
sim_hw_io_write_buffer (struct sim_state *sd,
|
||||
struct hw *hw,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes)
|
||||
{
|
||||
STATE_HW (sd)->cpu = NULL;
|
||||
return hw_io_write_buffer (hw, source, space, addr, nr_bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Abort the simulation specifying HW as the reason */
|
||||
|
||||
void
|
||||
hw_vabort (struct hw *me,
|
||||
const char *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
const char *name;
|
||||
char *msg;
|
||||
/* find an identity */
|
||||
if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0')
|
||||
name = hw_path (me);
|
||||
else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0')
|
||||
name = hw_name (me);
|
||||
else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0')
|
||||
name = hw_family (me);
|
||||
else
|
||||
name = "device";
|
||||
/* construct an updated format string */
|
||||
msg = alloca (strlen (name) + strlen (": ") + strlen (fmt) + 1);
|
||||
strcpy (msg, name);
|
||||
strcat (msg, ": ");
|
||||
strcat (msg, fmt);
|
||||
/* report the problem */
|
||||
sim_engine_vabort (hw_system (me),
|
||||
STATE_HW (hw_system (me))->cpu,
|
||||
STATE_HW (hw_system (me))->cia,
|
||||
msg, ap);
|
||||
}
|
||||
|
||||
void
|
||||
hw_abort (struct hw *me,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
/* report the problem */
|
||||
va_start (ap, fmt);
|
||||
hw_vabort (me, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
void
|
||||
sim_hw_abort (struct sim_state *sd,
|
||||
struct hw *me,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
if (me == NULL)
|
||||
sim_engine_vabort (sd, NULL, NULL_CIA, fmt, ap);
|
||||
else
|
||||
hw_vabort (me, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
|
||||
/* MISC routines to tie HW into the rest of the system */
|
||||
|
||||
void
|
||||
hw_halt (struct hw *me,
|
||||
int reason,
|
||||
int status)
|
||||
{
|
||||
struct sim_state *sd = hw_system (me);
|
||||
struct sim_hw *sim = STATE_HW (sd);
|
||||
sim_engine_halt (sd, sim->cpu, NULL, sim->cia, reason, status);
|
||||
}
|
||||
|
||||
struct _sim_cpu *
|
||||
hw_system_cpu (struct hw *me)
|
||||
{
|
||||
return STATE_HW (hw_system (me))->cpu;
|
||||
}
|
||||
|
||||
void
|
||||
hw_trace (struct hw *me,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
if (hw_trace_p (me)) /* to be sure, to be sure */
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
sim_io_eprintf (hw_system (me), "%s: ", hw_path (me));
|
||||
sim_io_evprintf (hw_system (me), fmt, ap);
|
||||
sim_io_eprintf (hw_system (me), "\n");
|
||||
va_end (ap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin() */
|
||||
|
||||
int
|
||||
do_hw_poll_read (struct hw *me,
|
||||
do_hw_poll_read_method *read,
|
||||
int sim_io_fd,
|
||||
void *buf,
|
||||
unsigned sizeof_buf)
|
||||
{
|
||||
int status = read (hw_system (me), sim_io_fd, buf, sizeof_buf);
|
||||
if (status > 0)
|
||||
return status;
|
||||
else if (status == 0 && sizeof_buf == 0)
|
||||
return 0;
|
||||
else if (status == 0)
|
||||
return HW_IO_EOF;
|
||||
else /* status < 0 */
|
||||
{
|
||||
#ifdef EAGAIN
|
||||
if (STATE_CALLBACK (hw_system (me))->last_errno == EAGAIN)
|
||||
return HW_IO_NOT_READY;
|
||||
else
|
||||
return HW_IO_EOF;
|
||||
#else
|
||||
return HW_IO_EOF;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The event queue abstraction (for devices) */
|
||||
|
||||
|
||||
struct _hw_event {
|
||||
void *data;
|
||||
struct hw *me;
|
||||
hw_event_handler *handler;
|
||||
sim_event *real;
|
||||
};
|
||||
|
||||
/* Pass the H/W event onto the real handler */
|
||||
|
||||
static void
|
||||
bounce_hw_event (SIM_DESC sd,
|
||||
void *data)
|
||||
{
|
||||
hw_event event = * (hw_event*) data;
|
||||
zfree (data);
|
||||
/* if we are delivering an event, we don't have a CPU. */
|
||||
STATE_HW (sd)->cpu = NULL;
|
||||
event.handler (event.me, event.data);
|
||||
}
|
||||
|
||||
|
||||
/* Map onto the event functions */
|
||||
|
||||
hw_event *
|
||||
hw_event_queue_schedule (struct hw *me,
|
||||
signed64 delta_time,
|
||||
hw_event_handler *handler,
|
||||
void *data)
|
||||
{
|
||||
hw_event *event = ZALLOC (hw_event);
|
||||
event->data = data;
|
||||
event->handler = handler;
|
||||
event->me = me;
|
||||
event->real = sim_events_schedule (hw_system (me),
|
||||
delta_time,
|
||||
bounce_hw_event,
|
||||
event);
|
||||
return event;
|
||||
}
|
||||
|
||||
void
|
||||
hw_event_queue_deschedule (struct hw *me,
|
||||
hw_event *event_to_remove)
|
||||
{
|
||||
sim_events_deschedule (hw_system (me),
|
||||
event_to_remove->real);
|
||||
zfree (event_to_remove);
|
||||
}
|
||||
|
||||
signed64
|
||||
hw_event_queue_time (struct hw *me)
|
||||
{
|
||||
return sim_events_time (hw_system (me));
|
||||
}
|
@ -23,6 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "sim-options.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
/* start-sanitize-am30 */
|
||||
#if WITH_HW
|
||||
#include "sim-hw.h"
|
||||
#endif
|
||||
/* end-sanitize-am30 */
|
||||
|
||||
#include "libiberty.h"
|
||||
|
||||
/* List of all modules. */
|
||||
@ -50,11 +56,16 @@ static MODULE_INSTALL_FN * const modules[] = {
|
||||
scache_install,
|
||||
#endif
|
||||
#ifdef SIM_HAVE_MODEL
|
||||
model_install,
|
||||
sim_model_install,
|
||||
#endif
|
||||
#ifdef SIM_HAVE_BREAKPOINTS
|
||||
sim_break_install,
|
||||
#endif
|
||||
/* start-sanitize-am30 */
|
||||
#if WITH_HW
|
||||
sim_hw_install,
|
||||
#endif
|
||||
/* end-sanitize-am30 */
|
||||
/* Configured in [simulator specific] additional modules. */
|
||||
#ifdef MODULE_LIST
|
||||
MODULE_LIST
|
||||
|
Reference in New Issue
Block a user