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