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