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