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