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