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