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