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