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