]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-events.c
sim: overhaul & unify endian settings management
[thirdparty/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 - time %ld, delta %ld - event %d, tag 0x%lx, time %ld, handler 0x%lx, data 0x%lx%s%s\n",
413 (long)current_time,
414 (long)events->time_from_event,
415 i,
416 (long)event,
417 (long)event->time_of_event,
418 (long)event->handler,
419 (long)event->data,
420 (event->trace != NULL) ? ", " : "",
421 (event->trace != NULL) ? event->trace : ""));
422 }
423 }
424 SIM_ASSERT (current_time == sim_events_time (sd));
425 }
426
427
428 #if EXTERN_SIM_EVENTS_P
429 static void
430 insert_sim_event (SIM_DESC sd,
431 sim_event *new_event,
432 signed64 delta)
433 {
434 sim_events *events = STATE_EVENTS (sd);
435 sim_event *curr;
436 sim_event **prev;
437 signed64 time_of_event;
438
439 if (delta < 0)
440 sim_io_error (sd, "what is past is past!\n");
441
442 /* compute when the event should occur */
443 time_of_event = sim_events_time (sd) + delta;
444
445 /* find the queue insertion point - things are time ordered */
446 prev = &events->queue;
447 curr = events->queue;
448 while (curr != NULL && time_of_event >= curr->time_of_event)
449 {
450 SIM_ASSERT (curr->next == NULL
451 || curr->time_of_event <= curr->next->time_of_event);
452 prev = &curr->next;
453 curr = curr->next;
454 }
455 SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
456
457 /* insert it */
458 new_event->next = curr;
459 *prev = new_event;
460 new_event->time_of_event = time_of_event;
461
462 /* adjust the time until the first event */
463 update_time_from_event (sd);
464 }
465 #endif
466
467
468 #if EXTERN_SIM_EVENTS_P
469 sim_event *
470 sim_events_schedule (SIM_DESC sd,
471 signed64 delta_time,
472 sim_event_handler *handler,
473 void *data)
474 {
475 return sim_events_schedule_tracef (sd, delta_time, handler, data, NULL);
476 }
477 #endif
478
479
480 #if EXTERN_SIM_EVENTS_P
481 sim_event *
482 sim_events_schedule_tracef (SIM_DESC sd,
483 signed64 delta_time,
484 sim_event_handler *handler,
485 void *data,
486 const char *fmt,
487 ...)
488 {
489 sim_event *new_event;
490 va_list ap;
491 va_start (ap, fmt);
492 new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
493 va_end (ap);
494 return new_event;
495 }
496 #endif
497
498
499 #if EXTERN_SIM_EVENTS_P
500 sim_event *
501 sim_events_schedule_vtracef (SIM_DESC sd,
502 signed64 delta_time,
503 sim_event_handler *handler,
504 void *data,
505 const char *fmt,
506 va_list ap)
507 {
508 sim_event *new_event = sim_events_zalloc (sd);
509 new_event->data = data;
510 new_event->handler = handler;
511 new_event->watching = watch_timer;
512 if (fmt == NULL || !STRACE_EVENTS_P (sd) || vasprintf (&new_event->trace, fmt, ap) < 0)
513 new_event->trace = NULL;
514 insert_sim_event (sd, new_event, delta_time);
515 ETRACE ((_ETRACE,
516 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
517 (long)sim_events_time (sd),
518 (long)new_event,
519 (long)new_event->time_of_event,
520 (long)new_event->handler,
521 (long)new_event->data,
522 (new_event->trace != NULL) ? ", " : "",
523 (new_event->trace != NULL) ? new_event->trace : ""));
524 return new_event;
525 }
526 #endif
527
528
529 #if EXTERN_SIM_EVENTS_P
530 void
531 sim_events_schedule_after_signal (SIM_DESC sd,
532 signed64 delta_time,
533 sim_event_handler *handler,
534 void *data)
535 {
536 sim_events *events = STATE_EVENTS (sd);
537 sim_event *new_event;
538 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
539 /*-LOCK-*/
540 sigset_t old_mask;
541 sigset_t new_mask;
542 sigfillset (&new_mask);
543 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
544 #endif
545
546 /* allocate an event entry from the signal buffer */
547 new_event = &events->held [events->nr_held];
548 events->nr_held ++;
549 if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
550 {
551 sim_engine_abort (NULL, NULL, NULL_CIA,
552 "sim_events_schedule_after_signal - buffer overflow");
553 }
554
555 new_event->data = data;
556 new_event->handler = handler;
557 new_event->time_of_event = delta_time; /* work it out later */
558 new_event->next = NULL;
559
560 events->work_pending = 1; /* notify main process */
561
562 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
563 /*-UNLOCK-*/
564 sigprocmask (SIG_SETMASK, &old_mask, NULL);
565 #endif
566
567 ETRACE ((_ETRACE,
568 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
569 (long)sim_events_time (sd),
570 (long)new_event,
571 (long)new_event->time_of_event,
572 (long)new_event->handler,
573 (long)new_event->data));
574 }
575 #endif
576
577
578 #if EXTERN_SIM_EVENTS_P
579 sim_event *
580 sim_events_watch_clock (SIM_DESC sd,
581 unsigned delta_ms_time,
582 sim_event_handler *handler,
583 void *data)
584 {
585 sim_events *events = STATE_EVENTS (sd);
586 sim_event *new_event = sim_events_zalloc (sd);
587 /* type */
588 new_event->watching = watch_clock;
589 /* handler */
590 new_event->data = data;
591 new_event->handler = handler;
592 /* data */
593 if (events->resume_wallclock == 0)
594 new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
595 else
596 new_event->wallclock = (events->elapsed_wallclock
597 + sim_elapsed_time_since (events->resume_wallclock)
598 + delta_ms_time);
599 /* insert */
600 new_event->next = events->watchpoints;
601 events->watchpoints = new_event;
602 events->work_pending = 1;
603 ETRACE ((_ETRACE,
604 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
605 (long)sim_events_time (sd),
606 (long)new_event,
607 (long)new_event->wallclock,
608 (long)new_event->handler,
609 (long)new_event->data));
610 return new_event;
611 }
612 #endif
613
614
615 #if EXTERN_SIM_EVENTS_P
616 sim_event *
617 sim_events_watch_pc (SIM_DESC sd,
618 int is_within,
619 unsigned64 lb,
620 unsigned64 ub,
621 sim_event_handler *handler,
622 void *data)
623 {
624 sim_events *events = STATE_EVENTS (sd);
625 sim_event *new_event = sim_events_zalloc (sd);
626 /* type */
627 new_event->watching = watch_pc;
628 /* handler */
629 new_event->data = data;
630 new_event->handler = handler;
631 /* data */
632 new_event->lb = lb;
633 new_event->lb64 = lb;
634 new_event->ub = ub;
635 new_event->ub64 = ub;
636 new_event->is_within = (is_within != 0);
637 /* insert */
638 new_event->next = events->watchpoints;
639 events->watchpoints = new_event;
640 events->work_pending = 1;
641 ETRACE ((_ETRACE,
642 "event watching pc at %ld - tag 0x%lx - pc 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
643 (long)sim_events_time (sd),
644 (long)new_event,
645 (long)new_event->lb,
646 (long)new_event->ub,
647 (long)new_event->handler,
648 (long)new_event->data));
649 return new_event;
650 }
651 #endif
652
653
654 #if EXTERN_SIM_EVENTS_P
655 sim_event *
656 sim_events_watch_sim (SIM_DESC sd,
657 void *host_addr,
658 int nr_bytes,
659 enum bfd_endian byte_order,
660 int is_within,
661 unsigned64 lb,
662 unsigned64 ub,
663 sim_event_handler *handler,
664 void *data)
665 {
666 sim_events *events = STATE_EVENTS (sd);
667 sim_event *new_event = sim_events_zalloc (sd);
668 /* type */
669 switch (byte_order)
670 {
671 case BFD_ENDIAN_UNKNOWN:
672 switch (nr_bytes)
673 {
674 case 1: new_event->watching = watch_sim_host_1; break;
675 case 2: new_event->watching = watch_sim_host_2; break;
676 case 4: new_event->watching = watch_sim_host_4; break;
677 case 8: new_event->watching = watch_sim_host_8; break;
678 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
679 }
680 break;
681 case BFD_ENDIAN_BIG:
682 switch (nr_bytes)
683 {
684 case 1: new_event->watching = watch_sim_be_1; break;
685 case 2: new_event->watching = watch_sim_be_2; break;
686 case 4: new_event->watching = watch_sim_be_4; break;
687 case 8: new_event->watching = watch_sim_be_8; break;
688 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
689 }
690 break;
691 case BFD_ENDIAN_LITTLE:
692 switch (nr_bytes)
693 {
694 case 1: new_event->watching = watch_sim_le_1; break;
695 case 2: new_event->watching = watch_sim_le_2; break;
696 case 4: new_event->watching = watch_sim_le_4; break;
697 case 8: new_event->watching = watch_sim_le_8; break;
698 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
699 }
700 break;
701 default:
702 sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
703 }
704 /* handler */
705 new_event->data = data;
706 new_event->handler = handler;
707 /* data */
708 new_event->host_addr = host_addr;
709 new_event->lb = lb;
710 new_event->lb64 = lb;
711 new_event->ub = ub;
712 new_event->ub64 = ub;
713 new_event->is_within = (is_within != 0);
714 /* insert */
715 new_event->next = events->watchpoints;
716 events->watchpoints = new_event;
717 events->work_pending = 1;
718 ETRACE ((_ETRACE,
719 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
720 (long)sim_events_time (sd),
721 (long)new_event,
722 (long)new_event->host_addr,
723 (long)new_event->lb,
724 (long)new_event->ub,
725 (long)new_event->handler,
726 (long)new_event->data));
727 return new_event;
728 }
729 #endif
730
731
732 #if EXTERN_SIM_EVENTS_P
733 sim_event *
734 sim_events_watch_core (SIM_DESC sd,
735 address_word core_addr,
736 unsigned core_map,
737 int nr_bytes,
738 enum bfd_endian byte_order,
739 int is_within,
740 unsigned64 lb,
741 unsigned64 ub,
742 sim_event_handler *handler,
743 void *data)
744 {
745 sim_events *events = STATE_EVENTS (sd);
746 sim_event *new_event = sim_events_zalloc (sd);
747 /* type */
748 switch (byte_order)
749 {
750 case BFD_ENDIAN_UNKNOWN:
751 switch (nr_bytes)
752 {
753 case 1: new_event->watching = watch_core_targ_1; break;
754 case 2: new_event->watching = watch_core_targ_2; break;
755 case 4: new_event->watching = watch_core_targ_4; break;
756 case 8: new_event->watching = watch_core_targ_8; break;
757 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
758 }
759 break;
760 case BFD_ENDIAN_BIG:
761 switch (nr_bytes)
762 {
763 case 1: new_event->watching = watch_core_be_1; break;
764 case 2: new_event->watching = watch_core_be_2; break;
765 case 4: new_event->watching = watch_core_be_4; break;
766 case 8: new_event->watching = watch_core_be_8; break;
767 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
768 }
769 break;
770 case BFD_ENDIAN_LITTLE:
771 switch (nr_bytes)
772 {
773 case 1: new_event->watching = watch_core_le_1; break;
774 case 2: new_event->watching = watch_core_le_2; break;
775 case 4: new_event->watching = watch_core_le_4; break;
776 case 8: new_event->watching = watch_core_le_8; break;
777 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
778 }
779 break;
780 default:
781 sim_io_error (sd, "sim_events_watch_core - invalid byte order");
782 }
783 /* handler */
784 new_event->data = data;
785 new_event->handler = handler;
786 /* data */
787 new_event->core_addr = core_addr;
788 new_event->core_map = core_map;
789 new_event->lb = lb;
790 new_event->lb64 = lb;
791 new_event->ub = ub;
792 new_event->ub64 = ub;
793 new_event->is_within = (is_within != 0);
794 /* insert */
795 new_event->next = events->watchpoints;
796 events->watchpoints = new_event;
797 events->work_pending = 1;
798 ETRACE ((_ETRACE,
799 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
800 (long)sim_events_time (sd),
801 (long)new_event,
802 (long)new_event->host_addr,
803 (long)new_event->lb,
804 (long)new_event->ub,
805 (long)new_event->handler,
806 (long)new_event->data));
807 return new_event;
808 }
809 #endif
810
811
812 #if EXTERN_SIM_EVENTS_P
813 void
814 sim_events_deschedule (SIM_DESC sd,
815 sim_event *event_to_remove)
816 {
817 sim_events *events = STATE_EVENTS (sd);
818 sim_event *to_remove = (sim_event*)event_to_remove;
819 if (event_to_remove != NULL)
820 {
821 sim_event **queue = NULL;
822 while ((queue = next_event_queue (sd, queue)) != NULL)
823 {
824 sim_event **ptr_to_current;
825 for (ptr_to_current = queue;
826 *ptr_to_current != NULL && *ptr_to_current != to_remove;
827 ptr_to_current = &(*ptr_to_current)->next);
828 if (*ptr_to_current == to_remove)
829 {
830 sim_event *dead = *ptr_to_current;
831 *ptr_to_current = dead->next;
832 ETRACE ((_ETRACE,
833 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
834 (long) sim_events_time (sd),
835 (long) event_to_remove,
836 (long) dead->time_of_event,
837 (long) dead->handler,
838 (long) dead->data,
839 (dead->trace != NULL) ? ", " : "",
840 (dead->trace != NULL) ? dead->trace : ""));
841 sim_events_free (sd, dead);
842 update_time_from_event (sd);
843 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
844 return;
845 }
846 }
847 }
848 ETRACE ((_ETRACE,
849 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
850 (long) sim_events_time (sd),
851 (long) event_to_remove));
852 }
853 #endif
854
855
856 STATIC_INLINE_SIM_EVENTS\
857 (int)
858 sim_watch_valid (SIM_DESC sd,
859 sim_event *to_do)
860 {
861 switch (to_do->watching)
862 {
863
864 #define WATCH_CORE(N,OP,EXT) \
865 int ok; \
866 unsigned_##N word = 0; \
867 int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
868 to_do->core_addr, sizeof (word)); \
869 OP (word); \
870 ok = (nr_read == sizeof (unsigned_##N) \
871 && (to_do->is_within \
872 == (word >= to_do->lb##EXT \
873 && word <= to_do->ub##EXT)));
874
875 case watch_core_targ_1:
876 {
877 WATCH_CORE (1, T2H,);
878 return ok;
879 }
880 case watch_core_targ_2:
881 {
882 WATCH_CORE (2, T2H,);
883 return ok;
884 }
885 case watch_core_targ_4:
886 {
887 WATCH_CORE (4, T2H,);
888 return ok;
889 }
890 case watch_core_targ_8:
891 {
892 WATCH_CORE (8, T2H,64);
893 return ok;
894 }
895
896 case watch_core_be_1:
897 {
898 WATCH_CORE (1, BE2H,);
899 return ok;
900 }
901 case watch_core_be_2:
902 {
903 WATCH_CORE (2, BE2H,);
904 return ok;
905 }
906 case watch_core_be_4:
907 {
908 WATCH_CORE (4, BE2H,);
909 return ok;
910 }
911 case watch_core_be_8:
912 {
913 WATCH_CORE (8, BE2H,64);
914 return ok;
915 }
916
917 case watch_core_le_1:
918 {
919 WATCH_CORE (1, LE2H,);
920 return ok;
921 }
922 case watch_core_le_2:
923 {
924 WATCH_CORE (2, LE2H,);
925 return ok;
926 }
927 case watch_core_le_4:
928 {
929 WATCH_CORE (4, LE2H,);
930 return ok;
931 }
932 case watch_core_le_8:
933 {
934 WATCH_CORE (8, LE2H,64);
935 return ok;
936 }
937 #undef WATCH_CORE
938
939 #define WATCH_SIM(N,OP,EXT) \
940 int ok; \
941 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
942 OP (word); \
943 ok = (to_do->is_within \
944 == (word >= to_do->lb##EXT \
945 && word <= to_do->ub##EXT));
946
947 case watch_sim_host_1:
948 {
949 WATCH_SIM (1, word = ,);
950 return ok;
951 }
952 case watch_sim_host_2:
953 {
954 WATCH_SIM (2, word = ,);
955 return ok;
956 }
957 case watch_sim_host_4:
958 {
959 WATCH_SIM (4, word = ,);
960 return ok;
961 }
962 case watch_sim_host_8:
963 {
964 WATCH_SIM (8, word = ,64);
965 return ok;
966 }
967
968 case watch_sim_be_1:
969 {
970 WATCH_SIM (1, BE2H,);
971 return ok;
972 }
973 case watch_sim_be_2:
974 {
975 WATCH_SIM (2, BE2H,);
976 return ok;
977 }
978 case watch_sim_be_4:
979 {
980 WATCH_SIM (4, BE2H,);
981 return ok;
982 }
983 case watch_sim_be_8:
984 {
985 WATCH_SIM (8, BE2H,64);
986 return ok;
987 }
988
989 case watch_sim_le_1:
990 {
991 WATCH_SIM (1, LE2H,);
992 return ok;
993 }
994 case watch_sim_le_2:
995 {
996 WATCH_SIM (1, LE2H,);
997 return ok;
998 }
999 case watch_sim_le_4:
1000 {
1001 WATCH_SIM (1, LE2H,);
1002 return ok;
1003 }
1004 case watch_sim_le_8:
1005 {
1006 WATCH_SIM (1, LE2H,64);
1007 return ok;
1008 }
1009 #undef WATCH_SIM
1010
1011 case watch_pc:
1012 {
1013 int c;
1014
1015 for (c = 0; c < MAX_NR_PROCESSORS; ++c)
1016 {
1017 sim_cpu *cpu = STATE_CPU (sd, c);
1018 sim_cia cia = sim_pc_get (cpu);
1019
1020 if (to_do->is_within == (cia >= to_do->lb64 && cia <= to_do->ub64))
1021 return 1;
1022 }
1023 return 0;
1024 }
1025
1026 case watch_clock: /* wallclock */
1027 {
1028 unsigned long elapsed_time = sim_events_elapsed_time (sd);
1029 return (elapsed_time >= to_do->wallclock);
1030 }
1031
1032 default:
1033 sim_io_error (sd, "sim_watch_valid - bad switch");
1034 break;
1035
1036 }
1037 return 1;
1038 }
1039
1040
1041 INLINE_SIM_EVENTS\
1042 (int)
1043 sim_events_tick (SIM_DESC sd)
1044 {
1045 sim_events *events = STATE_EVENTS (sd);
1046
1047 /* this should only be called after the previous ticks have been
1048 fully processed */
1049
1050 /* Advance the time but *only* if there is nothing to process */
1051 if (events->work_pending
1052 || events->time_from_event == 0)
1053 {
1054 events->nr_ticks_to_process += 1;
1055 return 1;
1056 }
1057 else
1058 {
1059 events->time_from_event -= 1;
1060 return 0;
1061 }
1062 }
1063
1064
1065 INLINE_SIM_EVENTS\
1066 (int)
1067 sim_events_tickn (SIM_DESC sd,
1068 int n)
1069 {
1070 sim_events *events = STATE_EVENTS (sd);
1071 SIM_ASSERT (n > 0);
1072
1073 /* this should only be called after the previous ticks have been
1074 fully processed */
1075
1076 /* Advance the time but *only* if there is nothing to process */
1077 if (events->work_pending || events->time_from_event < n)
1078 {
1079 events->nr_ticks_to_process += n;
1080 return 1;
1081 }
1082 else
1083 {
1084 events->time_from_event -= n;
1085 return 0;
1086 }
1087 }
1088
1089
1090 INLINE_SIM_EVENTS\
1091 (void)
1092 sim_events_slip (SIM_DESC sd,
1093 int slip)
1094 {
1095 sim_events *events = STATE_EVENTS (sd);
1096 SIM_ASSERT (slip > 0);
1097
1098 /* Flag a ready event with work_pending instead of number of ticks
1099 to process so that the time continues to be correct */
1100 if (events->time_from_event < slip)
1101 {
1102 events->work_pending = 1;
1103 }
1104 events->time_from_event -= slip;
1105 }
1106
1107
1108 INLINE_SIM_EVENTS\
1109 (void)
1110 sim_events_preprocess (SIM_DESC sd,
1111 int events_were_last,
1112 int events_were_next)
1113 {
1114 sim_events *events = STATE_EVENTS (sd);
1115 if (events_were_last)
1116 {
1117 /* Halted part way through event processing */
1118 ASSERT (events->nr_ticks_to_process != 0);
1119 /* The external world can't tell if the event that stopped the
1120 simulator was the last event to process. */
1121 ASSERT (events_were_next);
1122 sim_events_process (sd);
1123 }
1124 else if (events_were_next)
1125 {
1126 /* Halted by the last processor */
1127 if (sim_events_tick (sd))
1128 sim_events_process (sd);
1129 }
1130 }
1131
1132
1133 INLINE_SIM_EVENTS\
1134 (void)
1135 sim_events_process (SIM_DESC sd)
1136 {
1137 sim_events *events = STATE_EVENTS (sd);
1138 signed64 event_time = sim_events_time (sd);
1139
1140 /* Clear work_pending before checking nr_held. Clearing
1141 work_pending after nr_held (with out a lock could loose an
1142 event). */
1143 events->work_pending = 0;
1144
1145 /* move any events that were asynchronously queued by any signal
1146 handlers onto the real event queue. */
1147 if (events->nr_held > 0)
1148 {
1149 int i;
1150
1151 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1152 /*-LOCK-*/
1153 sigset_t old_mask;
1154 sigset_t new_mask;
1155 sigfillset (&new_mask);
1156 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
1157 #endif
1158
1159 for (i = 0; i < events->nr_held; i++)
1160 {
1161 sim_event *entry = &events->held [i];
1162 sim_events_schedule (sd,
1163 entry->time_of_event,
1164 entry->handler,
1165 entry->data);
1166 }
1167 events->nr_held = 0;
1168
1169 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1170 /*-UNLOCK-*/
1171 sigprocmask (SIG_SETMASK, &old_mask, NULL);
1172 #endif
1173
1174 }
1175
1176 /* Process any watchpoints. Be careful to allow a watchpoint to
1177 appear/disappear under our feet.
1178 To ensure that watchpoints are processed only once per cycle,
1179 they are moved onto a watched queue, this returned to the
1180 watchpoint queue when all queue processing has been
1181 completed. */
1182 while (events->watchpoints != NULL)
1183 {
1184 sim_event *to_do = events->watchpoints;
1185 events->watchpoints = to_do->next;
1186 if (sim_watch_valid (sd, to_do))
1187 {
1188 sim_event_handler *handler = to_do->handler;
1189 void *data = to_do->data;
1190 ETRACE ((_ETRACE,
1191 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1192 (long) event_time,
1193 (long) to_do,
1194 (long) handler,
1195 (long) data,
1196 (to_do->trace != NULL) ? ", " : "",
1197 (to_do->trace != NULL) ? to_do->trace : ""));
1198 sim_events_free (sd, to_do);
1199 handler (sd, data);
1200 }
1201 else
1202 {
1203 to_do->next = events->watchedpoints;
1204 events->watchedpoints = to_do;
1205 }
1206 }
1207
1208 /* consume all events for this or earlier times. Be careful to
1209 allow an event to appear/disappear under our feet */
1210 while (events->queue->time_of_event <
1211 (event_time + events->nr_ticks_to_process))
1212 {
1213 sim_event *to_do = events->queue;
1214 sim_event_handler *handler = to_do->handler;
1215 void *data = to_do->data;
1216 events->queue = to_do->next;
1217 update_time_from_event (sd);
1218 ETRACE ((_ETRACE,
1219 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1220 (long) event_time,
1221 (long) to_do,
1222 (long) handler,
1223 (long) data,
1224 (to_do->trace != NULL) ? ", " : "",
1225 (to_do->trace != NULL) ? to_do->trace : ""));
1226 sim_events_free (sd, to_do);
1227 handler (sd, data);
1228 }
1229
1230 /* put things back where they belong ready for the next iteration */
1231 events->watchpoints = events->watchedpoints;
1232 events->watchedpoints = NULL;
1233 if (events->watchpoints != NULL)
1234 events->work_pending = 1;
1235
1236 /* advance the time */
1237 SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1238 SIM_ASSERT (events->queue != NULL); /* always poll event */
1239 events->time_from_event -= events->nr_ticks_to_process;
1240
1241 /* this round of processing complete */
1242 events->nr_ticks_to_process = 0;
1243 }
1244
1245 #endif