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