/* The common simulator framework for GDB, the GNU Debugger.
- Copyright 2002 Free Software Foundation, Inc.
+ Copyright 2002-2022 Free Software Foundation, Inc.
Contributed by Andrew Cagney and Red Hat.
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 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _SIM_EVENTS_C_
#define _SIM_EVENTS_C_
-#include "sim-main.h"
-#include "sim-assert.h"
+/* This must come before any other includes. */
+#include "defs.h"
-#ifdef HAVE_STRING_H
+#include <signal.h> /* For SIGPROCMASK et al. */
+#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include "libiberty.h"
-#include <signal.h> /* For SIGPROCMASK et al. */
+#include "sim-main.h"
+#include "sim-assert.h"
+#include "sim-cpu.h"
typedef enum {
watch_invalid,
watch_sim_le_2,
watch_sim_le_4,
watch_sim_le_8,
-
+
+ /* pc */
+ watch_pc,
+
/* wallclock */
watch_clock,
void *data;
sim_event_handler *handler;
/* timer event */
- signed64 time_of_event;
+ int64_t time_of_event;
/* watch wallclock event */
unsigned wallclock;
/* watch core address */
int is_within; /* 0/1 */
unsigned ub;
unsigned lb;
- unsigned64 ub64;
- unsigned64 lb64;
+ uint64_t ub64;
+ uint64_t lb64;
/* trace info (if any) */
char *trace;
/* list */
/* The event queue maintains a single absolute time using two
variables.
-
+
TIME_OF_EVENT: this holds the time at which the next event is ment
to occur. If no next event it will hold the time of the last
event.
#define _ETRACE sd, NULL
-#undef ETRACE_P
-#define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace)
-
#undef ETRACE
#define ETRACE(ARGS) \
do \
{ \
- if (ETRACE_P) \
+ if (STRACE_EVENTS_P (sd)) \
{ \
if (STRACE_DEBUG_P (sd)) \
- { \
- const char *file; \
- SIM_FILTER_PATH (file, __FILE__); \
- trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
- } \
+ trace_printf (sd, NULL, "%s:%d: ", lbasename (__FILE__), __LINE__); \
trace_printf ARGS; \
} \
} \
/*-LOCK-*/
sigset_t old_mask;
sigset_t new_mask;
- sigfillset(&new_mask);
+ sigfillset (&new_mask);
sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
#endif
new = ZALLOC (sim_event);
INLINE_SIM_EVENTS\
-(signed64)
+(int64_t)
sim_events_time (SIM_DESC sd)
{
sim_events *events = STATE_EVENTS (sd);
/* Returns the time that remains before the event is raised. */
INLINE_SIM_EVENTS\
-(signed64)
+(int64_t)
sim_events_remain_time (SIM_DESC sd, sim_event *event)
{
if (event == 0)
return 0;
-
+
return (event->time_of_event - sim_events_time (sd));
}
update_time_from_event (SIM_DESC sd)
{
sim_events *events = STATE_EVENTS (sd);
- signed64 current_time = sim_events_time (sd);
+ int64_t current_time = sim_events_time (sd);
if (events->queue != NULL)
{
events->time_of_event = events->queue->time_of_event;
events->time_of_event = current_time - 1;
events->time_from_event = -1;
}
- if (ETRACE_P)
+ if (STRACE_EVENTS_P (sd))
{
sim_event *event;
int i;
event = event->next, i++)
{
ETRACE ((_ETRACE,
- "event time-from-event - time %ld, delta %ld - event %d, tag 0x%lx, time %ld, handler 0x%lx, data 0x%lx%s%s\n",
- (long)current_time,
- (long)events->time_from_event,
+ "event time-from-event - "
+ "time %" PRIi64 ", delta %" PRIi64 " - "
+ "event %i, tag %p, time %" PRIi64 ", handler %p, data "
+ "%p%s%s\n",
+ current_time,
+ events->time_from_event,
i,
- (long)event,
- (long)event->time_of_event,
- (long)event->handler,
- (long)event->data,
+ event,
+ event->time_of_event,
+ event->handler,
+ event->data,
(event->trace != NULL) ? ", " : "",
(event->trace != NULL) ? event->trace : ""));
}
static void
insert_sim_event (SIM_DESC sd,
sim_event *new_event,
- signed64 delta)
+ int64_t delta)
{
sim_events *events = STATE_EVENTS (sd);
sim_event *curr;
sim_event **prev;
- signed64 time_of_event;
+ int64_t time_of_event;
if (delta < 0)
sim_io_error (sd, "what is past is past!\n");
-
+
/* compute when the event should occur */
time_of_event = sim_events_time (sd) + delta;
-
+
/* find the queue insertion point - things are time ordered */
prev = &events->queue;
curr = events->queue;
curr = curr->next;
}
SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
-
+
/* insert it */
new_event->next = curr;
*prev = new_event;
new_event->time_of_event = time_of_event;
-
+
/* adjust the time until the first event */
update_time_from_event (sd);
}
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_events_schedule (SIM_DESC sd,
- signed64 delta_time,
+ int64_t delta_time,
sim_event_handler *handler,
void *data)
{
- va_list dummy;
- memset (&dummy, 0, sizeof dummy);
- return sim_events_schedule_vtracef (sd, delta_time, handler, data,
- NULL, dummy);
+ return sim_events_schedule_tracef (sd, delta_time, handler, data, NULL);
}
#endif
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_events_schedule_tracef (SIM_DESC sd,
- signed64 delta_time,
+ int64_t delta_time,
sim_event_handler *handler,
void *data,
const char *fmt,
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_events_schedule_vtracef (SIM_DESC sd,
- signed64 delta_time,
+ int64_t delta_time,
sim_event_handler *handler,
void *data,
const char *fmt,
new_event->data = data;
new_event->handler = handler;
new_event->watching = watch_timer;
- if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0)
+ if (fmt == NULL || !STRACE_EVENTS_P (sd) || vasprintf (&new_event->trace, fmt, ap) < 0)
new_event->trace = NULL;
- insert_sim_event(sd, new_event, delta_time);
- ETRACE((_ETRACE,
- "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
- (long)sim_events_time(sd),
- (long)new_event,
- (long)new_event->time_of_event,
- (long)new_event->handler,
- (long)new_event->data,
- (new_event->trace != NULL) ? ", " : "",
- (new_event->trace != NULL) ? new_event->trace : ""));
+ insert_sim_event (sd, new_event, delta_time);
+ ETRACE ((_ETRACE,
+ "event scheduled at %" PRIi64 " - "
+ "tag %p - time %" PRIi64 ", handler %p, data %p%s%s\n",
+ sim_events_time (sd),
+ new_event,
+ new_event->time_of_event,
+ new_event->handler,
+ new_event->data,
+ (new_event->trace != NULL) ? ", " : "",
+ (new_event->trace != NULL) ? new_event->trace : ""));
return new_event;
}
#endif
#if EXTERN_SIM_EVENTS_P
void
sim_events_schedule_after_signal (SIM_DESC sd,
- signed64 delta_time,
+ int64_t delta_time,
sim_event_handler *handler,
void *data)
{
/*-LOCK-*/
sigset_t old_mask;
sigset_t new_mask;
- sigfillset(&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");
+ "sim_events_schedule_after_signal - buffer overflow");
}
-
+
new_event->data = data;
new_event->handler = handler;
new_event->time_of_event = delta_time; /* work it out later */
/*-UNLOCK-*/
sigprocmask (SIG_SETMASK, &old_mask, NULL);
#endif
-
+
ETRACE ((_ETRACE,
- "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));
+ "signal scheduled at %" PRIi64 " - "
+ "tag %p - time %" PRIi64 ", handler %p, data %p\n",
+ sim_events_time (sd),
+ new_event,
+ new_event->time_of_event,
+ new_event->handler,
+ new_event->data));
}
#endif
events->watchpoints = new_event;
events->work_pending = 1;
ETRACE ((_ETRACE,
- "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
- (long)sim_events_time (sd),
- (long)new_event,
- (long)new_event->wallclock,
- (long)new_event->handler,
- (long)new_event->data));
+ "event watching clock at %" PRIi64 " - "
+ "tag %p - wallclock %u, handler %p, data %p\n",
+ sim_events_time (sd),
+ new_event,
+ new_event->wallclock,
+ new_event->handler,
+ new_event->data));
+ return new_event;
+}
+#endif
+
+
+#if EXTERN_SIM_EVENTS_P
+sim_event *
+sim_events_watch_pc (SIM_DESC sd,
+ int is_within,
+ uint64_t lb,
+ uint64_t ub,
+ sim_event_handler *handler,
+ void *data)
+{
+ sim_events *events = STATE_EVENTS (sd);
+ sim_event *new_event = sim_events_zalloc (sd);
+ /* type */
+ new_event->watching = watch_pc;
+ /* handler */
+ new_event->data = data;
+ new_event->handler = handler;
+ /* data */
+ new_event->lb = lb;
+ new_event->lb64 = lb;
+ new_event->ub = ub;
+ new_event->ub64 = ub;
+ new_event->is_within = (is_within != 0);
+ /* insert */
+ new_event->next = events->watchpoints;
+ events->watchpoints = new_event;
+ events->work_pending = 1;
+ ETRACE ((_ETRACE,
+ "event watching pc at %" PRIi64 " - "
+ "tag %p - pc 0x%x..0x%x, handler %p, data %p\n",
+ sim_events_time (sd),
+ new_event,
+ new_event->lb,
+ new_event->ub,
+ new_event->handler,
+ new_event->data));
return new_event;
}
#endif
sim_events_watch_sim (SIM_DESC sd,
void *host_addr,
int nr_bytes,
- int byte_order,
+ enum bfd_endian byte_order,
int is_within,
- unsigned64 lb,
- unsigned64 ub,
+ uint64_t lb,
+ uint64_t ub,
sim_event_handler *handler,
void *data)
{
/* type */
switch (byte_order)
{
- case 0:
+ case BFD_ENDIAN_UNKNOWN:
switch (nr_bytes)
{
case 1: new_event->watching = watch_sim_host_1; break;
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
}
break;
- case BIG_ENDIAN:
+ case BFD_ENDIAN_BIG:
switch (nr_bytes)
{
case 1: new_event->watching = watch_sim_be_1; break;
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
}
break;
- case LITTLE_ENDIAN:
+ case BFD_ENDIAN_LITTLE:
switch (nr_bytes)
{
case 1: new_event->watching = watch_sim_le_1; break;
events->watchpoints = new_event;
events->work_pending = 1;
ETRACE ((_ETRACE,
- "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
- (long)sim_events_time (sd),
- (long)new_event,
- (long)new_event->host_addr,
- (long)new_event->lb,
- (long)new_event->ub,
- (long)new_event->handler,
- (long)new_event->data));
+ "event watching host at %" PRIi64 " - "
+ "tag %p - host-addr %p, 0x%x..0x%x, handler %p, data %p\n",
+ sim_events_time (sd),
+ new_event,
+ new_event->host_addr,
+ new_event->lb,
+ new_event->ub,
+ new_event->handler,
+ new_event->data));
return new_event;
}
#endif
address_word core_addr,
unsigned core_map,
int nr_bytes,
- int byte_order,
+ enum bfd_endian byte_order,
int is_within,
- unsigned64 lb,
- unsigned64 ub,
+ uint64_t lb,
+ uint64_t ub,
sim_event_handler *handler,
void *data)
{
/* type */
switch (byte_order)
{
- case 0:
+ case BFD_ENDIAN_UNKNOWN:
switch (nr_bytes)
{
case 1: new_event->watching = watch_core_targ_1; break;
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
}
break;
- case BIG_ENDIAN:
+ case BFD_ENDIAN_BIG:
switch (nr_bytes)
{
case 1: new_event->watching = watch_core_be_1; break;
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
}
break;
- case LITTLE_ENDIAN:
+ case BFD_ENDIAN_LITTLE:
switch (nr_bytes)
{
case 1: new_event->watching = watch_core_le_1; break;
events->watchpoints = new_event;
events->work_pending = 1;
ETRACE ((_ETRACE,
- "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
- (long)sim_events_time (sd),
- (long)new_event,
- (long)new_event->host_addr,
- (long)new_event->lb,
- (long)new_event->ub,
- (long)new_event->handler,
- (long)new_event->data));
+ "event watching host at %" PRIi64 " - "
+ "tag %p - host-addr %p, 0x%x..0x%x, handler %p, data %p\n",
+ sim_events_time (sd),
+ new_event,
+ new_event->host_addr,
+ new_event->lb,
+ new_event->ub,
+ new_event->handler,
+ new_event->data));
return new_event;
}
#endif
sim_event *dead = *ptr_to_current;
*ptr_to_current = dead->next;
ETRACE ((_ETRACE,
- "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
- (long) sim_events_time (sd),
- (long) event_to_remove,
- (long) dead->time_of_event,
- (long) dead->handler,
- (long) dead->data,
+ "event/watch descheduled at %" PRIi64 " - "
+ "tag %p - time %" PRIi64 ", handler %p, data %p%s%s\n",
+ sim_events_time (sd),
+ event_to_remove,
+ dead->time_of_event,
+ dead->handler,
+ dead->data,
(dead->trace != NULL) ? ", " : "",
(dead->trace != NULL) ? dead->trace : ""));
sim_events_free (sd, dead);
}
}
ETRACE ((_ETRACE,
- "event/watch descheduled at %ld - tag 0x%lx - not found\n",
- (long) sim_events_time (sd),
- (long) event_to_remove));
+ "event/watch descheduled at %" PRIi64 " - tag %p - not found\n",
+ sim_events_time (sd),
+ event_to_remove));
}
#endif
}
#undef WATCH_SIM
+ case watch_pc:
+ {
+ int c;
+
+ for (c = 0; c < MAX_NR_PROCESSORS; ++c)
+ {
+ sim_cpu *cpu = STATE_CPU (sd, c);
+ sim_cia cia = sim_pc_get (cpu);
+
+ if (to_do->is_within == (cia >= to_do->lb64 && cia <= to_do->ub64))
+ return 1;
+ }
+ return 0;
+ }
+
case watch_clock: /* wallclock */
{
unsigned long elapsed_time = sim_events_elapsed_time (sd);
int events_were_last,
int events_were_next)
{
- sim_events *events = STATE_EVENTS(sd);
+ sim_events *events = STATE_EVENTS (sd);
if (events_were_last)
{
/* Halted part way through event processing */
(void)
sim_events_process (SIM_DESC sd)
{
- sim_events *events = STATE_EVENTS(sd);
- signed64 event_time = sim_events_time(sd);
+ sim_events *events = STATE_EVENTS (sd);
+ int64_t event_time = sim_events_time (sd);
/* Clear work_pending before checking nr_held. Clearing
work_pending after nr_held (with out a lock could loose an
if (events->nr_held > 0)
{
int i;
-
+
#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);
+ sigfillset (&new_mask);
+ sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
#endif
for (i = 0; i < events->nr_held; i++)
entry->data);
}
events->nr_held = 0;
-
+
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
/*-UNLOCK-*/
- sigprocmask(SIG_SETMASK, &old_mask, NULL);
+ sigprocmask (SIG_SETMASK, &old_mask, NULL);
#endif
-
+
}
-
+
/* Process any watchpoints. Be careful to allow a watchpoint to
appear/disappear under our feet.
To ensure that watchpoints are processed only once per cycle,
{
sim_event_handler *handler = to_do->handler;
void *data = to_do->data;
- ETRACE((_ETRACE,
- "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
- (long) event_time,
- (long) to_do,
- (long) handler,
- (long) data,
- (to_do->trace != NULL) ? ", " : "",
- (to_do->trace != NULL) ? to_do->trace : ""));
+ ETRACE ((_ETRACE,
+ "event issued at %" PRIi64 " - "
+ "tag %p - handler %p, data %p%s%s\n",
+ event_time,
+ to_do,
+ handler,
+ data,
+ (to_do->trace != NULL) ? ", " : "",
+ (to_do->trace != NULL) ? to_do->trace : ""));
sim_events_free (sd, to_do);
handler (sd, data);
}
events->watchedpoints = to_do;
}
}
-
+
/* 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 <
void *data = to_do->data;
events->queue = to_do->next;
update_time_from_event (sd);
- ETRACE((_ETRACE,
- "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
- (long) event_time,
- (long) to_do,
- (long) handler,
- (long) data,
- (to_do->trace != NULL) ? ", " : "",
- (to_do->trace != NULL) ? to_do->trace : ""));
+ ETRACE ((_ETRACE,
+ "event issued at %" PRIi64 " - tag %p - handler %p, data %p%s%s\n",
+ event_time,
+ to_do,
+ handler,
+ data,
+ (to_do->trace != NULL) ? ", " : "",
+ (to_do->trace != NULL) ? to_do->trace : ""));
sim_events_free (sd, to_do);
handler (sd, data);
}
-
+
/* put things back where they belong ready for the next iteration */
events->watchpoints = events->watchedpoints;
events->watchedpoints = NULL;
if (events->watchpoints != NULL)
events->work_pending = 1;
-
+
/* advance the time */
SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
SIM_ASSERT (events->queue != NULL); /* always poll event */