Watchpoint interface.
This commit is contained in:
parent
003c91bec4
commit
50a2a69182
@ -1,6 +1,13 @@
|
||||
Wed May 21 16:47:53 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* remote-sim.h (sim_set_profile_size): Add prototype, document as
|
||||
depreciated.
|
||||
|
||||
Tue May 20 09:32:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* remote-sim.h (sim_open): Add callback struct.
|
||||
(sim_set_callbacks): Drop SIM_DESC argument. Document.
|
||||
(sim_size): Remove recently added SIM_DESC argument. Document.
|
||||
|
||||
Mon May 19 19:14:44 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
|
@ -163,23 +163,22 @@ void sim_do_command PARAMS ((SIM_DESC sd, char *cmd));
|
||||
|
||||
|
||||
/* NOTE: sim_set_callbacks () is depreciated.
|
||||
|
||||
Provide simulator with a default (global) host_callback_struct. */
|
||||
|
||||
void sim_set_callbacks PARAMS ((struct host_callback_struct *));
|
||||
|
||||
|
||||
/* NOTE: sim_size() is depreciated.
|
||||
|
||||
sim_size() does not take a SIM_DESC argument as this function is
|
||||
used before sim_open() has been called. */
|
||||
|
||||
void sim_size PARAMS ((int i));
|
||||
|
||||
|
||||
/* NOTE: sim_trace() is depreciated. */
|
||||
|
||||
int sim_trace PARAMS ((SIM_DESC sd));
|
||||
|
||||
|
||||
/* NOTE: sim_set_profile_size is depreciated */
|
||||
void sim_set_profile_size PARAMS ((int n));
|
||||
|
||||
|
||||
#endif /* !defined (REMOTE_SIM_H) */
|
||||
|
@ -1,3 +1,64 @@
|
||||
Wed May 21 08:47:30 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* cgen-scache.c (scache_option_handler): Add is_command arg.
|
||||
|
||||
* sim-model.c (model_option_handler): Add is_command argument.
|
||||
|
||||
* sim-profile.c (profile_option_handler): Add is_command arg.
|
||||
|
||||
* sim-events.c (sim_watch_valid): Use ub64, lb64 when 64bit value
|
||||
involved.
|
||||
|
||||
* sim-module.c (sim_module_add_init_fn): Call init fn in the same
|
||||
order that they are registered.
|
||||
|
||||
* sim-options.h (OPTION_HANDLER): Add argument to differentiate
|
||||
between option and command line processing.
|
||||
|
||||
* sim-options.c: Include stdlib.h, ctype.h.
|
||||
|
||||
* Make-common.in (sim-watch.o): Add rule.
|
||||
(sim_main_headers): Assume sim-assert.h included.
|
||||
(sim-*.o): Simplify make rule.
|
||||
|
||||
* sim-module.c: Add sim_watch_install to module list.
|
||||
|
||||
Tue May 20 14:15:23 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* sim-base.h (STATE_LOADED_P): New predicate. Set once everything
|
||||
has been loaded.
|
||||
|
||||
* sim-trace.c (trace_install): Check magic. Include sim-assert.h.
|
||||
* sim-events.c (sim_events_install): Ditto.
|
||||
* sim-core.c (sim_core_install): Ditto.
|
||||
* sim-model.c (model_install): Ditto.
|
||||
* sim-options.c (standard_install): Ditto.
|
||||
* sim-profile.c (profile_install): Ditto.
|
||||
* sim-reason.c (sim_stop_reason): Ditto.
|
||||
* sim-run.c (sim_engine_run): Ditto.
|
||||
* sim-utils.c (sim_analyze_program): Ditto.
|
||||
|
||||
* sim-module.c (modules): Make profile_install and trace_install
|
||||
optional.
|
||||
|
||||
* sim-base.h (STATE_MEM_BASE): Define for flat memory systems.
|
||||
|
||||
* sim-options.c (standard_option_handler): Set the byte order.
|
||||
|
||||
* sim-events.c (sim_events_process): Allow multi tick processing.
|
||||
(sim_events_tickn): New function - multi cycle tick.
|
||||
|
||||
* sim-events.h (sim_events_tickn, sim_events_timewarp): Add
|
||||
prototypes. Under development.
|
||||
(sim_events): Replace processing with nr_ticks_to_process.
|
||||
|
||||
Tue May 20 09:39:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* nrun.c (main): Pass callbacks to sim_open instead of using
|
||||
sim_set_callbacks.
|
||||
|
||||
* run.c (main): Ditto.
|
||||
|
||||
Mon May 19 12:07:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* sim-events.c (sim_events_zalloc): Signal save memory allocator -
|
||||
|
@ -34,6 +34,7 @@ EXTERN_SIM_CORE\
|
||||
(SIM_RC)
|
||||
sim_core_install (SIM_DESC sd)
|
||||
{
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
sim_module_add_uninstall_fn (sd, sim_core_uninstall);
|
||||
sim_module_add_init_fn (sd, sim_core_init);
|
||||
return SIM_RC_OK;
|
||||
@ -77,6 +78,40 @@ sim_core_init (SIM_DESC sd)
|
||||
|
||||
|
||||
|
||||
#ifndef SIM_CORE_SIGNAL
|
||||
#define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
|
||||
sim_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR))
|
||||
|
||||
static void
|
||||
sim_core_signal (SIM_DESC sd,
|
||||
sim_cpu *cpu,
|
||||
sim_cia cia,
|
||||
sim_core_maps map,
|
||||
int nr_bytes,
|
||||
address_word addr,
|
||||
transfer_type transfer,
|
||||
sim_core_signals sig)
|
||||
{
|
||||
const char *copy = (transfer == read_transfer ? "read" : "write");
|
||||
switch (sig)
|
||||
{
|
||||
case sim_core_unmapped_signal:
|
||||
sim_engine_abort (sd, cpu, cia, "sim-core: %d byte %s to unmaped address 0x%lx",
|
||||
nr_bytes, copy, (unsigned long) addr);
|
||||
break;
|
||||
case sim_core_unaligned_signal:
|
||||
sim_engine_abort (sd, cpu, cia, "sim-core: %d byte misaligned %s to address 0x%lx",
|
||||
nr_bytes, copy, (unsigned long) addr);
|
||||
break;
|
||||
default:
|
||||
sim_engine_abort (sd, cpu, cia, "sim_core_signal - internal error - bad switch");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
STATIC_INLINE_SIM_CORE\
|
||||
(const char *)
|
||||
sim_core_map_to_str (sim_core_maps map)
|
||||
@ -94,13 +129,13 @@ sim_core_map_to_str (sim_core_maps map)
|
||||
STATIC_INLINE_SIM_CORE\
|
||||
(sim_core_mapping *)
|
||||
new_sim_core_mapping(SIM_DESC sd,
|
||||
attach_type attach,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
device *device,
|
||||
void *buffer,
|
||||
int free_buffer)
|
||||
attach_type attach,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
device *device,
|
||||
void *buffer,
|
||||
int free_buffer)
|
||||
{
|
||||
sim_core_mapping *new_mapping = ZALLOC(sim_core_mapping);
|
||||
/* common */
|
||||
@ -292,6 +327,7 @@ sim_core_find_mapping(sim_core *core,
|
||||
sim_core_maps map,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
transfer_type transfer,
|
||||
int abort, /*either 0 or 1 - hint to inline/-O */
|
||||
sim_cpu *cpu, /* abort => cpu != NULL */
|
||||
sim_cia cia)
|
||||
@ -309,12 +345,8 @@ sim_core_find_mapping(sim_core *core,
|
||||
}
|
||||
if (abort)
|
||||
{
|
||||
if (cpu == NULL)
|
||||
sim_io_error (NULL, "sim_core_find_map - internal error - can not abort without a processor");
|
||||
else
|
||||
engine_error (CPU_STATE (cpu), cpu, cia,
|
||||
"access to unmaped address 0x%lx (%d bytes)\n",
|
||||
(unsigned long) addr, nr_bytes);
|
||||
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, nr_bytes, addr, transfer,
|
||||
sim_core_unmapped_signal);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -342,7 +374,8 @@ sim_core_read_buffer(SIM_DESC sd,
|
||||
unsigned_word raddr = addr + count;
|
||||
sim_core_mapping *mapping =
|
||||
sim_core_find_mapping(STATE_CORE (sd), map,
|
||||
raddr, 1,
|
||||
raddr, /*nr-bytes*/1,
|
||||
read_transfer,
|
||||
0, NULL, NULL_CIA); /*dont-abort*/
|
||||
if (mapping == NULL)
|
||||
break;
|
||||
@ -383,7 +416,8 @@ sim_core_write_buffer(SIM_DESC sd,
|
||||
while (count < len) {
|
||||
unsigned_word raddr = addr + count;
|
||||
sim_core_mapping *mapping = sim_core_find_mapping(STATE_CORE (sd), map,
|
||||
raddr, 1,
|
||||
raddr, /*nr-bytes*/1,
|
||||
write_transfer,
|
||||
0, NULL, NULL_CIA); /*dont-abort*/
|
||||
if (mapping == NULL)
|
||||
break;
|
||||
|
@ -25,8 +25,17 @@
|
||||
#include "sim-main.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
watch_invalid,
|
||||
|
||||
@ -67,11 +76,11 @@ typedef enum {
|
||||
|
||||
/* timer */
|
||||
watch_timer,
|
||||
} sim_watchpoints;
|
||||
} sim_event_watchpoints;
|
||||
|
||||
|
||||
struct _sim_event {
|
||||
sim_watchpoints watching;
|
||||
sim_event_watchpoints watching;
|
||||
void *data;
|
||||
sim_event_handler *handler;
|
||||
/* timer event */
|
||||
@ -102,8 +111,9 @@ struct _sim_event {
|
||||
|
||||
TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
|
||||
event is pending, this will be positive. If no future event is
|
||||
pending this will be negative. This variable is decremented once
|
||||
for each iteration of a clock cycle.
|
||||
pending (eg when poll-event is being processed) this will be
|
||||
negative. This variable is decremented once for each iteration of
|
||||
a clock cycle.
|
||||
|
||||
Initially, the clock is started at time one (0) with TIME_OF_EVENT
|
||||
== 0 and TIME_FROM_EVENT == 0.
|
||||
@ -118,7 +128,7 @@ struct _sim_event {
|
||||
|
||||
|
||||
#if !defined (SIM_EVENTS_POLL_RATE)
|
||||
#define SIM_EVENTS_POLL_RATE 0x4000
|
||||
#define SIM_EVENTS_POLL_RATE 0x100000
|
||||
#endif
|
||||
|
||||
|
||||
@ -142,7 +152,8 @@ do \
|
||||
while (0)
|
||||
|
||||
|
||||
/* event queue iterator */
|
||||
/* event queue iterator - don't iterate over the held queue. */
|
||||
|
||||
STATIC_INLINE_SIM_EVENTS\
|
||||
(sim_event **)
|
||||
next_event_queue (SIM_DESC sd,
|
||||
@ -181,6 +192,7 @@ EXTERN_SIM_EVENTS\
|
||||
(SIM_RC)
|
||||
sim_events_install (SIM_DESC sd)
|
||||
{
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
sim_module_add_uninstall_fn (sd, sim_events_uninstall);
|
||||
sim_module_add_init_fn (sd, sim_events_init);
|
||||
return SIM_RC_OK;
|
||||
@ -197,6 +209,48 @@ sim_events_uninstall (SIM_DESC sd)
|
||||
}
|
||||
|
||||
|
||||
/* malloc/free */
|
||||
|
||||
STATIC_INLINE_SIM_EVENTS\
|
||||
(sim_event *)
|
||||
sim_events_zalloc (SIM_DESC sd)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
sim_event *new = events->free_list;
|
||||
if (new != NULL)
|
||||
{
|
||||
events->free_list = new->next;
|
||||
memset (new, 0, sizeof (*new));
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
|
||||
/*-LOCK-*/
|
||||
sigset_t old_mask;
|
||||
sigset_t new_mask;
|
||||
sigfillset(&new_mask);
|
||||
sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
|
||||
#endif
|
||||
new = ZALLOC (sim_event);
|
||||
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
|
||||
/*-UNLOCK-*/
|
||||
sigprocmask (SIG_SETMASK, &old_mask, NULL);
|
||||
#endif
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
STATIC_INLINE_SIM_EVENTS\
|
||||
(void)
|
||||
sim_events_free (SIM_DESC sd,
|
||||
sim_event *dead)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
dead->next = events->free_list;
|
||||
events->free_list = dead;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the simulator event manager */
|
||||
|
||||
EXTERN_SIM_EVENTS\
|
||||
@ -206,27 +260,9 @@ sim_events_init (SIM_DESC sd)
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
|
||||
/* drain the interrupt queue */
|
||||
{
|
||||
sim_event *event;
|
||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||
sigset_t old_mask;
|
||||
sigset_t new_mask;
|
||||
sigfillset(&new_mask);
|
||||
/*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
|
||||
#endif
|
||||
event = events->held;
|
||||
while (event != NULL) {
|
||||
sim_event *dead = event;
|
||||
event = event->next;
|
||||
zfree(dead);
|
||||
}
|
||||
events->held = NULL;
|
||||
events->held_end = &events->held;
|
||||
events->work_pending = 0;
|
||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||
/*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
#endif
|
||||
}
|
||||
events->nr_held = 0;
|
||||
if (events->held == NULL)
|
||||
events->held = zalloc (sizeof (sim_event) * MAX_NR_SIGNAL_SIM_EVENTS);
|
||||
|
||||
/* drain the normal queues */
|
||||
{
|
||||
@ -238,14 +274,14 @@ sim_events_init (SIM_DESC sd)
|
||||
{
|
||||
sim_event *dead = *queue;
|
||||
*queue = dead->next;
|
||||
zfree (dead);
|
||||
sim_events_free (sd, dead);
|
||||
}
|
||||
*queue = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* wind time back to zero */
|
||||
events->processing = 1; /* start by doing queue */
|
||||
events->nr_ticks_to_process = 1; /* start by doing queue */
|
||||
events->time_of_event = 0;
|
||||
events->time_from_event = 0;
|
||||
events->initial_wallclock = sim_elapsed_time_get ();
|
||||
@ -337,7 +373,7 @@ sim_events_schedule (SIM_DESC sd,
|
||||
sim_event_handler *handler,
|
||||
void *data)
|
||||
{
|
||||
sim_event *new_event = ZALLOC(sim_event);
|
||||
sim_event *new_event = sim_events_zalloc (sd);
|
||||
new_event->data = data;
|
||||
new_event->handler = handler;
|
||||
new_event->watching = watch_timer;
|
||||
@ -354,70 +390,69 @@ sim_events_schedule (SIM_DESC sd,
|
||||
|
||||
|
||||
EXTERN_SIM_EVENTS\
|
||||
(sim_event *)
|
||||
sim_events_schedule_after_signal(SIM_DESC sd,
|
||||
signed64 delta_time,
|
||||
sim_event_handler *handler,
|
||||
void *data)
|
||||
(void)
|
||||
sim_events_schedule_after_signal (SIM_DESC sd,
|
||||
signed64 delta_time,
|
||||
sim_event_handler *handler,
|
||||
void *data)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
sim_event *new_event = ZALLOC (sim_event);
|
||||
sim_event *new_event;
|
||||
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
|
||||
/*-LOCK-*/
|
||||
sigset_t old_mask;
|
||||
sigset_t new_mask;
|
||||
sigfillset(&new_mask);
|
||||
sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
|
||||
#endif
|
||||
|
||||
/* allocate an event entry from the signal buffer */
|
||||
new_event = &events->held [events->nr_held];
|
||||
events->nr_held ++;
|
||||
if (events->nr_held >= MAX_NR_SIGNAL_SIM_EVENTS)
|
||||
{
|
||||
sim_engine_abort (NULL, NULL, NULL_CIA,
|
||||
"sim_events_schedule_after_signal - buffer oveflow");
|
||||
}
|
||||
|
||||
new_event->data = data;
|
||||
new_event->handler = handler;
|
||||
new_event->time_of_event = delta_time; /* work it out later */
|
||||
new_event->next = NULL;
|
||||
|
||||
{
|
||||
|
||||
events->work_pending = 1; /* notify main process */
|
||||
|
||||
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
|
||||
/*-LOCK-*/
|
||||
sigset_t old_mask;
|
||||
sigset_t new_mask;
|
||||
sigfillset(&new_mask);
|
||||
sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
|
||||
/*-UNLOCK-*/
|
||||
sigprocmask (SIG_SETMASK, &old_mask, NULL);
|
||||
#endif
|
||||
if (events->held == NULL) {
|
||||
events->held = new_event;
|
||||
}
|
||||
else {
|
||||
*events->held_end = new_event;
|
||||
}
|
||||
events->held_end = &new_event->next;
|
||||
events->work_pending = 1; /* notify main process */
|
||||
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
|
||||
/*-UNLOCK-*/
|
||||
sigprocmask (SIG_SETMASK, &old_mask, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
ETRACE ((_ETRACE,
|
||||
"event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
||||
"signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
||||
(long)sim_events_time(sd),
|
||||
(long)new_event,
|
||||
(long)new_event->time_of_event,
|
||||
(long)new_event->handler,
|
||||
(long)new_event->data));
|
||||
|
||||
return new_event;
|
||||
}
|
||||
|
||||
|
||||
EXTERN_SIM_EVENTS\
|
||||
(sim_event *)
|
||||
sim_events_watch_clock (SIM_DESC sd,
|
||||
unsigned wallclock_ms_time,
|
||||
unsigned delta_ms_time,
|
||||
sim_event_handler *handler,
|
||||
void *data)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
sim_event *new_event = ZALLOC (sim_event);
|
||||
sim_event *new_event = sim_events_zalloc (sd);
|
||||
/* type */
|
||||
new_event->watching = watch_clock;
|
||||
/* handler */
|
||||
new_event->data = data;
|
||||
new_event->handler = handler;
|
||||
/* data */
|
||||
new_event->wallclock = wallclock_ms_time;
|
||||
new_event->wallclock = (sim_elapsed_time_since (events->initial_wallclock) + delta_ms_time);
|
||||
/* insert */
|
||||
new_event->next = events->watchpoints;
|
||||
events->watchpoints = new_event;
|
||||
@ -445,7 +480,7 @@ sim_events_watch_sim (SIM_DESC sd,
|
||||
void *data)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
sim_event *new_event = ZALLOC (sim_event);
|
||||
sim_event *new_event = sim_events_zalloc (sd);
|
||||
/* type */
|
||||
switch (byte_order)
|
||||
{
|
||||
@ -521,7 +556,7 @@ sim_events_watch_core (SIM_DESC sd,
|
||||
void *data)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
sim_event *new_event = ZALLOC (sim_event);
|
||||
sim_event *new_event = sim_events_zalloc (sd);
|
||||
/* type */
|
||||
switch (byte_order)
|
||||
{
|
||||
@ -613,7 +648,7 @@ sim_events_deschedule (SIM_DESC sd,
|
||||
(long) dead->time_of_event,
|
||||
(long) dead->handler,
|
||||
(long) dead->data));
|
||||
zfree (dead);
|
||||
sim_events_free (sd, dead);
|
||||
update_time_from_event (sd);
|
||||
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
|
||||
return;
|
||||
@ -635,60 +670,59 @@ sim_watch_valid (SIM_DESC sd,
|
||||
switch (to_do->watching)
|
||||
{
|
||||
|
||||
#define WATCH_CORE(N,OP) \
|
||||
#define WATCH_CORE(N,OP,EXT) \
|
||||
{ \
|
||||
unsigned_##N word; \
|
||||
sim_core_read_buffer (sd, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
|
||||
OP (word); \
|
||||
return (word >= to_do->lb && word <= to_do->ub); \
|
||||
return (word >= to_do->lb##EXT && word <= to_do->ub##EXT); \
|
||||
}
|
||||
case watch_core_targ_1: WATCH_CORE (1, T2H,);
|
||||
case watch_core_targ_2: WATCH_CORE (2, T2H,);
|
||||
case watch_core_targ_4: WATCH_CORE (4, T2H,);
|
||||
case watch_core_targ_8: WATCH_CORE (8, T2H,64);
|
||||
|
||||
case watch_core_targ_1: WATCH_CORE (1, T2H);
|
||||
case watch_core_targ_2: WATCH_CORE (2, T2H);
|
||||
case watch_core_targ_4: WATCH_CORE (4, T2H);
|
||||
case watch_core_targ_8: WATCH_CORE (8, T2H);
|
||||
|
||||
case watch_core_be_1: WATCH_CORE (1, BE2H);
|
||||
case watch_core_be_2: WATCH_CORE (2, BE2H);
|
||||
case watch_core_be_4: WATCH_CORE (4, BE2H);
|
||||
case watch_core_be_8: WATCH_CORE (8, BE2H);
|
||||
|
||||
case watch_core_le_1: WATCH_CORE (1, LE2H);
|
||||
case watch_core_le_2: WATCH_CORE (2, LE2H);
|
||||
case watch_core_le_4: WATCH_CORE (4, LE2H);
|
||||
case watch_core_le_8: WATCH_CORE (8, LE2H);
|
||||
case watch_core_be_1: WATCH_CORE (1, BE2H,);
|
||||
case watch_core_be_2: WATCH_CORE (2, BE2H,);
|
||||
case watch_core_be_4: WATCH_CORE (4, BE2H,);
|
||||
case watch_core_be_8: WATCH_CORE (8, BE2H,64);
|
||||
|
||||
case watch_core_le_1: WATCH_CORE (1, LE2H,);
|
||||
case watch_core_le_2: WATCH_CORE (2, LE2H,);
|
||||
case watch_core_le_4: WATCH_CORE (4, LE2H,);
|
||||
case watch_core_le_8: WATCH_CORE (8, LE2H,64);
|
||||
#undef WATCH_CORE
|
||||
|
||||
#define WATCH_SIM(N,OP) \
|
||||
#define WATCH_SIM(N,OP,EXT) \
|
||||
{ \
|
||||
unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
|
||||
OP (word); \
|
||||
return (word >= to_do->lb && word <= to_do->ub); \
|
||||
return (word >= to_do->lb##EXT && word <= to_do->ub##EXT); \
|
||||
}
|
||||
|
||||
case watch_sim_host_1: WATCH_SIM (1, word = );
|
||||
case watch_sim_host_2: WATCH_SIM (2, word = );
|
||||
case watch_sim_host_4: WATCH_SIM (4, word = );
|
||||
case watch_sim_host_8: WATCH_SIM (8, word = );
|
||||
case watch_sim_host_1: WATCH_SIM (1, word = ,);
|
||||
case watch_sim_host_2: WATCH_SIM (2, word = ,);
|
||||
case watch_sim_host_4: WATCH_SIM (4, word = ,);
|
||||
case watch_sim_host_8: WATCH_SIM (8, word = ,64);
|
||||
|
||||
case watch_sim_be_1: WATCH_SIM (1, BE2H);
|
||||
case watch_sim_be_2: WATCH_SIM (2, BE2H);
|
||||
case watch_sim_be_4: WATCH_SIM (4, BE2H);
|
||||
case watch_sim_be_8: WATCH_SIM (8, BE2H);
|
||||
case watch_sim_be_1: WATCH_SIM (1, BE2H,);
|
||||
case watch_sim_be_2: WATCH_SIM (2, BE2H,);
|
||||
case watch_sim_be_4: WATCH_SIM (4, BE2H,);
|
||||
case watch_sim_be_8: WATCH_SIM (8, BE2H,64);
|
||||
|
||||
case watch_sim_le_1: WATCH_SIM (1, LE2H);
|
||||
case watch_sim_le_2: WATCH_SIM (1, LE2H);
|
||||
case watch_sim_le_4: WATCH_SIM (1, LE2H);
|
||||
case watch_sim_le_8: WATCH_SIM (1, LE2H);
|
||||
case watch_sim_le_1: WATCH_SIM (1, LE2H,);
|
||||
case watch_sim_le_2: WATCH_SIM (1, LE2H,);
|
||||
case watch_sim_le_4: WATCH_SIM (1, LE2H,);
|
||||
case watch_sim_le_8: WATCH_SIM (1, LE2H,64);
|
||||
#undef WATCH_SIM
|
||||
|
||||
case watch_clock: /* wallclock */
|
||||
return (sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock)
|
||||
< to_do->wallclock);
|
||||
{
|
||||
unsigned long elapsed_time = sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock);
|
||||
return (elapsed_time >= to_do->wallclock);
|
||||
}
|
||||
|
||||
case watch_timer:
|
||||
case watch_invalid:
|
||||
default:
|
||||
sim_io_error (sd, "sim_watch_valid - bad switch");
|
||||
break;
|
||||
|
||||
@ -703,15 +737,15 @@ sim_events_tick (SIM_DESC sd)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
|
||||
/* this should only be called after the previous tick has been fully
|
||||
processed */
|
||||
SIM_ASSERT (!events->processing);
|
||||
/* this should only be called after the previous ticks have been
|
||||
fully processed */
|
||||
SIM_ASSERT (events->nr_ticks_to_process == 0);
|
||||
|
||||
/* Advance the time but *only* if there is nothing to process */
|
||||
if (events->work_pending
|
||||
|| events->time_from_event == 0)
|
||||
{
|
||||
events->processing = 1;
|
||||
events->nr_ticks_to_process = 1;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
@ -721,6 +755,32 @@ sim_events_tick (SIM_DESC sd)
|
||||
}
|
||||
|
||||
|
||||
INLINE_SIM_EVENTS\
|
||||
(int)
|
||||
sim_events_tickn (SIM_DESC sd,
|
||||
unsigned n)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS (sd);
|
||||
|
||||
/* this should only be called after the previous ticks have been
|
||||
fully processed */
|
||||
SIM_ASSERT (events->nr_ticks_to_process == 0);
|
||||
SIM_ASSERT (n > 0);
|
||||
|
||||
/* Advance the time but *only* if there is nothing to process */
|
||||
if (events->work_pending
|
||||
|| events->time_from_event < n)
|
||||
{
|
||||
events->nr_ticks_to_process = n;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
events->time_from_event -= n;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INLINE_SIM_EVENTS\
|
||||
(void)
|
||||
sim_events_preprocess (SIM_DESC sd,
|
||||
@ -728,7 +788,7 @@ sim_events_preprocess (SIM_DESC sd,
|
||||
int events_were_next)
|
||||
{
|
||||
sim_events *events = STATE_EVENTS(sd);
|
||||
if (events->processing)
|
||||
if (events->nr_ticks_to_process != 0)
|
||||
{
|
||||
/* Halted midway through event processing */
|
||||
ASSERT (events_were_last && events_were_next);
|
||||
@ -737,7 +797,7 @@ sim_events_preprocess (SIM_DESC sd,
|
||||
else if (events_were_next)
|
||||
{
|
||||
/* Halted by the last processor */
|
||||
ASSERT (!events->processing && !events_were_last);
|
||||
ASSERT (events->nr_ticks_to_process == 0 && !events_were_last);
|
||||
if (sim_events_tick (sd))
|
||||
sim_events_process (sd);
|
||||
}
|
||||
@ -751,14 +811,13 @@ sim_events_process (SIM_DESC sd)
|
||||
sim_events *events = STATE_EVENTS(sd);
|
||||
signed64 event_time = sim_events_time(sd);
|
||||
|
||||
ASSERT (events->processing);
|
||||
ASSERT (events->nr_ticks_to_process != 0);
|
||||
|
||||
/* move any events that were queued by any signal handlers onto
|
||||
the real event queue. */
|
||||
if (events->held != NULL)
|
||||
if (events->nr_held > 0)
|
||||
{
|
||||
sim_event *held_events;
|
||||
sim_event *curr_event;
|
||||
int i;
|
||||
|
||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||
/*-LOCK-*/
|
||||
@ -768,24 +827,21 @@ sim_events_process (SIM_DESC sd)
|
||||
sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
|
||||
#endif
|
||||
|
||||
held_events = events->held;
|
||||
events->held = NULL;
|
||||
events->held_end = &events->held;
|
||||
events->work_pending = 0;
|
||||
for (i = 0; i < events->nr_held; i++)
|
||||
{
|
||||
sim_event *entry = &events->held [i];
|
||||
sim_events_schedule (sd,
|
||||
entry->time_of_event,
|
||||
entry->handler,
|
||||
entry->data);
|
||||
}
|
||||
events->nr_held = 0;
|
||||
|
||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||
/*-UNLOCK-*/
|
||||
sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
curr_event = held_events;
|
||||
held_events = curr_event->next;
|
||||
insert_sim_event (sd, curr_event,
|
||||
curr_event->time_of_event);
|
||||
}
|
||||
while (held_events != NULL);
|
||||
}
|
||||
|
||||
/* Process any watchpoints. Be careful to allow a watchpoint to
|
||||
@ -809,7 +865,7 @@ sim_events_process (SIM_DESC sd)
|
||||
(long) to_do,
|
||||
(long) handler,
|
||||
(long) data));
|
||||
zfree (to_do);
|
||||
sim_events_free (sd, to_do);
|
||||
handler (sd, data);
|
||||
}
|
||||
else
|
||||
@ -821,7 +877,8 @@ sim_events_process (SIM_DESC sd)
|
||||
|
||||
/* consume all events for this or earlier times. Be careful to
|
||||
allow an event to appear/disappear under our feet */
|
||||
while (events->queue->time_of_event <= event_time)
|
||||
while (events->queue->time_of_event <
|
||||
(event_time + events->nr_ticks_to_process))
|
||||
{
|
||||
sim_event *to_do = events->queue;
|
||||
sim_event_handler *handler = to_do->handler;
|
||||
@ -833,7 +890,7 @@ sim_events_process (SIM_DESC sd)
|
||||
(long) to_do,
|
||||
(long) handler,
|
||||
(long) data));
|
||||
zfree (to_do);
|
||||
sim_events_free (sd, to_do);
|
||||
handler (sd, data);
|
||||
}
|
||||
|
||||
@ -843,13 +900,14 @@ sim_events_process (SIM_DESC sd)
|
||||
if (events->watchpoints != NULL)
|
||||
events->work_pending = 1;
|
||||
|
||||
/* this round of processing complete */
|
||||
events->processing = 0;
|
||||
|
||||
/* re-caculate time for new events - advance the time */
|
||||
/* re-caculate time for new events then advance the time */
|
||||
update_time_from_event(sd);
|
||||
SIM_ASSERT(events->time_from_event > 0 && events->queue != NULL);
|
||||
events->time_from_event -= 1;
|
||||
SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
|
||||
SIM_ASSERT (events->queue != NULL); /* always poll event */
|
||||
events->time_from_event -= events->nr_ticks_to_process;
|
||||
|
||||
/* this round of processing complete */
|
||||
events->nr_ticks_to_process = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -75,15 +75,19 @@ typedef struct _sim_event sim_event;
|
||||
|
||||
typedef struct _sim_events sim_events;
|
||||
struct _sim_events {
|
||||
int processing;
|
||||
int nr_ticks_to_process;
|
||||
sim_event *queue;
|
||||
sim_event *watchpoints;
|
||||
sim_event *watchedpoints;
|
||||
sim_event *free_list;
|
||||
/* flag additional work needed */
|
||||
volatile int work_pending;
|
||||
/* the asynchronous event queue */
|
||||
sim_event *volatile held;
|
||||
sim_event *volatile *volatile held_end;
|
||||
#ifndef MAX_NR_SIGNAL_SIM_EVENTS
|
||||
#define MAX_NR_SIGNAL_SIM_EVENTS 2
|
||||
#endif
|
||||
sim_event *held;
|
||||
volatile int nr_held;
|
||||
/* timekeeping */
|
||||
SIM_ELAPSED_TIME initial_wallclock;
|
||||
signed64 time_of_event;
|
||||
@ -131,21 +135,20 @@ EXTERN_SIM_EVENTS\
|
||||
void *data);
|
||||
|
||||
EXTERN_SIM_EVENTS\
|
||||
(sim_event *) sim_events_schedule_after_signal
|
||||
(void) sim_events_schedule_after_signal
|
||||
(SIM_DESC sd,
|
||||
signed64 delta_time,
|
||||
sim_event_handler *handler,
|
||||
void *data);
|
||||
|
||||
|
||||
/* Schedule an event WALLCLOCK milli-seconds from the start of the
|
||||
simulation. The exact interpretation of wallclock is host
|
||||
dependant. */
|
||||
/* Schedule an event milli-seconds from NOW. The exact interpretation
|
||||
of wallclock is host dependant. */
|
||||
|
||||
EXTERN_SIM_EVENTS\
|
||||
(sim_event *) sim_events_watch_clock
|
||||
(SIM_DESC sd,
|
||||
unsigned wallclock_ms_time,
|
||||
unsigned delta_ms_time,
|
||||
sim_event_handler *handler,
|
||||
void *data);
|
||||
|
||||
@ -186,7 +189,6 @@ EXTERN_SIM_EVENTS\
|
||||
sim_event_handler *handler,
|
||||
void *data);
|
||||
|
||||
|
||||
/* Deschedule the specified event */
|
||||
|
||||
EXTERN_SIM_EVENTS\
|
||||
@ -212,17 +214,33 @@ INLINE_SIM_EVENTS\
|
||||
|
||||
|
||||
/* Progress time - separated into two parts so that the main loop can
|
||||
save its context before the event queue is processed */
|
||||
save its context before the event queue is processed.
|
||||
|
||||
sim_events_tickn advances the clock by N cycles. */
|
||||
|
||||
INLINE_SIM_EVENTS\
|
||||
(int) sim_events_tick
|
||||
(SIM_DESC sd);
|
||||
|
||||
INLINE_SIM_EVENTS\
|
||||
(int) sim_events_tickn
|
||||
(SIM_DESC sd,
|
||||
unsigned n);
|
||||
|
||||
INLINE_SIM_EVENTS\
|
||||
(void) sim_events_process
|
||||
(SIM_DESC sd);
|
||||
|
||||
|
||||
/* Progress time such that an event shall occure upon the next call to
|
||||
sim_events tick */
|
||||
|
||||
#if 0
|
||||
INLINE_SIM_EVENTS\
|
||||
(void) sim_events_timewarp
|
||||
(SIM_DESC sd);
|
||||
#endif
|
||||
|
||||
|
||||
/* local concept of time */
|
||||
|
||||
|
@ -26,10 +26,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include "libiberty.h"
|
||||
#include "../libiberty/alloca-conf.h"
|
||||
#include "sim-options.h"
|
||||
#include "sim-io.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
/* Add a set of options to the simulator.
|
||||
TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry.
|
||||
@ -115,7 +120,7 @@ static const OPTION standard_options[] =
|
||||
#endif
|
||||
|
||||
{ {"do-command", required_argument, NULL, OPTION_DO_COMMAND},
|
||||
'\0', "COMMAND", "Perform a builtin command",
|
||||
'\0', "COMMAND", ""/*undocumented*/,
|
||||
standard_option_handler },
|
||||
|
||||
{ {"help", no_argument, NULL, 'H'},
|
||||
@ -126,10 +131,11 @@ static const OPTION standard_options[] =
|
||||
};
|
||||
|
||||
static SIM_RC
|
||||
standard_option_handler (sd, opt, arg)
|
||||
standard_option_handler (sd, opt, arg, is_command)
|
||||
SIM_DESC sd;
|
||||
int opt;
|
||||
char *arg;
|
||||
int is_command;
|
||||
{
|
||||
int i,n;
|
||||
|
||||
@ -149,6 +155,7 @@ standard_option_handler (sd, opt, arg)
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
/* FIXME:wip: Need to set something in STATE_CONFIG. */
|
||||
current_target_byte_order = BIG_ENDIAN;
|
||||
}
|
||||
else if (strcmp (arg, "little") == 0)
|
||||
{
|
||||
@ -158,6 +165,7 @@ standard_option_handler (sd, opt, arg)
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
/* FIXME:wip: Need to set something in STATE_CONFIG. */
|
||||
current_target_byte_order = LITTLE_ENDIAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -246,6 +254,7 @@ standard_option_handler (sd, opt, arg)
|
||||
SIM_RC
|
||||
standard_install (SIM_DESC sd)
|
||||
{
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
if (sim_add_option_table (sd, standard_options) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
return SIM_RC_OK;
|
||||
@ -372,7 +381,7 @@ sim_parse_args (sd, argv)
|
||||
if (optc == '?')
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
if ((*handlers[optc]) (sd, orig_val[optc], optarg) == SIM_RC_FAIL)
|
||||
if ((*handlers[optc]) (sd, orig_val[optc], optarg, 0/*!is_command*/) == SIM_RC_FAIL)
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
|
||||
@ -408,6 +417,9 @@ sim_print_help (sd)
|
||||
if (opt->doc == NULL)
|
||||
continue;
|
||||
|
||||
if (opt->doc_name != NULL && opt->doc_name [0] == '\0')
|
||||
continue;
|
||||
|
||||
sim_io_printf (sd, " ");
|
||||
|
||||
comma = 0;
|
||||
@ -442,14 +454,19 @@ sim_print_help (sd)
|
||||
o = opt;
|
||||
do
|
||||
{
|
||||
if (o->opt.name != NULL)
|
||||
const char *name;
|
||||
if (o->doc_name != NULL)
|
||||
name = o->doc_name;
|
||||
else
|
||||
name = o->opt.name;
|
||||
if (name != NULL)
|
||||
{
|
||||
sim_io_printf (sd, "%s--%s",
|
||||
comma ? ", " : "",
|
||||
o->opt.name);
|
||||
name);
|
||||
len += ((comma ? 2 : 0)
|
||||
+ 2
|
||||
+ strlen (o->opt.name));
|
||||
+ strlen (name));
|
||||
if (o->arg != NULL)
|
||||
{
|
||||
if (o->opt.has_arg == optional_argument)
|
||||
@ -515,40 +532,77 @@ sim_args_command (sd, cmd)
|
||||
const struct option_list *ol;
|
||||
const OPTION *opt;
|
||||
char **argv = buildargv (cmd);
|
||||
for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next)
|
||||
for (opt = ol->options; opt->opt.name != NULL; ++opt)
|
||||
{
|
||||
if (strcmp (argv[0], opt->opt.name) == 0)
|
||||
{
|
||||
switch (opt->opt.has_arg)
|
||||
{
|
||||
case no_argument:
|
||||
if (argv[1] == NULL)
|
||||
opt->handler (sd, opt->opt.val, NULL);
|
||||
else
|
||||
sim_io_eprintf (sd, "Command `%s' takes no arguments\n", opt->opt.name);
|
||||
/* most recent option match */
|
||||
const OPTION *matching_opt = NULL;
|
||||
int matching_argi = -1;
|
||||
if (argv [0] != NULL)
|
||||
for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next)
|
||||
for (opt = ol->options; opt->opt.name != NULL; ++opt)
|
||||
{
|
||||
int argi = 0;
|
||||
const char *name = opt->opt.name;
|
||||
while (strncmp (name, argv [argi], strlen (argv [argi])) == 0)
|
||||
{
|
||||
name = &name [strlen (argv[argi])];
|
||||
if (name [0] == '-')
|
||||
{
|
||||
/* leading match ...<a-b-c>-d-e-f - continue search */
|
||||
name ++; /* skip `-' */
|
||||
argi ++;
|
||||
continue;
|
||||
}
|
||||
else if (name [0] == '\0')
|
||||
{
|
||||
/* exact match ...<a-b-c-d-e-f> - better than before? */
|
||||
if (argi > matching_argi)
|
||||
{
|
||||
matching_argi = argi;
|
||||
matching_opt = opt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
case optional_argument:
|
||||
if (argv[1] == NULL)
|
||||
opt->handler (sd, opt->opt.val, NULL);
|
||||
else if (argv[2] == NULL)
|
||||
opt->handler (sd, opt->opt.val, argv[1]);
|
||||
else
|
||||
sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n", opt->opt.name);
|
||||
break;
|
||||
case required_argument:
|
||||
if (argv[1] == NULL)
|
||||
sim_io_eprintf (sd, "Command `%s' requires an argument\n", opt->opt.name);
|
||||
else if (argv[2] == NULL)
|
||||
opt->handler (sd, opt->opt.val, argv[1]);
|
||||
else
|
||||
sim_io_eprintf (sd, "Command `%s' requires only one argument\n", opt->opt.name);
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matching_opt != NULL)
|
||||
{
|
||||
switch (matching_opt->opt.has_arg)
|
||||
{
|
||||
case no_argument:
|
||||
if (argv [matching_argi + 1] == NULL)
|
||||
matching_opt->handler (sd, matching_opt->opt.val,
|
||||
NULL, 1/*is_command*/);
|
||||
else
|
||||
sim_io_eprintf (sd, "Command `%s' takes no arguments\n",
|
||||
matching_opt->opt.name);
|
||||
break;
|
||||
case optional_argument:
|
||||
if (argv [matching_argi + 1] == NULL)
|
||||
matching_opt->handler (sd, matching_opt->opt.val,
|
||||
NULL, 1/*is_command*/);
|
||||
else if (argv [matching_argi + 2] == NULL)
|
||||
matching_opt->handler (sd, matching_opt->opt.val,
|
||||
argv [matching_argi + 1], 1/*is_command*/);
|
||||
else
|
||||
sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n",
|
||||
matching_opt->opt.name);
|
||||
break;
|
||||
case required_argument:
|
||||
if (argv [matching_argi + 1] == NULL)
|
||||
sim_io_eprintf (sd, "Command `%s' requires an argument\n",
|
||||
matching_opt->opt.name);
|
||||
else if (argv [matching_argi + 2] == NULL)
|
||||
matching_opt->handler (sd, matching_opt->opt.val,
|
||||
argv [matching_argi + 1], 1/*is_command*/);
|
||||
else
|
||||
sim_io_eprintf (sd, "Command `%s' requires only one argument\n",
|
||||
matching_opt->opt.name);
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* didn't find anything that matched */
|
||||
|
||||
/* didn't find anything that remotly matched */
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
|
@ -29,13 +29,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
sim_open handles the large majority of them and it also parses the
|
||||
options when invoked by gdb [or any external program].
|
||||
|
||||
Per getopt: arg#2 is the option index; arg#3 is the option's
|
||||
argument, NULL if optional and missing. */
|
||||
arg#2 is the option index; arg#3 is the option's argument, NULL if
|
||||
optional and missing; arg#4 is nonzero if being called as a
|
||||
command. */
|
||||
|
||||
typedef SIM_RC (OPTION_HANDLER) PARAMS ((SIM_DESC, int, char *));
|
||||
typedef SIM_RC (OPTION_HANDLER) PARAMS ((SIM_DESC, int, char *, int));
|
||||
|
||||
/* Declare option handlers with a macro so it's usable on k&r systems. */
|
||||
#define DECLARE_OPTION_HANDLER(fn) SIM_RC fn PARAMS ((SIM_DESC, int, char *))
|
||||
#define DECLARE_OPTION_HANDLER(fn) SIM_RC fn PARAMS ((SIM_DESC, int, char *, int))
|
||||
|
||||
typedef struct {
|
||||
/* The long option information. */
|
||||
@ -49,6 +50,12 @@ typedef struct {
|
||||
const char *doc;
|
||||
/* A function to process the option. */
|
||||
OPTION_HANDLER *handler;
|
||||
/* The documented name of the option. If this is NULL, opt.name is
|
||||
listed; otherwize this is listed as the name of the option.
|
||||
Ex: given the options --set-pc, set-sp, et.al. the first option
|
||||
would have doc_opt set to `--set-REGNAME' with the others set to
|
||||
"". Only --set-REGNAME would then be listed. */
|
||||
const char *doc_name;
|
||||
} OPTION;
|
||||
|
||||
/* All options that don't have a short form equivalent begin with this for
|
||||
|
@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "sim-options.h"
|
||||
#include "bfd.h"
|
||||
|
||||
#include "sim-assert.h"
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
@ -69,44 +71,46 @@ enum {
|
||||
|
||||
static const OPTION trace_options[] =
|
||||
{
|
||||
{ {"trace", no_argument, NULL, 't'},
|
||||
't', NULL, "Perform tracing",
|
||||
{ {"trace", optional_argument, NULL, 't'},
|
||||
't', "on|off", "Perform tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-insn", no_argument, NULL, OPTION_TRACE_INSN},
|
||||
'\0', NULL, "Perform instruction tracing",
|
||||
{ {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN},
|
||||
'\0', "on|off", "Perform instruction tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-decode", no_argument, NULL, OPTION_TRACE_DECODE},
|
||||
'\0', NULL, "Perform instruction decoding tracing",
|
||||
{ {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE},
|
||||
'\0', "on|off", "Perform instruction decoding tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-extract", no_argument, NULL, OPTION_TRACE_EXTRACT},
|
||||
'\0', NULL, "Perform instruction extraction tracing",
|
||||
{ {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT},
|
||||
'\0', "on|off", "Perform instruction extraction tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-linenum", no_argument, NULL, OPTION_TRACE_LINENUM},
|
||||
'\0', NULL, "Perform line number tracing (implies --trace-insn)",
|
||||
{ {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM},
|
||||
'\0', "on|off", "Perform line number tracing (implies --trace-insn)",
|
||||
trace_option_handler },
|
||||
{ {"trace-memory", no_argument, NULL, OPTION_TRACE_MEMORY},
|
||||
'\0', NULL, "Perform memory tracing",
|
||||
{ {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY},
|
||||
'\0', "on|off", "Perform memory tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-model", no_argument, NULL, OPTION_TRACE_MODEL},
|
||||
'\0', NULL, "Perform model tracing",
|
||||
{ {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL},
|
||||
'\0', "on|off", "Perform model tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-alu", no_argument, NULL, OPTION_TRACE_ALU},
|
||||
'\0', NULL, "Perform ALU tracing",
|
||||
{ {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU},
|
||||
'\0', "on|off", "Perform ALU tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-core", no_argument, NULL, OPTION_TRACE_CORE},
|
||||
'\0', NULL, "Perform CORE tracing",
|
||||
#if (WITH_CORE)
|
||||
{ {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE},
|
||||
'\0', "on|off", "Perform CORE tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-events", no_argument, NULL, OPTION_TRACE_EVENTS},
|
||||
'\0', NULL, "Perform EVENTS tracing",
|
||||
#endif
|
||||
{ {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS},
|
||||
'\0', "on|off", "Perform EVENTS tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-fpu", no_argument, NULL, OPTION_TRACE_FPU},
|
||||
'\0', NULL, "Perform FPU tracing",
|
||||
{ {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU},
|
||||
'\0', "on|off", "Perform FPU tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-branch", no_argument, NULL, OPTION_TRACE_BRANCH},
|
||||
'\0', NULL, "Perform branch tracing",
|
||||
{ {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH},
|
||||
'\0', "on|off", "Perform branch tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-semantics", no_argument, NULL, OPTION_TRACE_SEMANTICS},
|
||||
'\0', NULL, "Perform ALU, FPU, and MEMORY tracing",
|
||||
{ {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS},
|
||||
'\0', "on|off", "Perform ALU, FPU, MEMORY, and BRANCH tracing",
|
||||
trace_option_handler },
|
||||
{ {"trace-file", required_argument, NULL, OPTION_TRACE_FILE},
|
||||
'\0', "FILE NAME", "Specify tracing output file",
|
||||
@ -114,13 +118,69 @@ static const OPTION trace_options[] =
|
||||
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
/* Set FIRST_TRACE .. LAST_TRACE according to arg. At least
|
||||
FIRST_TRACE is always set */
|
||||
|
||||
static SIM_RC
|
||||
trace_option_handler (sd, opt, arg)
|
||||
set_trace_options (sd, name, first_trace, last_trace, arg)
|
||||
SIM_DESC sd;
|
||||
const char *name;
|
||||
int first_trace;
|
||||
int last_trace;
|
||||
const char *arg;
|
||||
{
|
||||
int trace_nr;
|
||||
int cpu_nr;
|
||||
int trace_val = 1;
|
||||
if (arg != NULL)
|
||||
{
|
||||
if (strcmp (arg, "yes") == 0
|
||||
|| strcmp (arg, "on") == 0
|
||||
|| strcmp (arg, "1") == 0)
|
||||
trace_val = 1;
|
||||
else if (strcmp (arg, "no") == 0
|
||||
|| strcmp (arg, "off") == 0
|
||||
|| strcmp (arg, "0") == 0)
|
||||
trace_val = 0;
|
||||
else
|
||||
{
|
||||
sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
}
|
||||
trace_nr = first_trace;
|
||||
do
|
||||
{
|
||||
switch (trace_nr)
|
||||
{
|
||||
#if (WITH_CORE)
|
||||
case TRACE_CORE_IDX:
|
||||
STATE_CORE(sd)->trace = trace_val;
|
||||
break;
|
||||
#endif
|
||||
case TRACE_EVENTS_IDX:
|
||||
STATE_EVENTS(sd)->trace = trace_val;
|
||||
break;
|
||||
}
|
||||
for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
|
||||
{
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val;
|
||||
}
|
||||
}
|
||||
while (++trace_nr < last_trace);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
static SIM_RC
|
||||
trace_option_handler (sd, opt, arg, is_command)
|
||||
SIM_DESC sd;
|
||||
int opt;
|
||||
char *arg;
|
||||
int is_command;
|
||||
{
|
||||
int i,n;
|
||||
int n;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
@ -128,123 +188,104 @@ trace_option_handler (sd, opt, arg)
|
||||
if (! WITH_TRACE)
|
||||
sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
for (i = 0; i < MAX_TRACE_VALUES; ++i)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[i] = 1;
|
||||
STATE_CORE(sd)->trace = 1;
|
||||
STATE_EVENTS(sd)->trace = 1;
|
||||
}
|
||||
return set_trace_options (sd, "trace", 0, MAX_TRACE_VALUES, arg);
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_INSN :
|
||||
if (WITH_TRACE_INSN_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
|
||||
return set_trace_options (sd, "-insn", TRACE_INSN_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_DECODE :
|
||||
if (WITH_TRACE_DECODE_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_DECODE_IDX] = 1;
|
||||
return set_trace_options (sd, "-decode", TRACE_DECODE_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_EXTRACT :
|
||||
if (WITH_TRACE_EXTRACT_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EXTRACT_IDX] = 1;
|
||||
return set_trace_options (sd, "-extract", TRACE_EXTRACT_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_LINENUM :
|
||||
if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
{
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_LINENUM_IDX] = 1;
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
|
||||
}
|
||||
{
|
||||
if (set_trace_options (sd, "-linenum", TRACE_LINENUM_IDX, -1, arg) != SIM_RC_OK
|
||||
|| set_trace_options (sd, "-linenum", TRACE_INSN_IDX, -1, arg) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
else
|
||||
sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_MEMORY :
|
||||
if (WITH_TRACE_MEMORY_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1;
|
||||
return set_trace_options (sd, "-memory", TRACE_MEMORY_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_MODEL :
|
||||
if (WITH_TRACE_MODEL_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MODEL_IDX] = 1;
|
||||
return set_trace_options (sd, "-model", TRACE_MODEL_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_ALU :
|
||||
if (WITH_TRACE_ALU_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1;
|
||||
return set_trace_options (sd, "-alu", TRACE_ALU_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_CORE :
|
||||
if (WITH_TRACE_CORE_P)
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_CORE_IDX] = 1;
|
||||
STATE_CORE(sd)->trace = 1;
|
||||
}
|
||||
return set_trace_options (sd, "-core", TRACE_CORE_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_EVENTS :
|
||||
if (WITH_TRACE_EVENTS_P)
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EVENTS_IDX] = 1;
|
||||
STATE_EVENTS(sd)->trace = 1;
|
||||
}
|
||||
return set_trace_options (sd, "-events", TRACE_EVENTS_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_FPU :
|
||||
if (WITH_TRACE_FPU_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
|
||||
return set_trace_options (sd, "-fpu", TRACE_FPU_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_BRANCH :
|
||||
if (WITH_TRACE_BRANCH_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
|
||||
return set_trace_options (sd, "-branch", TRACE_BRANCH_IDX, -1, arg);
|
||||
else
|
||||
sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_SEMANTICS :
|
||||
if (WITH_TRACE_ALU_P && WITH_TRACE_FPU_P && WITH_TRACE_MEMORY_P)
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
{
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1;
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1;
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_BRANCH_IDX] = 1;
|
||||
}
|
||||
if (WITH_TRACE_ALU_P
|
||||
&& WITH_TRACE_FPU_P
|
||||
&& WITH_TRACE_MEMORY_P
|
||||
&& WITH_TRACE_BRANCH_P)
|
||||
{
|
||||
if (set_trace_options (sd, "-semantics", TRACE_ALU_IDX, -1, arg) != SIM_RC_OK
|
||||
|| set_trace_options (sd, "-semantics", TRACE_FPU_IDX, -1, arg) != SIM_RC_OK
|
||||
|| set_trace_options (sd, "-semantics", TRACE_MEMORY_IDX, -1, arg) != SIM_RC_OK
|
||||
|| set_trace_options (sd, "-semantics", TRACE_BRANCH_IDX, -1, arg) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
else
|
||||
sim_io_eprintf (sd, "Alu, fpu, and/or memory tracing not compiled in, `--trace-semantics' ignored\n");
|
||||
sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n");
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_FILE :
|
||||
@ -275,6 +316,8 @@ trace_install (SIM_DESC sd)
|
||||
{
|
||||
int i;
|
||||
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
|
||||
sim_add_option_table (sd, trace_options);
|
||||
for (i = 0; i < MAX_NR_PROCESSORS; ++i)
|
||||
memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
|
||||
|
295
sim/common/sim-watch.c
Normal file
295
sim/common/sim-watch.c
Normal file
@ -0,0 +1,295 @@
|
||||
/* Mips simulator watchpoint support.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
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-options.h"
|
||||
|
||||
#include "sim-assert.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 <signal.h>
|
||||
|
||||
static DECLARE_OPTION_HANDLER (watch_option_handler);
|
||||
|
||||
enum {
|
||||
OPTION_WATCH_DELETE = OPTION_START,
|
||||
|
||||
OPTION_WATCH_PC,
|
||||
OPTION_WATCH_CLOCK,
|
||||
OPTION_WATCH_CYCLES,
|
||||
|
||||
OPTION_ACTION_PC,
|
||||
OPTION_ACTION_CLOCK,
|
||||
OPTION_ACTION_CYCLES,
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
delete_watchpoint (SIM_DESC sd, watchpoint_type type)
|
||||
{
|
||||
sim_watch_point *point = &STATE_WATCHPOINTS (sd)->points[type];
|
||||
if (point->event != NULL)
|
||||
sim_events_deschedule (sd, point->event);
|
||||
point->action = invalid_watchpoint_action;
|
||||
point->event = NULL;
|
||||
}
|
||||
|
||||
|
||||
static sim_event_handler handle_watchpoint;
|
||||
|
||||
static SIM_RC
|
||||
schedule_watchpoint (SIM_DESC sd,
|
||||
watchpoint_type type,
|
||||
unsigned long arg,
|
||||
int is_command)
|
||||
{
|
||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||
sim_watch_point *point = &watch->points[type];
|
||||
if (point->event != NULL)
|
||||
delete_watchpoint (sd, type);
|
||||
point->arg = arg;
|
||||
if (point->action == invalid_watchpoint_action)
|
||||
point->action = break_watchpoint_action;
|
||||
if (is_command)
|
||||
switch (type)
|
||||
{
|
||||
case pc_watchpoint:
|
||||
point->event = sim_events_watch_sim (sd, watch->pc, watch->sizeof_pc,
|
||||
0/* host-endian */,
|
||||
point->arg, point->arg, /* PC == arg? */
|
||||
handle_watchpoint,
|
||||
point);
|
||||
return SIM_RC_OK;
|
||||
case clock_watchpoint:
|
||||
point->event = sim_events_watch_clock (sd,
|
||||
point->arg, /* ms time */
|
||||
handle_watchpoint,
|
||||
point);
|
||||
return SIM_RC_OK;
|
||||
case cycles_watchpoint:
|
||||
point->event = sim_events_schedule (sd, point->arg, /* time */
|
||||
handle_watchpoint,
|
||||
point);
|
||||
return SIM_RC_OK;
|
||||
default:
|
||||
sim_engine_abort (sd, NULL, NULL_CIA,
|
||||
"handle_watchpoint - internal error - bad switch");
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_watchpoint (SIM_DESC sd, void *data)
|
||||
{
|
||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||
sim_watch_point *point = data;
|
||||
watchpoint_type type = point - watch->points;
|
||||
|
||||
switch (point->action)
|
||||
{
|
||||
|
||||
case break_watchpoint_action:
|
||||
point->event = NULL; /* gone */
|
||||
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGINT);
|
||||
break;
|
||||
|
||||
case n_interrupt_watchpoint_action:
|
||||
/* First reschedule this event */
|
||||
schedule_watchpoint (sd, type, point->arg, 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
|
||||
action_watchpoint (SIM_DESC sd, watchpoint_type type, const char *arg)
|
||||
{
|
||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||
sim_watch_point *point = &watch->points[type];
|
||||
if (strcmp (arg, "break") == NULL)
|
||||
{
|
||||
point->action = break_watchpoint_action;
|
||||
}
|
||||
else if (strcmp (arg, "int") == NULL)
|
||||
{
|
||||
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
|
||||
{
|
||||
sim_io_eprintf (sd, "Interrupts other than `int' currently unsuported\n");
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
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 },
|
||||
|
||||
{ {"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
|
||||
watch_option_handler (sd, opt, arg, is_command)
|
||||
SIM_DESC sd;
|
||||
int opt;
|
||||
char *arg;
|
||||
int is_command;
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
||||
case OPTION_WATCH_DELETE:
|
||||
if (strcmp (arg, "all") == 0
|
||||
|| strcmp (arg, "pc") == 0)
|
||||
{
|
||||
delete_watchpoint (sd, pc_watchpoint);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
if (strcmp (arg, "all") == 0
|
||||
|| strcmp (arg, "clock") == 0)
|
||||
{
|
||||
delete_watchpoint (sd, clock_watchpoint);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
if (strcmp (arg, "all") == 0
|
||||
|| strcmp (arg, "cycles") == 0)
|
||||
{
|
||||
delete_watchpoint (sd, cycles_watchpoint);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
sim_io_eprintf (sd, "Unknown watchpoint type `%s'\n", arg);
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
case OPTION_WATCH_PC:
|
||||
if (STATE_WATCHPOINTS (sd)->pc == NULL)
|
||||
{
|
||||
sim_io_eprintf (sd, "PC watchpoints are not supported for this simulator\n");
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
return schedule_watchpoint (sd, pc_watchpoint, strtoul (arg, NULL, 0), is_command);
|
||||
|
||||
case OPTION_WATCH_CLOCK:
|
||||
return schedule_watchpoint (sd, clock_watchpoint, strtoul (arg, NULL, 0), is_command);
|
||||
|
||||
case OPTION_WATCH_CYCLES:
|
||||
return schedule_watchpoint (sd, cycles_watchpoint, strtoul (arg, NULL, 0), is_command);
|
||||
|
||||
case OPTION_ACTION_PC:
|
||||
return action_watchpoint (sd, cycles_watchpoint, arg);
|
||||
|
||||
case OPTION_ACTION_CLOCK:
|
||||
return action_watchpoint (sd, cycles_watchpoint, arg);
|
||||
|
||||
case OPTION_ACTION_CYCLES:
|
||||
return action_watchpoint (sd, cycles_watchpoint, arg);
|
||||
|
||||
|
||||
default:
|
||||
sim_io_eprintf (sd, "Unknown watch option %d\n", opt);
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static SIM_RC
|
||||
sim_watchpoint_init (SIM_DESC sd)
|
||||
{
|
||||
/* schedule any watchpoints enabled by command line options */
|
||||
sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
|
||||
watchpoint_type type;
|
||||
for (type = 0; type < nr_watchpoint_types; type++)
|
||||
{
|
||||
if (watch->points[type].action != invalid_watchpoint_action)
|
||||
schedule_watchpoint (sd, type, watch->points[type].arg, 1/*is-command*/);
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
SIM_RC
|
||||
sim_watchpoint_install (SIM_DESC sd)
|
||||
{
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
sim_add_option_table (sd, watch_options);
|
||||
sim_module_add_init_fn (sd, sim_watchpoint_init);
|
||||
return SIM_RC_OK;
|
||||
}
|
67
sim/common/sim-watch.h
Normal file
67
sim/common/sim-watch.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* Simulator watchpoint support.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
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. */
|
||||
|
||||
|
||||
#ifndef SIM_WATCH_H
|
||||
#define SIM_WATCH_H
|
||||
|
||||
typedef enum {
|
||||
pc_watchpoint,
|
||||
clock_watchpoint,
|
||||
cycles_watchpoint,
|
||||
nr_watchpoint_types,
|
||||
} watchpoint_type;
|
||||
|
||||
typedef enum {
|
||||
invalid_watchpoint_action,
|
||||
n_interrupt_watchpoint_action,
|
||||
interrupt_watchpoint_action,
|
||||
break_watchpoint_action,
|
||||
} watchpoint_action;
|
||||
|
||||
typedef struct _sim_watch_point {
|
||||
watchpoint_action action;
|
||||
long arg;
|
||||
sim_event *event;
|
||||
} sim_watch_point;
|
||||
|
||||
|
||||
typedef struct _sim_watchpoints {
|
||||
|
||||
/* Pointer into the host's data structures specifying the
|
||||
address/size of the program-counter */
|
||||
/* FIXME: In the future this shall be generalized so that any of the
|
||||
N processors M registers can be watched */
|
||||
void *pc;
|
||||
int sizeof_pc;
|
||||
|
||||
/* Pointer to the handler for interrupt watchpoints */
|
||||
/* FIXME: can this be done better? */
|
||||
sim_event_handler *interrupt_handler;
|
||||
|
||||
/* suported watchpoints */
|
||||
sim_watch_point points[nr_watchpoint_types];
|
||||
|
||||
} sim_watchpoints;
|
||||
|
||||
/* Watch install handler. */
|
||||
MODULE_INSTALL_FN sim_watchpoint_install;
|
||||
|
||||
#endif /* SIM_WATCH_H */
|
@ -1,3 +1,9 @@
|
||||
Tue May 20 10:18:25 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* sim-if.c (sim_open): Add callback argument.
|
||||
(sim_set_callbacks, sim_callback): Delete.
|
||||
(sim_load): Set STATE_LOADED_P.
|
||||
|
||||
Mon May 19 12:55:42 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* Makefile.in (SIM_OBJS): Link in sim-abort.o as a stub for
|
||||
|
@ -1,3 +1,79 @@
|
||||
Wed May 21 09:08:10 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (interrupt_event): New function. Pass exception event
|
||||
onto exception handler.
|
||||
|
||||
* configure.in: Check for stdlib.h.
|
||||
* configure: Regenerate.
|
||||
|
||||
* gencode.c (build_instruction): Add UNUSED attribute to tempS
|
||||
variable declaration.
|
||||
(build_instruction): Initialize memval1.
|
||||
(build_instruction): Add UNUSED attribute to byte, bigend,
|
||||
reverse.
|
||||
(build_operands): Ditto.
|
||||
|
||||
* interp.c: Fix GCC warnings.
|
||||
(sim_get_quit_code): Delete.
|
||||
|
||||
* configure.in: Add INLINE, ENDIAN, HOSTENDIAN and WARNINGS.
|
||||
* Makefile.in: Ditto.
|
||||
* configure: Re-generate.
|
||||
|
||||
* Makefile.in (SIM_OBJS): Add sim-watch.o module.
|
||||
|
||||
Tue May 20 15:08:56 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (mips_option_handler): New function parse argumes using
|
||||
sim-options.
|
||||
(myname): Replace with STATE_MY_NAME.
|
||||
(sim_open): Delete check for host endianness - performed by
|
||||
sim_config.
|
||||
(simHOSTBE, simBE): Delete, replaced by sim-endian flags.
|
||||
(sim_open): Move much of the initialization from here.
|
||||
(sim_load): To here. After the image has been loaded and
|
||||
endianness set.
|
||||
(sim_open): Move ColdReset from here.
|
||||
(sim_create_inferior): To here.
|
||||
(sim_open): Make FP check less dependant on host endianness.
|
||||
|
||||
* Makefile.in (SIM_RUN_OBJS): Set to nrun.o - use new version or
|
||||
run.
|
||||
* interp.c (sim_set_callbacks): Delete.
|
||||
|
||||
* interp.c (membank, membank_base, membank_size): Replace with
|
||||
STATE_MEMORY, STATE_MEM_SIZE, STATE_MEM_BASE.
|
||||
(sim_open): Remove call to callback->init. gdb/run do this.
|
||||
|
||||
* interp.c: Update
|
||||
|
||||
* sim-main.h (SIM_HAVE_FLATMEM): Define.
|
||||
|
||||
* interp.c (big_endian_p): Delete, replaced by
|
||||
current_target_byte_order.
|
||||
|
||||
Tue May 20 13:55:00 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (host_read_long, host_read_word, host_swap_word,
|
||||
host_swap_long): Delete. Using common sim-endian.
|
||||
(sim_fetch_register, sim_store_register): Use H2T.
|
||||
(pipeline_ticks): Delete. Handled by sim-events.
|
||||
(sim_info): Update.
|
||||
(sim_engine_run): Update.
|
||||
|
||||
Tue May 20 13:42:03 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (sim_stop_reason): Move code determining simEXCEPTION
|
||||
reason from here.
|
||||
(SignalException): To here. Signal using sim_engine_halt.
|
||||
(sim_stop_reason): Delete, moved to common.
|
||||
|
||||
Tue May 20 10:19:48 1997 Andrew Cagney <cagney@b2.cygnus.com>
|
||||
|
||||
* interp.c (sim_open): Add callback argument.
|
||||
(sim_set_callbacks): Delete SIM_DESC argument.
|
||||
(sim_size): Ditto.
|
||||
|
||||
Mon May 19 18:20:38 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* Makefile.in (SIM_OBJS): Add common modules.
|
||||
|
@ -5,6 +5,13 @@ AC_INIT(Makefile.in)
|
||||
|
||||
SIM_AC_COMMON
|
||||
|
||||
dnl Options available in this module
|
||||
SIM_AC_OPTION_INLINE(0)
|
||||
SIM_AC_OPTION_ENDIAN(BIG_ENDIAN)
|
||||
SIM_AC_OPTION_HOSTENDIAN
|
||||
SIM_AC_OPTION_WARNINGS
|
||||
|
||||
|
||||
# Ensure a reasonable default simulator is constructed:
|
||||
case "${target}" in
|
||||
# start-sanitize-r5900
|
||||
@ -17,7 +24,7 @@ case "${target}" in
|
||||
esac
|
||||
AC_SUBST(SIMCONF)
|
||||
|
||||
AC_CHECK_HEADERS(string.h strings.h stdlib.h)
|
||||
AC_CHECK_HEADERS(string.h strings.h stdlib.h stdlib.h)
|
||||
AC_CHECK_LIB(m, fabs)
|
||||
AC_CHECK_FUNCS(aint anint sqrt)
|
||||
|
||||
|
@ -1249,7 +1249,7 @@ build_operands(doisa,features,insn)
|
||||
|
||||
any_operand = 1;
|
||||
|
||||
printf(" %s %s = ",opfields[opindex].type,opfields[opindex].name);
|
||||
printf(" %s %s UNUSED = ",opfields[opindex].type,opfields[opindex].name);
|
||||
|
||||
if (opfields[opindex].flags & OP_SIGNX)
|
||||
printf("SIGNEXTEND((%s)",opfields[opindex].type);
|
||||
@ -2158,7 +2158,7 @@ build_instruction (doisa, features, mips16, insn)
|
||||
|
||||
if ((insn->type) == ADD) {
|
||||
printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype);
|
||||
printf(" %s tempS = (%s)temp;\n", signed_basetype, signed_basetype);
|
||||
printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
|
||||
if (insn->flags & OVERFLOW) {
|
||||
printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
|
||||
printf(" SignalException(IntegerOverflow);\n");
|
||||
@ -2170,7 +2170,7 @@ build_instruction (doisa, features, mips16, insn)
|
||||
printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
|
||||
} else { /* SUB */
|
||||
printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype, unsigned_basetype);
|
||||
printf(" %s tempS = (%s)temp;\n", signed_basetype, signed_basetype);
|
||||
printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
|
||||
if (insn->flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */
|
||||
printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
|
||||
printf(" SignalException(IntegerOverflow);\n");
|
||||
@ -2641,8 +2641,8 @@ build_instruction (doisa, features, mips16, insn)
|
||||
printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
|
||||
else {
|
||||
printf(" {\n");
|
||||
printf(" uword64 memval;\n");
|
||||
printf(" uword64 memval1;\n");
|
||||
printf(" uword64 memval = 0;\n");
|
||||
printf(" uword64 memval1 = 0;\n");
|
||||
|
||||
if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
|
||||
fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
|
||||
@ -2773,9 +2773,9 @@ build_instruction (doisa, features, mips16, insn)
|
||||
printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
|
||||
#endif
|
||||
printf(" unsigned int shift = %d;\n",(datalen >> 1));
|
||||
printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
|
||||
printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
|
||||
printf(" unsigned int byte;\n");
|
||||
printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
|
||||
printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
|
||||
printf(" unsigned int byte UNUSED;\n");
|
||||
|
||||
/* TODO: This should really also check for 32bit world performing 32bit access */
|
||||
if (datalen < 8) /* not for DOUBLEWORD or QUADWORD*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
||||
Tue May 20 09:33:31 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* sim-calls.c (sim_load): Set STATE_LOADED_P.
|
||||
|
||||
* sim-main.h: Include <unistd.h>.
|
||||
|
||||
* sim-calls.c (sim_set_callback): Delete.
|
||||
|
@ -50,7 +50,9 @@ struct sim_state simulation = { 0 };
|
||||
|
||||
|
||||
SIM_DESC
|
||||
sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *callback, char **argv)
|
||||
sim_open (SIM_OPEN_KIND kind,
|
||||
host_callback *callback,
|
||||
char **argv)
|
||||
{
|
||||
SIM_DESC sd = &simulation;
|
||||
STATE_OPEN_KIND (sd) = kind;
|
||||
|
Loading…
x
Reference in New Issue
Block a user