]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/sim-events.c
IGEN likes to cache the current instruction address (CIA). Change the
[thirdparty/binutils-gdb.git] / sim / common / sim-events.c
CommitLineData
8517f62b
AC
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
50a2a691
AC
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
8517f62b
AC
36#include <signal.h>
37
50a2a691 38
f03b093c
AC
39typedef 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,
50a2a691 79} sim_event_watchpoints;
f03b093c
AC
80
81
82struct _sim_event {
50a2a691 83 sim_event_watchpoints watching;
f03b093c
AC
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 */
2f2e6c5d 96 int is_within; /* 0/1 */
f03b093c
AC
97 unsigned ub;
98 unsigned lb;
99 unsigned64 ub64;
100 unsigned64 lb64;
101 /* list */
102 sim_event *next;
103};
104
8517f62b
AC
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
50a2a691
AC
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.
8517f62b
AC
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)
4a203fba 132#define SIM_EVENTS_POLL_RATE 0x1000
8517f62b
AC
133#endif
134
135
4a203fba 136#define _ETRACE sd, NULL
8517f62b
AC
137
138#undef ETRACE
139#define ETRACE(ARGS) \
140do \
141 { \
142 if (WITH_TRACE) \
143 { \
f03b093c 144 if (STATE_EVENTS (sd)->trace) \
8517f62b
AC
145 { \
146 const char *file; \
f03b093c 147 SIM_FILTER_PATH (file, __FILE__); \
4a203fba
AC
148 trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
149 trace_printf ARGS; \
8517f62b
AC
150 } \
151 } \
152 } \
153while (0)
154
155
50a2a691
AC
156/* event queue iterator - don't iterate over the held queue. */
157
f03b093c
AC
158STATIC_INLINE_SIM_EVENTS\
159(sim_event **)
160next_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
8517f62b
AC
177STATIC_INLINE_SIM_EVENTS\
178(void)
f03b093c
AC
179sim_events_poll (SIM_DESC sd,
180 void *data)
8517f62b
AC
181{
182 /* just re-schedule in 1000 million ticks time */
f03b093c 183 sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
8517f62b
AC
184 sim_io_poll_quit (sd);
185}
186
187
f03b093c
AC
188/* "events" module install handler.
189 This is called via sim_module_install to install the "events" subsystem
190 into the simulator. */
191
fdd64f95
AC
192STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
193STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
194STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
195STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
196
f03b093c
AC
197EXTERN_SIM_EVENTS\
198(SIM_RC)
199sim_events_install (SIM_DESC sd)
200{
50a2a691 201 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
f03b093c
AC
202 sim_module_add_uninstall_fn (sd, sim_events_uninstall);
203 sim_module_add_init_fn (sd, sim_events_init);
fdd64f95
AC
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
213STATIC_SIM_EVENTS\
214(SIM_RC)
215sim_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
224STATIC_SIM_EVENTS\
225(SIM_RC)
226sim_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;
f03b093c
AC
233 return SIM_RC_OK;
234}
235
236
237/* Uninstall the "events" subsystem from the simulator. */
238
fdd64f95 239STATIC_SIM_EVENTS\
8517f62b 240(void)
f03b093c 241sim_events_uninstall (SIM_DESC sd)
8517f62b 242{
fdd64f95 243 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
f03b093c
AC
244 /* FIXME: free buffers, etc. */
245}
246
247
50a2a691
AC
248/* malloc/free */
249
250STATIC_INLINE_SIM_EVENTS\
251(sim_event *)
252sim_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
279STATIC_INLINE_SIM_EVENTS\
280(void)
281sim_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
f03b093c
AC
290/* Initialize the simulator event manager */
291
292EXTERN_SIM_EVENTS\
293(SIM_RC)
294sim_events_init (SIM_DESC sd)
295{
296 sim_events *events = STATE_EVENTS (sd);
8517f62b
AC
297
298 /* drain the interrupt queue */
50a2a691
AC
299 events->nr_held = 0;
300 if (events->held == NULL)
301 events->held = zalloc (sizeof (sim_event) * MAX_NR_SIGNAL_SIM_EVENTS);
8517f62b 302
f03b093c
AC
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;
50a2a691 313 sim_events_free (sd, dead);
f03b093c
AC
314 }
315 *queue = NULL;
316 }
8517f62b 317 }
f03b093c 318
8517f62b 319 /* wind time back to zero */
50a2a691 320 events->nr_ticks_to_process = 1; /* start by doing queue */
8517f62b
AC
321 events->time_of_event = 0;
322 events->time_from_event = 0;
fdd64f95
AC
323 events->elapsed_wallclock = 0;
324 events->resume_wallclock = 0;
8517f62b
AC
325
326 /* schedule our initial counter event */
f03b093c 327 sim_events_schedule (sd, 0, sim_events_poll, sd);
8517f62b
AC
328
329 /* from now on, except when the large-int event is being processed
330 the event queue is non empty */
f03b093c
AC
331 SIM_ASSERT (events->queue != NULL);
332
333 return SIM_RC_OK;
8517f62b
AC
334}
335
f03b093c 336
8517f62b
AC
337INLINE_SIM_EVENTS\
338(signed64)
f03b093c 339sim_events_time (SIM_DESC sd)
8517f62b 340{
f03b093c 341 sim_events *events = STATE_EVENTS (sd);
8517f62b
AC
342 return events->time_of_event - events->time_from_event;
343}
344
f03b093c 345
93e7a1b5
AC
346INLINE_SIM_EVENTS\
347(unsigned long)
348sim_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
8517f62b
AC
355STATIC_INLINE_SIM_EVENTS\
356(void)
f03b093c 357update_time_from_event (SIM_DESC sd)
8517f62b 358{
f03b093c
AC
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));
8517f62b
AC
373}
374
f03b093c 375
8517f62b
AC
376STATIC_INLINE_SIM_EVENTS\
377(void)
f03b093c
AC
378insert_sim_event (SIM_DESC sd,
379 sim_event *new_event,
380 signed64 delta)
8517f62b 381{
f03b093c 382 sim_events *events = STATE_EVENTS (sd);
8517f62b
AC
383 sim_event *curr;
384 sim_event **prev;
385 signed64 time_of_event;
386
387 if (delta < 0)
f03b093c
AC
388 sim_io_error (sd, "what is past is past!\n");
389
8517f62b 390 /* compute when the event should occure */
f03b093c
AC
391 time_of_event = sim_events_time (sd) + delta;
392
8517f62b
AC
393 /* find the queue insertion point - things are time ordered */
394 prev = &events->queue;
395 curr = events->queue;
f03b093c
AC
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
8517f62b
AC
405 /* insert it */
406 new_event->next = curr;
407 *prev = new_event;
408 new_event->time_of_event = time_of_event;
f03b093c 409
8517f62b 410 /* adjust the time until the first event */
f03b093c 411 update_time_from_event (sd);
8517f62b
AC
412}
413
f03b093c
AC
414
415EXTERN_SIM_EVENTS\
8517f62b 416(sim_event *)
f03b093c
AC
417sim_events_schedule (SIM_DESC sd,
418 signed64 delta_time,
419 sim_event_handler *handler,
420 void *data)
8517f62b 421{
50a2a691 422 sim_event *new_event = sim_events_zalloc (sd);
8517f62b
AC
423 new_event->data = data;
424 new_event->handler = handler;
f03b093c 425 new_event->watching = watch_timer;
8517f62b
AC
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
f03b093c 438EXTERN_SIM_EVENTS\
50a2a691
AC
439(void)
440sim_events_schedule_after_signal (SIM_DESC sd,
441 signed64 delta_time,
442 sim_event_handler *handler,
443 void *data)
8517f62b 444{
f03b093c 445 sim_events *events = STATE_EVENTS (sd);
50a2a691
AC
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 ++;
f90b720b 458 if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
50a2a691
AC
459 {
460 sim_engine_abort (NULL, NULL, NULL_CIA,
461 "sim_events_schedule_after_signal - buffer oveflow");
462 }
f03b093c 463
8517f62b
AC
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;
50a2a691
AC
468
469 events->work_pending = 1; /* notify main process */
470
f03b093c 471#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
50a2a691
AC
472 /*-UNLOCK-*/
473 sigprocmask (SIG_SETMASK, &old_mask, NULL);
8517f62b 474#endif
f03b093c
AC
475
476 ETRACE ((_ETRACE,
50a2a691 477 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
f03b093c
AC
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));
f03b093c 483}
8517f62b 484
8517f62b 485
f03b093c
AC
486EXTERN_SIM_EVENTS\
487(sim_event *)
488sim_events_watch_clock (SIM_DESC sd,
50a2a691 489 unsigned delta_ms_time,
f03b093c
AC
490 sim_event_handler *handler,
491 void *data)
492{
493 sim_events *events = STATE_EVENTS (sd);
50a2a691 494 sim_event *new_event = sim_events_zalloc (sd);
f03b093c
AC
495 /* type */
496 new_event->watching = watch_clock;
497 /* handler */
498 new_event->data = data;
499 new_event->handler = handler;
500 /* data */
fdd64f95
AC
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);
f03b093c
AC
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));
8517f62b
AC
518 return new_event;
519}
520
521
f03b093c
AC
522EXTERN_SIM_EVENTS\
523(sim_event *)
524sim_events_watch_sim (SIM_DESC sd,
525 void *host_addr,
526 int nr_bytes,
527 int byte_order,
2f2e6c5d 528 int is_within,
f03b093c
AC
529 unsigned64 lb,
530 unsigned64 ub,
531 sim_event_handler *handler,
532 void *data)
533{
534 sim_events *events = STATE_EVENTS (sd);
50a2a691 535 sim_event *new_event = sim_events_zalloc (sd);
f03b093c
AC
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;
2f2e6c5d 581 new_event->is_within = (is_within != 0);
f03b093c
AC
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
599EXTERN_SIM_EVENTS\
600(sim_event *)
601sim_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,
2f2e6c5d 606 int is_within,
f03b093c
AC
607 unsigned64 lb,
608 unsigned64 ub,
609 sim_event_handler *handler,
610 void *data)
611{
612 sim_events *events = STATE_EVENTS (sd);
50a2a691 613 sim_event *new_event = sim_events_zalloc (sd);
f03b093c
AC
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;
2f2e6c5d 660 new_event->is_within = (is_within != 0);
f03b093c
AC
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
678EXTERN_SIM_EVENTS\
8517f62b 679(void)
f03b093c
AC
680sim_events_deschedule (SIM_DESC sd,
681 sim_event *event_to_remove)
8517f62b 682{
f03b093c 683 sim_events *events = STATE_EVENTS (sd);
8517f62b 684 sim_event *to_remove = (sim_event*)event_to_remove;
f03b093c
AC
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));
50a2a691 706 sim_events_free (sd, dead);
f03b093c
AC
707 update_time_from_event (sd);
708 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
709 return;
710 }
711 }
8517f62b 712 }
f03b093c
AC
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));
8517f62b
AC
717}
718
719
f03b093c
AC
720STATIC_INLINE_SIM_EVENTS\
721(int)
722sim_watch_valid (SIM_DESC sd,
723 sim_event *to_do)
724{
725 switch (to_do->watching)
726 {
727
50a2a691 728#define WATCH_CORE(N,OP,EXT) \
1a70e182
AC
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;
f03b093c 800 }
f03b093c
AC
801#undef WATCH_CORE
802
50a2a691 803#define WATCH_SIM(N,OP,EXT) \
1a70e182
AC
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;
f03b093c
AC
830 }
831
1a70e182
AC
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 }
f03b093c 852
1a70e182
AC
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 }
f03b093c
AC
873#undef WATCH_SIM
874
875 case watch_clock: /* wallclock */
50a2a691 876 {
93e7a1b5 877 unsigned long elapsed_time = sim_events_elapsed_time (sd);
50a2a691
AC
878 return (elapsed_time >= to_do->wallclock);
879 }
f03b093c 880
50a2a691 881 default:
f03b093c
AC
882 sim_io_error (sd, "sim_watch_valid - bad switch");
883 break;
884
885 }
886 return 1;
887}
8517f62b
AC
888
889
890INLINE_SIM_EVENTS\
891(int)
f03b093c 892sim_events_tick (SIM_DESC sd)
8517f62b 893{
f03b093c 894 sim_events *events = STATE_EVENTS (sd);
4a203fba 895 SIM_ASSERT (events->nr_ticks_to_process == 0);
8517f62b 896
50a2a691
AC
897 /* this should only be called after the previous ticks have been
898 fully processed */
8517f62b
AC
899
900 /* Advance the time but *only* if there is nothing to process */
f03b093c
AC
901 if (events->work_pending
902 || events->time_from_event == 0)
903 {
4a203fba 904 events->nr_ticks_to_process += 1;
f03b093c
AC
905 return 1;
906 }
8517f62b
AC
907 else {
908 events->time_from_event -= 1;
909 return 0;
910 }
911}
912
913
50a2a691
AC
914INLINE_SIM_EVENTS\
915(int)
916sim_events_tickn (SIM_DESC sd,
f90b720b 917 int n)
50a2a691
AC
918{
919 sim_events *events = STATE_EVENTS (sd);
4a203fba 920 SIM_ASSERT (n > 0);
50a2a691
AC
921
922 /* this should only be called after the previous ticks have been
923 fully processed */
50a2a691
AC
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 {
4a203fba 929 events->nr_ticks_to_process += n;
50a2a691
AC
930 return 1;
931 }
932 else {
933 events->time_from_event -= n;
934 return 0;
935 }
936}
937
938
4a203fba
AC
939INLINE_SIM_EVENTS\
940(void)
941sim_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
f03b093c
AC
963INLINE_SIM_EVENTS\
964(void)
965sim_events_preprocess (SIM_DESC sd,
966 int events_were_last,
967 int events_were_next)
968{
969 sim_events *events = STATE_EVENTS(sd);
4a203fba 970 if (events_were_last)
f03b093c 971 {
4a203fba
AC
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);
f03b093c
AC
977 sim_events_process (sd);
978 }
979 else if (events_were_next)
980 {
981 /* Halted by the last processor */
f03b093c
AC
982 if (sim_events_tick (sd))
983 sim_events_process (sd);
984 }
985}
986
8517f62b
AC
987
988INLINE_SIM_EVENTS\
989(void)
f03b093c 990sim_events_process (SIM_DESC sd)
8517f62b 991{
f03b093c 992 sim_events *events = STATE_EVENTS(sd);
8517f62b
AC
993 signed64 event_time = sim_events_time(sd);
994
50a2a691 995 ASSERT (events->nr_ticks_to_process != 0);
8517f62b 996
4a203fba
AC
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. */
50a2a691 1004 if (events->nr_held > 0)
f03b093c 1005 {
50a2a691 1006 int i;
f03b093c 1007
8517f62b 1008#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
f03b093c
AC
1009 /*-LOCK-*/
1010 sigset_t old_mask;
1011 sigset_t new_mask;
1012 sigfillset(&new_mask);
1013 sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
8517f62b 1014#endif
4a203fba 1015
50a2a691
AC
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;
f03b093c 1025
8517f62b 1026#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
f03b093c
AC
1027 /*-UNLOCK-*/
1028 sigprocmask(SIG_SETMASK, &old_mask, NULL);
8517f62b 1029#endif
f03b093c 1030
f03b093c
AC
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;
f03b093c
AC
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));
50a2a691 1053 sim_events_free (sd, to_do);
f03b093c
AC
1054 handler (sd, data);
1055 }
1056 else
1057 {
1058 to_do->next = events->watchedpoints;
1059 events->watchedpoints = to_do;
1060 }
1061 }
1062
8517f62b 1063 /* consume all events for this or earlier times. Be careful to
f03b093c 1064 allow an event to appear/disappear under our feet */
50a2a691
AC
1065 while (events->queue->time_of_event <
1066 (event_time + events->nr_ticks_to_process))
f03b093c
AC
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));
50a2a691 1078 sim_events_free (sd, to_do);
f03b093c
AC
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
50a2a691 1088 /* re-caculate time for new events then advance the time */
8517f62b 1089 update_time_from_event(sd);
50a2a691
AC
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;
8517f62b
AC
1096}
1097
1098#endif