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