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