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