diff options
Diffstat (limited to 'sim/common')
-rw-r--r-- | sim/common/ChangeLog | 61 | ||||
-rw-r--r-- | sim/common/sim-core.c | 64 | ||||
-rw-r--r-- | sim/common/sim-events.c | 322 | ||||
-rw-r--r-- | sim/common/sim-events.h | 38 | ||||
-rw-r--r-- | sim/common/sim-options.c | 132 | ||||
-rw-r--r-- | sim/common/sim-options.h | 15 | ||||
-rw-r--r-- | sim/common/sim-trace.c | 193 | ||||
-rw-r--r-- | sim/common/sim-watch.c | 295 | ||||
-rw-r--r-- | sim/common/sim-watch.h | 67 |
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 */ |