Extend xor-endian and per-cpu support in core module.
[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       { \
680         unsigned_##N word = 0; \
681         int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
682         OP (word); \
683         return (nr_read == sizeof (unsigned_##N) \
684                 && (to_do->is_within \
685                     == (word >= to_do->lb##EXT \
686                         && word <= to_do->ub##EXT))); \
687       }
688     case watch_core_targ_1: WATCH_CORE (1, T2H,);
689     case watch_core_targ_2: WATCH_CORE (2, T2H,);
690     case watch_core_targ_4: WATCH_CORE (4, T2H,);
691     case watch_core_targ_8: WATCH_CORE (8, T2H,64);
692
693     case watch_core_be_1: WATCH_CORE (1, BE2H,);
694     case watch_core_be_2: WATCH_CORE (2, BE2H,);
695     case watch_core_be_4: WATCH_CORE (4, BE2H,);
696     case watch_core_be_8: WATCH_CORE (8, BE2H,64);
697
698     case watch_core_le_1: WATCH_CORE (1, LE2H,);
699     case watch_core_le_2: WATCH_CORE (2, LE2H,);
700     case watch_core_le_4: WATCH_CORE (4, LE2H,);
701     case watch_core_le_8: WATCH_CORE (8, LE2H,64);
702 #undef WATCH_CORE
703
704 #define WATCH_SIM(N,OP,EXT) \
705       { \
706         unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
707         OP (word); \
708         return (to_do->is_within \
709                 == (word >= to_do->lb##EXT \
710                     && word <= to_do->ub##EXT)); \
711       }
712
713     case watch_sim_host_1: WATCH_SIM (1, word = ,);
714     case watch_sim_host_2: WATCH_SIM (2, word = ,);
715     case watch_sim_host_4: WATCH_SIM (4, word = ,);
716     case watch_sim_host_8: WATCH_SIM (8, word = ,64);
717
718     case watch_sim_be_1: WATCH_SIM (1, BE2H,);
719     case watch_sim_be_2: WATCH_SIM (2, BE2H,);
720     case watch_sim_be_4: WATCH_SIM (4, BE2H,);
721     case watch_sim_be_8: WATCH_SIM (8, BE2H,64);
722
723     case watch_sim_le_1: WATCH_SIM (1, LE2H,);
724     case watch_sim_le_2: WATCH_SIM (1, LE2H,);
725     case watch_sim_le_4: WATCH_SIM (1, LE2H,);
726     case watch_sim_le_8: WATCH_SIM (1, LE2H,64);
727 #undef WATCH_SIM
728
729     case watch_clock: /* wallclock */
730       {
731         unsigned long elapsed_time = sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock);
732         return (elapsed_time >= to_do->wallclock);
733       }
734
735     default:
736       sim_io_error (sd, "sim_watch_valid - bad switch");
737       break;
738
739     }
740   return 1;
741 }
742
743
744 INLINE_SIM_EVENTS\
745 (int)
746 sim_events_tick (SIM_DESC sd)
747 {
748   sim_events *events = STATE_EVENTS (sd);
749
750   /* this should only be called after the previous ticks have been
751      fully processed */
752   SIM_ASSERT (events->nr_ticks_to_process == 0);
753
754   /* Advance the time but *only* if there is nothing to process */
755   if (events->work_pending
756       || events->time_from_event == 0)
757     {
758       events->nr_ticks_to_process = 1;
759       return 1;
760     }
761   else {
762     events->time_from_event -= 1;
763     return 0;
764   }
765 }
766
767
768 INLINE_SIM_EVENTS\
769 (int)
770 sim_events_tickn (SIM_DESC sd,
771                   unsigned n)
772 {
773   sim_events *events = STATE_EVENTS (sd);
774
775   /* this should only be called after the previous ticks have been
776      fully processed */
777   SIM_ASSERT (events->nr_ticks_to_process == 0);
778   SIM_ASSERT (n > 0);
779
780   /* Advance the time but *only* if there is nothing to process */
781   if (events->work_pending
782       || events->time_from_event < n)
783     {
784       events->nr_ticks_to_process = n;
785       return 1;
786     }
787   else {
788     events->time_from_event -= n;
789     return 0;
790   }
791 }
792
793
794 INLINE_SIM_EVENTS\
795 (void)
796 sim_events_preprocess (SIM_DESC sd,
797                        int events_were_last,
798                        int events_were_next)
799 {
800   sim_events *events = STATE_EVENTS(sd);
801   if (events->nr_ticks_to_process != 0)
802     {
803       /* Halted midway through event processing */
804       ASSERT (events_were_last && events_were_next);
805       sim_events_process (sd);
806     }
807   else if (events_were_next)
808     {
809       /* Halted by the last processor */
810       ASSERT (events->nr_ticks_to_process == 0 && !events_were_last);
811       if (sim_events_tick (sd))
812         sim_events_process (sd);
813     }
814 }
815
816
817 INLINE_SIM_EVENTS\
818 (void)
819 sim_events_process (SIM_DESC sd)
820 {
821   sim_events *events = STATE_EVENTS(sd);
822   signed64 event_time = sim_events_time(sd);
823
824   ASSERT (events->nr_ticks_to_process != 0);
825
826   /* move any events that were queued by any signal handlers onto
827      the real event queue.  */
828   if (events->nr_held > 0)
829     {
830       int i;
831       
832 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
833       /*-LOCK-*/
834       sigset_t old_mask;
835       sigset_t new_mask;
836       sigfillset(&new_mask);
837       sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
838 #endif
839       
840       for (i = 0; i < events->nr_held; i++)
841         {
842           sim_event *entry = &events->held [i];
843           sim_events_schedule (sd,
844                                entry->time_of_event,
845                                entry->handler,
846                                entry->data);
847         }
848       events->nr_held = 0;
849       
850 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
851       /*-UNLOCK-*/
852       sigprocmask(SIG_SETMASK, &old_mask, NULL);
853 #endif
854       
855     }
856   
857   /* Process any watchpoints. Be careful to allow a watchpoint to
858      appear/disappear under our feet.
859      To ensure that watchpoints are processed only once per cycle,
860      they are moved onto a watched queue, this returned to the
861      watchpoint queue when all queue processing has been
862      completed. */
863   while (events->watchpoints != NULL)
864     {
865       sim_event *to_do = events->watchpoints;
866       events->watchpoints = to_do->next;
867       if (sim_watch_valid (sd, to_do))
868         {
869           sim_event_handler *handler = to_do->handler;
870           void *data = to_do->data;
871           events->queue = to_do->next;
872           ETRACE((_ETRACE,
873                   "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
874                   (long) event_time,
875                   (long) to_do,
876                   (long) handler,
877                   (long) data));
878           sim_events_free (sd, to_do);
879           handler (sd, data);
880         }
881       else
882         {
883           to_do->next = events->watchedpoints;
884           events->watchedpoints = to_do;
885         }
886     }
887   
888   /* consume all events for this or earlier times.  Be careful to
889      allow an event to appear/disappear under our feet */
890   while (events->queue->time_of_event <
891          (event_time + events->nr_ticks_to_process))
892     {
893       sim_event *to_do = events->queue;
894       sim_event_handler *handler = to_do->handler;
895       void *data = to_do->data;
896       events->queue = to_do->next;
897       ETRACE((_ETRACE,
898               "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
899               (long) event_time,
900               (long) to_do,
901               (long) handler,
902               (long) data));
903       sim_events_free (sd, to_do);
904       handler (sd, data);
905     }
906   
907   /* put things back where they belong ready for the next iteration */
908   events->watchpoints = events->watchedpoints;
909   events->watchedpoints = NULL;
910   if (events->watchpoints != NULL)
911     events->work_pending = 1;
912   
913   /* re-caculate time for new events then advance the time */
914   update_time_from_event(sd);
915   SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
916   SIM_ASSERT (events->queue != NULL); /* always poll event */
917   events->time_from_event -= events->nr_ticks_to_process;
918
919   /* this round of processing complete */
920   events->nr_ticks_to_process = 0;
921 }
922
923 #endif