Copyright updates for 2007.
[external/binutils.git] / sim / common / sim-events.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3    Copyright 2002, 2007 Free Software Foundation, Inc.
4
5    Contributed by Andrew Cagney and Red Hat.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330,
22    Boston, MA 02111-1307, USA.  */
23
24
25 #ifndef _SIM_EVENTS_C_
26 #define _SIM_EVENTS_C_
27
28 #include "sim-main.h"
29 #include "sim-assert.h"
30
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #else
34 #ifdef HAVE_STRINGS_H
35 #include <strings.h>
36 #endif
37 #endif
38
39 #ifdef HAVE_STDLIB_H
40 #include <stdlib.h>
41 #endif
42
43 #include <signal.h> /* For SIGPROCMASK et al. */
44
45 typedef enum {
46   watch_invalid,
47
48   /* core - target byte order */
49   watch_core_targ_1,
50   watch_core_targ_2,
51   watch_core_targ_4,
52   watch_core_targ_8,
53   /* core - big-endian */
54   watch_core_be_1,
55   watch_core_be_2,
56   watch_core_be_4,
57   watch_core_be_8,
58   /* core - little-endian */
59   watch_core_le_1,
60   watch_core_le_2,
61   watch_core_le_4,
62   watch_core_le_8,
63
64   /* sim - host byte order */
65   watch_sim_host_1,
66   watch_sim_host_2,
67   watch_sim_host_4,
68   watch_sim_host_8,
69   /* sim - big-endian */
70   watch_sim_be_1,
71   watch_sim_be_2,
72   watch_sim_be_4,
73   watch_sim_be_8,
74   /* sim - little-endian */
75   watch_sim_le_1,
76   watch_sim_le_2,
77   watch_sim_le_4,
78   watch_sim_le_8,
79   
80   /* wallclock */
81   watch_clock,
82
83   /* timer */
84   watch_timer,
85 } sim_event_watchpoints;
86
87
88 struct _sim_event {
89   sim_event_watchpoints watching;
90   void *data;
91   sim_event_handler *handler;
92   /* timer event */
93   signed64 time_of_event;
94   /* watch wallclock event */
95   unsigned wallclock;
96   /* watch core address */
97   address_word core_addr;
98   unsigned core_map;
99   /* watch sim addr */
100   void *host_addr;
101   /* watch core/sim range */
102   int is_within; /* 0/1 */
103   unsigned ub;
104   unsigned lb;
105   unsigned64 ub64;
106   unsigned64 lb64;
107   /* trace info (if any) */
108   char *trace;
109   /* list */
110   sim_event *next;
111 };
112
113
114 /* The event queue maintains a single absolute time using two
115    variables.
116    
117    TIME_OF_EVENT: this holds the time at which the next event is ment
118    to occur.  If no next event it will hold the time of the last
119    event.
120
121    TIME_FROM_EVENT: The current distance from TIME_OF_EVENT.  A value
122    <= 0 (except when poll-event is being processed) indicates that
123    event processing is due.  This variable is decremented once for
124    each iteration of a clock cycle.
125
126    Initially, the clock is started at time one (0) with TIME_OF_EVENT
127    == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1.
128
129    Clearly there is a bug in that this code assumes that the absolute
130    time counter will never become greater than 2^62.
131
132    To avoid the need to use 64bit arithmetic, the event queue always
133    contains at least one event scheduled every 16 000 ticks.  This
134    limits the time from event counter to values less than
135    16 000. */
136
137
138 #if !defined (SIM_EVENTS_POLL_RATE)
139 #define SIM_EVENTS_POLL_RATE 0x1000
140 #endif
141
142
143 #define _ETRACE sd, NULL
144
145 #undef ETRACE_P
146 #define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace)
147
148 #undef ETRACE
149 #define ETRACE(ARGS) \
150 do \
151   { \
152     if (ETRACE_P) \
153       { \
154         if (STRACE_DEBUG_P (sd)) \
155           { \
156             const char *file; \
157             SIM_FILTER_PATH (file, __FILE__); \
158             trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
159           } \
160         trace_printf  ARGS; \
161       } \
162   } \
163 while (0)
164
165
166 /* event queue iterator - don't iterate over the held queue. */
167
168 #if EXTERN_SIM_EVENTS_P
169 static sim_event **
170 next_event_queue (SIM_DESC sd,
171                   sim_event **queue)
172 {
173   if (queue == NULL)
174     return &STATE_EVENTS (sd)->queue;
175   else if (queue == &STATE_EVENTS (sd)->queue)
176     return &STATE_EVENTS (sd)->watchpoints;
177   else if (queue == &STATE_EVENTS (sd)->watchpoints)
178     return &STATE_EVENTS (sd)->watchedpoints;
179   else if (queue == &STATE_EVENTS (sd)->watchedpoints)
180     return NULL;
181   else
182     sim_io_error (sd, "next_event_queue - bad queue");
183   return NULL;
184 }
185 #endif
186
187
188 STATIC_INLINE_SIM_EVENTS\
189 (void)
190 sim_events_poll (SIM_DESC sd,
191                  void *data)
192 {
193   /* just re-schedule in 1000 million ticks time */
194   sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
195   sim_io_poll_quit (sd);
196 }
197
198
199 /* "events" module install handler.
200    This is called via sim_module_install to install the "events" subsystem
201    into the simulator.  */
202
203 #if EXTERN_SIM_EVENTS_P
204 STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
205 STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
206 STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
207 STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
208 #endif
209
210 #if EXTERN_SIM_EVENTS_P
211 SIM_RC
212 sim_events_install (SIM_DESC sd)
213 {
214   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
215   sim_module_add_uninstall_fn (sd, sim_events_uninstall);
216   sim_module_add_init_fn (sd, sim_events_init);
217   sim_module_add_resume_fn (sd, sim_events_resume);
218   sim_module_add_suspend_fn (sd, sim_events_suspend);
219   return SIM_RC_OK;
220 }
221 #endif
222
223
224 /* Suspend/resume the event queue manager when the simulator is not
225    running */
226
227 #if EXTERN_SIM_EVENTS_P
228 static SIM_RC
229 sim_events_resume (SIM_DESC sd)
230 {
231   sim_events *events = STATE_EVENTS (sd);
232   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
233   SIM_ASSERT (events->resume_wallclock == 0);
234   events->resume_wallclock = sim_elapsed_time_get ();
235   return SIM_RC_OK;
236 }
237 #endif
238
239 #if EXTERN_SIM_EVENTS_P
240 static SIM_RC
241 sim_events_suspend (SIM_DESC sd)
242 {
243   sim_events *events = STATE_EVENTS (sd);
244   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
245   SIM_ASSERT (events->resume_wallclock != 0);
246   events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock);
247   events->resume_wallclock = 0;
248   return SIM_RC_OK;
249 }
250 #endif
251
252
253 /* Uninstall the "events" subsystem from the simulator.  */
254
255 #if EXTERN_SIM_EVENTS_P
256 static void
257 sim_events_uninstall (SIM_DESC sd)
258 {
259   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
260   /* FIXME: free buffers, etc. */
261 }
262 #endif
263
264
265 /* malloc/free */
266
267 #if EXTERN_SIM_EVENTS_P
268 static sim_event *
269 sim_events_zalloc (SIM_DESC sd)
270 {
271   sim_events *events = STATE_EVENTS (sd);
272   sim_event *new = events->free_list;
273   if (new != NULL)
274     {
275       events->free_list = new->next;
276       memset (new, 0, sizeof (*new));
277     }
278   else
279     {
280 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
281       /*-LOCK-*/
282       sigset_t old_mask;
283       sigset_t new_mask;
284       sigfillset(&new_mask);
285       sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
286 #endif
287       new = ZALLOC (sim_event);
288 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
289       /*-UNLOCK-*/
290       sigprocmask (SIG_SETMASK, &old_mask, NULL);
291 #endif
292     }
293   return new;
294 }
295 #endif
296
297 STATIC_INLINE_SIM_EVENTS\
298 (void)
299 sim_events_free (SIM_DESC sd,
300                  sim_event *dead)
301 {
302   sim_events *events = STATE_EVENTS (sd);
303   dead->next = events->free_list;
304   events->free_list = dead;
305   if (dead->trace != NULL)
306     {
307       free (dead->trace); /* NB: asprintf returns a `free' buf */
308       dead->trace = NULL;
309     }
310 }
311
312
313 /* Initialize the simulator event manager */
314
315 #if EXTERN_SIM_EVENTS_P
316 SIM_RC
317 sim_events_init (SIM_DESC sd)
318 {
319   sim_events *events = STATE_EVENTS (sd);
320
321   /* drain the interrupt queue */
322   events->nr_held = 0;
323   if (events->held == NULL)
324     events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS);
325
326   /* drain the normal queues */
327   {
328     sim_event **queue = NULL;
329     while ((queue = next_event_queue (sd, queue)) != NULL)
330       {
331         if (queue == NULL) break;
332         while (*queue != NULL)
333           {
334             sim_event *dead = *queue;
335             *queue = dead->next;
336             sim_events_free (sd, dead);
337           }
338         *queue = NULL;
339       }
340   }
341
342   /* wind time back to zero */
343   events->nr_ticks_to_process = 1; /* start by doing queue */
344   events->time_of_event = 0;
345   events->time_from_event = 0;
346   events->elapsed_wallclock = 0;
347   events->resume_wallclock = 0;
348
349   /* schedule our initial counter event */
350   sim_events_schedule (sd, 0, sim_events_poll, sd);
351
352   /* from now on, except when the large-int event is being processed
353      the event queue is non empty */
354   SIM_ASSERT (events->queue != NULL);
355
356   return SIM_RC_OK;
357 }
358 #endif
359
360
361 INLINE_SIM_EVENTS\
362 (signed64)
363 sim_events_time (SIM_DESC sd)
364 {
365   sim_events *events = STATE_EVENTS (sd);
366   return (events->time_of_event - events->time_from_event);
367 }
368
369
370 INLINE_SIM_EVENTS\
371 (unsigned long)
372 sim_events_elapsed_time (SIM_DESC sd)
373 {
374   unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock;
375
376   /* Are we being called inside sim_resume?
377      (Is there a simulation in progress?)  */
378   if (STATE_EVENTS (sd)->resume_wallclock != 0)
379      elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock);
380
381   return elapsed;
382 }
383
384
385 /* Returns the time that remains before the event is raised. */
386 INLINE_SIM_EVENTS\
387 (signed64)
388 sim_events_remain_time (SIM_DESC sd, sim_event *event)
389 {
390   if (event == 0)
391     return 0;
392   
393   return (event->time_of_event - sim_events_time (sd));
394 }
395
396
397
398 STATIC_INLINE_SIM_EVENTS\
399 (void)
400 update_time_from_event (SIM_DESC sd)
401 {
402   sim_events *events = STATE_EVENTS (sd);
403   signed64 current_time = sim_events_time (sd);
404   if (events->queue != NULL)
405     {
406       events->time_of_event = events->queue->time_of_event;
407       events->time_from_event = (events->queue->time_of_event - current_time);
408     }
409   else
410     {
411       events->time_of_event = current_time - 1;
412       events->time_from_event = -1;
413     }
414   if (ETRACE_P)
415     {
416       sim_event *event;
417       int i;
418       for (event = events->queue, i = 0;
419            event != NULL;
420            event = event->next, i++)
421         {
422           ETRACE ((_ETRACE,
423                    "event time-from-event - time %ld, delta %ld - event %d, tag 0x%lx, time %ld, handler 0x%lx, data 0x%lx%s%s\n",
424                    (long)current_time,
425                    (long)events->time_from_event,
426                    i,
427                    (long)event,
428                    (long)event->time_of_event,
429                    (long)event->handler,
430                    (long)event->data,
431                    (event->trace != NULL) ? ", " : "",
432                    (event->trace != NULL) ? event->trace : ""));
433         }
434     }
435   SIM_ASSERT (current_time == sim_events_time (sd));
436 }
437
438
439 #if EXTERN_SIM_EVENTS_P
440 static void
441 insert_sim_event (SIM_DESC sd,
442                   sim_event *new_event,
443                   signed64 delta)
444 {
445   sim_events *events = STATE_EVENTS (sd);
446   sim_event *curr;
447   sim_event **prev;
448   signed64 time_of_event;
449
450   if (delta < 0)
451     sim_io_error (sd, "what is past is past!\n");
452   
453   /* compute when the event should occur */
454   time_of_event = sim_events_time (sd) + delta;
455   
456   /* find the queue insertion point - things are time ordered */
457   prev = &events->queue;
458   curr = events->queue;
459   while (curr != NULL && time_of_event >= curr->time_of_event)
460     {
461       SIM_ASSERT (curr->next == NULL
462                   || curr->time_of_event <= curr->next->time_of_event);
463       prev = &curr->next;
464       curr = curr->next;
465     }
466   SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
467   
468   /* insert it */
469   new_event->next = curr;
470   *prev = new_event;
471   new_event->time_of_event = time_of_event;
472   
473   /* adjust the time until the first event */
474   update_time_from_event (sd);
475 }
476 #endif
477
478
479 #if EXTERN_SIM_EVENTS_P
480 sim_event *
481 sim_events_schedule (SIM_DESC sd,
482                      signed64 delta_time,
483                      sim_event_handler *handler,
484                      void *data)
485 {
486   va_list dummy;
487   memset (&dummy, 0, sizeof dummy);
488   return sim_events_schedule_vtracef (sd, delta_time, handler, data,
489                                       NULL, dummy);
490 }
491 #endif
492
493
494 #if EXTERN_SIM_EVENTS_P
495 sim_event *
496 sim_events_schedule_tracef (SIM_DESC sd,
497                             signed64 delta_time,
498                             sim_event_handler *handler,
499                             void *data,
500                             const char *fmt,
501                             ...)
502 {
503   sim_event *new_event;
504   va_list ap;
505   va_start (ap, fmt);
506   new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
507   va_end (ap);
508   return new_event;
509 }
510 #endif
511
512
513 #if EXTERN_SIM_EVENTS_P
514 sim_event *
515 sim_events_schedule_vtracef (SIM_DESC sd,
516                              signed64 delta_time,
517                              sim_event_handler *handler,
518                              void *data,
519                              const char *fmt,
520                              va_list ap)
521 {
522   sim_event *new_event = sim_events_zalloc (sd);
523   new_event->data = data;
524   new_event->handler = handler;
525   new_event->watching = watch_timer;
526   if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0)
527     new_event->trace = NULL;
528   insert_sim_event(sd, new_event, delta_time);
529   ETRACE((_ETRACE,
530           "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
531           (long)sim_events_time(sd),
532           (long)new_event,
533           (long)new_event->time_of_event,
534           (long)new_event->handler,
535           (long)new_event->data,
536           (new_event->trace != NULL) ? ", " : "",
537           (new_event->trace != NULL) ? new_event->trace : ""));
538   return new_event;
539 }
540 #endif
541
542
543 #if EXTERN_SIM_EVENTS_P
544 void
545 sim_events_schedule_after_signal (SIM_DESC sd,
546                                   signed64 delta_time,
547                                   sim_event_handler *handler,
548                                   void *data)
549 {
550   sim_events *events = STATE_EVENTS (sd);
551   sim_event *new_event;
552 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
553   /*-LOCK-*/
554   sigset_t old_mask;
555   sigset_t new_mask;
556   sigfillset(&new_mask);
557   sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
558 #endif
559   
560   /* allocate an event entry from the signal buffer */
561   new_event = &events->held [events->nr_held];
562   events->nr_held ++;
563   if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
564     {
565       sim_engine_abort (NULL, NULL, NULL_CIA,
566                         "sim_events_schedule_after_signal - buffer oveflow");
567     }
568   
569   new_event->data = data;
570   new_event->handler = handler;
571   new_event->time_of_event = delta_time; /* work it out later */
572   new_event->next = NULL;
573
574   events->work_pending = 1; /* notify main process */
575
576 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
577   /*-UNLOCK-*/
578   sigprocmask (SIG_SETMASK, &old_mask, NULL);
579 #endif
580   
581   ETRACE ((_ETRACE,
582            "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
583            (long)sim_events_time(sd),
584            (long)new_event,
585            (long)new_event->time_of_event,
586            (long)new_event->handler,
587            (long)new_event->data));
588 }
589 #endif
590
591
592 #if EXTERN_SIM_EVENTS_P
593 sim_event *
594 sim_events_watch_clock (SIM_DESC sd,
595                         unsigned delta_ms_time,
596                         sim_event_handler *handler,
597                         void *data)
598 {
599   sim_events *events = STATE_EVENTS (sd);
600   sim_event *new_event = sim_events_zalloc (sd);
601   /* type */
602   new_event->watching = watch_clock;
603   /* handler */
604   new_event->data = data;
605   new_event->handler = handler;
606   /* data */
607   if (events->resume_wallclock == 0)
608     new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
609   else
610     new_event->wallclock = (events->elapsed_wallclock
611                             + sim_elapsed_time_since (events->resume_wallclock)
612                             + delta_ms_time);
613   /* insert */
614   new_event->next = events->watchpoints;
615   events->watchpoints = new_event;
616   events->work_pending = 1;
617   ETRACE ((_ETRACE,
618           "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
619            (long)sim_events_time (sd),
620            (long)new_event,
621            (long)new_event->wallclock,
622            (long)new_event->handler,
623            (long)new_event->data));
624   return new_event;
625 }
626 #endif
627
628
629 #if EXTERN_SIM_EVENTS_P
630 sim_event *
631 sim_events_watch_sim (SIM_DESC sd,
632                       void *host_addr,
633                       int nr_bytes,
634                       int byte_order,
635                       int is_within,
636                       unsigned64 lb,
637                       unsigned64 ub,
638                       sim_event_handler *handler,
639                       void *data)
640 {
641   sim_events *events = STATE_EVENTS (sd);
642   sim_event *new_event = sim_events_zalloc (sd);
643   /* type */
644   switch (byte_order)
645     {
646     case 0:
647       switch (nr_bytes)
648         {
649         case 1: new_event->watching = watch_sim_host_1; break;
650         case 2: new_event->watching = watch_sim_host_2; break;
651         case 4: new_event->watching = watch_sim_host_4; break;
652         case 8: new_event->watching = watch_sim_host_8; break;
653         default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
654         }
655       break;
656     case BIG_ENDIAN:
657       switch (nr_bytes)
658         {
659         case 1: new_event->watching = watch_sim_be_1; break;
660         case 2: new_event->watching = watch_sim_be_2; break;
661         case 4: new_event->watching = watch_sim_be_4; break;
662         case 8: new_event->watching = watch_sim_be_8; break;
663         default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
664         }
665       break;
666     case LITTLE_ENDIAN:
667       switch (nr_bytes)
668         {
669         case 1: new_event->watching = watch_sim_le_1; break;
670         case 2: new_event->watching = watch_sim_le_2; break;
671         case 4: new_event->watching = watch_sim_le_4; break;
672         case 8: new_event->watching = watch_sim_le_8; break;
673         default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
674         }
675       break;
676     default:
677       sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
678     }
679   /* handler */
680   new_event->data = data;
681   new_event->handler = handler;
682   /* data */
683   new_event->host_addr = host_addr;
684   new_event->lb = lb;
685   new_event->lb64 = lb;
686   new_event->ub = ub;
687   new_event->ub64 = ub;
688   new_event->is_within = (is_within != 0);
689   /* insert */
690   new_event->next = events->watchpoints;
691   events->watchpoints = new_event;
692   events->work_pending = 1;
693   ETRACE ((_ETRACE,
694            "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
695            (long)sim_events_time (sd),
696            (long)new_event,
697            (long)new_event->host_addr,
698            (long)new_event->lb,
699            (long)new_event->ub,
700            (long)new_event->handler,
701            (long)new_event->data));
702   return new_event;
703 }
704 #endif
705
706
707 #if EXTERN_SIM_EVENTS_P
708 sim_event *
709 sim_events_watch_core (SIM_DESC sd,
710                        address_word core_addr,
711                        unsigned core_map,
712                        int nr_bytes,
713                        int byte_order,
714                        int is_within,
715                        unsigned64 lb,
716                        unsigned64 ub,
717                        sim_event_handler *handler,
718                        void *data)
719 {
720   sim_events *events = STATE_EVENTS (sd);
721   sim_event *new_event = sim_events_zalloc (sd);
722   /* type */
723   switch (byte_order)
724     {
725     case 0:
726       switch (nr_bytes)
727         {
728         case 1: new_event->watching = watch_core_targ_1; break;
729         case 2: new_event->watching = watch_core_targ_2; break;
730         case 4: new_event->watching = watch_core_targ_4; break;
731         case 8: new_event->watching = watch_core_targ_8; break;
732         default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
733         }
734       break;
735     case BIG_ENDIAN:
736       switch (nr_bytes)
737         {
738         case 1: new_event->watching = watch_core_be_1; break;
739         case 2: new_event->watching = watch_core_be_2; break;
740         case 4: new_event->watching = watch_core_be_4; break;
741         case 8: new_event->watching = watch_core_be_8; break;
742         default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
743         }
744       break;
745     case LITTLE_ENDIAN:
746       switch (nr_bytes)
747         {
748         case 1: new_event->watching = watch_core_le_1; break;
749         case 2: new_event->watching = watch_core_le_2; break;
750         case 4: new_event->watching = watch_core_le_4; break;
751         case 8: new_event->watching = watch_core_le_8; break;
752         default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
753         }
754       break;
755     default:
756       sim_io_error (sd, "sim_events_watch_core - invalid byte order");
757     }
758   /* handler */
759   new_event->data = data;
760   new_event->handler = handler;
761   /* data */
762   new_event->core_addr = core_addr;
763   new_event->core_map = core_map;
764   new_event->lb = lb;
765   new_event->lb64 = lb;
766   new_event->ub = ub;
767   new_event->ub64 = ub;
768   new_event->is_within = (is_within != 0);
769   /* insert */
770   new_event->next = events->watchpoints;
771   events->watchpoints = new_event;
772   events->work_pending = 1;
773   ETRACE ((_ETRACE,
774            "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
775            (long)sim_events_time (sd),
776            (long)new_event,
777            (long)new_event->host_addr,
778            (long)new_event->lb,
779            (long)new_event->ub,
780            (long)new_event->handler,
781            (long)new_event->data));
782   return new_event;
783 }
784 #endif
785
786
787 #if EXTERN_SIM_EVENTS_P
788 void
789 sim_events_deschedule (SIM_DESC sd,
790                        sim_event *event_to_remove)
791 {
792   sim_events *events = STATE_EVENTS (sd);
793   sim_event *to_remove = (sim_event*)event_to_remove;
794   if (event_to_remove != NULL)
795     {
796       sim_event **queue = NULL;
797       while ((queue = next_event_queue (sd, queue)) != NULL)
798         {
799           sim_event **ptr_to_current;
800           for (ptr_to_current = queue;
801                *ptr_to_current != NULL && *ptr_to_current != to_remove;
802                ptr_to_current = &(*ptr_to_current)->next);
803           if (*ptr_to_current == to_remove)
804             {
805               sim_event *dead = *ptr_to_current;
806               *ptr_to_current = dead->next;
807               ETRACE ((_ETRACE,
808                        "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
809                        (long) sim_events_time (sd),
810                        (long) event_to_remove,
811                        (long) dead->time_of_event,
812                        (long) dead->handler,
813                        (long) dead->data,
814                        (dead->trace != NULL) ? ", " : "",
815                        (dead->trace != NULL) ? dead->trace : ""));
816               sim_events_free (sd, dead);
817               update_time_from_event (sd);
818               SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
819               return;
820             }
821         }
822     }
823   ETRACE ((_ETRACE,
824            "event/watch descheduled at %ld - tag 0x%lx - not found\n",
825            (long) sim_events_time (sd),
826            (long) event_to_remove));
827 }
828 #endif
829
830
831 STATIC_INLINE_SIM_EVENTS\
832 (int)
833 sim_watch_valid (SIM_DESC sd,
834                  sim_event *to_do)
835 {
836   switch (to_do->watching)
837     {
838
839 #define WATCH_CORE(N,OP,EXT) \
840       int ok; \
841       unsigned_##N word = 0; \
842       int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
843                                           to_do->core_addr, sizeof (word)); \
844       OP (word); \
845       ok = (nr_read == sizeof (unsigned_##N) \
846             && (to_do->is_within \
847                 == (word >= to_do->lb##EXT \
848                     && word <= to_do->ub##EXT)));
849
850     case watch_core_targ_1:
851       {
852         WATCH_CORE (1, T2H,);
853         return ok;
854       }
855     case watch_core_targ_2:
856       {
857         WATCH_CORE (2, T2H,);
858         return ok;
859       }
860     case watch_core_targ_4:
861       {
862         WATCH_CORE (4, T2H,);
863         return ok;
864       }
865     case watch_core_targ_8:
866       {
867         WATCH_CORE (8, T2H,64);
868         return ok;
869       }
870
871     case watch_core_be_1:
872       {
873         WATCH_CORE (1, BE2H,);
874         return ok;
875       }
876     case watch_core_be_2:
877       {
878         WATCH_CORE (2, BE2H,);
879         return ok;
880       }
881     case watch_core_be_4:
882       {
883         WATCH_CORE (4, BE2H,);
884         return ok;
885       }
886     case watch_core_be_8:
887       {
888         WATCH_CORE (8, BE2H,64);
889         return ok;
890       }
891
892     case watch_core_le_1:
893       {
894         WATCH_CORE (1, LE2H,);
895         return ok;
896       }
897     case watch_core_le_2:
898       {
899         WATCH_CORE (2, LE2H,);
900         return ok;
901       }
902     case watch_core_le_4:
903       {
904         WATCH_CORE (4, LE2H,);
905         return ok;
906       }
907     case watch_core_le_8:
908       {
909         WATCH_CORE (8, LE2H,64);
910         return ok;
911       }
912 #undef WATCH_CORE
913
914 #define WATCH_SIM(N,OP,EXT) \
915       int ok; \
916       unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
917       OP (word); \
918       ok = (to_do->is_within \
919             == (word >= to_do->lb##EXT \
920                 && word <= to_do->ub##EXT));
921
922     case watch_sim_host_1:
923       {
924         WATCH_SIM (1, word = ,);
925         return ok;
926       }
927     case watch_sim_host_2:
928       {
929         WATCH_SIM (2, word = ,);
930         return ok;
931       }
932     case watch_sim_host_4:
933       {
934         WATCH_SIM (4, word = ,);
935         return ok;
936       }
937     case watch_sim_host_8:
938       {
939         WATCH_SIM (8, word = ,64);
940         return ok;
941       }
942
943     case watch_sim_be_1:
944       {
945         WATCH_SIM (1, BE2H,);
946         return ok;
947       }
948     case watch_sim_be_2:
949       {
950         WATCH_SIM (2, BE2H,);
951         return ok;
952       }
953     case watch_sim_be_4:
954       {
955         WATCH_SIM (4, BE2H,);
956         return ok;
957       }
958     case watch_sim_be_8:
959       {
960         WATCH_SIM (8, BE2H,64);
961         return ok;
962       }
963
964     case watch_sim_le_1:
965       {
966         WATCH_SIM (1, LE2H,);
967         return ok;
968       }
969     case watch_sim_le_2:
970       {
971         WATCH_SIM (1, LE2H,);
972         return ok;
973       }
974     case watch_sim_le_4:
975       {
976         WATCH_SIM (1, LE2H,);
977         return ok;
978       }
979     case watch_sim_le_8:
980       {
981         WATCH_SIM (1, LE2H,64);
982         return ok;
983       }
984 #undef WATCH_SIM
985
986     case watch_clock: /* wallclock */
987       {
988         unsigned long elapsed_time = sim_events_elapsed_time (sd);
989         return (elapsed_time >= to_do->wallclock);
990       }
991
992     default:
993       sim_io_error (sd, "sim_watch_valid - bad switch");
994       break;
995
996     }
997   return 1;
998 }
999
1000
1001 INLINE_SIM_EVENTS\
1002 (int)
1003 sim_events_tick (SIM_DESC sd)
1004 {
1005   sim_events *events = STATE_EVENTS (sd);
1006
1007   /* this should only be called after the previous ticks have been
1008      fully processed */
1009
1010   /* Advance the time but *only* if there is nothing to process */
1011   if (events->work_pending
1012       || events->time_from_event == 0)
1013     {
1014       events->nr_ticks_to_process += 1;
1015       return 1;
1016     }
1017   else
1018     {
1019       events->time_from_event -= 1;
1020       return 0;
1021     }
1022 }
1023
1024
1025 INLINE_SIM_EVENTS\
1026 (int)
1027 sim_events_tickn (SIM_DESC sd,
1028                   int n)
1029 {
1030   sim_events *events = STATE_EVENTS (sd);
1031   SIM_ASSERT (n > 0);
1032
1033   /* this should only be called after the previous ticks have been
1034      fully processed */
1035
1036   /* Advance the time but *only* if there is nothing to process */
1037   if (events->work_pending || events->time_from_event < n)
1038     {
1039       events->nr_ticks_to_process += n;
1040       return 1;
1041     }
1042   else
1043     {
1044       events->time_from_event -= n;
1045       return 0;
1046     }
1047 }
1048
1049
1050 INLINE_SIM_EVENTS\
1051 (void)
1052 sim_events_slip (SIM_DESC sd,
1053                  int slip)
1054 {
1055   sim_events *events = STATE_EVENTS (sd);
1056   SIM_ASSERT (slip > 0);
1057
1058   /* Flag a ready event with work_pending instead of number of ticks
1059      to process so that the time continues to be correct */
1060   if (events->time_from_event < slip)
1061     {
1062       events->work_pending = 1;
1063     }
1064   events->time_from_event -= slip;
1065 }
1066
1067
1068 INLINE_SIM_EVENTS\
1069 (void)
1070 sim_events_preprocess (SIM_DESC sd,
1071                        int events_were_last,
1072                        int events_were_next)
1073 {
1074   sim_events *events = STATE_EVENTS(sd);
1075   if (events_were_last)
1076     {
1077       /* Halted part way through event processing */
1078       ASSERT (events->nr_ticks_to_process != 0);
1079       /* The external world can't tell if the event that stopped the
1080          simulator was the last event to process. */
1081       ASSERT (events_were_next);
1082       sim_events_process (sd);
1083     }
1084   else if (events_were_next)
1085     {
1086       /* Halted by the last processor */
1087       if (sim_events_tick (sd))
1088         sim_events_process (sd);
1089     }
1090 }
1091
1092
1093 INLINE_SIM_EVENTS\
1094 (void)
1095 sim_events_process (SIM_DESC sd)
1096 {
1097   sim_events *events = STATE_EVENTS(sd);
1098   signed64 event_time = sim_events_time(sd);
1099
1100   /* Clear work_pending before checking nr_held.  Clearing
1101      work_pending after nr_held (with out a lock could loose an
1102      event). */
1103   events->work_pending = 0;
1104
1105   /* move any events that were asynchronously queued by any signal
1106      handlers onto the real event queue.  */
1107   if (events->nr_held > 0)
1108     {
1109       int i;
1110       
1111 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1112       /*-LOCK-*/
1113       sigset_t old_mask;
1114       sigset_t new_mask;
1115       sigfillset(&new_mask);
1116       sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
1117 #endif
1118
1119       for (i = 0; i < events->nr_held; i++)
1120         {
1121           sim_event *entry = &events->held [i];
1122           sim_events_schedule (sd,
1123                                entry->time_of_event,
1124                                entry->handler,
1125                                entry->data);
1126         }
1127       events->nr_held = 0;
1128       
1129 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1130       /*-UNLOCK-*/
1131       sigprocmask(SIG_SETMASK, &old_mask, NULL);
1132 #endif
1133       
1134     }
1135   
1136   /* Process any watchpoints. Be careful to allow a watchpoint to
1137      appear/disappear under our feet.
1138      To ensure that watchpoints are processed only once per cycle,
1139      they are moved onto a watched queue, this returned to the
1140      watchpoint queue when all queue processing has been
1141      completed. */
1142   while (events->watchpoints != NULL)
1143     {
1144       sim_event *to_do = events->watchpoints;
1145       events->watchpoints = to_do->next;
1146       if (sim_watch_valid (sd, to_do))
1147         {
1148           sim_event_handler *handler = to_do->handler;
1149           void *data = to_do->data;
1150           ETRACE((_ETRACE,
1151                   "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1152                   (long) event_time,
1153                   (long) to_do,
1154                   (long) handler,
1155                   (long) data,
1156                   (to_do->trace != NULL) ? ", " : "",
1157                   (to_do->trace != NULL) ? to_do->trace : ""));
1158           sim_events_free (sd, to_do);
1159           handler (sd, data);
1160         }
1161       else
1162         {
1163           to_do->next = events->watchedpoints;
1164           events->watchedpoints = to_do;
1165         }
1166     }
1167   
1168   /* consume all events for this or earlier times.  Be careful to
1169      allow an event to appear/disappear under our feet */
1170   while (events->queue->time_of_event <
1171          (event_time + events->nr_ticks_to_process))
1172     {
1173       sim_event *to_do = events->queue;
1174       sim_event_handler *handler = to_do->handler;
1175       void *data = to_do->data;
1176       events->queue = to_do->next;
1177       update_time_from_event (sd);
1178       ETRACE((_ETRACE,
1179               "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1180               (long) event_time,
1181               (long) to_do,
1182               (long) handler,
1183               (long) data,
1184               (to_do->trace != NULL) ? ", " : "",
1185               (to_do->trace != NULL) ? to_do->trace : ""));
1186       sim_events_free (sd, to_do);
1187       handler (sd, data);
1188     }
1189   
1190   /* put things back where they belong ready for the next iteration */
1191   events->watchpoints = events->watchedpoints;
1192   events->watchedpoints = NULL;
1193   if (events->watchpoints != NULL)
1194     events->work_pending = 1;
1195   
1196   /* advance the time */
1197   SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1198   SIM_ASSERT (events->queue != NULL); /* always poll event */
1199   events->time_from_event -= events->nr_ticks_to_process;
1200
1201   /* this round of processing complete */
1202   events->nr_ticks_to_process = 0;
1203 }
1204
1205 #endif