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