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