From 50a2a691824992f474b19bf40bbff016b2f67150 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Wed, 21 May 1997 06:54:13 +0000 Subject: [PATCH] Watchpoint interface. --- include/ChangeLog | 7 + include/remote-sim.h | 9 +- sim/common/ChangeLog | 61 +++ sim/common/sim-core.c | 64 ++- sim/common/sim-events.c | 322 +++++++----- sim/common/sim-events.h | 38 +- sim/common/sim-options.c | 132 +++-- sim/common/sim-options.h | 15 +- sim/common/sim-trace.c | 193 +++++--- sim/common/sim-watch.c | 295 +++++++++++ sim/common/sim-watch.h | 67 +++ sim/m32r/ChangeLog | 6 + sim/mips/ChangeLog | 76 +++ sim/mips/configure.in | 9 +- sim/mips/gencode.c | 16 +- sim/mips/interp.c | 1003 ++++++++++++++++++-------------------- sim/tic80/ChangeLog | 2 + sim/tic80/sim-calls.c | 4 +- 18 files changed, 1497 insertions(+), 822 deletions(-) create mode 100644 sim/common/sim-watch.c create mode 100644 sim/common/sim-watch.h diff --git a/include/ChangeLog b/include/ChangeLog index c370eeca48b..000088931c7 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,6 +1,13 @@ +Wed May 21 16:47:53 1997 Andrew Cagney + + * remote-sim.h (sim_set_profile_size): Add prototype, document as + depreciated. + Tue May 20 09:32:22 1997 Andrew Cagney * remote-sim.h (sim_open): Add callback struct. + (sim_set_callbacks): Drop SIM_DESC argument. Document. + (sim_size): Remove recently added SIM_DESC argument. Document. Mon May 19 19:14:44 1997 Andrew Cagney diff --git a/include/remote-sim.h b/include/remote-sim.h index fb13a249772..c04109f5079 100644 --- a/include/remote-sim.h +++ b/include/remote-sim.h @@ -163,23 +163,22 @@ void sim_do_command PARAMS ((SIM_DESC sd, char *cmd)); /* NOTE: sim_set_callbacks () is depreciated. - Provide simulator with a default (global) host_callback_struct. */ - void sim_set_callbacks PARAMS ((struct host_callback_struct *)); /* NOTE: sim_size() is depreciated. - sim_size() does not take a SIM_DESC argument as this function is used before sim_open() has been called. */ - void sim_size PARAMS ((int i)); /* NOTE: sim_trace() is depreciated. */ - int sim_trace PARAMS ((SIM_DESC sd)); +/* NOTE: sim_set_profile_size is depreciated */ +void sim_set_profile_size PARAMS ((int n)); + + #endif /* !defined (REMOTE_SIM_H) */ diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 6398e02401f..6dfbdcd3a28 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,64 @@ +Wed May 21 08:47:30 1997 Andrew Cagney + + * 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 + + * 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 + + * 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 * 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 e9102cfd7a6..3b9786cd0b8 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 00fac12a13d..0053fbb8902 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 +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + #include + 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 { @@ -721,6 +755,32 @@ sim_events_tick (SIM_DESC sd) } +INLINE_SIM_EVENTS\ +(int) +sim_events_tickn (SIM_DESC sd, + unsigned n) +{ + sim_events *events = STATE_EVENTS (sd); + + /* this should only be called after the previous ticks have been + fully processed */ + SIM_ASSERT (events->nr_ticks_to_process == 0); + SIM_ASSERT (n > 0); + + /* Advance the time but *only* if there is nothing to process */ + if (events->work_pending + || events->time_from_event < n) + { + events->nr_ticks_to_process = n; + return 1; + } + else { + events->time_from_event -= n; + return 0; + } +} + + INLINE_SIM_EVENTS\ (void) sim_events_preprocess (SIM_DESC sd, @@ -728,7 +788,7 @@ sim_events_preprocess (SIM_DESC sd, int events_were_next) { sim_events *events = STATE_EVENTS(sd); - if (events->processing) + if (events->nr_ticks_to_process != 0) { /* Halted midway through event processing */ ASSERT (events_were_last && events_were_next); @@ -737,7 +797,7 @@ sim_events_preprocess (SIM_DESC sd, else if (events_were_next) { /* Halted by the last processor */ - ASSERT (!events->processing && !events_were_last); + ASSERT (events->nr_ticks_to_process == 0 && !events_were_last); if (sim_events_tick (sd)) sim_events_process (sd); } @@ -751,14 +811,13 @@ sim_events_process (SIM_DESC sd) sim_events *events = STATE_EVENTS(sd); signed64 event_time = sim_events_time(sd); - ASSERT (events->processing); + ASSERT (events->nr_ticks_to_process != 0); /* move any events that were queued by any signal handlers onto the real event queue. */ - if (events->held != NULL) + if (events->nr_held > 0) { - sim_event *held_events; - sim_event *curr_event; + int i; #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) /*-LOCK-*/ @@ -768,24 +827,21 @@ sim_events_process (SIM_DESC sd) sigprocmask(SIG_SETMASK, &new_mask, &old_mask); #endif - held_events = events->held; - events->held = NULL; - events->held_end = &events->held; - events->work_pending = 0; + for (i = 0; i < events->nr_held; i++) + { + sim_event *entry = &events->held [i]; + sim_events_schedule (sd, + entry->time_of_event, + entry->handler, + entry->data); + } + events->nr_held = 0; #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL); #endif - do - { - curr_event = held_events; - held_events = curr_event->next; - insert_sim_event (sd, curr_event, - curr_event->time_of_event); - } - while (held_events != NULL); } /* Process any watchpoints. Be careful to allow a watchpoint to @@ -809,7 +865,7 @@ sim_events_process (SIM_DESC sd) (long) to_do, (long) handler, (long) data)); - zfree (to_do); + sim_events_free (sd, to_do); handler (sd, data); } else @@ -821,7 +877,8 @@ sim_events_process (SIM_DESC sd) /* consume all events for this or earlier times. Be careful to allow an event to appear/disappear under our feet */ - while (events->queue->time_of_event <= event_time) + while (events->queue->time_of_event < + (event_time + events->nr_ticks_to_process)) { sim_event *to_do = events->queue; sim_event_handler *handler = to_do->handler; @@ -833,7 +890,7 @@ sim_events_process (SIM_DESC sd) (long) to_do, (long) handler, (long) data)); - zfree (to_do); + sim_events_free (sd, to_do); handler (sd, data); } @@ -843,13 +900,14 @@ sim_events_process (SIM_DESC sd) if (events->watchpoints != NULL) events->work_pending = 1; - /* this round of processing complete */ - events->processing = 0; - - /* re-caculate time for new events - advance the time */ + /* re-caculate time for new events then advance the time */ update_time_from_event(sd); - SIM_ASSERT(events->time_from_event > 0 && events->queue != NULL); - events->time_from_event -= 1; + SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process); + SIM_ASSERT (events->queue != NULL); /* always poll event */ + events->time_from_event -= events->nr_ticks_to_process; + + /* this round of processing complete */ + events->nr_ticks_to_process = 0; } #endif diff --git a/sim/common/sim-events.h b/sim/common/sim-events.h index 8c419276f83..fffde4776ee 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 5207457ef07..4f8890b9291 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 #endif #endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include #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 ...-d-e-f - continue search */ + name ++; /* skip `-' */ + argi ++; + continue; + } + else if (name [0] == '\0') + { + /* exact match ... - 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 f6f4ddedb81..586b91cfa68 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 f617783808b..944a7813300 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 #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 00000000000..9a0b1bc0988 --- /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 +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include + +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 00000000000..b101ebbea9a --- /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 */ diff --git a/sim/m32r/ChangeLog b/sim/m32r/ChangeLog index 55058dcb8e5..ba131c5c72f 100644 --- a/sim/m32r/ChangeLog +++ b/sim/m32r/ChangeLog @@ -1,3 +1,9 @@ +Tue May 20 10:18:25 1997 Andrew Cagney + + * sim-if.c (sim_open): Add callback argument. + (sim_set_callbacks, sim_callback): Delete. + (sim_load): Set STATE_LOADED_P. + Mon May 19 12:55:42 1997 Andrew Cagney * Makefile.in (SIM_OBJS): Link in sim-abort.o as a stub for diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 75e4c029681..946fd340441 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,79 @@ +Wed May 21 09:08:10 1997 Andrew Cagney + + * interp.c (interrupt_event): New function. Pass exception event + onto exception handler. + + * configure.in: Check for stdlib.h. + * configure: Regenerate. + + * gencode.c (build_instruction): Add UNUSED attribute to tempS + variable declaration. + (build_instruction): Initialize memval1. + (build_instruction): Add UNUSED attribute to byte, bigend, + reverse. + (build_operands): Ditto. + + * interp.c: Fix GCC warnings. + (sim_get_quit_code): Delete. + + * configure.in: Add INLINE, ENDIAN, HOSTENDIAN and WARNINGS. + * Makefile.in: Ditto. + * configure: Re-generate. + + * Makefile.in (SIM_OBJS): Add sim-watch.o module. + +Tue May 20 15:08:56 1997 Andrew Cagney + + * interp.c (mips_option_handler): New function parse argumes using + sim-options. + (myname): Replace with STATE_MY_NAME. + (sim_open): Delete check for host endianness - performed by + sim_config. + (simHOSTBE, simBE): Delete, replaced by sim-endian flags. + (sim_open): Move much of the initialization from here. + (sim_load): To here. After the image has been loaded and + endianness set. + (sim_open): Move ColdReset from here. + (sim_create_inferior): To here. + (sim_open): Make FP check less dependant on host endianness. + + * Makefile.in (SIM_RUN_OBJS): Set to nrun.o - use new version or + run. + * interp.c (sim_set_callbacks): Delete. + + * interp.c (membank, membank_base, membank_size): Replace with + STATE_MEMORY, STATE_MEM_SIZE, STATE_MEM_BASE. + (sim_open): Remove call to callback->init. gdb/run do this. + + * interp.c: Update + + * sim-main.h (SIM_HAVE_FLATMEM): Define. + + * interp.c (big_endian_p): Delete, replaced by + current_target_byte_order. + +Tue May 20 13:55:00 1997 Andrew Cagney + + * interp.c (host_read_long, host_read_word, host_swap_word, + host_swap_long): Delete. Using common sim-endian. + (sim_fetch_register, sim_store_register): Use H2T. + (pipeline_ticks): Delete. Handled by sim-events. + (sim_info): Update. + (sim_engine_run): Update. + +Tue May 20 13:42:03 1997 Andrew Cagney + + * interp.c (sim_stop_reason): Move code determining simEXCEPTION + reason from here. + (SignalException): To here. Signal using sim_engine_halt. + (sim_stop_reason): Delete, moved to common. + +Tue May 20 10:19:48 1997 Andrew Cagney + + * interp.c (sim_open): Add callback argument. + (sim_set_callbacks): Delete SIM_DESC argument. + (sim_size): Ditto. + Mon May 19 18:20:38 1997 Andrew Cagney * Makefile.in (SIM_OBJS): Add common modules. diff --git a/sim/mips/configure.in b/sim/mips/configure.in index 179940af75e..6349731ad4b 100644 --- a/sim/mips/configure.in +++ b/sim/mips/configure.in @@ -5,6 +5,13 @@ AC_INIT(Makefile.in) SIM_AC_COMMON +dnl Options available in this module +SIM_AC_OPTION_INLINE(0) +SIM_AC_OPTION_ENDIAN(BIG_ENDIAN) +SIM_AC_OPTION_HOSTENDIAN +SIM_AC_OPTION_WARNINGS + + # Ensure a reasonable default simulator is constructed: case "${target}" in # start-sanitize-r5900 @@ -17,7 +24,7 @@ case "${target}" in esac AC_SUBST(SIMCONF) -AC_CHECK_HEADERS(string.h strings.h stdlib.h) +AC_CHECK_HEADERS(string.h strings.h stdlib.h stdlib.h) AC_CHECK_LIB(m, fabs) AC_CHECK_FUNCS(aint anint sqrt) diff --git a/sim/mips/gencode.c b/sim/mips/gencode.c index 73521c3dc07..bdd88028fac 100644 --- a/sim/mips/gencode.c +++ b/sim/mips/gencode.c @@ -1249,7 +1249,7 @@ build_operands(doisa,features,insn) any_operand = 1; - printf(" %s %s = ",opfields[opindex].type,opfields[opindex].name); + printf(" %s %s UNUSED = ",opfields[opindex].type,opfields[opindex].name); if (opfields[opindex].flags & OP_SIGNX) printf("SIGNEXTEND((%s)",opfields[opindex].type); @@ -2158,7 +2158,7 @@ build_instruction (doisa, features, mips16, insn) if ((insn->type) == ADD) { printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype); - printf(" %s tempS = (%s)temp;\n", signed_basetype, signed_basetype); + printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype); if (insn->flags & OVERFLOW) { printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n"); printf(" SignalException(IntegerOverflow);\n"); @@ -2170,7 +2170,7 @@ build_instruction (doisa, features, mips16, insn) printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype); } else { /* SUB */ printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype, unsigned_basetype); - printf(" %s tempS = (%s)temp;\n", signed_basetype, signed_basetype); + printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype); if (insn->flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */ printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n"); printf(" SignalException(IntegerOverflow);\n"); @@ -2641,8 +2641,8 @@ build_instruction (doisa, features, mips16, insn) printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n"); else { printf(" {\n"); - printf(" uword64 memval;\n"); - printf(" uword64 memval1;\n"); + printf(" uword64 memval = 0;\n"); + printf(" uword64 memval1 = 0;\n"); if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) { fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name); @@ -2773,9 +2773,9 @@ build_instruction (doisa, features, mips16, insn) printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3)); #endif printf(" unsigned int shift = %d;\n",(datalen >> 1)); - printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n"); - printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n"); - printf(" unsigned int byte;\n"); + printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n"); + printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n"); + printf(" unsigned int byte UNUSED;\n"); /* TODO: This should really also check for 32bit world performing 32bit access */ if (datalen < 8) /* not for DOUBLEWORD or QUADWORD*/ diff --git a/sim/mips/interp.c b/sim/mips/interp.c index ea7adcdf42f..e2a005640f5 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -44,6 +44,7 @@ code on the hardware. #include "sim-main.h" #include "sim-utils.h" #include "sim-options.h" +#include "sim-assert.h" #include "config.h" @@ -91,9 +92,7 @@ char* pr_uword64 PARAMS ((uword64 addr)); #include "engine.c" #undef SIM_MANIFESTS -struct sim_state simulator = { 0 }; -static char *myname; -static int big_endian_p; +struct sim_state simulator; /* The following reserved instruction value is used when a simulator trap is required. NOTE: Care must be taken, since this value may be @@ -189,7 +188,9 @@ typedef enum { and then going back to the point where the context was saved and changing some state before continuing. i.e. the ability to perform UNDOs on simulations. It would also allow the simulation of - shared-memory multi-processor systems. */ + shared-memory multi-processor systems. + + [NOTE: This is now partially implemented] */ static host_callback *callback = NULL; /* handle onto the current callback structure */ @@ -498,10 +499,6 @@ static int HIACCESS = 0; static int LOACCESS = 0; static int HI1ACCESS = 0; static int LO1ACCESS = 0; -/* The HIACCESS and LOACCESS counts are used to ensure that - corruptions caused by using the HI or LO register to close to a - following operation are spotted. */ -static ut_reg HLPC = 0; /* ??? The 4300 and a few other processors have interlocks on hi/lo register reads, and hence do not have this problem. To avoid spurious warnings, @@ -509,6 +506,10 @@ static ut_reg HLPC = 0; #if 1 #define CHECKHILO(s) #else +/* The HIACCESS and LOACCESS counts are used to ensure that + corruptions caused by using the HI or LO register to close to a + following operation are spotted. */ +static ut_reg HLPC = 0; /* If either of the preceding two instructions have accessed the HI or LO registers, then the values they see should be undefined. However, to keep the simulator world simple, we just let @@ -531,11 +532,12 @@ static ut_reg HLPC = 0; /* Hardware configuration. Affects endianness of LoadMemory and StoreMemory and the endianness of Kernel and Supervisor mode execution. The value is 0 for little-endian; 1 for big-endian. */ -#define BigEndianMem ((state & simBE) ? 1 : 0) +#define BigEndianMem (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) +/*(state & simBE) ? 1 : 0)*/ /* ByteSwapMem */ /* This is true if the host and target have different endianness. */ -#define ByteSwapMem (!(state & simHOSTBE) != !(state & simBE)) +#define ByteSwapMem (CURRENT_TARGET_BYTE_ORDER != CURRENT_HOST_BYTE_ORDER) /* ReverseEndian */ /* This mode is selected if in User mode with the RE bit being set in @@ -556,40 +558,21 @@ static ut_reg HLPC = 0; engine. */ static unsigned int instruction_fetches = 0; static unsigned int instruction_fetch_overflow = 0; -static unsigned int pipeline_ticks = 0; #endif /* Flags in the "state" variable: */ -#if 0 -#define simSTOP (1 << 0) /* 0 = execute; 1 = stop simulation */ -#define simSTEP (1 << 1) /* 0 = run; 1 = single-step */ -#endif #define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */ #define simHALTIN (1 << 3) /* 0 = run; 1 = halt on interrupt */ #define simTRACE (1 << 8) /* 0 = do nothing; 1 = trace address activity */ #define simPROFILE (1 << 9) /* 0 = do nothing; 1 = gather profiling samples */ -#define simHOSTBE (1 << 10) /* 0 = little-endian; 1 = big-endian (host endianness) */ -/* Whilst simSTOP is not set, the simulator control loop should just - keep simulating instructions. The simSTEP flag is used to force - single-step execution. */ -#define simBE (1 << 16) /* 0 = little-endian; 1 = big-endian (target endianness) */ #define simPCOC0 (1 << 17) /* COC[1] from current */ #define simPCOC1 (1 << 18) /* COC[1] from previous */ #define simDELAYSLOT (1 << 24) /* 0 = do nothing; 1 = delay slot entry exists */ #define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */ -#if 0 -#define simEXCEPTION (1 << 26) /* 0 = no exception; 1 = exception has occurred */ -#endif -#if 0 -#define simEXIT (1 << 27) /* 0 = do nothing; 1 = run-time exit() processing */ -#endif #define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */ #define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */ static unsigned int state = 0; -#if 0 -static unsigned int rcexit = 0; /* _exit() reason code holder */ -#endif #define DELAYSLOT() {\ if (state & simDELAYSLOT)\ @@ -615,15 +598,6 @@ static unsigned int rcexit = 0; /* _exit() reason code holder */ #define K1BASE (0xA0000000) #define K1SIZE (0x20000000) -/* Very simple memory model to start with: */ -static unsigned char *membank = NULL; -static ut_reg membank_base = K1BASE; -/* The ddb.ld linker script loads text at K1BASE+1MB, and the idt.ld linker - script loads text at K1BASE+128KB. We allocate 2MB, so that we have a - minimum of 1 MB available for the user process. We must have memory - above _end in order for sbrk to work. */ -static unsigned membank_size = (2 << 20); - /* Simple run-time monitor support */ static unsigned char *monitor = NULL; static ut_reg monitor_base = 0xBFC00000; @@ -647,69 +621,178 @@ static ut_reg profile_maxpc; static int profile_shift = 0; /* address shift amount */ #endif /* PROFILE */ -#if 0 -/* The following are used to provide shortcuts to the required version - of host<->target copying. This avoids run-time conditionals, which - would slow the simulator throughput. */ -typedef unsigned int (*fnptr_read_word) PARAMS((unsigned char *memory)); -typedef unsigned int (*fnptr_swap_word) PARAMS((unsigned int data)); -typedef uword64 (*fnptr_read_long) PARAMS((unsigned char *memory)); -typedef uword64 (*fnptr_swap_long) PARAMS((uword64 data)); -#endif -static unsigned int -host_read_word (unsigned char *memory) -{ - /* actuall target->host */ - return T2H_4 (*(unsigned int*)memory); -} -static uword64 -host_read_long (unsigned char *memory) +static SIM_RC +mips_option_handler (sd, opt, arg) + SIM_DESC sd; + int opt; + char *arg; { - /* actuall target->host */ - return T2H_8 (*(uword64*)memory); + switch (opt) + { + case 'l': + if (arg != NULL) { + char *tmp; + tmp = (char *)malloc(strlen(arg) + 1); + if (tmp == NULL) + callback->printf_filtered(callback,"Failed to allocate buffer for logfile name \"%s\"\n",optarg); + else { + strcpy(tmp,optarg); + logfile = tmp; + } + } + return SIM_RC_OK; + + case 'n': /* OK */ + callback->printf_filtered(callback,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg); + return SIM_RC_FAIL; + + case 't': /* ??? */ +#if defined(TRACE) + /* Eventually the simTRACE flag could be treated as a toggle, to + allow external control of the program points being traced + (i.e. only from main onwards, excluding the run-time setup, + etc.). */ + if (arg == NULL) + state |= simTRACE; + else if (strcmp (arg, "yes") == 0) + state |= simTRACE; + else if (strcmp (arg, "no") == 0) + state &= ~simTRACE; + else + { + fprintf (stderr, "Unreconized trace option `%s'\n", arg); + return SIM_RC_FAIL; + } + return SIM_RC_OK; +#else /* !TRACE */ + fprintf(stderr,"\ +Simulator constructed without tracing support (for performance).\n\ +Re-compile simulator with \"-DTRACE\" to enable this option.\n"); + return SIM_RC_FAIL; +#endif /* !TRACE */ + + case 'z': +#if defined(TRACE) + if (optarg != NULL) { + char *tmp; + tmp = (char *)malloc(strlen(optarg) + 1); + if (tmp == NULL) + { + callback->printf_filtered(callback,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg); + return SIM_RC_FAIL; + } + else { + strcpy(tmp,optarg); + tracefile = tmp; + callback->printf_filtered(callback,"Placing trace information into file \"%s\"\n",tracefile); + } + } +#endif /* TRACE */ + return SIM_RC_OK; + + case 'p': +#if defined(PROFILE) + state |= simPROFILE; + return SIM_RC_OK; +#else /* !PROFILE */ + fprintf(stderr,"\ +Simulator constructed without profiling support (for performance).\n\ +Re-compile simulator with \"-DPROFILE\" to enable this option.\n"); + return SIM_RC_FAIL; +#endif /* !PROFILE */ + + case 'x': +#if defined(PROFILE) + profile_nsamples = (unsigned)getnum(optarg); +#endif /* PROFILE */ + return SIM_RC_OK; + + case 'y': +#if defined(PROFILE) + sim_set_profile((int)getnum(optarg)); +#endif /* PROFILE */ + return SIM_RC_OK; + + } + + return SIM_RC_OK; } -static unsigned int -host_swap_word (unsigned int val) + +static const OPTION mips_options[] = { - /* actuall host->target */ - return H2T_4 (val); -} -static uword64 -host_swap_long (uword64 val) + { {"log", required_argument, NULL,'l'}, + 'l', "FILE", "Log file", + mips_option_handler }, + { {"name", required_argument, NULL,'n'}, + 'n', "MODEL", "Select arch model", + mips_option_handler }, + { {"profile", optional_argument, NULL,'p'}, + 'p', "on|off", "Enable profiling", + mips_option_handler }, + { {"trace", optional_argument, NULL,'t'}, + 't', "on|off", "Enable tracing", + mips_option_handler }, + { {"tracefile",required_argument, NULL,'z'}, + 'z', "FILE", "Write trace to file", + mips_option_handler }, + { {"frequency",required_argument, NULL,'y'}, + 'y', "FREQ", "Profile frequency", + mips_option_handler }, + { {"samples", required_argument, NULL,'x'}, + 'y', "SIZE", "Profile sample size", + mips_option_handler }, + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + + +static void +interrupt_event (SIM_DESC sd, void *data) { - /* actuall host->target */ - return H2T_8 (val); + SignalException (Interrupt); } + /*---------------------------------------------------------------------------*/ /*-- GDB simulator interface ------------------------------------------------*/ /*---------------------------------------------------------------------------*/ SIM_DESC -sim_open (kind,argv) +sim_open (kind,cb,argv) SIM_OPEN_KIND kind; + host_callback *cb; char **argv; { SIM_DESC sd = &simulator; + STATE_OPEN_KIND (sd) = kind; STATE_MAGIC (sd) = SIM_MAGIC_NUMBER; + STATE_CALLBACK (sd) = cb; + callback = cb; CPU_STATE (STATE_CPU (sd, 0)) = sd; + /* FIXME: watchpoints code shouldn't need this */ + STATE_WATCHPOINTS (sd)->pc = &(PC); + STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC); + STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event; + + /* memory defaults (unless sim_size was here first) */ + if (STATE_MEM_SIZE (sd) == 0) + STATE_MEM_SIZE (sd) = (2 << 20); + STATE_MEM_BASE (sd) = K1BASE; + if (callback == NULL) { fprintf(stderr,"SIM Error: sim_open() called without callbacks attached\n"); return 0; } - /* The following ensures that the standard file handles for stdin, - stdout and stderr are initialised: */ - callback->init(callback); - + state = 0; + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) return 0; + sim_add_option_table (sd, mips_options); -#if 0 /* getopt will print the error message so we just have to exit if this fails. FIXME: Hmmm... in the case of gdb we need getopt to call print_filtered. */ @@ -720,7 +803,6 @@ sim_open (kind,argv) sim_module_uninstall (sd); return 0; } -#endif if (sim_post_argv_init (sd) != SIM_RC_OK) { @@ -730,40 +812,35 @@ sim_open (kind,argv) return 0; } - myname = argv[0]; - - state = 0; - - /* doesn't return if a problem occures */ + /* verify assumptions the simulator made about the host type system. + This macro does not return if there is a problem */ CHECKSIM(); - /* check endianness */ - { - int data = 0x12; - if (*((char *)&data) != 0x12) - state |= simHOSTBE; /* big-endian host */ - } - #if defined(HASFPU) /* Check that the host FPU conforms to IEEE 754-1985 for the SINGLE and DOUBLE binary formats. This is a bit nasty, requiring that we trust the explicit manifests held in the source: */ + /* TODO: We need to cope with the simulated target and the host not + having the same endianness. This will require the high and low + words of a (double) to be swapped when converting between the + host and the simulated target. */ { - unsigned int s[2]; - s[state & simHOSTBE ? 0 : 1] = 0x40805A5A; - s[state & simHOSTBE ? 1 : 0] = 0x00000000; - - /* TODO: We need to cope with the simulated target and the host - not having the same endianness. This will require the high and - low words of a (double) to be swapped when converting between - the host and the simulated target. */ - - if (((float)4.01102924346923828125 != *(float *)(s + ((state & simHOSTBE) ? 0 : 1))) || ((double)523.2939453125 != *(double *)s)) { - fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n"); - fprintf(stderr,"*(float *)s = %.20f (4.01102924346923828125)\n",*(float *)s); - fprintf(stderr,"*(double *)s = %.20f (523.2939453125)\n",*(double *)s); - exit(1); - } + union { + unsigned int i[2]; + double d; + float f[2]; + } s; + + s.d = (double)523.2939453125; + + if ((s.i[0] == 0 && (s.f[1] != (float)4.01102924346923828125 + || s.i[1] != 0x40805A5A)) + || (s.i[1] == 0 && (s.f[0] != (float)4.01102924346923828125 + || s.i[0] != 0x40805A5A))) + { + fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n"); + return 0; + } } #endif /* HASFPU */ @@ -785,146 +862,6 @@ sim_open (kind,argv) } } - /* It would be good if we could select particular named MIPS - architecture simulators. However, having a pre-built, fixed - engine would mean including multiple engines. If the simulator is - changed to a run-time conditional version, then the ability to - select a particular architecture would be straightforward. */ - { - int c; - char *cline; - int argc; - static struct option cmdline[] = { - {"help", 0,0,'h'}, - {"log", 1,0,'l'}, - {"name", 1,0,'n'}, - {"profile", 0,0,'p'}, - {"size", 1,0,'s'}, - {"trace", 0,0,'t'}, - {"tracefile",1,0,'z'}, - {"frequency",1,0,'y'}, - {"samples", 1,0,'x'}, - {0, 0,0,0} - }; - - for (argc = 0; argv[argc]; argc++); - - /* Ensure getopt is reset [don't know whether caller used it]. */ - optind = 0; - - while (1) { - int option_index = 0; - - c = getopt_long(argc,argv,"E:hn:s:tp",cmdline,&option_index); - if (c == -1) - break; - - switch (c) { - case 'E' : - big_endian_p = strcmp (optarg, "big") == 0; - break; - - case 'h': - callback->printf_filtered(callback,"Usage:\n\t\ -target sim [-h] [--log=] [--name=] [--size=]"); -#if defined(TRACE) - callback->printf_filtered(callback," [-t [--tracefile=]]"); -#endif /* TRACE */ -#if defined(PROFILE) - callback->printf_filtered(callback," [-p [--frequency=] [--samples=]]"); -#endif /* PROFILE */ - callback->printf_filtered(callback,"\n"); - break; - - case 'l': - if (optarg != NULL) { - char *tmp; - tmp = (char *)malloc(strlen(optarg) + 1); - if (tmp == NULL) - callback->printf_filtered(callback,"Failed to allocate buffer for logfile name \"%s\"\n",optarg); - else { - strcpy(tmp,optarg); - logfile = tmp; - } - } - break; - - case 'n': - callback->printf_filtered(callback,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg); - break; - - case 's': - membank_size = (unsigned)getnum(optarg); - break; - - case 't': -#if defined(TRACE) - /* Eventually the simTRACE flag could be treated as a toggle, to - allow external control of the program points being traced - (i.e. only from main onwards, excluding the run-time setup, - etc.). */ - state |= simTRACE; -#else /* !TRACE */ - fprintf(stderr,"\ -Simulator constructed without tracing support (for performance).\n\ -Re-compile simulator with \"-DTRACE\" to enable this option.\n"); -#endif /* !TRACE */ - break; - - case 'z': -#if defined(TRACE) - if (optarg != NULL) { - char *tmp; - tmp = (char *)malloc(strlen(optarg) + 1); - if (tmp == NULL) - callback->printf_filtered(callback,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg); - else { - strcpy(tmp,optarg); - tracefile = tmp; - callback->printf_filtered(callback,"Placing trace information into file \"%s\"\n",tracefile); - } - } -#endif /* TRACE */ - break; - - case 'p': -#if defined(PROFILE) - state |= simPROFILE; -#else /* !PROFILE */ - fprintf(stderr,"\ -Simulator constructed without profiling support (for performance).\n\ -Re-compile simulator with \"-DPROFILE\" to enable this option.\n"); -#endif /* !PROFILE */ - break; - - case 'x': -#if defined(PROFILE) - profile_nsamples = (unsigned)getnum(optarg); -#endif /* PROFILE */ - break; - - case 'y': -#if defined(PROFILE) - sim_set_profile((int)getnum(optarg)); -#endif /* PROFILE */ - break; - - default: - callback->printf_filtered(callback,"Warning: Simulator getopt returned unrecognised code 0x%08X\n",c); - case '?': - break; - } - } - -#if 0 - if (optind < argc) { - callback->printf_filtered(callback,"Warning: Ignoring spurious non-option arguments "); - while (optind < argc) - callback->printf_filtered(callback,"\"%s\" ",argv[optind++]); - callback->printf_filtered(callback,"\n"); - } -#endif - } if (logfile != NULL) { if (strcmp(logfile,"-") == 0) @@ -938,104 +875,28 @@ Re-compile simulator with \"-DPROFILE\" to enable this option.\n"); } } - sim_config (sd, big_endian_p ? BIG_ENDIAN : LITTLE_ENDIAN); + /* FIXME: In the future both of these malloc's can be replaced by + calls to sim-core. */ /* If the host has "mmap" available we could use it to provide a very large virtual address space for the simulator, since memory would only be allocated within the "mmap" space as it is accessed. This can also be linked to the architecture specific support, required to simulate the MMU. */ - sim_size(sd, membank_size); - /* NOTE: The above will also have enabled any profiling state */ - - ColdReset(); - /* If we were providing a more complete I/O, co-processor or memory - simulation, we should perform any "device" initialisation at this - point. This can include pre-loading memory areas with particular - patterns (e.g. simulating ROM monitors). */ + sim_size(STATE_MEM_SIZE (sd)); + /* NOTE: The above will also have enabled any profiling state! */ - /* We can start writing to the memory, now that the processor has - been reset: */ + /* Create the monitor address space as well */ monitor = (unsigned char *)calloc(1,monitor_size); - if (!monitor) { - fprintf(stderr,"Not enough VM for monitor simulation (%d bytes)\n",monitor_size); - } else { - unsigned loop; - /* Entry into the IDT monitor is via fixed address vectors, and - not using machine instructions. To avoid clashing with use of - the MIPS TRAP system, we place our own (simulator specific) - "undefined" instructions into the relevant vector slots. */ - for (loop = 0; (loop < monitor_size); loop += 4) { - uword64 vaddr = (monitor_base + loop); - uword64 paddr; - int cca; - if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) - StoreMemory(cca,AccessLength_WORD,(RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT)),0,paddr,vaddr,isRAW); - } - /* The PMON monitor uses the same address space, but rather than - branching into it the address of a routine is loaded. We can - cheat for the moment, and direct the PMON routine to IDT style - instructions within the monitor space. This relies on the IDT - monitor not using the locations from 0xBFC00500 onwards as its - entry points.*/ - for (loop = 0; (loop < 24); loop++) - { - uword64 vaddr = (monitor_base + 0x500 + (loop * 4)); - uword64 paddr; - int cca; - unsigned int value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */ - switch (loop) - { - case 0: /* read */ - value = 7; - break; - - case 1: /* write */ - value = 8; - break; - - case 2: /* open */ - value = 6; - break; - - case 3: /* close */ - value = 10; - break; - - case 5: /* printf */ - value = ((0x500 - 16) / 8); /* not an IDT reason code */ - break; - - case 8: /* cliexit */ - value = 17; - break; - - case 11: /* flush_cache */ - value = 28; - break; - } - /* FIXME - should monitor_base be SIM_ADDR?? */ - value = ((unsigned int)monitor_base + (value * 8)); - if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) - StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW); - else - sim_error("Failed to write to monitor space 0x%s",pr_addr(vaddr)); - - /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */ - vaddr -= 0x300; - if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) - StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW); - else - sim_error("Failed to write to monitor space 0x%s",pr_addr(vaddr)); - } - } + if (!monitor) + fprintf(stderr,"Not enough VM for monitor simulation (%d bytes)\n", + monitor_size); #if defined(TRACE) if (state & simTRACE) open_trace(); #endif /* TRACE */ - /* fudge our descriptor for now */ return sd; } @@ -1066,7 +927,7 @@ writeout32(fh,val) char buff[4]; int res = 1; - if (state & simHOSTBE) { + if (CURRENT_HOST_BYTE_ORDER == BIG_ENDIAN) { buff[3] = ((val >> 0) & 0xFF); buff[2] = ((val >> 8) & 0xFF); buff[1] = ((val >> 16) & 0xFF); @@ -1091,7 +952,7 @@ writeout16(fh,val) { char buff[2]; int res = 1; - if (state & simHOSTBE) { + if (CURRENT_HOST_BYTE_ORDER == BIG_ENDIAN) { buff[1] = ((val >> 0) & 0xFF); buff[0] = ((val >> 8) & 0xFF); } else { @@ -1123,7 +984,6 @@ sim_close (sd, quitting) #if defined(PROFILE) if ((state & simPROFILE) && (profile_hist != NULL)) { - unsigned short *p = profile_hist; FILE *pf = fopen("gmon.out","wb"); unsigned loop; @@ -1169,9 +1029,9 @@ sim_close (sd, quitting) fclose(logfh); logfh = NULL; - if (membank) - free(membank); /* cfree not available on all hosts */ - membank = NULL; + if (STATE_MEMORY (sd) != NULL) + free(STATE_MEMORY (sd)); /* cfree not available on all hosts */ + STATE_MEMORY (sd) = NULL; return; } @@ -1326,6 +1186,8 @@ sim_store_register (sd,rn,memory) int rn; unsigned char *memory; { + /* NOTE: gdb (the client) stores registers in target byte order + while the simulator uses host byte order */ #ifdef DEBUG callback->printf_filtered(callback,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory))); #endif /* DEBUG */ @@ -1333,14 +1195,16 @@ sim_store_register (sd,rn,memory) /* Unfortunately this suffers from the same problem as the register numbering one. We need to know what the width of each logical register number is for the architecture being simulated. */ + if (register_widths[rn] == 0) - sim_warning("Invalid register width for %d (register store ignored)",rn); - else { - if (register_widths[rn] == 32) - registers[rn] = host_read_word(memory); - else - registers[rn] = host_read_long(memory); - } + sim_warning("Invalid register width for %d (register store ignored)",rn); + else + { + if (register_widths[rn] == 32) + registers[rn] = T2H_4 (*(unsigned int*)memory); + else + registers[rn] = T2H_8 (*(uword64*)memory); + } return; } @@ -1351,96 +1215,25 @@ sim_fetch_register (sd,rn,memory) int rn; unsigned char *memory; { + /* NOTE: gdb (the client) stores registers in target byte order + while the simulator uses host byte order */ #ifdef DEBUG callback->printf_filtered(callback,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn])); #endif /* DEBUG */ if (register_widths[rn] == 0) - sim_warning("Invalid register width for %d (register fetch ignored)",rn); - else { - if (register_widths[rn] == 32) - *((unsigned int *)memory) = host_swap_word((unsigned int)(registers[rn] & 0xFFFFFFFF)); - else /* 64bit register */ - *((uword64 *)memory) = host_swap_long(registers[rn]); - } - return; -} - -#if 0 -void -sim_stop_reason (sd,reason,sigrc) - SIM_DESC sd; - enum sim_stop *reason; - int *sigrc; -{ -/* We can have "*reason = {sim_exited, sim_stopped, sim_signalled}", so - sim_exited *sigrc = argument to exit() - sim_stopped *sigrc = exception number - sim_signalled *sigrc = signal number -*/ - if (state & simEXCEPTION) { - /* If "sim_signalled" is used, GDB expects normal SIGNAL numbers, - and not the MIPS specific exception codes. */ -#if 1 - /* For some reason, sending GDB a sim_signalled reason cause it to - terminate out. */ - *reason = sim_stopped; -#else - *reason = sim_signalled; -#endif - switch ((CAUSE >> 2) & 0x1F) { - case Interrupt: - *sigrc = SIGINT; /* wrong type of interrupt, but it will do for the moment */ - break; - - case TLBModification: - case TLBLoad: - case TLBStore: - case AddressLoad: - case AddressStore: - case InstructionFetch: - case DataReference: - *sigrc = SIGBUS; - break; - - case ReservedInstruction: - case CoProcessorUnusable: - *sigrc = SIGILL; - break; - - case IntegerOverflow: - case FPE: - *sigrc = SIGFPE; - break; - - case Trap: - case Watch: - case SystemCall: - case BreakPoint: - *sigrc = SIGTRAP; - break; - - default : /* Unknown internal exception */ - *sigrc = SIGQUIT; - break; + sim_warning("Invalid register width for %d (register fetch ignored)",rn); + else + { + if (register_widths[rn] == 32) + *((unsigned int *)memory) = H2T_4 ((unsigned int)(registers[rn] & 0xFFFFFFFF)); + else /* 64bit register */ + *((uword64 *)memory) = H2T_8 (registers[rn]); } - } else if (state & simEXIT) { -#if DEBUG - printf("DBG: simEXIT (%d)\n",rcexit); -#endif - *reason = sim_exited; - *sigrc = rcexit; - } else if (state & simSIGINT) { - *reason = sim_stopped; - *sigrc = SIGINT; - } else { /* assume single-stepping */ - *reason = sim_stopped; - *sigrc = SIGTRAP; - } - state &= ~(simEXCEPTION | simEXIT | simSIGINT); + return; } -#endif + void sim_info (sd,verbose) @@ -1451,16 +1244,21 @@ sim_info (sd,verbose) callback->printf_filtered(callback,"MIPS %d-bit simulator\n",(PROCESSOR_64BIT ? 64 : 32)); - callback->printf_filtered(callback,"%s endian memory model\n",(state & simBE ? "Big" : "Little")); + callback->printf_filtered(callback,"%s endian memory model\n", + (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN + ? "Big" : "Little")); - callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%s\n",(unsigned int)membank_size,pr_addr(membank_base)); + callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%s\n", + STATE_MEM_SIZE (sd), + pr_addr (STATE_MEM_BASE (sd))); #if !defined(FASTSIM) if (instruction_fetch_overflow != 0) callback->printf_filtered(callback,"Instruction fetches = 0x%08X%08X\n",instruction_fetch_overflow,instruction_fetches); else callback->printf_filtered(callback,"Instruction fetches = %d\n",instruction_fetches); - callback->printf_filtered(callback,"Pipeline ticks = %d\n",pipeline_ticks); + callback->printf_filtered(callback,"Pipeline ticks = %ld\n", + (long) sim_events_time (sd)); /* It would be a useful feature, if when performing multi-cycle simulations (rather than single-stepping) we keep the start and end times of the execution, so that we can give a performance @@ -1491,7 +1289,7 @@ sim_load (sd,prog,abfd,from_tty) bfd *prog_bfd; prog_bfd = sim_load_file (sd, - myname, + STATE_MY_NAME (sd), callback, prog, /* pass NULL for abfd, we always open our own */ @@ -1500,6 +1298,87 @@ sim_load (sd,prog,abfd,from_tty) if (prog_bfd == NULL) return SIM_RC_FAIL; sim_analyze_program (sd, prog_bfd); + + /* Configure/verify the target byte order and other runtime + configuration options */ + sim_config (sd, PREFERED_TARGET_BYTE_ORDER(prog_bfd)); + + /* (re) Write the monitor trap address handlers into the monitor + (eeprom) address space. This can only be done once the target + endianness has been determined. */ + { + unsigned loop; + /* Entry into the IDT monitor is via fixed address vectors, and + not using machine instructions. To avoid clashing with use of + the MIPS TRAP system, we place our own (simulator specific) + "undefined" instructions into the relevant vector slots. */ + for (loop = 0; (loop < monitor_size); loop += 4) { + uword64 vaddr = (monitor_base + loop); + uword64 paddr; + int cca; + if (AddressTranslation(vaddr, isDATA, isSTORE, &paddr, &cca, isTARGET, isRAW)) + StoreMemory(cca, AccessLength_WORD, + (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT)), + 0, paddr, vaddr, isRAW); + } + /* The PMON monitor uses the same address space, but rather than + branching into it the address of a routine is loaded. We can + cheat for the moment, and direct the PMON routine to IDT style + instructions within the monitor space. This relies on the IDT + monitor not using the locations from 0xBFC00500 onwards as its + entry points.*/ + for (loop = 0; (loop < 24); loop++) + { + uword64 vaddr = (monitor_base + 0x500 + (loop * 4)); + uword64 paddr; + int cca; + unsigned int value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */ + switch (loop) + { + case 0: /* read */ + value = 7; + break; + + case 1: /* write */ + value = 8; + break; + + case 2: /* open */ + value = 6; + break; + + case 3: /* close */ + value = 10; + break; + + case 5: /* printf */ + value = ((0x500 - 16) / 8); /* not an IDT reason code */ + break; + + case 8: /* cliexit */ + value = 17; + break; + + case 11: /* flush_cache */ + value = 28; + break; + } + /* FIXME - should monitor_base be SIM_ADDR?? */ + value = ((unsigned int)monitor_base + (value * 8)); + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) + StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW); + else + sim_error("Failed to write to monitor space 0x%s",pr_addr(vaddr)); + + /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */ + vaddr -= 0x300; + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) + StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW); + else + sim_error("Failed to write to monitor space 0x%s",pr_addr(vaddr)); + } + } + return SIM_RC_OK; } @@ -1509,11 +1388,18 @@ sim_create_inferior (sd, argv,env) char **argv; char **env; { + #ifdef DEBUG printf("DBG: sim_create_inferior entered: start_address = 0x%s\n", pr_addr(PC)); #endif /* DEBUG */ + ColdReset(); + /* If we were providing a more complete I/O, co-processor or memory + simulation, we should perform any "device" initialisation at this + point. This can include pre-loading memory areas with particular + patterns (e.g. simulating ROM monitors). */ + #if 1 PC = (uword64) STATE_START_ADDR(sd); #else @@ -1559,27 +1445,6 @@ sim_kill (sd) return; } -ut_reg -sim_get_quit_code () -{ - /* The standard MIPS PCS (Procedure Calling Standard) uses V0(r2) as - the function return value. However, it may be more correct for - this to return the argument to the exit() function (if - called). */ - return(V0); -} - -void -sim_set_callbacks (sd,p) - SIM_DESC sd; - host_callback *p; -{ - /* NOTE - sd may be NULL! */ - STATE_CALLBACK (&simulator) = p; - callback = p; - return; -} - typedef enum {e_terminate,e_help,e_setmemsize,e_reset} e_cmds; static struct t_sim_command { @@ -1625,7 +1490,7 @@ sim_do_command (sd,cmd) case e_setmemsize: /* memory size argument */ { unsigned int newsize = (unsigned int)getnum(cmd); - sim_size(sd, newsize); + sim_size(newsize); } break; @@ -1670,22 +1535,23 @@ void sim_set_profile_size (n) int n; { + SIM_DESC sd = &simulator; #if defined(PROFILE) if (state & simPROFILE) { int bsize; /* Since we KNOW that the memory banks are a power-of-2 in size: */ profile_nsamples = power2(n); - profile_minpc = membank_base; - profile_maxpc = (membank_base + membank_size); + profile_minpc = STATE_MEM_BASE (sd); + profile_maxpc = (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)); /* Just in-case we are sampling every address: NOTE: The shift right of 2 is because we only have word-aligned PC addresses. */ - if (profile_nsamples > (membank_size >> 2)) - profile_nsamples = (membank_size >> 2); + if (profile_nsamples > (STATE_MEM_SIZE (sd) >> 2)) + profile_nsamples = (STATE_MEM_SIZE (sd) >> 2); /* Since we are dealing with power-of-2 values: */ - profile_shift = (((membank_size >> 2) / profile_nsamples) - 1); + profile_shift = (((STATE_MEM_SIZE (sd) >> 2) / profile_nsamples) - 1); bsize = (profile_nsamples * sizeof(unsigned short)); if (profile_hist == NULL) @@ -1703,29 +1569,29 @@ sim_set_profile_size (n) } void -sim_size(sd, newsize) - SIM_DESC sd; +sim_size(newsize) int newsize; { + SIM_DESC sd = &simulator; char *new; /* Used by "run", and internally, to set the simulated memory size */ if (newsize == 0) { - callback->printf_filtered(callback,"Zero not valid: Memory size still 0x%08X bytes\n",membank_size); + callback->printf_filtered(callback,"Zero not valid: Memory size still 0x%08X bytes\n",STATE_MEM_SIZE (sd)); return; } newsize = power2(newsize); - if (membank == NULL) - new = (char *)calloc(64,(membank_size / 64)); + if (STATE_MEMORY (sd) == NULL) + new = (char *)calloc(64,(STATE_MEM_SIZE (sd) / 64)); else - new = (char *)realloc(membank,newsize); + new = (char *)realloc(STATE_MEMORY (sd),newsize); if (new == NULL) { - if (membank == NULL) - sim_error("Not enough VM for simulation memory of 0x%08X bytes",membank_size); + if (STATE_MEMORY (sd) == NULL) + sim_error("Not enough VM for simulation memory of 0x%08X bytes",STATE_MEM_SIZE (sd)); else - sim_warning("Failed to resize memory (still 0x%08X bytes)",membank_size); + sim_warning("Failed to resize memory (still 0x%08X bytes)",STATE_MEM_SIZE (sd)); } else { - membank_size = (unsigned)newsize; - membank = new; + STATE_MEM_SIZE (sd) = (unsigned)newsize; + STATE_MEMORY (sd) = new; #if defined(PROFILE) /* Ensure that we sample across the new memory range */ sim_set_profile_size(profile_nsamples); @@ -1849,10 +1715,6 @@ sim_monitor(reason) case 17: /* void _exit() */ sim_warning("sim_monitor(17): _exit(int reason) to be coded"); -#if 0 - state |= (simSTOP | simEXIT); /* stop executing code */ - rcexit = (unsigned int)(A0 & 0xFFFFFFFF)); -#endif sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, sim_exited, (unsigned int)(A0 & 0xFFFFFFFF)); break; @@ -1877,7 +1739,7 @@ sim_monitor(reason) /* Memory size */ if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isREAL)) { - value = (uword64)membank_size; + value = (uword64)STATE_MEM_SIZE (sd); StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW); /* We re-do the address translations, in-case the block overlaps a memory boundary: */ @@ -1922,7 +1784,6 @@ sim_monitor(reason) char tmp[40]; enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST; int width = 0, trunc = 0, haddot = 0, longlong = 0; - int base = 10; s++; for (; *s; s++) { if (strchr ("dobxXulscefg%", *s)) @@ -2381,6 +2242,7 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) int host; int raw; { + SIM_DESC sd = &simulator; int res = -1; /* TRUE : Assume good return */ #ifdef DEBUG @@ -2394,7 +2256,7 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) vAddr &= 0xFFFFFFFF; /* Treat the kernel memory spaces identically for the moment: */ - if ((membank_base == K1BASE) && (vAddr >= K0BASE) && (vAddr < (K0BASE + K0SIZE))) + if ((STATE_MEM_BASE (sd) == K1BASE) && (vAddr >= K0BASE) && (vAddr < (K0BASE + K0SIZE))) vAddr += (K1BASE - K0BASE); /* Also assume that the K1BASE memory wraps. This is required to @@ -2403,7 +2265,7 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) around the fact that the monitor memory is currently held in the K1BASE space. */ if (((vAddr < monitor_base) || (vAddr >= (monitor_base + monitor_size))) && (vAddr >= K1BASE && vAddr < (K1BASE + K1SIZE))) - vAddr = (K1BASE | (vAddr & (membank_size - 1))); + vAddr = (K1BASE | (vAddr & (STATE_MEM_SIZE (sd) - 1))); *pAddr = vAddr; /* default for isTARGET */ *CCA = Uncached; /* not used for isHOST */ @@ -2411,9 +2273,9 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) /* NOTE: This is a duplicate of the code that appears in the LoadMemory and StoreMemory functions. They should be merged into a single function (that can be in-lined if required). */ - if ((vAddr >= membank_base) && (vAddr < (membank_base + membank_size))) { + if ((vAddr >= STATE_MEM_BASE (sd)) && (vAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) { if (host) - *pAddr = (int)&membank[((unsigned int)(vAddr - membank_base) & (membank_size - 1))]; + *pAddr = (int)&STATE_MEMORY (sd)[((unsigned int)(vAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1))]; } else if ((vAddr >= monitor_base) && (vAddr < (monitor_base + monitor_size))) { if (host) *pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))]; @@ -2443,7 +2305,8 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) which an implementation specific action is taken. The action taken may increase performance, but must not change the meaning of the program, or alter architecturally-visible state. */ -static void + +static void UNUSED Prefetch(CCA,pAddr,vAddr,DATA,hint) int CCA; uword64 pAddr; @@ -2485,11 +2348,12 @@ LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) int IorD; int raw; { - uword64 value; - uword64 value1; + SIM_DESC sd = &simulator; + uword64 value = 0; + uword64 value1 = 0; #ifdef DEBUG - if (membank == NULL) + if (STATE_MEMORY (sd) == NULL) callback->printf_filtered(callback,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(raw ? "isRAW" : "isREAL")); #endif /* DEBUG */ @@ -2517,7 +2381,7 @@ LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0))) SignalException(InstructionFetch); else { - unsigned int index; + unsigned int index = 0; unsigned char *mem = NULL; #if defined(TRACE) @@ -2528,9 +2392,9 @@ LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) /* NOTE: Quicker methods of decoding the address space can be used when a real memory map is being simulated (i.e. using hi-order address bits to select device). */ - if ((pAddr >= membank_base) && (pAddr < (membank_base + membank_size))) { - index = ((unsigned int)(pAddr - membank_base) & (membank_size - 1)); - mem = membank; + if ((pAddr >= STATE_MEM_BASE (sd)) && (pAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) { + index = ((unsigned int)(pAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1)); + mem = STATE_MEMORY (sd); } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) { index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1)); mem = monitor; @@ -2543,8 +2407,6 @@ LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) accesses. However, without that information we must perform slow transfer, and hope that the compiler optimisation will merge successive loads. */ - value = 0; /* no data loaded yet */ - value1 = 0; /* In reality we should always be loading a doubleword value (or word value in 32bit memory worlds). The external code then @@ -2658,7 +2520,8 @@ if (memval1p) *memval1p = value1; } -/* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */ +/* Description from page A-23 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ /* Store a value to memory. The specified data is stored into the physical location pAddr using the memory hierarchy (data caches and main memory) as specified by the Cache Coherence Algorithm @@ -2680,6 +2543,7 @@ StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) uword64 vAddr; int raw; { + SIM_DESC sd = &simulator; #ifdef DEBUG callback->printf_filtered(callback,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s,%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr),(raw ? "isRAW" : "isREAL")); #endif /* DEBUG */ @@ -2703,12 +2567,12 @@ StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) routine. However, this would slow the simulator down with run-time conditionals. */ { - unsigned int index; + unsigned int index = 0; unsigned char *mem = NULL; - if ((pAddr >= membank_base) && (pAddr < (membank_base + membank_size))) { - index = ((unsigned int)(pAddr - membank_base) & (membank_size - 1)); - mem = membank; + if ((pAddr >= STATE_MEM_BASE (sd)) && (pAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) { + index = ((unsigned int)(pAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1)); + mem = STATE_MEMORY (sd); } else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) { index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1)); mem = monitor; @@ -2856,9 +2720,7 @@ SyncOperation(stype) /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ /* Signal an exception condition. This will result in an exception that aborts the instruction. The instruction operation pseudocode - will never see a return from this function call. - - The above code was bogus. */ + will never see a return from this function call. */ static void SignalException (int exception,...) @@ -2898,9 +2760,6 @@ SignalException (int exception,...) instruction was used to enter the vector (which is the case with the current IDT monitor). */ sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA); -#if 0 - break; /* out of the switch statement */ -#endif } /* Look for the mips16 entry and exit instructions, and simulate a handler for them. */ @@ -2909,9 +2768,6 @@ SignalException (int exception,...) && (instruction & 0x0c0) != 0x0c0) { mips16_entry (instruction); sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA); -#if 0 - break; -#endif } /* else fall through to normal exception processing */ sim_warning("ReservedInstruction 0x%08X at IPC = 0x%s",instruction,pr_addr(IPC)); } @@ -2940,11 +2796,6 @@ SignalException (int exception,...) if ((instruction & 0x03FFFFC0) == 0x03ff0000) { sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, sim_exited, (unsigned int)(A0 & 0xFFFFFFFF)); -#if 0 - rcexit = (unsigned int)(A0 & 0xFFFFFFFF); - state &= ~simEXCEPTION; - state |= simEXIT; -#endif } } @@ -2959,9 +2810,44 @@ SignalException (int exception,...) /* The following is so that the simulator will continue from the exception address on breakpoint operations. */ PC = EPC; - sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, - sim_stopped, SIGILL); - break; + switch ((CAUSE >> 2) & 0x1F) + { + case Interrupt: + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIGINT); + + case TLBModification: + case TLBLoad: + case TLBStore: + case AddressLoad: + case AddressStore: + case InstructionFetch: + case DataReference: + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIGBUS); + + case ReservedInstruction: + case CoProcessorUnusable: + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIGILL); + + case IntegerOverflow: + case FPE: + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIGFPE); + + case Trap: + case Watch: + case SystemCall: + case BreakPoint: + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIGTRAP); + + default : /* Unknown internal exception */ + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIGQUIT); + + } case SimulatorFault: { @@ -2969,16 +2855,10 @@ SignalException (int exception,...) char *msg; va_start(ap,exception); msg = va_arg(ap,char *); + va_end(ap); sim_engine_abort (sd, STATE_CPU (sd, 0), NULL_CIA, "FATAL: Simulator error \"%s\"\n",msg); -#if 0 - fprintf(stderr,"FATAL: Simulator error \"%s\"\n",msg); -#endif - va_end(ap); } -#if 0 - exit(1); -#endif } return; @@ -3004,7 +2884,7 @@ UndefinedResult() } #endif /* WARN_RESULT */ -static void +static void UNUSED CacheOp(op,pAddr,vAddr,instruction) int op; uword64 pAddr; @@ -3150,7 +3030,7 @@ ValueFPR(fpr,fmt) int fpr; FP_formats fmt; { - uword64 value; + uword64 value = 0; int err = 0; /* Treat unused register values, as fixed-point 64bit values: */ @@ -3351,6 +3231,9 @@ NaN(op,fmt) case fmt_long: boolean = (op == FPQNaN_LONG); break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3419,6 +3302,9 @@ Less(op1,op2,fmt) case fmt_double: boolean = (*(double *)&op1 < *(double *)&op2); break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3450,6 +3336,9 @@ Equal(op1,op2,fmt) case fmt_double: boolean = (op1 == op2); break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3464,7 +3353,7 @@ AbsoluteValue(op,fmt) uword64 op; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); @@ -3484,6 +3373,9 @@ AbsoluteValue(op,fmt) double tmp = (fabs(*(double *)&op)); result = *(uword64 *)&tmp; } + default: + fprintf (stderr, "Bad switch\n"); + abort (); } return(result); @@ -3494,7 +3386,7 @@ Negate(op,fmt) uword64 op; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); @@ -3515,6 +3407,9 @@ Negate(op,fmt) result = *(uword64 *)&tmp; } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } return(result); @@ -3526,7 +3421,7 @@ Add(op1,op2,fmt) uword64 op2; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); @@ -3551,6 +3446,9 @@ Add(op1,op2,fmt) result = *(uword64 *)&tmp; } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3566,7 +3464,7 @@ Sub(op1,op2,fmt) uword64 op2; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); @@ -3591,6 +3489,9 @@ Sub(op1,op2,fmt) result = *(uword64 *)&tmp; } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3606,7 +3507,7 @@ Multiply(op1,op2,fmt) uword64 op2; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); @@ -3631,6 +3532,9 @@ Multiply(op1,op2,fmt) result = *(uword64 *)&tmp; } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3646,7 +3550,7 @@ Divide(op1,op2,fmt) uword64 op2; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); @@ -3671,6 +3575,9 @@ Divide(op1,op2,fmt) result = *(uword64 *)&tmp; } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3680,12 +3587,12 @@ Divide(op1,op2,fmt) return(result); } -static uword64 +static uword64 UNUSED Recip(op,fmt) uword64 op; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); @@ -3709,6 +3616,9 @@ Recip(op,fmt) result = *(uword64 *)&tmp; } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3723,7 +3633,7 @@ SquareRoot(op,fmt) uword64 op; FP_formats fmt; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); @@ -3757,6 +3667,9 @@ SquareRoot(op,fmt) #endif } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -3773,7 +3686,7 @@ Convert(rm,op,from,to) FP_formats from; FP_formats to; { - uword64 result; + uword64 result = 0; #ifdef DEBUG printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC)); @@ -3800,6 +3713,9 @@ Convert(rm,op,from,to) case fmt_long: tmp = (float)((word64)op); break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #if 0 @@ -3868,6 +3784,10 @@ Convert(rm,op,from,to) case fmt_long: tmp = (double)((word64)op); break; + + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #if 0 @@ -3913,7 +3833,7 @@ Convert(rm,op,from,to) SignalException(FPE); } else { if (to == fmt_word) { - int tmp; + int tmp = 0; switch (from) { case fmt_single: { @@ -3927,10 +3847,13 @@ Convert(rm,op,from,to) printf("DBG: from double %.30f (0x%s) to word: 0x%08X\n",*((double *)&op),pr_addr(op),tmp); #endif /* DEBUG */ break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } result = (uword64)tmp; } else { /* fmt_long */ - word64 tmp; + word64 tmp = 0; switch (from) { case fmt_single: { @@ -3941,11 +3864,17 @@ Convert(rm,op,from,to) case fmt_double: tmp = (word64)*((double *)&op); break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } result = (uword64)tmp; } } break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); } #ifdef DEBUG @@ -4138,7 +4067,9 @@ decode_coproc(instruction) */ if (((code == 0x00) || (code == 0x04)) && ((instruction & 0x7FF) == 0)) { int rt = ((instruction >> 16) & 0x1F); +#if 0 int rd = ((instruction >> 11) & 0x1F); +#endif if (code == 0x00) { /* MF : move from */ #if 0 /* message should be controlled by configuration option */ callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd); @@ -4179,10 +4110,12 @@ sim_engine_run (sd, next_cpu_nr, siggnal) int next_cpu_nr; /* ignore */ int siggnal; /* ignore */ { +#if !defined(FASTSIM) unsigned int pipeline_count = 1; +#endif #ifdef DEBUG - if (membank == NULL) { + if (STATE_MEMORY (sd) == NULL) { printf("DBG: simulate() entered with no memory\n"); exit(1); } @@ -4315,7 +4248,9 @@ sim_engine_run (sd, next_cpu_nr, siggnal) treated as using a single cycle. NOTE: A standard system is not provided by the default simulator because different MIPS architectures have different cycle counts for the same - instructions. */ + instructions. + + [NOTE: pipeline_count has been replaced the event queue] */ #if defined(HASFPU) /* Set previous flag, depending on current: */ @@ -4441,14 +4376,18 @@ sim_engine_run (sd, next_cpu_nr, siggnal) } #if !defined(FASTSIM) - pipeline_ticks += pipeline_count; -#endif /* FASTSIM */ - + if (sim_events_tickn (sd, pipeline_count)) + { + /* cpu->cia = cia; */ + sim_events_process (sd); + } +#else if (sim_events_tick (sd)) { /* cpu->cia = cia; */ sim_events_process (sd); } +#endif /* FASTSIM */ } } @@ -4480,11 +4419,11 @@ pr_addr(addr) switch (sizeof(addr)) { case 8: - sprintf(paddr_str,"%08x%08x", + sprintf(paddr_str,"%08lx%08lx", (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); break; case 4: - sprintf(paddr_str,"%08x",(unsigned long)addr); + sprintf(paddr_str,"%08lx",(unsigned long)addr); break; case 2: sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff)); @@ -4500,7 +4439,7 @@ pr_uword64(addr) uword64 addr; { char *paddr_str=get_cell(); - sprintf(paddr_str,"%08x%08x", + sprintf(paddr_str,"%08lx%08lx", (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); return paddr_str; } diff --git a/sim/tic80/ChangeLog b/sim/tic80/ChangeLog index 28e6de572f5..b6fdd6f91fe 100644 --- a/sim/tic80/ChangeLog +++ b/sim/tic80/ChangeLog @@ -1,5 +1,7 @@ Tue May 20 09:33:31 1997 Andrew Cagney + * sim-calls.c (sim_load): Set STATE_LOADED_P. + * sim-main.h: Include . * sim-calls.c (sim_set_callback): Delete. diff --git a/sim/tic80/sim-calls.c b/sim/tic80/sim-calls.c index d7b0af609d1..ffa610e2396 100644 --- a/sim/tic80/sim-calls.c +++ b/sim/tic80/sim-calls.c @@ -50,7 +50,9 @@ struct sim_state simulation = { 0 }; SIM_DESC -sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *callback, char **argv) +sim_open (SIM_OPEN_KIND kind, + host_callback *callback, + char **argv) { SIM_DESC sd = &simulation; STATE_OPEN_KIND (sd) = kind; -- 2.30.2