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