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