sim: common: migrate to standard uintXX_t types
[binutils-gdb.git] / sim / common / sim-events.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002-2022 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