Add function sim_events_slip()
[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 0x1000
133 #endif
134
135
136 #define _ETRACE sd, NULL
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             trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
149             trace_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 INLINE_SIM_EVENTS\
347 (unsigned long)
348 sim_events_elapsed_time (SIM_DESC sd)
349 {
350   return (sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock)
351           + STATE_EVENTS (sd)->elapsed_wallclock);
352 }
353
354
355 STATIC_INLINE_SIM_EVENTS\
356 (void)
357 update_time_from_event (SIM_DESC sd)
358 {
359   sim_events *events = STATE_EVENTS (sd);
360   signed64 current_time = sim_events_time (sd);
361   if (events->queue != NULL)
362     {
363       events->time_from_event = (events->queue->time_of_event - current_time);
364       events->time_of_event = events->queue->time_of_event;
365     }
366   else
367     {
368       events->time_of_event = current_time - 1;
369       events->time_from_event = -1;
370     }
371   SIM_ASSERT (current_time == sim_events_time (sd));
372   SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
373 }
374
375
376 STATIC_INLINE_SIM_EVENTS\
377 (void)
378 insert_sim_event (SIM_DESC sd,
379                   sim_event *new_event,
380                   signed64 delta)
381 {
382   sim_events *events = STATE_EVENTS (sd);
383   sim_event *curr;
384   sim_event **prev;
385   signed64 time_of_event;
386
387   if (delta < 0)
388     sim_io_error (sd, "what is past is past!\n");
389   
390   /* compute when the event should occure */
391   time_of_event = sim_events_time (sd) + delta;
392   
393   /* find the queue insertion point - things are time ordered */
394   prev = &events->queue;
395   curr = events->queue;
396   while (curr != NULL && time_of_event >= curr->time_of_event)
397     {
398       SIM_ASSERT (curr->next == NULL
399                   || curr->time_of_event <= curr->next->time_of_event);
400       prev = &curr->next;
401       curr = curr->next;
402     }
403   SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
404   
405   /* insert it */
406   new_event->next = curr;
407   *prev = new_event;
408   new_event->time_of_event = time_of_event;
409   
410   /* adjust the time until the first event */
411   update_time_from_event (sd);
412 }
413
414
415 EXTERN_SIM_EVENTS\
416 (sim_event *)
417 sim_events_schedule (SIM_DESC sd,
418                      signed64 delta_time,
419                      sim_event_handler *handler,
420                      void *data)
421 {
422   sim_event *new_event = sim_events_zalloc (sd);
423   new_event->data = data;
424   new_event->handler = handler;
425   new_event->watching = watch_timer;
426   insert_sim_event(sd, new_event, delta_time);
427   ETRACE((_ETRACE,
428           "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
429           (long)sim_events_time(sd),
430           (long)new_event,
431           (long)new_event->time_of_event,
432           (long)new_event->handler,
433           (long)new_event->data));
434   return new_event;
435 }
436
437
438 EXTERN_SIM_EVENTS\
439 (void)
440 sim_events_schedule_after_signal (SIM_DESC sd,
441                                   signed64 delta_time,
442                                   sim_event_handler *handler,
443                                   void *data)
444 {
445   sim_events *events = STATE_EVENTS (sd);
446   sim_event *new_event;
447 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
448   /*-LOCK-*/
449   sigset_t old_mask;
450   sigset_t new_mask;
451   sigfillset(&new_mask);
452   sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
453 #endif
454   
455   /* allocate an event entry from the signal buffer */
456   new_event = &events->held [events->nr_held];
457   events->nr_held ++;
458   if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
459     {
460       sim_engine_abort (NULL, NULL, NULL_CIA,
461                         "sim_events_schedule_after_signal - buffer oveflow");
462     }
463   
464   new_event->data = data;
465   new_event->handler = handler;
466   new_event->time_of_event = delta_time; /* work it out later */
467   new_event->next = NULL;
468
469   events->work_pending = 1; /* notify main process */
470
471 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
472   /*-UNLOCK-*/
473   sigprocmask (SIG_SETMASK, &old_mask, NULL);
474 #endif
475   
476   ETRACE ((_ETRACE,
477            "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
478            (long)sim_events_time(sd),
479            (long)new_event,
480            (long)new_event->time_of_event,
481            (long)new_event->handler,
482            (long)new_event->data));
483 }
484
485
486 EXTERN_SIM_EVENTS\
487 (sim_event *)
488 sim_events_watch_clock (SIM_DESC sd,
489                         unsigned delta_ms_time,
490                         sim_event_handler *handler,
491                         void *data)
492 {
493   sim_events *events = STATE_EVENTS (sd);
494   sim_event *new_event = sim_events_zalloc (sd);
495   /* type */
496   new_event->watching = watch_clock;
497   /* handler */
498   new_event->data = data;
499   new_event->handler = handler;
500   /* data */
501   if (events->resume_wallclock == 0)
502     new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
503   else
504     new_event->wallclock = (events->elapsed_wallclock
505                             + sim_elapsed_time_since (events->resume_wallclock)
506                             + delta_ms_time);
507   /* insert */
508   new_event->next = events->watchpoints;
509   events->watchpoints = new_event;
510   events->work_pending = 1;
511   ETRACE ((_ETRACE,
512           "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
513            (long)sim_events_time (sd),
514            (long)new_event,
515            (long)new_event->wallclock,
516            (long)new_event->handler,
517            (long)new_event->data));
518   return new_event;
519 }
520
521
522 EXTERN_SIM_EVENTS\
523 (sim_event *)
524 sim_events_watch_sim (SIM_DESC sd,
525                       void *host_addr,
526                       int nr_bytes,
527                       int byte_order,
528                       int is_within,
529                       unsigned64 lb,
530                       unsigned64 ub,
531                       sim_event_handler *handler,
532                       void *data)
533 {
534   sim_events *events = STATE_EVENTS (sd);
535   sim_event *new_event = sim_events_zalloc (sd);
536   /* type */
537   switch (byte_order)
538     {
539     case 0:
540       switch (nr_bytes)
541         {
542         case 1: new_event->watching = watch_sim_host_1; break;
543         case 2: new_event->watching = watch_sim_host_2; break;
544         case 4: new_event->watching = watch_sim_host_4; break;
545         case 8: new_event->watching = watch_sim_host_8; break;
546         default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
547         }
548       break;
549     case BIG_ENDIAN:
550       switch (nr_bytes)
551         {
552         case 1: new_event->watching = watch_sim_be_1; break;
553         case 2: new_event->watching = watch_sim_be_2; break;
554         case 4: new_event->watching = watch_sim_be_4; break;
555         case 8: new_event->watching = watch_sim_be_8; break;
556         default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
557         }
558       break;
559     case LITTLE_ENDIAN:
560       switch (nr_bytes)
561         {
562         case 1: new_event->watching = watch_sim_le_1; break;
563         case 2: new_event->watching = watch_sim_le_2; break;
564         case 4: new_event->watching = watch_sim_le_4; break;
565         case 8: new_event->watching = watch_sim_le_8; break;
566         default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
567         }
568       break;
569     default:
570       sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
571     }
572   /* handler */
573   new_event->data = data;
574   new_event->handler = handler;
575   /* data */
576   new_event->host_addr = host_addr;
577   new_event->lb = lb;
578   new_event->lb64 = lb;
579   new_event->ub = ub;
580   new_event->ub64 = ub;
581   new_event->is_within = (is_within != 0);
582   /* insert */
583   new_event->next = events->watchpoints;
584   events->watchpoints = new_event;
585   events->work_pending = 1;
586   ETRACE ((_ETRACE,
587            "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
588            (long)sim_events_time (sd),
589            (long)new_event,
590            (long)new_event->host_addr,
591            (long)new_event->lb,
592            (long)new_event->ub,
593            (long)new_event->handler,
594            (long)new_event->data));
595   return new_event;
596 }
597
598
599 EXTERN_SIM_EVENTS\
600 (sim_event *)
601 sim_events_watch_core (SIM_DESC sd,
602                        address_word core_addr,
603                        sim_core_maps core_map,
604                        int nr_bytes,
605                        int byte_order,
606                        int is_within,
607                        unsigned64 lb,
608                        unsigned64 ub,
609                        sim_event_handler *handler,
610                        void *data)
611 {
612   sim_events *events = STATE_EVENTS (sd);
613   sim_event *new_event = sim_events_zalloc (sd);
614   /* type */
615   switch (byte_order)
616     {
617     case 0:
618       switch (nr_bytes)
619         {
620         case 1: new_event->watching = watch_core_targ_1; break;
621         case 2: new_event->watching = watch_core_targ_2; break;
622         case 4: new_event->watching = watch_core_targ_4; break;
623         case 8: new_event->watching = watch_core_targ_8; break;
624         default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
625         }
626       break;
627     case BIG_ENDIAN:
628       switch (nr_bytes)
629         {
630         case 1: new_event->watching = watch_core_be_1; break;
631         case 2: new_event->watching = watch_core_be_2; break;
632         case 4: new_event->watching = watch_core_be_4; break;
633         case 8: new_event->watching = watch_core_be_8; break;
634         default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
635         }
636       break;
637     case LITTLE_ENDIAN:
638       switch (nr_bytes)
639         {
640         case 1: new_event->watching = watch_core_le_1; break;
641         case 2: new_event->watching = watch_core_le_2; break;
642         case 4: new_event->watching = watch_core_le_4; break;
643         case 8: new_event->watching = watch_core_le_8; break;
644         default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
645         }
646       break;
647     default:
648       sim_io_error (sd, "sim_events_watch_core - invalid byte order");
649     }
650   /* handler */
651   new_event->data = data;
652   new_event->handler = handler;
653   /* data */
654   new_event->core_addr = core_addr;
655   new_event->core_map = core_map;
656   new_event->lb = lb;
657   new_event->lb64 = lb;
658   new_event->ub = ub;
659   new_event->ub64 = ub;
660   new_event->is_within = (is_within != 0);
661   /* insert */
662   new_event->next = events->watchpoints;
663   events->watchpoints = new_event;
664   events->work_pending = 1;
665   ETRACE ((_ETRACE,
666            "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
667            (long)sim_events_time (sd),
668            (long)new_event,
669            (long)new_event->host_addr,
670            (long)new_event->lb,
671            (long)new_event->ub,
672            (long)new_event->handler,
673            (long)new_event->data));
674   return new_event;
675 }
676
677
678 EXTERN_SIM_EVENTS\
679 (void)
680 sim_events_deschedule (SIM_DESC sd,
681                        sim_event *event_to_remove)
682 {
683   sim_events *events = STATE_EVENTS (sd);
684   sim_event *to_remove = (sim_event*)event_to_remove;
685   SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
686   if (event_to_remove != NULL)
687     {
688       sim_event **queue = NULL;
689       while ((queue = next_event_queue (sd, queue)) != NULL)
690         {
691           sim_event **ptr_to_current;
692           for (ptr_to_current = queue;
693                *ptr_to_current != NULL && *ptr_to_current != to_remove;
694                ptr_to_current = &(*ptr_to_current)->next);
695           if (*ptr_to_current == to_remove)
696             {
697               sim_event *dead = *ptr_to_current;
698               *ptr_to_current = dead->next;
699               ETRACE ((_ETRACE,
700                        "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
701                        (long) sim_events_time (sd),
702                        (long) event_to_remove,
703                        (long) dead->time_of_event,
704                        (long) dead->handler,
705                        (long) dead->data));
706               sim_events_free (sd, dead);
707               update_time_from_event (sd);
708               SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
709               return;
710             }
711         }
712     }
713   ETRACE ((_ETRACE,
714            "event/watch descheduled at %ld - tag 0x%lx - not found\n",
715            (long) sim_events_time (sd),
716            (long) event_to_remove));
717 }
718
719
720 STATIC_INLINE_SIM_EVENTS\
721 (int)
722 sim_watch_valid (SIM_DESC sd,
723                  sim_event *to_do)
724 {
725   switch (to_do->watching)
726     {
727
728 #define WATCH_CORE(N,OP,EXT) \
729       int ok; \
730       unsigned_##N word = 0; \
731       int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
732                                           to_do->core_addr, sizeof (word)); \
733       OP (word); \
734       ok = (nr_read == sizeof (unsigned_##N) \
735             && (to_do->is_within \
736                 == (word >= to_do->lb##EXT \
737                     && word <= to_do->ub##EXT)));
738
739     case watch_core_targ_1:
740       {
741         WATCH_CORE (1, T2H,);
742         return ok;
743       }
744     case watch_core_targ_2:
745       {
746         WATCH_CORE (2, T2H,);
747         return ok;
748       }
749     case watch_core_targ_4:
750       {
751         WATCH_CORE (4, T2H,);
752         return ok;
753       }
754     case watch_core_targ_8:
755       {
756         WATCH_CORE (8, T2H,64);
757         return ok;
758       }
759
760     case watch_core_be_1:
761       {
762         WATCH_CORE (1, BE2H,);
763         return ok;
764       }
765     case watch_core_be_2:
766       {
767         WATCH_CORE (2, BE2H,);
768         return ok;
769       }
770     case watch_core_be_4:
771       {
772         WATCH_CORE (4, BE2H,);
773         return ok;
774       }
775     case watch_core_be_8:
776       {
777         WATCH_CORE (8, BE2H,64);
778         return ok;
779       }
780
781     case watch_core_le_1:
782       {
783         WATCH_CORE (1, LE2H,);
784         return ok;
785       }
786     case watch_core_le_2:
787       {
788         WATCH_CORE (2, LE2H,);
789         return ok;
790       }
791     case watch_core_le_4:
792       {
793         WATCH_CORE (4, LE2H,);
794         return ok;
795       }
796     case watch_core_le_8:
797       {
798         WATCH_CORE (8, LE2H,64);
799         return ok;
800       }
801 #undef WATCH_CORE
802
803 #define WATCH_SIM(N,OP,EXT) \
804       int ok; \
805       unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
806       OP (word); \
807       ok = (to_do->is_within \
808             == (word >= to_do->lb##EXT \
809                 && word <= to_do->ub##EXT));
810
811     case watch_sim_host_1:
812       {
813         WATCH_SIM (1, word = ,);
814         return ok;
815       }
816     case watch_sim_host_2:
817       {
818         WATCH_SIM (2, word = ,);
819         return ok;
820       }
821     case watch_sim_host_4:
822       {
823         WATCH_SIM (4, word = ,);
824         return ok;
825       }
826     case watch_sim_host_8:
827       {
828         WATCH_SIM (8, word = ,64);
829         return ok;
830       }
831
832     case watch_sim_be_1:
833       {
834         WATCH_SIM (1, BE2H,);
835         return ok;
836       }
837     case watch_sim_be_2:
838       {
839         WATCH_SIM (2, BE2H,);
840         return ok;
841       }
842     case watch_sim_be_4:
843       {
844         WATCH_SIM (4, BE2H,);
845         return ok;
846       }
847     case watch_sim_be_8:
848       {
849         WATCH_SIM (8, BE2H,64);
850         return ok;
851       }
852
853     case watch_sim_le_1:
854       {
855         WATCH_SIM (1, LE2H,);
856         return ok;
857       }
858     case watch_sim_le_2:
859       {
860         WATCH_SIM (1, LE2H,);
861         return ok;
862       }
863     case watch_sim_le_4:
864       {
865         WATCH_SIM (1, LE2H,);
866         return ok;
867       }
868     case watch_sim_le_8:
869       {
870         WATCH_SIM (1, LE2H,64);
871         return ok;
872       }
873 #undef WATCH_SIM
874
875     case watch_clock: /* wallclock */
876       {
877         unsigned long elapsed_time = sim_events_elapsed_time (sd);
878         return (elapsed_time >= to_do->wallclock);
879       }
880
881     default:
882       sim_io_error (sd, "sim_watch_valid - bad switch");
883       break;
884
885     }
886   return 1;
887 }
888
889
890 INLINE_SIM_EVENTS\
891 (int)
892 sim_events_tick (SIM_DESC sd)
893 {
894   sim_events *events = STATE_EVENTS (sd);
895   SIM_ASSERT (events->nr_ticks_to_process == 0);
896
897   /* this should only be called after the previous ticks have been
898      fully processed */
899
900   /* Advance the time but *only* if there is nothing to process */
901   if (events->work_pending
902       || events->time_from_event == 0)
903     {
904       events->nr_ticks_to_process += 1;
905       return 1;
906     }
907   else {
908     events->time_from_event -= 1;
909     return 0;
910   }
911 }
912
913
914 INLINE_SIM_EVENTS\
915 (int)
916 sim_events_tickn (SIM_DESC sd,
917                   int n)
918 {
919   sim_events *events = STATE_EVENTS (sd);
920   SIM_ASSERT (n > 0);
921
922   /* this should only be called after the previous ticks have been
923      fully processed */
924
925   /* Advance the time but *only* if there is nothing to process */
926   if (events->work_pending
927       || events->time_from_event < n)
928     {
929       events->nr_ticks_to_process += n;
930       return 1;
931     }
932   else {
933     events->time_from_event -= n;
934     return 0;
935   }
936 }
937
938
939 INLINE_SIM_EVENTS\
940 (void)
941 sim_events_slip (SIM_DESC sd,
942                  int slip)
943 {
944   sim_events *events = STATE_EVENTS (sd);
945   SIM_ASSERT (slip > 0);
946
947   /* Advance either TIME_FROM_EVENT or NR_TICKS_TO_PROCESS dependant
948      on which is closer for this SLIP.  While previous slips may have
949      advanced a different counter is sitll valid as the accumulative
950      effect is still the same. */
951   if (events->time_from_event < slip)
952     {
953       events->nr_ticks_to_process += slip;
954       events->work_pending = 1;
955     }
956   else 
957     {
958       events->time_from_event -= slip;
959     }
960 }
961
962
963 INLINE_SIM_EVENTS\
964 (void)
965 sim_events_preprocess (SIM_DESC sd,
966                        int events_were_last,
967                        int events_were_next)
968 {
969   sim_events *events = STATE_EVENTS(sd);
970   if (events_were_last)
971     {
972       /* Halted part way through event processing */
973       ASSERT (events->nr_ticks_to_process != 0);
974       /* The external world can't tell if the event that stopped the
975          simulator was the last event to process. */
976       ASSERT (events_were_next);
977       sim_events_process (sd);
978     }
979   else if (events_were_next)
980     {
981       /* Halted by the last processor */
982       if (sim_events_tick (sd))
983         sim_events_process (sd);
984     }
985 }
986
987
988 INLINE_SIM_EVENTS\
989 (void)
990 sim_events_process (SIM_DESC sd)
991 {
992   sim_events *events = STATE_EVENTS(sd);
993   signed64 event_time = sim_events_time(sd);
994
995   ASSERT (events->nr_ticks_to_process != 0);
996
997   /* Clear work_pending before checking nr_held.  Clearing
998      work_pending after nr_held (with out a lock could loose an
999      event). */
1000   events->work_pending = 0;
1001
1002   /* move any events that were asynchronously queued by any signal
1003      handlers onto the real event queue.  */
1004   if (events->nr_held > 0)
1005     {
1006       int i;
1007       
1008 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1009       /*-LOCK-*/
1010       sigset_t old_mask;
1011       sigset_t new_mask;
1012       sigfillset(&new_mask);
1013       sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
1014 #endif
1015
1016       for (i = 0; i < events->nr_held; i++)
1017         {
1018           sim_event *entry = &events->held [i];
1019           sim_events_schedule (sd,
1020                                entry->time_of_event,
1021                                entry->handler,
1022                                entry->data);
1023         }
1024       events->nr_held = 0;
1025       
1026 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1027       /*-UNLOCK-*/
1028       sigprocmask(SIG_SETMASK, &old_mask, NULL);
1029 #endif
1030       
1031     }
1032   
1033   /* Process any watchpoints. Be careful to allow a watchpoint to
1034      appear/disappear under our feet.
1035      To ensure that watchpoints are processed only once per cycle,
1036      they are moved onto a watched queue, this returned to the
1037      watchpoint queue when all queue processing has been
1038      completed. */
1039   while (events->watchpoints != NULL)
1040     {
1041       sim_event *to_do = events->watchpoints;
1042       events->watchpoints = to_do->next;
1043       if (sim_watch_valid (sd, to_do))
1044         {
1045           sim_event_handler *handler = to_do->handler;
1046           void *data = to_do->data;
1047           ETRACE((_ETRACE,
1048                   "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
1049                   (long) event_time,
1050                   (long) to_do,
1051                   (long) handler,
1052                   (long) data));
1053           sim_events_free (sd, to_do);
1054           handler (sd, data);
1055         }
1056       else
1057         {
1058           to_do->next = events->watchedpoints;
1059           events->watchedpoints = to_do;
1060         }
1061     }
1062   
1063   /* consume all events for this or earlier times.  Be careful to
1064      allow an event to appear/disappear under our feet */
1065   while (events->queue->time_of_event <
1066          (event_time + events->nr_ticks_to_process))
1067     {
1068       sim_event *to_do = events->queue;
1069       sim_event_handler *handler = to_do->handler;
1070       void *data = to_do->data;
1071       events->queue = to_do->next;
1072       ETRACE((_ETRACE,
1073               "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
1074               (long) event_time,
1075               (long) to_do,
1076               (long) handler,
1077               (long) data));
1078       sim_events_free (sd, to_do);
1079       handler (sd, data);
1080     }
1081   
1082   /* put things back where they belong ready for the next iteration */
1083   events->watchpoints = events->watchedpoints;
1084   events->watchedpoints = NULL;
1085   if (events->watchpoints != NULL)
1086     events->work_pending = 1;
1087   
1088   /* re-caculate time for new events then advance the time */
1089   update_time_from_event(sd);
1090   SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1091   SIM_ASSERT (events->queue != NULL); /* always poll event */
1092   events->time_from_event -= events->nr_ticks_to_process;
1093
1094   /* this round of processing complete */
1095   events->nr_ticks_to_process = 0;
1096 }
1097
1098 #endif