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