]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/sim-events.c
Fix compile time error introduced by d774bf9b3623239a1cfa729afcf048a15da657d3 for...
[thirdparty/binutils-gdb.git] / sim / common / sim-events.c
CommitLineData
b85e4829
AC
1/* The common simulator framework for GDB, the GNU Debugger.
2
1d506c26 3 Copyright 2002-2024 Free Software Foundation, Inc.
b85e4829
AC
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
4744ac1b 11 the Free Software Foundation; either version 3 of the License, or
b85e4829
AC
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
4744ac1b 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22
23#ifndef _SIM_EVENTS_C_
24#define _SIM_EVENTS_C_
25
6df01ab8
MF
26/* This must come before any other includes. */
27#include "defs.h"
28
20a8e078 29#include <signal.h> /* For SIGPROCMASK et al. */
2c29882f 30#include <stdarg.h>
20a8e078
MF
31#include <stdlib.h>
32#include <string.h>
33
34#include "libiberty.h"
35
c906108c
SS
36#include "sim-main.h"
37#include "sim-assert.h"
4c0d76b9 38#include "sim-cpu.h"
c906108c 39
c906108c
SS
40typedef 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,
028f6515 74
4c0d76b9
MF
75 /* pc */
76 watch_pc,
77
c906108c
SS
78 /* wallclock */
79 watch_clock,
80
81 /* timer */
82 watch_timer,
83} sim_event_watchpoints;
84
85
86struct _sim_event {
87 sim_event_watchpoints watching;
88 void *data;
89 sim_event_handler *handler;
90 /* timer event */
e4c803f5 91 int64_t time_of_event;
c906108c
SS
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;
e4c803f5
MF
103 uint64_t ub64;
104 uint64_t lb64;
c906108c
SS
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.
028f6515 114
c906108c 115 TIME_OF_EVENT: this holds the time at which the next event is ment
6439295f 116 to occur. If no next event it will hold the time of the last
c906108c
SS
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
c906108c
SS
143#undef ETRACE
144#define ETRACE(ARGS) \
145do \
146 { \
83034798 147 if (STRACE_EVENTS_P (sd)) \
c906108c
SS
148 { \
149 if (STRACE_DEBUG_P (sd)) \
e7505490 150 trace_printf (sd, NULL, "%s:%d: ", lbasename (__FILE__), __LINE__); \
c906108c
SS
151 trace_printf ARGS; \
152 } \
153 } \
154while (0)
155
156
157/* event queue iterator - don't iterate over the held queue. */
158
159#if EXTERN_SIM_EVENTS_P
160static sim_event **
161next_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
179STATIC_INLINE_SIM_EVENTS\
180(void)
181sim_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
195STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
196STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
197STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
198STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
199#endif
200
201#if EXTERN_SIM_EVENTS_P
202SIM_RC
203sim_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
219static SIM_RC
220sim_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
231static SIM_RC
232sim_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
247static void
248sim_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
259static sim_event *
260sim_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;
34b47c38 275 sigfillset (&new_mask);
c906108c
SS
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
288STATIC_INLINE_SIM_EVENTS\
289(void)
290sim_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
307SIM_RC
308sim_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
352INLINE_SIM_EVENTS\
e4c803f5 353(int64_t)
c906108c
SS
354sim_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
361INLINE_SIM_EVENTS\
362(unsigned long)
363sim_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
38e64f35
AC
376/* Returns the time that remains before the event is raised. */
377INLINE_SIM_EVENTS\
e4c803f5 378(int64_t)
38e64f35
AC
379sim_events_remain_time (SIM_DESC sd, sim_event *event)
380{
381 if (event == 0)
382 return 0;
028f6515 383
38e64f35
AC
384 return (event->time_of_event - sim_events_time (sd));
385}
386
387
388
c906108c
SS
389STATIC_INLINE_SIM_EVENTS\
390(void)
391update_time_from_event (SIM_DESC sd)
392{
393 sim_events *events = STATE_EVENTS (sd);
e4c803f5 394 int64_t current_time = sim_events_time (sd);
c906108c
SS
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 }
83034798 405 if (STRACE_EVENTS_P (sd))
5eb1a8fa
AC
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,
c704d6e7
MF
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,
5eb1a8fa 420 i,
c704d6e7
MF
421 event,
422 event->time_of_event,
423 event->handler,
424 event->data,
5eb1a8fa
AC
425 (event->trace != NULL) ? ", " : "",
426 (event->trace != NULL) ? event->trace : ""));
427 }
428 }
c906108c
SS
429 SIM_ASSERT (current_time == sim_events_time (sd));
430}
431
432
433#if EXTERN_SIM_EVENTS_P
434static void
435insert_sim_event (SIM_DESC sd,
436 sim_event *new_event,
e4c803f5 437 int64_t delta)
c906108c
SS
438{
439 sim_events *events = STATE_EVENTS (sd);
440 sim_event *curr;
441 sim_event **prev;
e4c803f5 442 int64_t time_of_event;
c906108c
SS
443
444 if (delta < 0)
445 sim_io_error (sd, "what is past is past!\n");
028f6515 446
6439295f 447 /* compute when the event should occur */
c906108c 448 time_of_event = sim_events_time (sd) + delta;
028f6515 449
c906108c
SS
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);
028f6515 461
c906108c
SS
462 /* insert it */
463 new_event->next = curr;
464 *prev = new_event;
465 new_event->time_of_event = time_of_event;
028f6515 466
c906108c
SS
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
474sim_event *
475sim_events_schedule (SIM_DESC sd,
e4c803f5 476 int64_t delta_time,
c906108c
SS
477 sim_event_handler *handler,
478 void *data)
479{
dbc0e7ce 480 return sim_events_schedule_tracef (sd, delta_time, handler, data, NULL);
c906108c
SS
481}
482#endif
483
484
485#if EXTERN_SIM_EVENTS_P
486sim_event *
487sim_events_schedule_tracef (SIM_DESC sd,
e4c803f5 488 int64_t delta_time,
c906108c
SS
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
505sim_event *
506sim_events_schedule_vtracef (SIM_DESC sd,
e4c803f5 507 int64_t delta_time,
c906108c
SS
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;
83034798 517 if (fmt == NULL || !STRACE_EVENTS_P (sd) || vasprintf (&new_event->trace, fmt, ap) < 0)
c906108c 518 new_event->trace = NULL;
34b47c38
MF
519 insert_sim_event (sd, new_event, delta_time);
520 ETRACE ((_ETRACE,
c704d6e7
MF
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,
34b47c38
MF
528 (new_event->trace != NULL) ? ", " : "",
529 (new_event->trace != NULL) ? new_event->trace : ""));
c906108c
SS
530 return new_event;
531}
532#endif
533
534
535#if EXTERN_SIM_EVENTS_P
536void
537sim_events_schedule_after_signal (SIM_DESC sd,
e4c803f5 538 int64_t delta_time,
c906108c
SS
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;
34b47c38 548 sigfillset (&new_mask);
c906108c
SS
549 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
550#endif
028f6515 551
c906108c
SS
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,
509c2f32 558 "sim_events_schedule_after_signal - buffer overflow");
c906108c 559 }
028f6515 560
c906108c
SS
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
028f6515 572
c906108c 573 ETRACE ((_ETRACE,
c704d6e7
MF
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));
c906108c
SS
581}
582#endif
583
584
585#if EXTERN_SIM_EVENTS_P
586sim_event *
587sim_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,
c704d6e7
MF
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));
c906108c
SS
618 return new_event;
619}
620#endif
621
622
4c0d76b9
MF
623#if EXTERN_SIM_EVENTS_P
624sim_event *
625sim_events_watch_pc (SIM_DESC sd,
c704d6e7 626 int is_within,
e4c803f5
MF
627 uint64_t lb,
628 uint64_t ub,
c704d6e7
MF
629 sim_event_handler *handler,
630 void *data)
4c0d76b9
MF
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,
c704d6e7
MF
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));
4c0d76b9
MF
658 return new_event;
659}
660#endif
661
662
c906108c
SS
663#if EXTERN_SIM_EVENTS_P
664sim_event *
665sim_events_watch_sim (SIM_DESC sd,
666 void *host_addr,
667 int nr_bytes,
62fe7512 668 enum bfd_endian byte_order,
c906108c 669 int is_within,
e4c803f5
MF
670 uint64_t lb,
671 uint64_t ub,
c906108c
SS
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 {
1ac72f06 680 case BFD_ENDIAN_UNKNOWN:
c906108c
SS
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;
1ac72f06 690 case BFD_ENDIAN_BIG:
c906108c
SS
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;
1ac72f06 700 case BFD_ENDIAN_LITTLE:
c906108c
SS
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,
c704d6e7
MF
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));
c906108c
SS
737 return new_event;
738}
739#endif
740
741
742#if EXTERN_SIM_EVENTS_P
743sim_event *
744sim_events_watch_core (SIM_DESC sd,
745 address_word core_addr,
746 unsigned core_map,
747 int nr_bytes,
62fe7512 748 enum bfd_endian byte_order,
c906108c 749 int is_within,
e4c803f5
MF
750 uint64_t lb,
751 uint64_t ub,
c906108c
SS
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 {
1ac72f06 760 case BFD_ENDIAN_UNKNOWN:
c906108c
SS
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;
1ac72f06 770 case BFD_ENDIAN_BIG:
c906108c
SS
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;
1ac72f06 780 case BFD_ENDIAN_LITTLE:
c906108c
SS
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,
c704d6e7
MF
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));
c906108c
SS
818 return new_event;
819}
820#endif
821
822
823#if EXTERN_SIM_EVENTS_P
824void
825sim_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,
c704d6e7
MF
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,
c906108c
SS
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,
c704d6e7
MF
861 "event/watch descheduled at %" PRIi64 " - tag %p - not found\n",
862 sim_events_time (sd),
863 event_to_remove));
c906108c
SS
864}
865#endif
866
867
868STATIC_INLINE_SIM_EVENTS\
869(int)
870sim_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
4c0d76b9
MF
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
c906108c
SS
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
1053INLINE_SIM_EVENTS\
1054(int)
1055sim_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
1077INLINE_SIM_EVENTS\
1078(int)
1079sim_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
1102INLINE_SIM_EVENTS\
1103(void)
1104sim_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
1120INLINE_SIM_EVENTS\
1121(void)
1122sim_events_preprocess (SIM_DESC sd,
1123 int events_were_last,
1124 int events_were_next)
1125{
34b47c38 1126 sim_events *events = STATE_EVENTS (sd);
c906108c
SS
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
1145INLINE_SIM_EVENTS\
1146(void)
1147sim_events_process (SIM_DESC sd)
1148{
34b47c38 1149 sim_events *events = STATE_EVENTS (sd);
e4c803f5 1150 int64_t event_time = sim_events_time (sd);
c906108c
SS
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;
028f6515 1162
c906108c
SS
1163#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1164 /*-LOCK-*/
1165 sigset_t old_mask;
1166 sigset_t new_mask;
34b47c38
MF
1167 sigfillset (&new_mask);
1168 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
c906108c
SS
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;
028f6515 1180
c906108c
SS
1181#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1182 /*-UNLOCK-*/
34b47c38 1183 sigprocmask (SIG_SETMASK, &old_mask, NULL);
c906108c 1184#endif
028f6515 1185
c906108c 1186 }
028f6515 1187
c906108c
SS
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;
34b47c38 1202 ETRACE ((_ETRACE,
c704d6e7
MF
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,
34b47c38
MF
1209 (to_do->trace != NULL) ? ", " : "",
1210 (to_do->trace != NULL) ? to_do->trace : ""));
c906108c
SS
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 }
028f6515 1220
c906108c
SS
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);
34b47c38 1231 ETRACE ((_ETRACE,
c704d6e7
MF
1232 "event issued at %" PRIi64 " - tag %p - handler %p, data %p%s%s\n",
1233 event_time,
1234 to_do,
1235 handler,
1236 data,
34b47c38
MF
1237 (to_do->trace != NULL) ? ", " : "",
1238 (to_do->trace != NULL) ? to_do->trace : ""));
c906108c
SS
1239 sim_events_free (sd, to_do);
1240 handler (sd, data);
1241 }
028f6515 1242
c906108c
SS
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;
028f6515 1248
c906108c
SS
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;
c906108c
SS
1256}
1257
1258#endif