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