Extend xor-endian and per-cpu support in core module.
[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 0x100000
133 #endif
134
135
136 #define _ETRACE sd
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 sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
149 sim_io_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 EXTERN_SIM_EVENTS\
193 (SIM_RC)
194 sim_events_install (SIM_DESC sd)
195 {
196 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
197 sim_module_add_uninstall_fn (sd, sim_events_uninstall);
198 sim_module_add_init_fn (sd, sim_events_init);
199 return SIM_RC_OK;
200 }
201
202
203 /* Uninstall the "events" subsystem from the simulator. */
204
205 EXTERN_SIM_EVENTS\
206 (void)
207 sim_events_uninstall (SIM_DESC sd)
208 {
209 /* FIXME: free buffers, etc. */
210 }
211
212
213 /* malloc/free */
214
215 STATIC_INLINE_SIM_EVENTS\
216 (sim_event *)
217 sim_events_zalloc (SIM_DESC sd)
218 {
219 sim_events *events = STATE_EVENTS (sd);
220 sim_event *new = events->free_list;
221 if (new != NULL)
222 {
223 events->free_list = new->next;
224 memset (new, 0, sizeof (*new));
225 }
226 else
227 {
228 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
229 /*-LOCK-*/
230 sigset_t old_mask;
231 sigset_t new_mask;
232 sigfillset(&new_mask);
233 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
234 #endif
235 new = ZALLOC (sim_event);
236 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
237 /*-UNLOCK-*/
238 sigprocmask (SIG_SETMASK, &old_mask, NULL);
239 #endif
240 }
241 return new;
242 }
243
244 STATIC_INLINE_SIM_EVENTS\
245 (void)
246 sim_events_free (SIM_DESC sd,
247 sim_event *dead)
248 {
249 sim_events *events = STATE_EVENTS (sd);
250 dead->next = events->free_list;
251 events->free_list = dead;
252 }
253
254
255 /* Initialize the simulator event manager */
256
257 EXTERN_SIM_EVENTS\
258 (SIM_RC)
259 sim_events_init (SIM_DESC sd)
260 {
261 sim_events *events = STATE_EVENTS (sd);
262
263 /* drain the interrupt queue */
264 events->nr_held = 0;
265 if (events->held == NULL)
266 events->held = zalloc (sizeof (sim_event) * MAX_NR_SIGNAL_SIM_EVENTS);
267
268 /* drain the normal queues */
269 {
270 sim_event **queue = NULL;
271 while ((queue = next_event_queue (sd, queue)) != NULL)
272 {
273 if (queue == NULL) break;
274 while (*queue != NULL)
275 {
276 sim_event *dead = *queue;
277 *queue = dead->next;
278 sim_events_free (sd, dead);
279 }
280 *queue = NULL;
281 }
282 }
283
284 /* wind time back to zero */
285 events->nr_ticks_to_process = 1; /* start by doing queue */
286 events->time_of_event = 0;
287 events->time_from_event = 0;
288 events->initial_wallclock = sim_elapsed_time_get ();
289
290 /* schedule our initial counter event */
291 sim_events_schedule (sd, 0, sim_events_poll, sd);
292
293 /* from now on, except when the large-int event is being processed
294 the event queue is non empty */
295 SIM_ASSERT (events->queue != NULL);
296
297 return SIM_RC_OK;
298 }
299
300
301 INLINE_SIM_EVENTS\
302 (signed64)
303 sim_events_time (SIM_DESC sd)
304 {
305 sim_events *events = STATE_EVENTS (sd);
306 return events->time_of_event - events->time_from_event;
307 }
308
309
310 STATIC_INLINE_SIM_EVENTS\
311 (void)
312 update_time_from_event (SIM_DESC sd)
313 {
314 sim_events *events = STATE_EVENTS (sd);
315 signed64 current_time = sim_events_time (sd);
316 if (events->queue != NULL)
317 {
318 events->time_from_event = (events->queue->time_of_event - current_time);
319 events->time_of_event = events->queue->time_of_event;
320 }
321 else
322 {
323 events->time_of_event = current_time - 1;
324 events->time_from_event = -1;
325 }
326 SIM_ASSERT (current_time == sim_events_time (sd));
327 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
328 }
329
330
331 STATIC_INLINE_SIM_EVENTS\
332 (void)
333 insert_sim_event (SIM_DESC sd,
334 sim_event *new_event,
335 signed64 delta)
336 {
337 sim_events *events = STATE_EVENTS (sd);
338 sim_event *curr;
339 sim_event **prev;
340 signed64 time_of_event;
341
342 if (delta < 0)
343 sim_io_error (sd, "what is past is past!\n");
344
345 /* compute when the event should occure */
346 time_of_event = sim_events_time (sd) + delta;
347
348 /* find the queue insertion point - things are time ordered */
349 prev = &events->queue;
350 curr = events->queue;
351 while (curr != NULL && time_of_event >= curr->time_of_event)
352 {
353 SIM_ASSERT (curr->next == NULL
354 || curr->time_of_event <= curr->next->time_of_event);
355 prev = &curr->next;
356 curr = curr->next;
357 }
358 SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
359
360 /* insert it */
361 new_event->next = curr;
362 *prev = new_event;
363 new_event->time_of_event = time_of_event;
364
365 /* adjust the time until the first event */
366 update_time_from_event (sd);
367 }
368
369
370 EXTERN_SIM_EVENTS\
371 (sim_event *)
372 sim_events_schedule (SIM_DESC sd,
373 signed64 delta_time,
374 sim_event_handler *handler,
375 void *data)
376 {
377 sim_event *new_event = sim_events_zalloc (sd);
378 new_event->data = data;
379 new_event->handler = handler;
380 new_event->watching = watch_timer;
381 insert_sim_event(sd, new_event, delta_time);
382 ETRACE((_ETRACE,
383 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
384 (long)sim_events_time(sd),
385 (long)new_event,
386 (long)new_event->time_of_event,
387 (long)new_event->handler,
388 (long)new_event->data));
389 return new_event;
390 }
391
392
393 EXTERN_SIM_EVENTS\
394 (void)
395 sim_events_schedule_after_signal (SIM_DESC sd,
396 signed64 delta_time,
397 sim_event_handler *handler,
398 void *data)
399 {
400 sim_events *events = STATE_EVENTS (sd);
401 sim_event *new_event;
402 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
403 /*-LOCK-*/
404 sigset_t old_mask;
405 sigset_t new_mask;
406 sigfillset(&new_mask);
407 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
408 #endif
409
410 /* allocate an event entry from the signal buffer */
411 new_event = &events->held [events->nr_held];
412 events->nr_held ++;
413 if (events->nr_held >= MAX_NR_SIGNAL_SIM_EVENTS)
414 {
415 sim_engine_abort (NULL, NULL, NULL_CIA,
416 "sim_events_schedule_after_signal - buffer oveflow");
417 }
418
419 new_event->data = data;
420 new_event->handler = handler;
421 new_event->time_of_event = delta_time; /* work it out later */
422 new_event->next = NULL;
423
424 events->work_pending = 1; /* notify main process */
425
426 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
427 /*-UNLOCK-*/
428 sigprocmask (SIG_SETMASK, &old_mask, NULL);
429 #endif
430
431 ETRACE ((_ETRACE,
432 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
433 (long)sim_events_time(sd),
434 (long)new_event,
435 (long)new_event->time_of_event,
436 (long)new_event->handler,
437 (long)new_event->data));
438 }
439
440
441 EXTERN_SIM_EVENTS\
442 (sim_event *)
443 sim_events_watch_clock (SIM_DESC sd,
444 unsigned delta_ms_time,
445 sim_event_handler *handler,
446 void *data)
447 {
448 sim_events *events = STATE_EVENTS (sd);
449 sim_event *new_event = sim_events_zalloc (sd);
450 /* type */
451 new_event->watching = watch_clock;
452 /* handler */
453 new_event->data = data;
454 new_event->handler = handler;
455 /* data */
456 new_event->wallclock = (sim_elapsed_time_since (events->initial_wallclock) + delta_ms_time);
457 /* insert */
458 new_event->next = events->watchpoints;
459 events->watchpoints = new_event;
460 events->work_pending = 1;
461 ETRACE ((_ETRACE,
462 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
463 (long)sim_events_time (sd),
464 (long)new_event,
465 (long)new_event->wallclock,
466 (long)new_event->handler,
467 (long)new_event->data));
468 return new_event;
469 }
470
471
472 EXTERN_SIM_EVENTS\
473 (sim_event *)
474 sim_events_watch_sim (SIM_DESC sd,
475 void *host_addr,
476 int nr_bytes,
477 int byte_order,
478 int is_within,
479 unsigned64 lb,
480 unsigned64 ub,
481 sim_event_handler *handler,
482 void *data)
483 {
484 sim_events *events = STATE_EVENTS (sd);
485 sim_event *new_event = sim_events_zalloc (sd);
486 /* type */
487 switch (byte_order)
488 {
489 case 0:
490 switch (nr_bytes)
491 {
492 case 1: new_event->watching = watch_sim_host_1; break;
493 case 2: new_event->watching = watch_sim_host_2; break;
494 case 4: new_event->watching = watch_sim_host_4; break;
495 case 8: new_event->watching = watch_sim_host_8; break;
496 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
497 }
498 break;
499 case BIG_ENDIAN:
500 switch (nr_bytes)
501 {
502 case 1: new_event->watching = watch_sim_be_1; break;
503 case 2: new_event->watching = watch_sim_be_2; break;
504 case 4: new_event->watching = watch_sim_be_4; break;
505 case 8: new_event->watching = watch_sim_be_8; break;
506 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
507 }
508 break;
509 case LITTLE_ENDIAN:
510 switch (nr_bytes)
511 {
512 case 1: new_event->watching = watch_sim_le_1; break;
513 case 2: new_event->watching = watch_sim_le_2; break;
514 case 4: new_event->watching = watch_sim_le_4; break;
515 case 8: new_event->watching = watch_sim_le_8; break;
516 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
517 }
518 break;
519 default:
520 sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
521 }
522 /* handler */
523 new_event->data = data;
524 new_event->handler = handler;
525 /* data */
526 new_event->host_addr = host_addr;
527 new_event->lb = lb;
528 new_event->lb64 = lb;
529 new_event->ub = ub;
530 new_event->ub64 = ub;
531 new_event->is_within = (is_within != 0);
532 /* insert */
533 new_event->next = events->watchpoints;
534 events->watchpoints = new_event;
535 events->work_pending = 1;
536 ETRACE ((_ETRACE,
537 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
538 (long)sim_events_time (sd),
539 (long)new_event,
540 (long)new_event->host_addr,
541 (long)new_event->lb,
542 (long)new_event->ub,
543 (long)new_event->handler,
544 (long)new_event->data));
545 return new_event;
546 }
547
548
549 EXTERN_SIM_EVENTS\
550 (sim_event *)
551 sim_events_watch_core (SIM_DESC sd,
552 address_word core_addr,
553 sim_core_maps core_map,
554 int nr_bytes,
555 int byte_order,
556 int is_within,
557 unsigned64 lb,
558 unsigned64 ub,
559 sim_event_handler *handler,
560 void *data)
561 {
562 sim_events *events = STATE_EVENTS (sd);
563 sim_event *new_event = sim_events_zalloc (sd);
564 /* type */
565 switch (byte_order)
566 {
567 case 0:
568 switch (nr_bytes)
569 {
570 case 1: new_event->watching = watch_core_targ_1; break;
571 case 2: new_event->watching = watch_core_targ_2; break;
572 case 4: new_event->watching = watch_core_targ_4; break;
573 case 8: new_event->watching = watch_core_targ_8; break;
574 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
575 }
576 break;
577 case BIG_ENDIAN:
578 switch (nr_bytes)
579 {
580 case 1: new_event->watching = watch_core_be_1; break;
581 case 2: new_event->watching = watch_core_be_2; break;
582 case 4: new_event->watching = watch_core_be_4; break;
583 case 8: new_event->watching = watch_core_be_8; break;
584 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
585 }
586 break;
587 case LITTLE_ENDIAN:
588 switch (nr_bytes)
589 {
590 case 1: new_event->watching = watch_core_le_1; break;
591 case 2: new_event->watching = watch_core_le_2; break;
592 case 4: new_event->watching = watch_core_le_4; break;
593 case 8: new_event->watching = watch_core_le_8; break;
594 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
595 }
596 break;
597 default:
598 sim_io_error (sd, "sim_events_watch_core - invalid byte order");
599 }
600 /* handler */
601 new_event->data = data;
602 new_event->handler = handler;
603 /* data */
604 new_event->core_addr = core_addr;
605 new_event->core_map = core_map;
606 new_event->lb = lb;
607 new_event->lb64 = lb;
608 new_event->ub = ub;
609 new_event->ub64 = ub;
610 new_event->is_within = (is_within != 0);
611 /* insert */
612 new_event->next = events->watchpoints;
613 events->watchpoints = new_event;
614 events->work_pending = 1;
615 ETRACE ((_ETRACE,
616 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
617 (long)sim_events_time (sd),
618 (long)new_event,
619 (long)new_event->host_addr,
620 (long)new_event->lb,
621 (long)new_event->ub,
622 (long)new_event->handler,
623 (long)new_event->data));
624 return new_event;
625 }
626
627
628 EXTERN_SIM_EVENTS\
629 (void)
630 sim_events_deschedule (SIM_DESC sd,
631 sim_event *event_to_remove)
632 {
633 sim_events *events = STATE_EVENTS (sd);
634 sim_event *to_remove = (sim_event*)event_to_remove;
635 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
636 if (event_to_remove != NULL)
637 {
638 sim_event **queue = NULL;
639 while ((queue = next_event_queue (sd, queue)) != NULL)
640 {
641 sim_event **ptr_to_current;
642 for (ptr_to_current = queue;
643 *ptr_to_current != NULL && *ptr_to_current != to_remove;
644 ptr_to_current = &(*ptr_to_current)->next);
645 if (*ptr_to_current == to_remove)
646 {
647 sim_event *dead = *ptr_to_current;
648 *ptr_to_current = dead->next;
649 ETRACE ((_ETRACE,
650 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
651 (long) sim_events_time (sd),
652 (long) event_to_remove,
653 (long) dead->time_of_event,
654 (long) dead->handler,
655 (long) dead->data));
656 sim_events_free (sd, dead);
657 update_time_from_event (sd);
658 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
659 return;
660 }
661 }
662 }
663 ETRACE ((_ETRACE,
664 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
665 (long) sim_events_time (sd),
666 (long) event_to_remove));
667 }
668
669
670 STATIC_INLINE_SIM_EVENTS\
671 (int)
672 sim_watch_valid (SIM_DESC sd,
673 sim_event *to_do)
674 {
675 switch (to_do->watching)
676 {
677
678 #define WATCH_CORE(N,OP,EXT) \
679 { \
680 unsigned_##N word = 0; \
681 int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
682 OP (word); \
683 return (nr_read == sizeof (unsigned_##N) \
684 && (to_do->is_within \
685 == (word >= to_do->lb##EXT \
686 && word <= to_do->ub##EXT))); \
687 }
688 case watch_core_targ_1: WATCH_CORE (1, T2H,);
689 case watch_core_targ_2: WATCH_CORE (2, T2H,);
690 case watch_core_targ_4: WATCH_CORE (4, T2H,);
691 case watch_core_targ_8: WATCH_CORE (8, T2H,64);
692
693 case watch_core_be_1: WATCH_CORE (1, BE2H,);
694 case watch_core_be_2: WATCH_CORE (2, BE2H,);
695 case watch_core_be_4: WATCH_CORE (4, BE2H,);
696 case watch_core_be_8: WATCH_CORE (8, BE2H,64);
697
698 case watch_core_le_1: WATCH_CORE (1, LE2H,);
699 case watch_core_le_2: WATCH_CORE (2, LE2H,);
700 case watch_core_le_4: WATCH_CORE (4, LE2H,);
701 case watch_core_le_8: WATCH_CORE (8, LE2H,64);
702 #undef WATCH_CORE
703
704 #define WATCH_SIM(N,OP,EXT) \
705 { \
706 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
707 OP (word); \
708 return (to_do->is_within \
709 == (word >= to_do->lb##EXT \
710 && word <= to_do->ub##EXT)); \
711 }
712
713 case watch_sim_host_1: WATCH_SIM (1, word = ,);
714 case watch_sim_host_2: WATCH_SIM (2, word = ,);
715 case watch_sim_host_4: WATCH_SIM (4, word = ,);
716 case watch_sim_host_8: WATCH_SIM (8, word = ,64);
717
718 case watch_sim_be_1: WATCH_SIM (1, BE2H,);
719 case watch_sim_be_2: WATCH_SIM (2, BE2H,);
720 case watch_sim_be_4: WATCH_SIM (4, BE2H,);
721 case watch_sim_be_8: WATCH_SIM (8, BE2H,64);
722
723 case watch_sim_le_1: WATCH_SIM (1, LE2H,);
724 case watch_sim_le_2: WATCH_SIM (1, LE2H,);
725 case watch_sim_le_4: WATCH_SIM (1, LE2H,);
726 case watch_sim_le_8: WATCH_SIM (1, LE2H,64);
727 #undef WATCH_SIM
728
729 case watch_clock: /* wallclock */
730 {
731 unsigned long elapsed_time = sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock);
732 return (elapsed_time >= to_do->wallclock);
733 }
734
735 default:
736 sim_io_error (sd, "sim_watch_valid - bad switch");
737 break;
738
739 }
740 return 1;
741 }
742
743
744 INLINE_SIM_EVENTS\
745 (int)
746 sim_events_tick (SIM_DESC sd)
747 {
748 sim_events *events = STATE_EVENTS (sd);
749
750 /* this should only be called after the previous ticks have been
751 fully processed */
752 SIM_ASSERT (events->nr_ticks_to_process == 0);
753
754 /* Advance the time but *only* if there is nothing to process */
755 if (events->work_pending
756 || events->time_from_event == 0)
757 {
758 events->nr_ticks_to_process = 1;
759 return 1;
760 }
761 else {
762 events->time_from_event -= 1;
763 return 0;
764 }
765 }
766
767
768 INLINE_SIM_EVENTS\
769 (int)
770 sim_events_tickn (SIM_DESC sd,
771 unsigned n)
772 {
773 sim_events *events = STATE_EVENTS (sd);
774
775 /* this should only be called after the previous ticks have been
776 fully processed */
777 SIM_ASSERT (events->nr_ticks_to_process == 0);
778 SIM_ASSERT (n > 0);
779
780 /* Advance the time but *only* if there is nothing to process */
781 if (events->work_pending
782 || events->time_from_event < n)
783 {
784 events->nr_ticks_to_process = n;
785 return 1;
786 }
787 else {
788 events->time_from_event -= n;
789 return 0;
790 }
791 }
792
793
794 INLINE_SIM_EVENTS\
795 (void)
796 sim_events_preprocess (SIM_DESC sd,
797 int events_were_last,
798 int events_were_next)
799 {
800 sim_events *events = STATE_EVENTS(sd);
801 if (events->nr_ticks_to_process != 0)
802 {
803 /* Halted midway through event processing */
804 ASSERT (events_were_last && events_were_next);
805 sim_events_process (sd);
806 }
807 else if (events_were_next)
808 {
809 /* Halted by the last processor */
810 ASSERT (events->nr_ticks_to_process == 0 && !events_were_last);
811 if (sim_events_tick (sd))
812 sim_events_process (sd);
813 }
814 }
815
816
817 INLINE_SIM_EVENTS\
818 (void)
819 sim_events_process (SIM_DESC sd)
820 {
821 sim_events *events = STATE_EVENTS(sd);
822 signed64 event_time = sim_events_time(sd);
823
824 ASSERT (events->nr_ticks_to_process != 0);
825
826 /* move any events that were queued by any signal handlers onto
827 the real event queue. */
828 if (events->nr_held > 0)
829 {
830 int i;
831
832 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
833 /*-LOCK-*/
834 sigset_t old_mask;
835 sigset_t new_mask;
836 sigfillset(&new_mask);
837 sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
838 #endif
839
840 for (i = 0; i < events->nr_held; i++)
841 {
842 sim_event *entry = &events->held [i];
843 sim_events_schedule (sd,
844 entry->time_of_event,
845 entry->handler,
846 entry->data);
847 }
848 events->nr_held = 0;
849
850 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
851 /*-UNLOCK-*/
852 sigprocmask(SIG_SETMASK, &old_mask, NULL);
853 #endif
854
855 }
856
857 /* Process any watchpoints. Be careful to allow a watchpoint to
858 appear/disappear under our feet.
859 To ensure that watchpoints are processed only once per cycle,
860 they are moved onto a watched queue, this returned to the
861 watchpoint queue when all queue processing has been
862 completed. */
863 while (events->watchpoints != NULL)
864 {
865 sim_event *to_do = events->watchpoints;
866 events->watchpoints = to_do->next;
867 if (sim_watch_valid (sd, to_do))
868 {
869 sim_event_handler *handler = to_do->handler;
870 void *data = to_do->data;
871 events->queue = to_do->next;
872 ETRACE((_ETRACE,
873 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
874 (long) event_time,
875 (long) to_do,
876 (long) handler,
877 (long) data));
878 sim_events_free (sd, to_do);
879 handler (sd, data);
880 }
881 else
882 {
883 to_do->next = events->watchedpoints;
884 events->watchedpoints = to_do;
885 }
886 }
887
888 /* consume all events for this or earlier times. Be careful to
889 allow an event to appear/disappear under our feet */
890 while (events->queue->time_of_event <
891 (event_time + events->nr_ticks_to_process))
892 {
893 sim_event *to_do = events->queue;
894 sim_event_handler *handler = to_do->handler;
895 void *data = to_do->data;
896 events->queue = to_do->next;
897 ETRACE((_ETRACE,
898 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
899 (long) event_time,
900 (long) to_do,
901 (long) handler,
902 (long) data));
903 sim_events_free (sd, to_do);
904 handler (sd, data);
905 }
906
907 /* put things back where they belong ready for the next iteration */
908 events->watchpoints = events->watchedpoints;
909 events->watchedpoints = NULL;
910 if (events->watchpoints != NULL)
911 events->work_pending = 1;
912
913 /* re-caculate time for new events then advance the time */
914 update_time_from_event(sd);
915 SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
916 SIM_ASSERT (events->queue != NULL); /* always poll event */
917 events->time_from_event -= events->nr_ticks_to_process;
918
919 /* this round of processing complete */
920 events->nr_ticks_to_process = 0;
921 }
922
923 #endif