Home | History | Annotate | Line # | Download | only in common
      1   1.1  christos /* The common simulator framework for GDB, the GNU Debugger.
      2   1.1  christos 
      3  1.11  christos    Copyright 2002-2024 Free Software Foundation, Inc.
      4   1.1  christos 
      5   1.1  christos    Contributed by Andrew Cagney and Red Hat.
      6   1.1  christos 
      7   1.1  christos    This file is part of GDB.
      8   1.1  christos 
      9   1.1  christos    This program is free software; you can redistribute it and/or modify
     10   1.1  christos    it under the terms of the GNU General Public License as published by
     11   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12   1.1  christos    (at your option) any later version.
     13   1.1  christos 
     14   1.1  christos    This program is distributed in the hope that it will be useful,
     15   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17   1.1  christos    GNU General Public License for more details.
     18   1.1  christos 
     19   1.1  christos    You should have received a copy of the GNU General Public License
     20   1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21   1.1  christos 
     22   1.1  christos 
     23   1.1  christos #ifndef _SIM_EVENTS_C_
     24   1.1  christos #define _SIM_EVENTS_C_
     25   1.1  christos 
     26  1.10  christos /* This must come before any other includes.  */
     27  1.10  christos #include "defs.h"
     28   1.1  christos 
     29  1.10  christos #include <signal.h> /* For SIGPROCMASK et al. */
     30  1.10  christos #include <stdarg.h>
     31  1.10  christos #include <stdlib.h>
     32   1.1  christos #include <string.h>
     33   1.1  christos 
     34  1.10  christos #include "libiberty.h"
     35   1.1  christos 
     36  1.10  christos #include "sim-main.h"
     37  1.10  christos #include "sim-assert.h"
     38  1.10  christos #include "sim-cpu.h"
     39   1.1  christos 
     40   1.1  christos typedef enum {
     41   1.1  christos   watch_invalid,
     42   1.1  christos 
     43   1.1  christos   /* core - target byte order */
     44   1.1  christos   watch_core_targ_1,
     45   1.1  christos   watch_core_targ_2,
     46   1.1  christos   watch_core_targ_4,
     47   1.1  christos   watch_core_targ_8,
     48   1.1  christos   /* core - big-endian */
     49   1.1  christos   watch_core_be_1,
     50   1.1  christos   watch_core_be_2,
     51   1.1  christos   watch_core_be_4,
     52   1.1  christos   watch_core_be_8,
     53   1.1  christos   /* core - little-endian */
     54   1.1  christos   watch_core_le_1,
     55   1.1  christos   watch_core_le_2,
     56   1.1  christos   watch_core_le_4,
     57   1.1  christos   watch_core_le_8,
     58   1.1  christos 
     59   1.1  christos   /* sim - host byte order */
     60   1.1  christos   watch_sim_host_1,
     61   1.1  christos   watch_sim_host_2,
     62   1.1  christos   watch_sim_host_4,
     63   1.1  christos   watch_sim_host_8,
     64   1.1  christos   /* sim - big-endian */
     65   1.1  christos   watch_sim_be_1,
     66   1.1  christos   watch_sim_be_2,
     67   1.1  christos   watch_sim_be_4,
     68   1.1  christos   watch_sim_be_8,
     69   1.1  christos   /* sim - little-endian */
     70   1.1  christos   watch_sim_le_1,
     71   1.1  christos   watch_sim_le_2,
     72   1.1  christos   watch_sim_le_4,
     73   1.1  christos   watch_sim_le_8,
     74   1.1  christos 
     75  1.10  christos   /* pc */
     76  1.10  christos   watch_pc,
     77  1.10  christos 
     78   1.1  christos   /* wallclock */
     79   1.1  christos   watch_clock,
     80   1.1  christos 
     81   1.1  christos   /* timer */
     82   1.1  christos   watch_timer,
     83   1.1  christos } sim_event_watchpoints;
     84   1.1  christos 
     85   1.1  christos 
     86   1.1  christos struct _sim_event {
     87   1.1  christos   sim_event_watchpoints watching;
     88   1.1  christos   void *data;
     89   1.1  christos   sim_event_handler *handler;
     90   1.1  christos   /* timer event */
     91  1.10  christos   int64_t time_of_event;
     92   1.1  christos   /* watch wallclock event */
     93   1.1  christos   unsigned wallclock;
     94   1.1  christos   /* watch core address */
     95   1.1  christos   address_word core_addr;
     96   1.1  christos   unsigned core_map;
     97   1.1  christos   /* watch sim addr */
     98   1.1  christos   void *host_addr;
     99   1.1  christos   /* watch core/sim range */
    100   1.1  christos   int is_within; /* 0/1 */
    101   1.1  christos   unsigned ub;
    102   1.1  christos   unsigned lb;
    103  1.10  christos   uint64_t ub64;
    104  1.10  christos   uint64_t lb64;
    105   1.1  christos   /* trace info (if any) */
    106   1.1  christos   char *trace;
    107   1.1  christos   /* list */
    108   1.1  christos   sim_event *next;
    109   1.1  christos };
    110   1.1  christos 
    111   1.1  christos 
    112   1.1  christos /* The event queue maintains a single absolute time using two
    113   1.1  christos    variables.
    114   1.1  christos 
    115   1.1  christos    TIME_OF_EVENT: this holds the time at which the next event is ment
    116   1.1  christos    to occur.  If no next event it will hold the time of the last
    117   1.1  christos    event.
    118   1.1  christos 
    119   1.1  christos    TIME_FROM_EVENT: The current distance from TIME_OF_EVENT.  A value
    120   1.1  christos    <= 0 (except when poll-event is being processed) indicates that
    121   1.1  christos    event processing is due.  This variable is decremented once for
    122   1.1  christos    each iteration of a clock cycle.
    123   1.1  christos 
    124   1.1  christos    Initially, the clock is started at time one (0) with TIME_OF_EVENT
    125   1.1  christos    == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1.
    126   1.1  christos 
    127   1.1  christos    Clearly there is a bug in that this code assumes that the absolute
    128   1.1  christos    time counter will never become greater than 2^62.
    129   1.1  christos 
    130   1.1  christos    To avoid the need to use 64bit arithmetic, the event queue always
    131   1.1  christos    contains at least one event scheduled every 16 000 ticks.  This
    132   1.1  christos    limits the time from event counter to values less than
    133   1.1  christos    16 000. */
    134   1.1  christos 
    135   1.1  christos 
    136   1.1  christos #if !defined (SIM_EVENTS_POLL_RATE)
    137   1.1  christos #define SIM_EVENTS_POLL_RATE 0x1000
    138   1.1  christos #endif
    139   1.1  christos 
    140   1.1  christos 
    141   1.1  christos #define _ETRACE sd, NULL
    142   1.1  christos 
    143   1.1  christos #undef ETRACE
    144   1.1  christos #define ETRACE(ARGS) \
    145   1.1  christos do \
    146   1.1  christos   { \
    147   1.5  christos     if (STRACE_EVENTS_P (sd)) \
    148   1.1  christos       { \
    149   1.1  christos         if (STRACE_DEBUG_P (sd)) \
    150   1.5  christos 	  trace_printf (sd, NULL, "%s:%d: ", lbasename (__FILE__), __LINE__); \
    151   1.1  christos         trace_printf  ARGS; \
    152   1.1  christos       } \
    153   1.1  christos   } \
    154   1.1  christos while (0)
    155   1.1  christos 
    156   1.1  christos 
    157   1.1  christos /* event queue iterator - don't iterate over the held queue. */
    158   1.1  christos 
    159   1.1  christos #if EXTERN_SIM_EVENTS_P
    160   1.1  christos static sim_event **
    161   1.1  christos next_event_queue (SIM_DESC sd,
    162   1.1  christos 		  sim_event **queue)
    163   1.1  christos {
    164   1.1  christos   if (queue == NULL)
    165   1.1  christos     return &STATE_EVENTS (sd)->queue;
    166   1.1  christos   else if (queue == &STATE_EVENTS (sd)->queue)
    167   1.1  christos     return &STATE_EVENTS (sd)->watchpoints;
    168   1.1  christos   else if (queue == &STATE_EVENTS (sd)->watchpoints)
    169   1.1  christos     return &STATE_EVENTS (sd)->watchedpoints;
    170   1.1  christos   else if (queue == &STATE_EVENTS (sd)->watchedpoints)
    171   1.1  christos     return NULL;
    172   1.1  christos   else
    173   1.1  christos     sim_io_error (sd, "next_event_queue - bad queue");
    174   1.1  christos   return NULL;
    175   1.1  christos }
    176   1.1  christos #endif
    177   1.1  christos 
    178   1.1  christos 
    179   1.1  christos STATIC_INLINE_SIM_EVENTS\
    180   1.1  christos (void)
    181   1.1  christos sim_events_poll (SIM_DESC sd,
    182   1.1  christos 		 void *data)
    183   1.1  christos {
    184   1.1  christos   /* just re-schedule in 1000 million ticks time */
    185   1.1  christos   sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
    186   1.1  christos   sim_io_poll_quit (sd);
    187   1.1  christos }
    188   1.1  christos 
    189   1.1  christos 
    190   1.1  christos /* "events" module install handler.
    191   1.1  christos    This is called via sim_module_install to install the "events" subsystem
    192   1.1  christos    into the simulator.  */
    193   1.1  christos 
    194   1.1  christos #if EXTERN_SIM_EVENTS_P
    195   1.1  christos STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
    196   1.1  christos STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
    197   1.1  christos STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
    198   1.1  christos STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
    199   1.1  christos #endif
    200   1.1  christos 
    201   1.1  christos #if EXTERN_SIM_EVENTS_P
    202   1.1  christos SIM_RC
    203   1.1  christos sim_events_install (SIM_DESC sd)
    204   1.1  christos {
    205   1.1  christos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
    206   1.1  christos   sim_module_add_uninstall_fn (sd, sim_events_uninstall);
    207   1.1  christos   sim_module_add_init_fn (sd, sim_events_init);
    208   1.1  christos   sim_module_add_resume_fn (sd, sim_events_resume);
    209   1.1  christos   sim_module_add_suspend_fn (sd, sim_events_suspend);
    210   1.1  christos   return SIM_RC_OK;
    211   1.1  christos }
    212   1.1  christos #endif
    213   1.1  christos 
    214   1.1  christos 
    215   1.1  christos /* Suspend/resume the event queue manager when the simulator is not
    216   1.1  christos    running */
    217   1.1  christos 
    218   1.1  christos #if EXTERN_SIM_EVENTS_P
    219   1.1  christos static SIM_RC
    220   1.1  christos sim_events_resume (SIM_DESC sd)
    221   1.1  christos {
    222   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    223   1.1  christos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
    224   1.1  christos   SIM_ASSERT (events->resume_wallclock == 0);
    225   1.1  christos   events->resume_wallclock = sim_elapsed_time_get ();
    226   1.1  christos   return SIM_RC_OK;
    227   1.1  christos }
    228   1.1  christos #endif
    229   1.1  christos 
    230   1.1  christos #if EXTERN_SIM_EVENTS_P
    231   1.1  christos static SIM_RC
    232   1.1  christos sim_events_suspend (SIM_DESC sd)
    233   1.1  christos {
    234   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    235   1.1  christos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
    236   1.1  christos   SIM_ASSERT (events->resume_wallclock != 0);
    237   1.1  christos   events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock);
    238   1.1  christos   events->resume_wallclock = 0;
    239   1.1  christos   return SIM_RC_OK;
    240   1.1  christos }
    241   1.1  christos #endif
    242   1.1  christos 
    243   1.1  christos 
    244   1.1  christos /* Uninstall the "events" subsystem from the simulator.  */
    245   1.1  christos 
    246   1.1  christos #if EXTERN_SIM_EVENTS_P
    247   1.1  christos static void
    248   1.1  christos sim_events_uninstall (SIM_DESC sd)
    249   1.1  christos {
    250   1.1  christos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
    251   1.1  christos   /* FIXME: free buffers, etc. */
    252   1.1  christos }
    253   1.1  christos #endif
    254   1.1  christos 
    255   1.1  christos 
    256   1.1  christos /* malloc/free */
    257   1.1  christos 
    258   1.1  christos #if EXTERN_SIM_EVENTS_P
    259   1.1  christos static sim_event *
    260   1.1  christos sim_events_zalloc (SIM_DESC sd)
    261   1.1  christos {
    262   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    263   1.1  christos   sim_event *new = events->free_list;
    264   1.1  christos   if (new != NULL)
    265   1.1  christos     {
    266   1.1  christos       events->free_list = new->next;
    267   1.1  christos       memset (new, 0, sizeof (*new));
    268   1.1  christos     }
    269   1.1  christos   else
    270   1.1  christos     {
    271   1.1  christos #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
    272   1.1  christos       /*-LOCK-*/
    273   1.1  christos       sigset_t old_mask;
    274   1.1  christos       sigset_t new_mask;
    275   1.1  christos       sigfillset (&new_mask);
    276   1.1  christos       sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
    277   1.1  christos #endif
    278   1.1  christos       new = ZALLOC (sim_event);
    279   1.1  christos #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
    280   1.1  christos       /*-UNLOCK-*/
    281   1.1  christos       sigprocmask (SIG_SETMASK, &old_mask, NULL);
    282   1.1  christos #endif
    283   1.1  christos     }
    284   1.1  christos   return new;
    285   1.1  christos }
    286   1.1  christos #endif
    287   1.1  christos 
    288   1.1  christos STATIC_INLINE_SIM_EVENTS\
    289   1.1  christos (void)
    290   1.1  christos sim_events_free (SIM_DESC sd,
    291   1.1  christos 		 sim_event *dead)
    292   1.1  christos {
    293   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    294   1.1  christos   dead->next = events->free_list;
    295   1.1  christos   events->free_list = dead;
    296   1.1  christos   if (dead->trace != NULL)
    297   1.1  christos     {
    298   1.1  christos       free (dead->trace); /* NB: asprintf returns a `free' buf */
    299   1.1  christos       dead->trace = NULL;
    300   1.1  christos     }
    301   1.1  christos }
    302   1.1  christos 
    303   1.1  christos 
    304   1.1  christos /* Initialize the simulator event manager */
    305   1.1  christos 
    306   1.1  christos #if EXTERN_SIM_EVENTS_P
    307   1.1  christos SIM_RC
    308   1.1  christos sim_events_init (SIM_DESC sd)
    309   1.1  christos {
    310   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    311   1.1  christos 
    312   1.1  christos   /* drain the interrupt queue */
    313   1.1  christos   events->nr_held = 0;
    314   1.1  christos   if (events->held == NULL)
    315   1.1  christos     events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS);
    316   1.1  christos 
    317   1.1  christos   /* drain the normal queues */
    318   1.1  christos   {
    319   1.1  christos     sim_event **queue = NULL;
    320   1.1  christos     while ((queue = next_event_queue (sd, queue)) != NULL)
    321   1.1  christos       {
    322   1.1  christos 	if (queue == NULL) break;
    323   1.1  christos 	while (*queue != NULL)
    324   1.1  christos 	  {
    325   1.1  christos 	    sim_event *dead = *queue;
    326   1.1  christos 	    *queue = dead->next;
    327   1.1  christos 	    sim_events_free (sd, dead);
    328   1.1  christos 	  }
    329   1.1  christos 	*queue = NULL;
    330   1.1  christos       }
    331   1.1  christos   }
    332   1.1  christos 
    333   1.1  christos   /* wind time back to zero */
    334   1.1  christos   events->nr_ticks_to_process = 1; /* start by doing queue */
    335   1.1  christos   events->time_of_event = 0;
    336   1.1  christos   events->time_from_event = 0;
    337   1.1  christos   events->elapsed_wallclock = 0;
    338   1.1  christos   events->resume_wallclock = 0;
    339   1.1  christos 
    340   1.1  christos   /* schedule our initial counter event */
    341   1.1  christos   sim_events_schedule (sd, 0, sim_events_poll, sd);
    342   1.1  christos 
    343   1.1  christos   /* from now on, except when the large-int event is being processed
    344   1.1  christos      the event queue is non empty */
    345   1.1  christos   SIM_ASSERT (events->queue != NULL);
    346   1.1  christos 
    347   1.1  christos   return SIM_RC_OK;
    348   1.1  christos }
    349   1.1  christos #endif
    350   1.1  christos 
    351   1.1  christos 
    352   1.1  christos INLINE_SIM_EVENTS\
    353  1.10  christos (int64_t)
    354   1.1  christos sim_events_time (SIM_DESC sd)
    355   1.1  christos {
    356   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    357   1.1  christos   return (events->time_of_event - events->time_from_event);
    358   1.1  christos }
    359   1.1  christos 
    360   1.1  christos 
    361   1.1  christos INLINE_SIM_EVENTS\
    362   1.1  christos (unsigned long)
    363   1.1  christos sim_events_elapsed_time (SIM_DESC sd)
    364   1.1  christos {
    365   1.1  christos   unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock;
    366   1.1  christos 
    367   1.1  christos   /* Are we being called inside sim_resume?
    368   1.1  christos      (Is there a simulation in progress?)  */
    369   1.1  christos   if (STATE_EVENTS (sd)->resume_wallclock != 0)
    370   1.1  christos      elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock);
    371   1.1  christos 
    372   1.1  christos   return elapsed;
    373   1.1  christos }
    374   1.1  christos 
    375   1.1  christos 
    376   1.1  christos /* Returns the time that remains before the event is raised. */
    377   1.1  christos INLINE_SIM_EVENTS\
    378  1.10  christos (int64_t)
    379   1.1  christos sim_events_remain_time (SIM_DESC sd, sim_event *event)
    380   1.1  christos {
    381   1.1  christos   if (event == 0)
    382   1.1  christos     return 0;
    383   1.1  christos 
    384   1.1  christos   return (event->time_of_event - sim_events_time (sd));
    385   1.1  christos }
    386   1.1  christos 
    387   1.1  christos 
    388   1.1  christos 
    389   1.1  christos STATIC_INLINE_SIM_EVENTS\
    390   1.1  christos (void)
    391   1.1  christos update_time_from_event (SIM_DESC sd)
    392   1.1  christos {
    393   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    394  1.10  christos   int64_t current_time = sim_events_time (sd);
    395   1.1  christos   if (events->queue != NULL)
    396   1.1  christos     {
    397   1.1  christos       events->time_of_event = events->queue->time_of_event;
    398   1.1  christos       events->time_from_event = (events->queue->time_of_event - current_time);
    399   1.1  christos     }
    400   1.1  christos   else
    401   1.1  christos     {
    402   1.1  christos       events->time_of_event = current_time - 1;
    403   1.1  christos       events->time_from_event = -1;
    404   1.1  christos     }
    405   1.5  christos   if (STRACE_EVENTS_P (sd))
    406   1.1  christos     {
    407   1.1  christos       sim_event *event;
    408   1.1  christos       int i;
    409   1.1  christos       for (event = events->queue, i = 0;
    410   1.1  christos 	   event != NULL;
    411   1.1  christos 	   event = event->next, i++)
    412   1.1  christos 	{
    413   1.1  christos 	  ETRACE ((_ETRACE,
    414  1.10  christos 		   "event time-from-event - "
    415  1.10  christos 		   "time %" PRIi64 ", delta %" PRIi64 " - "
    416  1.10  christos 		   "event %i, tag %p, time %" PRIi64 ", handler %p, data "
    417  1.10  christos 		   "%p%s%s\n",
    418  1.10  christos 		   current_time,
    419  1.10  christos 		   events->time_from_event,
    420   1.1  christos 		   i,
    421  1.10  christos 		   event,
    422  1.10  christos 		   event->time_of_event,
    423  1.10  christos 		   event->handler,
    424  1.10  christos 		   event->data,
    425   1.1  christos 		   (event->trace != NULL) ? ", " : "",
    426   1.1  christos 		   (event->trace != NULL) ? event->trace : ""));
    427   1.1  christos 	}
    428   1.1  christos     }
    429   1.1  christos   SIM_ASSERT (current_time == sim_events_time (sd));
    430   1.1  christos }
    431   1.1  christos 
    432   1.1  christos 
    433   1.1  christos #if EXTERN_SIM_EVENTS_P
    434   1.1  christos static void
    435   1.1  christos insert_sim_event (SIM_DESC sd,
    436   1.1  christos 		  sim_event *new_event,
    437  1.10  christos 		  int64_t delta)
    438   1.1  christos {
    439   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    440   1.1  christos   sim_event *curr;
    441   1.1  christos   sim_event **prev;
    442  1.10  christos   int64_t time_of_event;
    443   1.1  christos 
    444   1.1  christos   if (delta < 0)
    445   1.1  christos     sim_io_error (sd, "what is past is past!\n");
    446   1.1  christos 
    447   1.1  christos   /* compute when the event should occur */
    448   1.1  christos   time_of_event = sim_events_time (sd) + delta;
    449   1.1  christos 
    450   1.1  christos   /* find the queue insertion point - things are time ordered */
    451   1.1  christos   prev = &events->queue;
    452   1.1  christos   curr = events->queue;
    453   1.1  christos   while (curr != NULL && time_of_event >= curr->time_of_event)
    454   1.1  christos     {
    455   1.1  christos       SIM_ASSERT (curr->next == NULL
    456   1.1  christos 		  || curr->time_of_event <= curr->next->time_of_event);
    457   1.1  christos       prev = &curr->next;
    458   1.1  christos       curr = curr->next;
    459   1.1  christos     }
    460   1.1  christos   SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
    461   1.1  christos 
    462   1.1  christos   /* insert it */
    463   1.1  christos   new_event->next = curr;
    464   1.1  christos   *prev = new_event;
    465   1.1  christos   new_event->time_of_event = time_of_event;
    466   1.1  christos 
    467   1.1  christos   /* adjust the time until the first event */
    468   1.1  christos   update_time_from_event (sd);
    469   1.1  christos }
    470   1.1  christos #endif
    471   1.1  christos 
    472   1.1  christos 
    473   1.1  christos #if EXTERN_SIM_EVENTS_P
    474   1.1  christos sim_event *
    475   1.1  christos sim_events_schedule (SIM_DESC sd,
    476  1.10  christos 		     int64_t delta_time,
    477   1.1  christos 		     sim_event_handler *handler,
    478   1.1  christos 		     void *data)
    479   1.1  christos {
    480  1.10  christos   return sim_events_schedule_tracef (sd, delta_time, handler, data, NULL);
    481   1.1  christos }
    482   1.1  christos #endif
    483   1.1  christos 
    484   1.1  christos 
    485   1.1  christos #if EXTERN_SIM_EVENTS_P
    486   1.1  christos sim_event *
    487   1.1  christos sim_events_schedule_tracef (SIM_DESC sd,
    488  1.10  christos 			    int64_t delta_time,
    489   1.1  christos 			    sim_event_handler *handler,
    490   1.1  christos 			    void *data,
    491   1.1  christos 			    const char *fmt,
    492   1.1  christos 			    ...)
    493   1.1  christos {
    494   1.1  christos   sim_event *new_event;
    495   1.1  christos   va_list ap;
    496   1.1  christos   va_start (ap, fmt);
    497   1.1  christos   new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
    498   1.1  christos   va_end (ap);
    499   1.1  christos   return new_event;
    500   1.1  christos }
    501   1.1  christos #endif
    502   1.1  christos 
    503   1.1  christos 
    504   1.1  christos #if EXTERN_SIM_EVENTS_P
    505   1.1  christos sim_event *
    506   1.1  christos sim_events_schedule_vtracef (SIM_DESC sd,
    507  1.10  christos 			     int64_t delta_time,
    508   1.1  christos 			     sim_event_handler *handler,
    509   1.1  christos 			     void *data,
    510   1.1  christos 			     const char *fmt,
    511   1.1  christos 			     va_list ap)
    512   1.1  christos {
    513   1.1  christos   sim_event *new_event = sim_events_zalloc (sd);
    514   1.1  christos   new_event->data = data;
    515   1.1  christos   new_event->handler = handler;
    516   1.1  christos   new_event->watching = watch_timer;
    517   1.5  christos   if (fmt == NULL || !STRACE_EVENTS_P (sd) || vasprintf (&new_event->trace, fmt, ap) < 0)
    518   1.1  christos     new_event->trace = NULL;
    519   1.1  christos   insert_sim_event (sd, new_event, delta_time);
    520   1.1  christos   ETRACE ((_ETRACE,
    521  1.10  christos 	   "event scheduled at %" PRIi64 " - "
    522  1.10  christos 	   "tag %p - time %" PRIi64 ", handler %p, data %p%s%s\n",
    523  1.10  christos 	   sim_events_time (sd),
    524  1.10  christos 	   new_event,
    525  1.10  christos 	   new_event->time_of_event,
    526  1.10  christos 	   new_event->handler,
    527  1.10  christos 	   new_event->data,
    528   1.1  christos 	   (new_event->trace != NULL) ? ", " : "",
    529   1.1  christos 	   (new_event->trace != NULL) ? new_event->trace : ""));
    530   1.1  christos   return new_event;
    531   1.1  christos }
    532   1.1  christos #endif
    533   1.1  christos 
    534   1.1  christos 
    535   1.1  christos #if EXTERN_SIM_EVENTS_P
    536   1.1  christos void
    537   1.1  christos sim_events_schedule_after_signal (SIM_DESC sd,
    538  1.10  christos 				  int64_t delta_time,
    539   1.1  christos 				  sim_event_handler *handler,
    540   1.1  christos 				  void *data)
    541   1.1  christos {
    542   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    543   1.1  christos   sim_event *new_event;
    544   1.1  christos #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
    545   1.1  christos   /*-LOCK-*/
    546   1.1  christos   sigset_t old_mask;
    547   1.1  christos   sigset_t new_mask;
    548   1.1  christos   sigfillset (&new_mask);
    549   1.1  christos   sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
    550   1.1  christos #endif
    551   1.1  christos 
    552   1.1  christos   /* allocate an event entry from the signal buffer */
    553   1.1  christos   new_event = &events->held [events->nr_held];
    554   1.1  christos   events->nr_held ++;
    555   1.1  christos   if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
    556   1.1  christos     {
    557   1.1  christos       sim_engine_abort (NULL, NULL, NULL_CIA,
    558   1.5  christos 			"sim_events_schedule_after_signal - buffer overflow");
    559   1.1  christos     }
    560   1.1  christos 
    561   1.1  christos   new_event->data = data;
    562   1.1  christos   new_event->handler = handler;
    563   1.1  christos   new_event->time_of_event = delta_time; /* work it out later */
    564   1.1  christos   new_event->next = NULL;
    565   1.1  christos 
    566   1.1  christos   events->work_pending = 1; /* notify main process */
    567   1.1  christos 
    568   1.1  christos #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
    569   1.1  christos   /*-UNLOCK-*/
    570   1.1  christos   sigprocmask (SIG_SETMASK, &old_mask, NULL);
    571   1.1  christos #endif
    572   1.1  christos 
    573   1.1  christos   ETRACE ((_ETRACE,
    574  1.10  christos 	   "signal scheduled at %" PRIi64 " - "
    575  1.10  christos 	   "tag %p - time %" PRIi64 ", handler %p, data %p\n",
    576  1.10  christos 	   sim_events_time (sd),
    577  1.10  christos 	   new_event,
    578  1.10  christos 	   new_event->time_of_event,
    579  1.10  christos 	   new_event->handler,
    580  1.10  christos 	   new_event->data));
    581   1.1  christos }
    582   1.1  christos #endif
    583   1.1  christos 
    584   1.1  christos 
    585   1.1  christos #if EXTERN_SIM_EVENTS_P
    586   1.1  christos sim_event *
    587   1.1  christos sim_events_watch_clock (SIM_DESC sd,
    588   1.1  christos 			unsigned delta_ms_time,
    589   1.1  christos 			sim_event_handler *handler,
    590   1.1  christos 			void *data)
    591   1.1  christos {
    592   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    593   1.1  christos   sim_event *new_event = sim_events_zalloc (sd);
    594   1.1  christos   /* type */
    595   1.1  christos   new_event->watching = watch_clock;
    596   1.1  christos   /* handler */
    597   1.1  christos   new_event->data = data;
    598   1.1  christos   new_event->handler = handler;
    599   1.1  christos   /* data */
    600   1.1  christos   if (events->resume_wallclock == 0)
    601   1.1  christos     new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
    602   1.1  christos   else
    603   1.1  christos     new_event->wallclock = (events->elapsed_wallclock
    604   1.1  christos 			    + sim_elapsed_time_since (events->resume_wallclock)
    605   1.1  christos 			    + delta_ms_time);
    606   1.1  christos   /* insert */
    607   1.1  christos   new_event->next = events->watchpoints;
    608   1.1  christos   events->watchpoints = new_event;
    609   1.1  christos   events->work_pending = 1;
    610   1.1  christos   ETRACE ((_ETRACE,
    611  1.10  christos 	   "event watching clock at %" PRIi64 " - "
    612  1.10  christos 	   "tag %p - wallclock %u, handler %p, data %p\n",
    613  1.10  christos 	   sim_events_time (sd),
    614  1.10  christos 	   new_event,
    615  1.10  christos 	   new_event->wallclock,
    616  1.10  christos 	   new_event->handler,
    617  1.10  christos 	   new_event->data));
    618  1.10  christos   return new_event;
    619  1.10  christos }
    620  1.10  christos #endif
    621  1.10  christos 
    622  1.10  christos 
    623  1.10  christos #if EXTERN_SIM_EVENTS_P
    624  1.10  christos sim_event *
    625  1.10  christos sim_events_watch_pc (SIM_DESC sd,
    626  1.10  christos 		     int is_within,
    627  1.10  christos 		     uint64_t lb,
    628  1.10  christos 		     uint64_t ub,
    629  1.10  christos 		     sim_event_handler *handler,
    630  1.10  christos 		     void *data)
    631  1.10  christos {
    632  1.10  christos   sim_events *events = STATE_EVENTS (sd);
    633  1.10  christos   sim_event *new_event = sim_events_zalloc (sd);
    634  1.10  christos   /* type */
    635  1.10  christos   new_event->watching = watch_pc;
    636  1.10  christos   /* handler */
    637  1.10  christos   new_event->data = data;
    638  1.10  christos   new_event->handler = handler;
    639  1.10  christos   /* data */
    640  1.10  christos   new_event->lb = lb;
    641  1.10  christos   new_event->lb64 = lb;
    642  1.10  christos   new_event->ub = ub;
    643  1.10  christos   new_event->ub64 = ub;
    644  1.10  christos   new_event->is_within = (is_within != 0);
    645  1.10  christos   /* insert */
    646  1.10  christos   new_event->next = events->watchpoints;
    647  1.10  christos   events->watchpoints = new_event;
    648  1.10  christos   events->work_pending = 1;
    649  1.10  christos   ETRACE ((_ETRACE,
    650  1.10  christos 	   "event watching pc at %" PRIi64 " - "
    651  1.10  christos 	   "tag %p - pc 0x%x..0x%x, handler %p, data %p\n",
    652  1.10  christos 	   sim_events_time (sd),
    653  1.10  christos 	   new_event,
    654  1.10  christos 	   new_event->lb,
    655  1.10  christos 	   new_event->ub,
    656  1.10  christos 	   new_event->handler,
    657  1.10  christos 	   new_event->data));
    658   1.1  christos   return new_event;
    659   1.1  christos }
    660   1.1  christos #endif
    661   1.1  christos 
    662   1.1  christos 
    663   1.1  christos #if EXTERN_SIM_EVENTS_P
    664   1.1  christos sim_event *
    665   1.1  christos sim_events_watch_sim (SIM_DESC sd,
    666   1.1  christos 		      void *host_addr,
    667   1.1  christos 		      int nr_bytes,
    668  1.10  christos 		      enum bfd_endian byte_order,
    669   1.1  christos 		      int is_within,
    670  1.10  christos 		      uint64_t lb,
    671  1.10  christos 		      uint64_t ub,
    672   1.1  christos 		      sim_event_handler *handler,
    673   1.1  christos 		      void *data)
    674   1.1  christos {
    675   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    676   1.1  christos   sim_event *new_event = sim_events_zalloc (sd);
    677   1.1  christos   /* type */
    678   1.1  christos   switch (byte_order)
    679   1.1  christos     {
    680   1.6  christos     case BFD_ENDIAN_UNKNOWN:
    681   1.1  christos       switch (nr_bytes)
    682   1.1  christos 	{
    683   1.1  christos 	case 1: new_event->watching = watch_sim_host_1; break;
    684   1.1  christos 	case 2: new_event->watching = watch_sim_host_2; break;
    685   1.1  christos 	case 4: new_event->watching = watch_sim_host_4; break;
    686   1.1  christos 	case 8: new_event->watching = watch_sim_host_8; break;
    687   1.1  christos 	default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
    688   1.1  christos 	}
    689   1.1  christos       break;
    690   1.6  christos     case BFD_ENDIAN_BIG:
    691   1.1  christos       switch (nr_bytes)
    692   1.1  christos 	{
    693   1.1  christos 	case 1: new_event->watching = watch_sim_be_1; break;
    694   1.1  christos 	case 2: new_event->watching = watch_sim_be_2; break;
    695   1.1  christos 	case 4: new_event->watching = watch_sim_be_4; break;
    696   1.1  christos 	case 8: new_event->watching = watch_sim_be_8; break;
    697   1.1  christos 	default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
    698   1.1  christos 	}
    699   1.1  christos       break;
    700   1.6  christos     case BFD_ENDIAN_LITTLE:
    701   1.1  christos       switch (nr_bytes)
    702   1.1  christos 	{
    703   1.1  christos 	case 1: new_event->watching = watch_sim_le_1; break;
    704   1.1  christos 	case 2: new_event->watching = watch_sim_le_2; break;
    705   1.1  christos 	case 4: new_event->watching = watch_sim_le_4; break;
    706   1.1  christos 	case 8: new_event->watching = watch_sim_le_8; break;
    707   1.1  christos 	default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
    708   1.1  christos 	}
    709   1.1  christos       break;
    710   1.1  christos     default:
    711   1.1  christos       sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
    712   1.1  christos     }
    713   1.1  christos   /* handler */
    714   1.1  christos   new_event->data = data;
    715   1.1  christos   new_event->handler = handler;
    716   1.1  christos   /* data */
    717   1.1  christos   new_event->host_addr = host_addr;
    718   1.1  christos   new_event->lb = lb;
    719   1.1  christos   new_event->lb64 = lb;
    720   1.1  christos   new_event->ub = ub;
    721   1.1  christos   new_event->ub64 = ub;
    722   1.1  christos   new_event->is_within = (is_within != 0);
    723   1.1  christos   /* insert */
    724   1.1  christos   new_event->next = events->watchpoints;
    725   1.1  christos   events->watchpoints = new_event;
    726   1.1  christos   events->work_pending = 1;
    727   1.1  christos   ETRACE ((_ETRACE,
    728  1.10  christos 	   "event watching host at %" PRIi64 " - "
    729  1.10  christos 	   "tag %p - host-addr %p, 0x%x..0x%x, handler %p, data %p\n",
    730  1.10  christos 	   sim_events_time (sd),
    731  1.10  christos 	   new_event,
    732  1.10  christos 	   new_event->host_addr,
    733  1.10  christos 	   new_event->lb,
    734  1.10  christos 	   new_event->ub,
    735  1.10  christos 	   new_event->handler,
    736  1.10  christos 	   new_event->data));
    737   1.1  christos   return new_event;
    738   1.1  christos }
    739   1.1  christos #endif
    740   1.1  christos 
    741   1.1  christos 
    742   1.1  christos #if EXTERN_SIM_EVENTS_P
    743   1.1  christos sim_event *
    744   1.1  christos sim_events_watch_core (SIM_DESC sd,
    745   1.1  christos 		       address_word core_addr,
    746   1.1  christos 		       unsigned core_map,
    747   1.1  christos 		       int nr_bytes,
    748  1.10  christos 		       enum bfd_endian byte_order,
    749   1.1  christos 		       int is_within,
    750  1.10  christos 		       uint64_t lb,
    751  1.10  christos 		       uint64_t ub,
    752   1.1  christos 		       sim_event_handler *handler,
    753   1.1  christos 		       void *data)
    754   1.1  christos {
    755   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    756   1.1  christos   sim_event *new_event = sim_events_zalloc (sd);
    757   1.1  christos   /* type */
    758   1.1  christos   switch (byte_order)
    759   1.1  christos     {
    760   1.6  christos     case BFD_ENDIAN_UNKNOWN:
    761   1.1  christos       switch (nr_bytes)
    762   1.1  christos 	{
    763   1.1  christos 	case 1: new_event->watching = watch_core_targ_1; break;
    764   1.1  christos 	case 2: new_event->watching = watch_core_targ_2; break;
    765   1.1  christos 	case 4: new_event->watching = watch_core_targ_4; break;
    766   1.1  christos 	case 8: new_event->watching = watch_core_targ_8; break;
    767   1.1  christos 	default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
    768   1.1  christos 	}
    769   1.1  christos       break;
    770   1.6  christos     case BFD_ENDIAN_BIG:
    771   1.1  christos       switch (nr_bytes)
    772   1.1  christos 	{
    773   1.1  christos 	case 1: new_event->watching = watch_core_be_1; break;
    774   1.1  christos 	case 2: new_event->watching = watch_core_be_2; break;
    775   1.1  christos 	case 4: new_event->watching = watch_core_be_4; break;
    776   1.1  christos 	case 8: new_event->watching = watch_core_be_8; break;
    777   1.1  christos 	default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
    778   1.1  christos 	}
    779   1.1  christos       break;
    780   1.6  christos     case BFD_ENDIAN_LITTLE:
    781   1.1  christos       switch (nr_bytes)
    782   1.1  christos 	{
    783   1.1  christos 	case 1: new_event->watching = watch_core_le_1; break;
    784   1.1  christos 	case 2: new_event->watching = watch_core_le_2; break;
    785   1.1  christos 	case 4: new_event->watching = watch_core_le_4; break;
    786   1.1  christos 	case 8: new_event->watching = watch_core_le_8; break;
    787   1.1  christos 	default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
    788   1.1  christos 	}
    789   1.1  christos       break;
    790   1.1  christos     default:
    791   1.1  christos       sim_io_error (sd, "sim_events_watch_core - invalid byte order");
    792   1.1  christos     }
    793   1.1  christos   /* handler */
    794   1.1  christos   new_event->data = data;
    795   1.1  christos   new_event->handler = handler;
    796   1.1  christos   /* data */
    797   1.1  christos   new_event->core_addr = core_addr;
    798   1.1  christos   new_event->core_map = core_map;
    799   1.1  christos   new_event->lb = lb;
    800   1.1  christos   new_event->lb64 = lb;
    801   1.1  christos   new_event->ub = ub;
    802   1.1  christos   new_event->ub64 = ub;
    803   1.1  christos   new_event->is_within = (is_within != 0);
    804   1.1  christos   /* insert */
    805   1.1  christos   new_event->next = events->watchpoints;
    806   1.1  christos   events->watchpoints = new_event;
    807   1.1  christos   events->work_pending = 1;
    808   1.1  christos   ETRACE ((_ETRACE,
    809  1.10  christos 	   "event watching host at %" PRIi64 " - "
    810  1.10  christos 	   "tag %p - host-addr %p, 0x%x..0x%x, handler %p, data %p\n",
    811  1.10  christos 	   sim_events_time (sd),
    812  1.10  christos 	   new_event,
    813  1.10  christos 	   new_event->host_addr,
    814  1.10  christos 	   new_event->lb,
    815  1.10  christos 	   new_event->ub,
    816  1.10  christos 	   new_event->handler,
    817  1.10  christos 	   new_event->data));
    818   1.1  christos   return new_event;
    819   1.1  christos }
    820   1.1  christos #endif
    821   1.1  christos 
    822   1.1  christos 
    823   1.1  christos #if EXTERN_SIM_EVENTS_P
    824   1.1  christos void
    825   1.1  christos sim_events_deschedule (SIM_DESC sd,
    826   1.1  christos 		       sim_event *event_to_remove)
    827   1.1  christos {
    828   1.1  christos   sim_events *events = STATE_EVENTS (sd);
    829   1.1  christos   sim_event *to_remove = (sim_event*)event_to_remove;
    830   1.1  christos   if (event_to_remove != NULL)
    831   1.1  christos     {
    832   1.1  christos       sim_event **queue = NULL;
    833   1.1  christos       while ((queue = next_event_queue (sd, queue)) != NULL)
    834   1.1  christos 	{
    835   1.1  christos 	  sim_event **ptr_to_current;
    836   1.1  christos 	  for (ptr_to_current = queue;
    837   1.1  christos 	       *ptr_to_current != NULL && *ptr_to_current != to_remove;
    838   1.1  christos 	       ptr_to_current = &(*ptr_to_current)->next);
    839   1.1  christos 	  if (*ptr_to_current == to_remove)
    840   1.1  christos 	    {
    841   1.1  christos 	      sim_event *dead = *ptr_to_current;
    842   1.1  christos 	      *ptr_to_current = dead->next;
    843   1.1  christos 	      ETRACE ((_ETRACE,
    844  1.10  christos 		       "event/watch descheduled at %" PRIi64 " - "
    845  1.10  christos 		       "tag %p - time %" PRIi64 ", handler %p, data %p%s%s\n",
    846  1.10  christos 		       sim_events_time (sd),
    847  1.10  christos 		       event_to_remove,
    848  1.10  christos 		       dead->time_of_event,
    849  1.10  christos 		       dead->handler,
    850  1.10  christos 		       dead->data,
    851   1.1  christos 		       (dead->trace != NULL) ? ", " : "",
    852   1.1  christos 		       (dead->trace != NULL) ? dead->trace : ""));
    853   1.1  christos 	      sim_events_free (sd, dead);
    854   1.1  christos 	      update_time_from_event (sd);
    855   1.1  christos 	      SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
    856   1.1  christos 	      return;
    857   1.1  christos 	    }
    858   1.1  christos 	}
    859   1.1  christos     }
    860   1.1  christos   ETRACE ((_ETRACE,
    861  1.10  christos 	   "event/watch descheduled at %" PRIi64 " - tag %p - not found\n",
    862  1.10  christos 	   sim_events_time (sd),
    863  1.10  christos 	   event_to_remove));
    864   1.1  christos }
    865   1.1  christos #endif
    866   1.1  christos 
    867   1.1  christos 
    868   1.1  christos STATIC_INLINE_SIM_EVENTS\
    869   1.1  christos (int)
    870   1.1  christos sim_watch_valid (SIM_DESC sd,
    871   1.1  christos 		 sim_event *to_do)
    872   1.1  christos {
    873   1.1  christos   switch (to_do->watching)
    874   1.1  christos     {
    875   1.1  christos 
    876   1.1  christos #define WATCH_CORE(N,OP,EXT) \
    877   1.1  christos       int ok; \
    878   1.1  christos       unsigned_##N word = 0; \
    879   1.1  christos       int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
    880   1.1  christos 					  to_do->core_addr, sizeof (word)); \
    881   1.1  christos       OP (word); \
    882   1.1  christos       ok = (nr_read == sizeof (unsigned_##N) \
    883   1.1  christos 	    && (to_do->is_within \
    884   1.1  christos 		== (word >= to_do->lb##EXT \
    885   1.1  christos 		    && word <= to_do->ub##EXT)));
    886   1.1  christos 
    887   1.1  christos     case watch_core_targ_1:
    888   1.1  christos       {
    889   1.1  christos 	WATCH_CORE (1, T2H,);
    890   1.1  christos 	return ok;
    891   1.1  christos       }
    892   1.1  christos     case watch_core_targ_2:
    893   1.1  christos       {
    894   1.1  christos         WATCH_CORE (2, T2H,);
    895   1.1  christos 	return ok;
    896   1.1  christos       }
    897   1.1  christos     case watch_core_targ_4:
    898   1.1  christos       {
    899   1.1  christos         WATCH_CORE (4, T2H,);
    900   1.1  christos 	return ok;
    901   1.1  christos       }
    902   1.1  christos     case watch_core_targ_8:
    903   1.1  christos       {
    904   1.1  christos         WATCH_CORE (8, T2H,64);
    905   1.1  christos 	return ok;
    906   1.1  christos       }
    907   1.1  christos 
    908   1.1  christos     case watch_core_be_1:
    909   1.1  christos       {
    910   1.1  christos         WATCH_CORE (1, BE2H,);
    911   1.1  christos 	return ok;
    912   1.1  christos       }
    913   1.1  christos     case watch_core_be_2:
    914   1.1  christos       {
    915   1.1  christos         WATCH_CORE (2, BE2H,);
    916   1.1  christos 	return ok;
    917   1.1  christos       }
    918   1.1  christos     case watch_core_be_4:
    919   1.1  christos       {
    920   1.1  christos         WATCH_CORE (4, BE2H,);
    921   1.1  christos 	return ok;
    922   1.1  christos       }
    923   1.1  christos     case watch_core_be_8:
    924   1.1  christos       {
    925   1.1  christos         WATCH_CORE (8, BE2H,64);
    926   1.1  christos 	return ok;
    927   1.1  christos       }
    928   1.1  christos 
    929   1.1  christos     case watch_core_le_1:
    930   1.1  christos       {
    931   1.1  christos         WATCH_CORE (1, LE2H,);
    932   1.1  christos 	return ok;
    933   1.1  christos       }
    934   1.1  christos     case watch_core_le_2:
    935   1.1  christos       {
    936   1.1  christos         WATCH_CORE (2, LE2H,);
    937   1.1  christos 	return ok;
    938   1.1  christos       }
    939   1.1  christos     case watch_core_le_4:
    940   1.1  christos       {
    941   1.1  christos         WATCH_CORE (4, LE2H,);
    942   1.1  christos 	return ok;
    943   1.1  christos       }
    944   1.1  christos     case watch_core_le_8:
    945   1.1  christos       {
    946   1.1  christos         WATCH_CORE (8, LE2H,64);
    947   1.1  christos 	return ok;
    948   1.1  christos       }
    949   1.1  christos #undef WATCH_CORE
    950   1.1  christos 
    951   1.1  christos #define WATCH_SIM(N,OP,EXT) \
    952   1.1  christos       int ok; \
    953   1.1  christos       unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
    954   1.1  christos       OP (word); \
    955   1.1  christos       ok = (to_do->is_within \
    956   1.1  christos 	    == (word >= to_do->lb##EXT \
    957   1.1  christos 		&& word <= to_do->ub##EXT));
    958   1.1  christos 
    959   1.1  christos     case watch_sim_host_1:
    960   1.1  christos       {
    961   1.1  christos         WATCH_SIM (1, word = ,);
    962   1.1  christos 	return ok;
    963   1.1  christos       }
    964   1.1  christos     case watch_sim_host_2:
    965   1.1  christos       {
    966   1.1  christos         WATCH_SIM (2, word = ,);
    967   1.1  christos 	return ok;
    968   1.1  christos       }
    969   1.1  christos     case watch_sim_host_4:
    970   1.1  christos       {
    971   1.1  christos         WATCH_SIM (4, word = ,);
    972   1.1  christos 	return ok;
    973   1.1  christos       }
    974   1.1  christos     case watch_sim_host_8:
    975   1.1  christos       {
    976   1.1  christos         WATCH_SIM (8, word = ,64);
    977   1.1  christos 	return ok;
    978   1.1  christos       }
    979   1.1  christos 
    980   1.1  christos     case watch_sim_be_1:
    981   1.1  christos       {
    982   1.1  christos         WATCH_SIM (1, BE2H,);
    983   1.1  christos 	return ok;
    984   1.1  christos       }
    985   1.1  christos     case watch_sim_be_2:
    986   1.1  christos       {
    987   1.1  christos         WATCH_SIM (2, BE2H,);
    988   1.1  christos 	return ok;
    989   1.1  christos       }
    990   1.1  christos     case watch_sim_be_4:
    991   1.1  christos       {
    992   1.1  christos         WATCH_SIM (4, BE2H,);
    993   1.1  christos 	return ok;
    994   1.1  christos       }
    995   1.1  christos     case watch_sim_be_8:
    996   1.1  christos       {
    997   1.1  christos         WATCH_SIM (8, BE2H,64);
    998   1.1  christos 	return ok;
    999   1.1  christos       }
   1000   1.1  christos 
   1001   1.1  christos     case watch_sim_le_1:
   1002   1.1  christos       {
   1003   1.1  christos         WATCH_SIM (1, LE2H,);
   1004   1.1  christos 	return ok;
   1005   1.1  christos       }
   1006   1.1  christos     case watch_sim_le_2:
   1007   1.1  christos       {
   1008   1.1  christos         WATCH_SIM (1, LE2H,);
   1009   1.1  christos 	return ok;
   1010   1.1  christos       }
   1011   1.1  christos     case watch_sim_le_4:
   1012   1.1  christos       {
   1013   1.1  christos         WATCH_SIM (1, LE2H,);
   1014   1.1  christos 	return ok;
   1015   1.1  christos       }
   1016   1.1  christos     case watch_sim_le_8:
   1017   1.1  christos       {
   1018   1.1  christos         WATCH_SIM (1, LE2H,64);
   1019   1.1  christos 	return ok;
   1020   1.1  christos       }
   1021   1.1  christos #undef WATCH_SIM
   1022   1.1  christos 
   1023  1.10  christos     case watch_pc:
   1024  1.10  christos       {
   1025  1.10  christos 	int c;
   1026  1.10  christos 
   1027  1.10  christos 	for (c = 0; c < MAX_NR_PROCESSORS; ++c)
   1028  1.10  christos 	  {
   1029  1.10  christos 	    sim_cpu *cpu = STATE_CPU (sd, c);
   1030  1.10  christos 	    sim_cia cia = sim_pc_get (cpu);
   1031  1.10  christos 
   1032  1.10  christos 	    if (to_do->is_within == (cia >= to_do->lb64 && cia <= to_do->ub64))
   1033  1.10  christos 	      return 1;
   1034  1.10  christos 	  }
   1035  1.10  christos 	return 0;
   1036  1.10  christos       }
   1037  1.10  christos 
   1038   1.1  christos     case watch_clock: /* wallclock */
   1039   1.1  christos       {
   1040   1.1  christos 	unsigned long elapsed_time = sim_events_elapsed_time (sd);
   1041   1.1  christos 	return (elapsed_time >= to_do->wallclock);
   1042   1.1  christos       }
   1043   1.1  christos 
   1044   1.1  christos     default:
   1045   1.1  christos       sim_io_error (sd, "sim_watch_valid - bad switch");
   1046   1.1  christos       break;
   1047   1.1  christos 
   1048   1.1  christos     }
   1049   1.1  christos   return 1;
   1050   1.1  christos }
   1051   1.1  christos 
   1052   1.1  christos 
   1053   1.1  christos INLINE_SIM_EVENTS\
   1054   1.1  christos (int)
   1055   1.1  christos sim_events_tick (SIM_DESC sd)
   1056   1.1  christos {
   1057   1.1  christos   sim_events *events = STATE_EVENTS (sd);
   1058   1.1  christos 
   1059   1.1  christos   /* this should only be called after the previous ticks have been
   1060   1.1  christos      fully processed */
   1061   1.1  christos 
   1062   1.1  christos   /* Advance the time but *only* if there is nothing to process */
   1063   1.1  christos   if (events->work_pending
   1064   1.1  christos       || events->time_from_event == 0)
   1065   1.1  christos     {
   1066   1.1  christos       events->nr_ticks_to_process += 1;
   1067   1.1  christos       return 1;
   1068   1.1  christos     }
   1069   1.1  christos   else
   1070   1.1  christos     {
   1071   1.1  christos       events->time_from_event -= 1;
   1072   1.1  christos       return 0;
   1073   1.1  christos     }
   1074   1.1  christos }
   1075   1.1  christos 
   1076   1.1  christos 
   1077   1.1  christos INLINE_SIM_EVENTS\
   1078   1.1  christos (int)
   1079   1.1  christos sim_events_tickn (SIM_DESC sd,
   1080   1.1  christos 		  int n)
   1081   1.1  christos {
   1082   1.1  christos   sim_events *events = STATE_EVENTS (sd);
   1083   1.1  christos   SIM_ASSERT (n > 0);
   1084   1.1  christos 
   1085   1.1  christos   /* this should only be called after the previous ticks have been
   1086   1.1  christos      fully processed */
   1087   1.1  christos 
   1088   1.1  christos   /* Advance the time but *only* if there is nothing to process */
   1089   1.1  christos   if (events->work_pending || events->time_from_event < n)
   1090   1.1  christos     {
   1091   1.1  christos       events->nr_ticks_to_process += n;
   1092   1.1  christos       return 1;
   1093   1.1  christos     }
   1094   1.1  christos   else
   1095   1.1  christos     {
   1096   1.1  christos       events->time_from_event -= n;
   1097   1.1  christos       return 0;
   1098   1.1  christos     }
   1099   1.1  christos }
   1100   1.1  christos 
   1101   1.1  christos 
   1102   1.1  christos INLINE_SIM_EVENTS\
   1103   1.1  christos (void)
   1104   1.1  christos sim_events_slip (SIM_DESC sd,
   1105   1.1  christos 		 int slip)
   1106   1.1  christos {
   1107   1.1  christos   sim_events *events = STATE_EVENTS (sd);
   1108   1.1  christos   SIM_ASSERT (slip > 0);
   1109   1.1  christos 
   1110   1.1  christos   /* Flag a ready event with work_pending instead of number of ticks
   1111   1.1  christos      to process so that the time continues to be correct */
   1112   1.1  christos   if (events->time_from_event < slip)
   1113   1.1  christos     {
   1114   1.1  christos       events->work_pending = 1;
   1115   1.1  christos     }
   1116   1.1  christos   events->time_from_event -= slip;
   1117   1.1  christos }
   1118   1.1  christos 
   1119   1.1  christos 
   1120   1.1  christos INLINE_SIM_EVENTS\
   1121   1.1  christos (void)
   1122   1.1  christos sim_events_preprocess (SIM_DESC sd,
   1123   1.1  christos 		       int events_were_last,
   1124   1.1  christos 		       int events_were_next)
   1125   1.1  christos {
   1126   1.1  christos   sim_events *events = STATE_EVENTS (sd);
   1127   1.1  christos   if (events_were_last)
   1128   1.1  christos     {
   1129   1.1  christos       /* Halted part way through event processing */
   1130   1.1  christos       ASSERT (events->nr_ticks_to_process != 0);
   1131   1.1  christos       /* The external world can't tell if the event that stopped the
   1132   1.1  christos          simulator was the last event to process. */
   1133   1.1  christos       ASSERT (events_were_next);
   1134   1.1  christos       sim_events_process (sd);
   1135   1.1  christos     }
   1136   1.1  christos   else if (events_were_next)
   1137   1.1  christos     {
   1138   1.1  christos       /* Halted by the last processor */
   1139   1.1  christos       if (sim_events_tick (sd))
   1140   1.1  christos 	sim_events_process (sd);
   1141   1.1  christos     }
   1142   1.1  christos }
   1143   1.1  christos 
   1144   1.1  christos 
   1145   1.1  christos INLINE_SIM_EVENTS\
   1146   1.1  christos (void)
   1147   1.1  christos sim_events_process (SIM_DESC sd)
   1148   1.1  christos {
   1149   1.1  christos   sim_events *events = STATE_EVENTS (sd);
   1150  1.10  christos   int64_t event_time = sim_events_time (sd);
   1151   1.1  christos 
   1152   1.1  christos   /* Clear work_pending before checking nr_held.  Clearing
   1153   1.1  christos      work_pending after nr_held (with out a lock could loose an
   1154   1.1  christos      event). */
   1155   1.1  christos   events->work_pending = 0;
   1156   1.1  christos 
   1157   1.1  christos   /* move any events that were asynchronously queued by any signal
   1158   1.1  christos      handlers onto the real event queue.  */
   1159   1.1  christos   if (events->nr_held > 0)
   1160   1.1  christos     {
   1161   1.1  christos       int i;
   1162   1.1  christos 
   1163   1.1  christos #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
   1164   1.1  christos       /*-LOCK-*/
   1165   1.1  christos       sigset_t old_mask;
   1166   1.1  christos       sigset_t new_mask;
   1167   1.1  christos       sigfillset (&new_mask);
   1168   1.1  christos       sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
   1169   1.1  christos #endif
   1170   1.1  christos 
   1171   1.1  christos       for (i = 0; i < events->nr_held; i++)
   1172   1.1  christos 	{
   1173   1.1  christos 	  sim_event *entry = &events->held [i];
   1174   1.1  christos 	  sim_events_schedule (sd,
   1175   1.1  christos 			       entry->time_of_event,
   1176   1.1  christos 			       entry->handler,
   1177   1.1  christos 			       entry->data);
   1178   1.1  christos 	}
   1179   1.1  christos       events->nr_held = 0;
   1180   1.1  christos 
   1181   1.1  christos #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
   1182   1.1  christos       /*-UNLOCK-*/
   1183   1.1  christos       sigprocmask (SIG_SETMASK, &old_mask, NULL);
   1184   1.1  christos #endif
   1185   1.1  christos 
   1186   1.1  christos     }
   1187   1.1  christos 
   1188   1.1  christos   /* Process any watchpoints. Be careful to allow a watchpoint to
   1189   1.1  christos      appear/disappear under our feet.
   1190   1.1  christos      To ensure that watchpoints are processed only once per cycle,
   1191   1.1  christos      they are moved onto a watched queue, this returned to the
   1192   1.1  christos      watchpoint queue when all queue processing has been
   1193   1.1  christos      completed. */
   1194   1.1  christos   while (events->watchpoints != NULL)
   1195   1.1  christos     {
   1196   1.1  christos       sim_event *to_do = events->watchpoints;
   1197   1.1  christos       events->watchpoints = to_do->next;
   1198   1.1  christos       if (sim_watch_valid (sd, to_do))
   1199   1.1  christos 	{
   1200   1.1  christos 	  sim_event_handler *handler = to_do->handler;
   1201   1.1  christos 	  void *data = to_do->data;
   1202   1.1  christos 	  ETRACE ((_ETRACE,
   1203  1.10  christos 		   "event issued at %" PRIi64 " - "
   1204  1.10  christos 		   "tag %p - handler %p, data %p%s%s\n",
   1205  1.10  christos 		   event_time,
   1206  1.10  christos 		   to_do,
   1207  1.10  christos 		   handler,
   1208  1.10  christos 		   data,
   1209   1.1  christos 		   (to_do->trace != NULL) ? ", " : "",
   1210   1.1  christos 		   (to_do->trace != NULL) ? to_do->trace : ""));
   1211   1.1  christos 	  sim_events_free (sd, to_do);
   1212   1.1  christos 	  handler (sd, data);
   1213   1.1  christos 	}
   1214   1.1  christos       else
   1215   1.1  christos 	{
   1216   1.1  christos 	  to_do->next = events->watchedpoints;
   1217   1.1  christos 	  events->watchedpoints = to_do;
   1218   1.1  christos 	}
   1219   1.1  christos     }
   1220   1.1  christos 
   1221   1.1  christos   /* consume all events for this or earlier times.  Be careful to
   1222   1.1  christos      allow an event to appear/disappear under our feet */
   1223   1.1  christos   while (events->queue->time_of_event <
   1224   1.1  christos 	 (event_time + events->nr_ticks_to_process))
   1225   1.1  christos     {
   1226   1.1  christos       sim_event *to_do = events->queue;
   1227   1.1  christos       sim_event_handler *handler = to_do->handler;
   1228   1.1  christos       void *data = to_do->data;
   1229   1.1  christos       events->queue = to_do->next;
   1230   1.1  christos       update_time_from_event (sd);
   1231   1.1  christos       ETRACE ((_ETRACE,
   1232  1.10  christos 	       "event issued at %" PRIi64 " - tag %p - handler %p, data %p%s%s\n",
   1233  1.10  christos 	       event_time,
   1234  1.10  christos 	       to_do,
   1235  1.10  christos 	       handler,
   1236  1.10  christos 	       data,
   1237   1.1  christos 	       (to_do->trace != NULL) ? ", " : "",
   1238   1.1  christos 	       (to_do->trace != NULL) ? to_do->trace : ""));
   1239   1.1  christos       sim_events_free (sd, to_do);
   1240   1.1  christos       handler (sd, data);
   1241   1.1  christos     }
   1242   1.1  christos 
   1243   1.1  christos   /* put things back where they belong ready for the next iteration */
   1244   1.1  christos   events->watchpoints = events->watchedpoints;
   1245   1.1  christos   events->watchedpoints = NULL;
   1246   1.1  christos   if (events->watchpoints != NULL)
   1247   1.1  christos     events->work_pending = 1;
   1248   1.1  christos 
   1249   1.1  christos   /* advance the time */
   1250   1.1  christos   SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
   1251   1.1  christos   SIM_ASSERT (events->queue != NULL); /* always poll event */
   1252   1.1  christos   events->time_from_event -= events->nr_ticks_to_process;
   1253   1.1  christos 
   1254   1.1  christos   /* this round of processing complete */
   1255   1.1  christos   events->nr_ticks_to_process = 0;
   1256   1.1  christos }
   1257   1.1  christos 
   1258   1.1  christos #endif
   1259