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