aboutsummaryrefslogtreecommitdiff
path: root/sim/common
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>1997-05-21 06:54:13 +0000
committerAndrew Cagney <cagney@redhat.com>1997-05-21 06:54:13 +0000
commit50a2a691824992f474b19bf40bbff016b2f67150 (patch)
tree00df34e93ad0cb95e742316790b57f1ced5d7bb8 /sim/common
parent003c91bec4849e4a5b54d6e81383a4ff4376e996 (diff)
downloadfsf-binutils-gdb-50a2a691824992f474b19bf40bbff016b2f67150.zip
fsf-binutils-gdb-50a2a691824992f474b19bf40bbff016b2f67150.tar.gz
fsf-binutils-gdb-50a2a691824992f474b19bf40bbff016b2f67150.tar.bz2
Watchpoint interface.
Diffstat (limited to 'sim/common')
-rw-r--r--sim/common/ChangeLog61
-rw-r--r--sim/common/sim-core.c64
-rw-r--r--sim/common/sim-events.c322
-rw-r--r--sim/common/sim-events.h38
-rw-r--r--sim/common/sim-options.c132
-rw-r--r--sim/common/sim-options.h15
-rw-r--r--sim/common/sim-trace.c193
-rw-r--r--sim/common/sim-watch.c295
-rw-r--r--sim/common/sim-watch.h67
9 files changed, 912 insertions, 275 deletions
diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog
index 6398e02..6dfbdcd 100644
--- a/sim/common/ChangeLog
+++ b/sim/common/ChangeLog
@@ -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 -
diff --git a/sim/common/sim-core.c b/sim/common/sim-core.c
index e9102cf..3b9786c 100644
--- a/sim/common/sim-core.c
+++ b/sim/common/sim-core.c
@@ -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;
diff --git a/sim/common/sim-events.c b/sim/common/sim-events.c
index 00fac12..0053fbb 100644
--- a/sim/common/sim-events.c
+++ b/sim/common/sim-events.c
@@ -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;
-
- {
-#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
- 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 */
+
+ events->work_pending = 1; /* notify main process */
+
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
- /*-UNLOCK-*/
- sigprocmask (SIG_SETMASK, &old_mask, NULL);
+ /*-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);
-
- 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_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_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 {
@@ -722,13 +756,39 @@ 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,
int events_were_last,
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
diff --git a/sim/common/sim-events.h b/sim/common/sim-events.h
index 8c41927..fffde47 100644
--- a/sim/common/sim-events.h
+++ b/sim/common/sim-events.h
@@ -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 */
diff --git a/sim/common/sim-options.c b/sim/common/sim-options.c
index 5207457..4f8890b 100644
--- a/sim/common/sim-options.c
+++ b/sim/common/sim-options.c
@@ -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);
- 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);
+ /* 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 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;
}
diff --git a/sim/common/sim-options.h b/sim/common/sim-options.h
index f6f4dde..586b91c 100644
--- a/sim/common/sim-options.h
+++ b/sim/common/sim-options.h
@@ -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
diff --git a/sim/common/sim-trace.c b/sim/common/sim-trace.c
index f617783..944a781 100644
--- a/sim/common/sim-trace.c
+++ b/sim/common/sim-trace.c
@@ -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,
diff --git a/sim/common/sim-watch.c b/sim/common/sim-watch.c
new file mode 100644
index 0000000..9a0b1bc
--- /dev/null
+++ b/sim/common/sim-watch.c
@@ -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;
+}
diff --git a/sim/common/sim-watch.h b/sim/common/sim-watch.h
new file mode 100644
index 0000000..b101ebb
--- /dev/null
+++ b/sim/common/sim-watch.h
@@ -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 */