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