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