Redo watchpoint code so that it target can specify interrupt names.
Replace v850 interrupt code with this common watchpoint code. Other minor fixes to core.
This commit is contained in:
parent
1b465b54e1
commit
1bba340afe
4 changed files with 371 additions and 215 deletions
|
@ -1,5 +1,20 @@
|
||||||
Fri Sep 5 08:39:02 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
Fri Sep 5 08:39:02 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* sim-core.c (sim_core_attach): Fix checks of modulo/mask.
|
||||||
|
|
||||||
|
* sim-watch.c (delete_watchpoint): Delete by ident and type.
|
||||||
|
(watch_option_handler): Call delete_watchpoint with ident or type.
|
||||||
|
(sim_watchpoint_install): Create interrupt specific watchpoint
|
||||||
|
commands on the fly.
|
||||||
|
(do_watchpoint_create): New function, create a watch point using
|
||||||
|
type/int-nr info encoded in the option nr.
|
||||||
|
(do_watchpoint_info): New function. List active watchpoints.
|
||||||
|
|
||||||
|
* sim-watch.h: Change data structure to a list.
|
||||||
|
|
||||||
|
* sim-memopt.c (memory_option_handler): Require explicit "all"
|
||||||
|
before deleting all memory regions.
|
||||||
|
|
||||||
* sim-utils.c (sim_do_commandf): New function, printf version of
|
* sim-utils.c (sim_do_commandf): New function, printf version of
|
||||||
sim_do_command.
|
sim_do_command.
|
||||||
|
|
||||||
|
|
|
@ -297,8 +297,12 @@ sim_core_attach (SIM_DESC sd,
|
||||||
if (mask < 7) /* 8 is minimum modulo */
|
if (mask < 7) /* 8 is minimum modulo */
|
||||||
mask = 0;
|
mask = 0;
|
||||||
while (mask > 1) /* no zero bits */
|
while (mask > 1) /* no zero bits */
|
||||||
|
{
|
||||||
if ((mask & 1) == 0)
|
if ((mask & 1) == 0)
|
||||||
mask = 0;
|
mask = 0;
|
||||||
|
else
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
if (mask == 0)
|
if (mask == 0)
|
||||||
{
|
{
|
||||||
#if (WITH_DEVICES)
|
#if (WITH_DEVICES)
|
||||||
|
@ -308,7 +312,7 @@ sim_core_attach (SIM_DESC sd,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (WITH_MODULO_MEMORY && modulo != 0)
|
else if (!WITH_MODULO_MEMORY && modulo != 0)
|
||||||
{
|
{
|
||||||
#if (WITH_DEVICES)
|
#if (WITH_DEVICES)
|
||||||
device_error (client, "sim_core_attach - internal error - modulo memory disabled");
|
device_error (client, "sim_core_attach - internal error - modulo memory disabled");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Mips simulator watchpoint support.
|
/* Generic simulator watchpoint support.
|
||||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||||
Contributed by Cygnus Support.
|
Contributed by Cygnus Support.
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include "sim-assert.h"
|
#include "sim-assert.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#ifdef HAVE_STRING_H
|
#ifdef HAVE_STRING_H
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#else
|
#else
|
||||||
|
@ -37,68 +39,167 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
static DECLARE_OPTION_HANDLER (watch_option_handler);
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OPTION_WATCH_DELETE = OPTION_START,
|
OPTION_WATCH_DELETE = OPTION_START,
|
||||||
|
|
||||||
OPTION_WATCH_PC,
|
OPTION_WATCH_INFO,
|
||||||
OPTION_WATCH_CLOCK,
|
OPTION_WATCH_CLOCK,
|
||||||
OPTION_WATCH_CYCLES,
|
OPTION_WATCH_CYCLES,
|
||||||
|
OPTION_WATCH_PC,
|
||||||
|
|
||||||
OPTION_ACTION_PC,
|
OPTION_WATCH_OP,
|
||||||
OPTION_ACTION_CLOCK,
|
|
||||||
OPTION_ACTION_CYCLES,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
/* Break an option number into its op/int-nr */
|
||||||
delete_watchpoint (SIM_DESC sd, watchpoint_type type)
|
static watchpoint_type
|
||||||
|
option_to_type (SIM_DESC sd,
|
||||||
|
int option)
|
||||||
{
|
{
|
||||||
sim_watch_point *point = &STATE_WATCHPOINTS (sd)->points[type];
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
if (point->event != NULL)
|
watchpoint_type type = ((option - OPTION_WATCH_OP)
|
||||||
sim_events_deschedule (sd, point->event);
|
/ (watch->nr_interrupts + 1));
|
||||||
point->action = invalid_watchpoint_action;
|
SIM_ASSERT (type >= 0 && type < nr_watchpoint_types);
|
||||||
point->event = NULL;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_to_interrupt_nr (SIM_DESC sd,
|
||||||
|
int option)
|
||||||
|
{
|
||||||
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
|
int interrupt_nr = ((option - OPTION_WATCH_OP)
|
||||||
|
% (watch->nr_interrupts + 1));
|
||||||
|
return interrupt_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
type_to_option (SIM_DESC sd,
|
||||||
|
watchpoint_type type,
|
||||||
|
int interrupt_nr)
|
||||||
|
{
|
||||||
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
|
return ((type * (watch->nr_interrupts + 1))
|
||||||
|
+ interrupt_nr
|
||||||
|
+ OPTION_WATCH_OP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Delete one or more watchpoints. Fail if no watchpoints were found */
|
||||||
|
|
||||||
|
static SIM_RC
|
||||||
|
do_watchpoint_delete (SIM_DESC sd,
|
||||||
|
int ident,
|
||||||
|
watchpoint_type type)
|
||||||
|
{
|
||||||
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
|
sim_watch_point **entry = &watch->points;
|
||||||
|
SIM_RC status = SIM_RC_FAIL;
|
||||||
|
while ((*entry) != NULL)
|
||||||
|
{
|
||||||
|
if ((*entry)->ident == ident
|
||||||
|
|| (*entry)->type == type)
|
||||||
|
{
|
||||||
|
sim_watch_point *dead = (*entry);
|
||||||
|
(*entry) = (*entry)->next;
|
||||||
|
sim_events_deschedule (sd, dead->event);
|
||||||
|
zfree (dead);
|
||||||
|
status = SIM_RC_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
entry = &(*entry)->next;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
watchpoint_type_to_str (SIM_DESC sd,
|
||||||
|
watchpoint_type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case pc_watchpoint:
|
||||||
|
return "pc";
|
||||||
|
case clock_watchpoint:
|
||||||
|
return "clock";
|
||||||
|
case cycles_watchpoint:
|
||||||
|
return "cycles";
|
||||||
|
case invalid_watchpoint:
|
||||||
|
case nr_watchpoint_types:
|
||||||
|
return "(invalid-type)";
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
interrupt_nr_to_str (SIM_DESC sd,
|
||||||
|
int interrupt_nr)
|
||||||
|
{
|
||||||
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
|
if (interrupt_nr < 0)
|
||||||
|
return "(invalid-interrupt)";
|
||||||
|
else if (interrupt_nr >= watch->nr_interrupts)
|
||||||
|
return "breakpoint";
|
||||||
|
else
|
||||||
|
return watch->interrupt_names[interrupt_nr];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_watchpoint_info (SIM_DESC sd)
|
||||||
|
{
|
||||||
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
|
sim_watch_point *point;
|
||||||
|
sim_io_printf (sd, "Watchpoints:\n");
|
||||||
|
for (point = watch->points; point != NULL; point = point->next)
|
||||||
|
{
|
||||||
|
sim_io_printf (sd, "%3d: watch %s %s ",
|
||||||
|
point->ident,
|
||||||
|
watchpoint_type_to_str (sd, point->type),
|
||||||
|
interrupt_nr_to_str (sd, point->interrupt_nr));
|
||||||
|
if (point->is_periodic)
|
||||||
|
sim_io_printf (sd, "+");
|
||||||
|
if (!point->is_within)
|
||||||
|
sim_io_printf (sd, "!");
|
||||||
|
sim_io_printf (sd, "0x%lx", point->arg0);
|
||||||
|
if (point->arg1 != point->arg0)
|
||||||
|
sim_io_printf (sd, ",0x%lx", point->arg1);
|
||||||
|
sim_io_printf (sd, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static sim_event_handler handle_watchpoint;
|
static sim_event_handler handle_watchpoint;
|
||||||
|
|
||||||
static SIM_RC
|
static SIM_RC
|
||||||
schedule_watchpoint (SIM_DESC sd,
|
schedule_watchpoint (SIM_DESC sd,
|
||||||
watchpoint_type type,
|
sim_watch_point *point)
|
||||||
unsigned long arg,
|
|
||||||
int is_within,
|
|
||||||
int is_command)
|
|
||||||
{
|
{
|
||||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
sim_watch_point *point = &watch->points[type];
|
switch (point->type)
|
||||||
if (point->event != NULL)
|
|
||||||
sim_events_deschedule (sd, point->event);
|
|
||||||
point->arg = arg;
|
|
||||||
point->is_within = is_within;
|
|
||||||
if (point->action == invalid_watchpoint_action)
|
|
||||||
point->action = break_watchpoint_action;
|
|
||||||
if (is_command)
|
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case pc_watchpoint:
|
case pc_watchpoint:
|
||||||
point->event = sim_events_watch_sim (sd, watch->pc, watch->sizeof_pc,
|
point->event = sim_events_watch_sim (sd,
|
||||||
|
watch->pc,
|
||||||
|
watch->sizeof_pc,
|
||||||
0/* host-endian */,
|
0/* host-endian */,
|
||||||
point->is_within,
|
point->is_within,
|
||||||
point->arg, point->arg, /* PC == arg? */
|
point->arg0, point->arg1,
|
||||||
|
/* PC in arg0..arg1 */
|
||||||
handle_watchpoint,
|
handle_watchpoint,
|
||||||
point);
|
point);
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
case clock_watchpoint:
|
case clock_watchpoint:
|
||||||
point->event = sim_events_watch_clock (sd,
|
point->event = sim_events_watch_clock (sd,
|
||||||
point->arg, /* ms time */
|
point->arg0, /* ms time */
|
||||||
handle_watchpoint,
|
handle_watchpoint,
|
||||||
point);
|
point);
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
case cycles_watchpoint:
|
case cycles_watchpoint:
|
||||||
point->event = sim_events_schedule (sd, point->arg, /* time */
|
point->event = sim_events_schedule (sd,
|
||||||
|
point->arg0, /* time */
|
||||||
handle_watchpoint,
|
handle_watchpoint,
|
||||||
point);
|
point);
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
|
@ -115,163 +216,139 @@ static void
|
||||||
handle_watchpoint (SIM_DESC sd, void *data)
|
handle_watchpoint (SIM_DESC sd, void *data)
|
||||||
{
|
{
|
||||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
sim_watch_point *point = data;
|
sim_watch_point *point = (sim_watch_point *) data;
|
||||||
watchpoint_type type = point - watch->points;
|
int interrupt_nr = point->interrupt_nr;
|
||||||
|
|
||||||
switch (point->action)
|
if (point->is_periodic)
|
||||||
{
|
/* reschedule this event before processing it */
|
||||||
|
schedule_watchpoint (sd, point);
|
||||||
|
else
|
||||||
|
do_watchpoint_delete (sd, point->ident, invalid_watchpoint);
|
||||||
|
|
||||||
case break_watchpoint_action:
|
if (point->interrupt_nr == watch->nr_interrupts)
|
||||||
point->event = NULL; /* gone */
|
|
||||||
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGINT);
|
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGINT);
|
||||||
break;
|
else
|
||||||
|
watch->interrupt_handler (sd, &interrupt_nr);
|
||||||
case n_interrupt_watchpoint_action:
|
|
||||||
/* First reschedule this event */
|
|
||||||
schedule_watchpoint (sd, type, point->arg, point->is_within, 1/*is-command*/);
|
|
||||||
/* FALL-THROUGH */
|
|
||||||
|
|
||||||
case interrupt_watchpoint_action:
|
|
||||||
watch->interrupt_handler (sd, NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
sim_engine_abort (sd, NULL, NULL_CIA,
|
|
||||||
"handle_watchpoint - internal error - bad switch");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SIM_RC
|
static SIM_RC
|
||||||
action_watchpoint (SIM_DESC sd, watchpoint_type type, const char *arg)
|
do_watchpoint_create (SIM_DESC sd,
|
||||||
|
watchpoint_type type,
|
||||||
|
int opt,
|
||||||
|
char *arg)
|
||||||
{
|
{
|
||||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
sim_watch_point *point = &watch->points[type];
|
sim_watch_point **point;
|
||||||
if (strcmp (arg, "break") == 0)
|
|
||||||
|
/* create the watchpoint */
|
||||||
|
point = &watch->points;
|
||||||
|
while ((*point) != NULL)
|
||||||
|
point = &(*point)->next;
|
||||||
|
(*point) = ZALLOC (sim_watch_point);
|
||||||
|
|
||||||
|
/* fill in the details */
|
||||||
|
(*point)->ident = ++(watch->last_point_nr);
|
||||||
|
(*point)->type = option_to_type (sd, opt);
|
||||||
|
(*point)->interrupt_nr = option_to_interrupt_nr (sd, opt);
|
||||||
|
/* prefixes to arg - +== periodic, !==not or outside */
|
||||||
|
(*point)->is_within = 1;
|
||||||
|
while (1)
|
||||||
{
|
{
|
||||||
point->action = break_watchpoint_action;
|
if (arg[0] == '+')
|
||||||
}
|
(*point)->is_periodic = 1;
|
||||||
else if (strcmp (arg, "int") == 0)
|
else if (arg[0] == '!')
|
||||||
{
|
(*point)->is_within = 0;
|
||||||
if (watch->interrupt_handler == NULL)
|
|
||||||
{
|
|
||||||
sim_io_eprintf (sd, "This simulator does not support int watchpoints\n");
|
|
||||||
return SIM_RC_FAIL;
|
|
||||||
}
|
|
||||||
point->action = interrupt_watchpoint_action;
|
|
||||||
}
|
|
||||||
else if (strcmp (arg, "+int") == 0)
|
|
||||||
{
|
|
||||||
if (watch->interrupt_handler == NULL)
|
|
||||||
{
|
|
||||||
sim_io_eprintf (sd, "This simulator does not support int watchpoints\n");
|
|
||||||
return SIM_RC_FAIL;
|
|
||||||
}
|
|
||||||
point->action = n_interrupt_watchpoint_action;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
break;
|
||||||
sim_io_eprintf (sd, "Interrupts other than `int' currently unsuported\n");
|
arg++;
|
||||||
return SIM_RC_FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(*point)->arg0 = strtoul (arg, &arg, 0);
|
||||||
|
if (arg[0] == ',')
|
||||||
|
(*point)->arg0 = strtoul (arg, NULL, 0);
|
||||||
|
else
|
||||||
|
(*point)->arg1 = (*point)->arg0;
|
||||||
|
|
||||||
|
/* schedule it */
|
||||||
|
schedule_watchpoint (sd, (*point));
|
||||||
|
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const OPTION watch_options[] =
|
|
||||||
{
|
|
||||||
{ {"watch-delete", required_argument, NULL, OPTION_WATCH_DELETE },
|
|
||||||
'\0', "all|pc|cycles|clock", "Delete a watchpoint",
|
|
||||||
watch_option_handler },
|
|
||||||
{ {"delete-watch", required_argument, NULL, OPTION_WATCH_DELETE },
|
|
||||||
'\0', "all|pc|cycles|clock", NULL,
|
|
||||||
watch_option_handler },
|
|
||||||
|
|
||||||
{ {"watch-pc", required_argument, NULL, OPTION_WATCH_PC },
|
|
||||||
'\0', "[!] VALUE", "Watch the PC (break)",
|
|
||||||
watch_option_handler },
|
|
||||||
{ {"watch-clock", required_argument, NULL, OPTION_WATCH_CLOCK },
|
|
||||||
'\0', "TIME-IN-MS", "Watch the clock (break)",
|
|
||||||
watch_option_handler },
|
|
||||||
{ {"watch-cycles", required_argument, NULL, OPTION_WATCH_CYCLES },
|
|
||||||
'\0', "CYCLES", "Watch the cycles (break)",
|
|
||||||
watch_option_handler },
|
|
||||||
|
|
||||||
{ {"action-pc", required_argument, NULL, OPTION_ACTION_PC },
|
|
||||||
'\0', "break|int|+int", "Action taken by PC watchpoint",
|
|
||||||
watch_option_handler },
|
|
||||||
{ {"action-clock", required_argument, NULL, OPTION_ACTION_CLOCK },
|
|
||||||
'\0', "break|int|+int", "Action taken by CLOCK watchpoint",
|
|
||||||
watch_option_handler },
|
|
||||||
{ {"action-cycles", required_argument, NULL, OPTION_ACTION_CYCLES },
|
|
||||||
'\0', "break|int|+int", "Action taken by CYCLES watchpoint",
|
|
||||||
watch_option_handler },
|
|
||||||
|
|
||||||
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static SIM_RC
|
static SIM_RC
|
||||||
watch_option_handler (sd, opt, arg, is_command)
|
watchpoint_option_handler (sd, opt, arg, is_command)
|
||||||
SIM_DESC sd;
|
SIM_DESC sd;
|
||||||
int opt;
|
int opt;
|
||||||
char *arg;
|
char *arg;
|
||||||
int is_command;
|
int is_command;
|
||||||
{
|
{
|
||||||
|
if (opt >= OPTION_WATCH_OP)
|
||||||
|
return do_watchpoint_create (sd, clock_watchpoint, opt, arg);
|
||||||
|
else
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
|
|
||||||
case OPTION_WATCH_DELETE:
|
case OPTION_WATCH_DELETE:
|
||||||
if (strcmp (arg, "all") == 0
|
if (isdigit ((int) arg[0]))
|
||||||
|| strcmp (arg, "pc") == 0)
|
|
||||||
{
|
{
|
||||||
delete_watchpoint (sd, pc_watchpoint);
|
int ident = strtol (arg, NULL, 0);
|
||||||
|
if (do_watchpoint_delete (sd, ident, invalid_watchpoint)
|
||||||
|
!= SIM_RC_OK)
|
||||||
|
{
|
||||||
|
sim_io_eprintf (sd, "Watchpoint %d not found\n", ident);
|
||||||
|
return SIM_RC_FAIL;
|
||||||
|
}
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
if (strcmp (arg, "all") == 0
|
else if (strcasecmp (arg, "all") == 0)
|
||||||
|| strcmp (arg, "clock") == 0)
|
|
||||||
{
|
{
|
||||||
delete_watchpoint (sd, clock_watchpoint);
|
watchpoint_type type;
|
||||||
|
for (type = invalid_watchpoint + 1;
|
||||||
|
type < nr_watchpoint_types;
|
||||||
|
type++)
|
||||||
|
{
|
||||||
|
do_watchpoint_delete (sd, 0, type);
|
||||||
|
}
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
if (strcmp (arg, "all") == 0
|
else if (strcasecmp (arg, "pc") == 0)
|
||||||
|| strcmp (arg, "cycles") == 0)
|
|
||||||
{
|
{
|
||||||
delete_watchpoint (sd, cycles_watchpoint);
|
if (do_watchpoint_delete (sd, 0, pc_watchpoint)
|
||||||
|
!= SIM_RC_OK)
|
||||||
|
{
|
||||||
|
sim_io_eprintf (sd, "No PC watchpoints found\n");
|
||||||
|
return SIM_RC_FAIL;
|
||||||
|
}
|
||||||
|
return SIM_RC_OK;
|
||||||
|
}
|
||||||
|
else if (strcasecmp (arg, "clock") == 0)
|
||||||
|
{
|
||||||
|
if (do_watchpoint_delete (sd, 0, clock_watchpoint) != SIM_RC_OK)
|
||||||
|
{
|
||||||
|
sim_io_eprintf (sd, "No CLOCK watchpoints found\n");
|
||||||
|
return SIM_RC_FAIL;
|
||||||
|
}
|
||||||
|
return SIM_RC_OK;
|
||||||
|
}
|
||||||
|
else if (strcasecmp (arg, "cycles") == 0)
|
||||||
|
{
|
||||||
|
if (do_watchpoint_delete (sd, 0, cycles_watchpoint) != SIM_RC_OK)
|
||||||
|
{
|
||||||
|
sim_io_eprintf (sd, "No CYCLES watchpoints found\n");
|
||||||
|
return SIM_RC_FAIL;
|
||||||
|
}
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
sim_io_eprintf (sd, "Unknown watchpoint type `%s'\n", arg);
|
sim_io_eprintf (sd, "Unknown watchpoint type `%s'\n", arg);
|
||||||
return SIM_RC_FAIL;
|
return SIM_RC_FAIL;
|
||||||
|
|
||||||
case OPTION_WATCH_PC:
|
case OPTION_WATCH_INFO:
|
||||||
if (STATE_WATCHPOINTS (sd)->pc == NULL)
|
|
||||||
{
|
{
|
||||||
sim_io_eprintf (sd, "PC watchpoints are not supported for this simulator\n");
|
do_watchpoint_info (sd);
|
||||||
return SIM_RC_FAIL;
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
if (arg[0] == '!')
|
|
||||||
return schedule_watchpoint (sd, pc_watchpoint, strtoul (arg + 1, NULL, 0),
|
|
||||||
0 /* !is_within */, is_command);
|
|
||||||
else
|
|
||||||
return schedule_watchpoint (sd, pc_watchpoint, strtoul (arg, NULL, 0),
|
|
||||||
1 /* is_within */, is_command);
|
|
||||||
|
|
||||||
case OPTION_WATCH_CLOCK:
|
|
||||||
return schedule_watchpoint (sd, clock_watchpoint, strtoul (arg, NULL, 0), 0, is_command);
|
|
||||||
|
|
||||||
case OPTION_WATCH_CYCLES:
|
|
||||||
return schedule_watchpoint (sd, cycles_watchpoint, strtoul (arg, NULL, 0), 0, is_command);
|
|
||||||
|
|
||||||
case OPTION_ACTION_PC:
|
|
||||||
return action_watchpoint (sd, pc_watchpoint, arg);
|
|
||||||
|
|
||||||
case OPTION_ACTION_CLOCK:
|
|
||||||
return action_watchpoint (sd, clock_watchpoint, arg);
|
|
||||||
|
|
||||||
case OPTION_ACTION_CYCLES:
|
|
||||||
return action_watchpoint (sd, cycles_watchpoint, arg);
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sim_io_eprintf (sd, "Unknown watch option %d\n", opt);
|
sim_io_eprintf (sd, "Unknown watch option %d\n", opt);
|
||||||
|
@ -281,29 +358,81 @@ watch_option_handler (sd, opt, arg, is_command)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SIM_RC
|
static SIM_RC
|
||||||
sim_watchpoint_init (SIM_DESC sd)
|
sim_watchpoint_init (SIM_DESC sd)
|
||||||
{
|
{
|
||||||
/* schedule any watchpoints enabled by command line options */
|
|
||||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
watchpoint_type type;
|
sim_watch_point *point;
|
||||||
for (type = 0; type < nr_watchpoint_types; type++)
|
/* NOTE: Do not need to de-schedule any previous watchpoints as
|
||||||
|
sim-events has already done this */
|
||||||
|
/* schedule any watchpoints enabled by command line options */
|
||||||
|
for (point = watch->points; point != NULL; point = point->next)
|
||||||
{
|
{
|
||||||
if (watch->points[type].action != invalid_watchpoint_action)
|
schedule_watchpoint (sd, point);
|
||||||
schedule_watchpoint (sd, type,
|
|
||||||
watch->points[type].arg,
|
|
||||||
watch->points[type].is_within,
|
|
||||||
1 /*is-command*/);
|
|
||||||
}
|
}
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const OPTION watchpoint_options[] =
|
||||||
|
{
|
||||||
|
{ {"watch-delete", required_argument, NULL, OPTION_WATCH_DELETE },
|
||||||
|
'\0', "IDENT|all|pc|cycles|clock", "Delete a watchpoint",
|
||||||
|
watchpoint_option_handler },
|
||||||
|
|
||||||
|
{ {"watch-info", no_argument, NULL, OPTION_WATCH_INFO },
|
||||||
|
'\0', NULL, "List scheduled watchpoints",
|
||||||
|
watchpoint_option_handler },
|
||||||
|
|
||||||
|
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const OPTION template_int_option = {
|
||||||
|
{ NULL, required_argument, NULL, 0 },
|
||||||
|
'\0', "VALUE", "Create the specified watchpoint",
|
||||||
|
watchpoint_option_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *default_interrupt_names[] = { "int", 0, };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SIM_RC
|
SIM_RC
|
||||||
sim_watchpoint_install (SIM_DESC sd)
|
sim_watchpoint_install (SIM_DESC sd)
|
||||||
{
|
{
|
||||||
|
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||||
sim_add_option_table (sd, watch_options);
|
/* the basic command set */
|
||||||
sim_module_add_init_fn (sd, sim_watchpoint_init);
|
sim_module_add_init_fn (sd, sim_watchpoint_init);
|
||||||
|
sim_add_option_table (sd, watchpoint_options);
|
||||||
|
/* fill in some details */
|
||||||
|
if (watch->interrupt_names == NULL)
|
||||||
|
watch->interrupt_names = default_interrupt_names;
|
||||||
|
watch->nr_interrupts = 0;
|
||||||
|
while (watch->interrupt_names[watch->nr_interrupts] != NULL)
|
||||||
|
watch->nr_interrupts++;
|
||||||
|
/* generate more advansed commands */
|
||||||
|
{
|
||||||
|
OPTION *int_options = NZALLOC (OPTION, 1 + (watch->nr_interrupts + 1) * nr_watchpoint_types);
|
||||||
|
int interrupt_nr;
|
||||||
|
for (interrupt_nr = 0; interrupt_nr <= watch->nr_interrupts; interrupt_nr++)
|
||||||
|
{
|
||||||
|
watchpoint_type type;
|
||||||
|
for (type = 0; type < nr_watchpoint_types; type++)
|
||||||
|
{
|
||||||
|
int nr = interrupt_nr * nr_watchpoint_types + type;
|
||||||
|
OPTION *option = &int_options[nr];
|
||||||
|
char *name;
|
||||||
|
*option = template_int_option;
|
||||||
|
asprintf (&name, "watch-%s-%s",
|
||||||
|
watchpoint_type_to_str (sd, type),
|
||||||
|
interrupt_nr_to_str (sd, interrupt_nr));
|
||||||
|
option->opt.name = name;
|
||||||
|
option->opt.val = type_to_option (sd, type, interrupt_nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sim_add_option_table (sd, int_options);
|
||||||
|
}
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,25 +23,25 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define SIM_WATCH_H
|
#define SIM_WATCH_H
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
invalid_watchpoint = -1,
|
||||||
pc_watchpoint,
|
pc_watchpoint,
|
||||||
clock_watchpoint,
|
clock_watchpoint,
|
||||||
cycles_watchpoint,
|
cycles_watchpoint,
|
||||||
nr_watchpoint_types,
|
nr_watchpoint_types,
|
||||||
} watchpoint_type;
|
} watchpoint_type;
|
||||||
|
|
||||||
typedef enum {
|
typedef struct _sim_watch_point sim_watch_point;
|
||||||
invalid_watchpoint_action,
|
struct _sim_watch_point {
|
||||||
n_interrupt_watchpoint_action,
|
int ident;
|
||||||
interrupt_watchpoint_action,
|
watchpoint_type type;
|
||||||
break_watchpoint_action,
|
int interrupt_nr; /* == nr_interrupts -> breakpoint */
|
||||||
} watchpoint_action;
|
int is_periodic;
|
||||||
|
|
||||||
typedef struct _sim_watch_point {
|
|
||||||
watchpoint_action action;
|
|
||||||
int is_within;
|
int is_within;
|
||||||
long arg;
|
unsigned long arg0;
|
||||||
|
unsigned long arg1;
|
||||||
sim_event *event;
|
sim_event *event;
|
||||||
} sim_watch_point;
|
sim_watch_point *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct _sim_watchpoints {
|
typedef struct _sim_watchpoints {
|
||||||
|
@ -55,10 +55,18 @@ typedef struct _sim_watchpoints {
|
||||||
|
|
||||||
/* Pointer to the handler for interrupt watchpoints */
|
/* Pointer to the handler for interrupt watchpoints */
|
||||||
/* FIXME: can this be done better? */
|
/* FIXME: can this be done better? */
|
||||||
|
/* NOTE, interrupt is passed in as the target of the pointer! */
|
||||||
sim_event_handler *interrupt_handler;
|
sim_event_handler *interrupt_handler;
|
||||||
|
|
||||||
/* suported watchpoints */
|
/* Pointer to a null terminated list of interrupt names */
|
||||||
sim_watch_point points[nr_watchpoint_types];
|
/* FIXME: can this be done better? Look at the PPC's interrupt
|
||||||
|
mechanism and table for a rough idea of where it will go next */
|
||||||
|
int nr_interrupts;
|
||||||
|
char **interrupt_names;
|
||||||
|
|
||||||
|
/* active watchpoints */
|
||||||
|
int last_point_nr;
|
||||||
|
sim_watch_point *points;
|
||||||
|
|
||||||
} sim_watchpoints;
|
} sim_watchpoints;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue