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