]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/sim-events.c
Short form of sample-size option had wrong value.
[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)
50a2a691 132#define SIM_EVENTS_POLL_RATE 0x100000
8517f62b
AC
133#endif
134
135
136#define _ETRACE sd
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__); \
8517f62b
AC
148 sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
149 sim_io_printf ARGS; \
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
8517f62b
AC
346STATIC_INLINE_SIM_EVENTS\
347(void)
f03b093c 348update_time_from_event (SIM_DESC sd)
8517f62b 349{
f03b093c
AC
350 sim_events *events = STATE_EVENTS (sd);
351 signed64 current_time = sim_events_time (sd);
352 if (events->queue != NULL)
353 {
354 events->time_from_event = (events->queue->time_of_event - current_time);
355 events->time_of_event = events->queue->time_of_event;
356 }
357 else
358 {
359 events->time_of_event = current_time - 1;
360 events->time_from_event = -1;
361 }
362 SIM_ASSERT (current_time == sim_events_time (sd));
363 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
8517f62b
AC
364}
365
f03b093c 366
8517f62b
AC
367STATIC_INLINE_SIM_EVENTS\
368(void)
f03b093c
AC
369insert_sim_event (SIM_DESC sd,
370 sim_event *new_event,
371 signed64 delta)
8517f62b 372{
f03b093c 373 sim_events *events = STATE_EVENTS (sd);
8517f62b
AC
374 sim_event *curr;
375 sim_event **prev;
376 signed64 time_of_event;
377
378 if (delta < 0)
f03b093c
AC
379 sim_io_error (sd, "what is past is past!\n");
380
8517f62b 381 /* compute when the event should occure */
f03b093c
AC
382 time_of_event = sim_events_time (sd) + delta;
383
8517f62b
AC
384 /* find the queue insertion point - things are time ordered */
385 prev = &events->queue;
386 curr = events->queue;
f03b093c
AC
387 while (curr != NULL && time_of_event >= curr->time_of_event)
388 {
389 SIM_ASSERT (curr->next == NULL
390 || curr->time_of_event <= curr->next->time_of_event);
391 prev = &curr->next;
392 curr = curr->next;
393 }
394 SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
395
8517f62b
AC
396 /* insert it */
397 new_event->next = curr;
398 *prev = new_event;
399 new_event->time_of_event = time_of_event;
f03b093c 400
8517f62b 401 /* adjust the time until the first event */
f03b093c 402 update_time_from_event (sd);
8517f62b
AC
403}
404
f03b093c
AC
405
406EXTERN_SIM_EVENTS\
8517f62b 407(sim_event *)
f03b093c
AC
408sim_events_schedule (SIM_DESC sd,
409 signed64 delta_time,
410 sim_event_handler *handler,
411 void *data)
8517f62b 412{
50a2a691 413 sim_event *new_event = sim_events_zalloc (sd);
8517f62b
AC
414 new_event->data = data;
415 new_event->handler = handler;
f03b093c 416 new_event->watching = watch_timer;
8517f62b
AC
417 insert_sim_event(sd, new_event, delta_time);
418 ETRACE((_ETRACE,
419 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
420 (long)sim_events_time(sd),
421 (long)new_event,
422 (long)new_event->time_of_event,
423 (long)new_event->handler,
424 (long)new_event->data));
425 return new_event;
426}
427
428
f03b093c 429EXTERN_SIM_EVENTS\
50a2a691
AC
430(void)
431sim_events_schedule_after_signal (SIM_DESC sd,
432 signed64 delta_time,
433 sim_event_handler *handler,
434 void *data)
8517f62b 435{
f03b093c 436 sim_events *events = STATE_EVENTS (sd);
50a2a691
AC
437 sim_event *new_event;
438#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
439 /*-LOCK-*/
440 sigset_t old_mask;
441 sigset_t new_mask;
442 sigfillset(&new_mask);
443 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
444#endif
445
446 /* allocate an event entry from the signal buffer */
447 new_event = &events->held [events->nr_held];
448 events->nr_held ++;
f90b720b 449 if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
50a2a691
AC
450 {
451 sim_engine_abort (NULL, NULL, NULL_CIA,
452 "sim_events_schedule_after_signal - buffer oveflow");
453 }
f03b093c 454
8517f62b
AC
455 new_event->data = data;
456 new_event->handler = handler;
457 new_event->time_of_event = delta_time; /* work it out later */
458 new_event->next = NULL;
50a2a691
AC
459
460 events->work_pending = 1; /* notify main process */
461
f03b093c 462#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
50a2a691
AC
463 /*-UNLOCK-*/
464 sigprocmask (SIG_SETMASK, &old_mask, NULL);
8517f62b 465#endif
f03b093c
AC
466
467 ETRACE ((_ETRACE,
50a2a691 468 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
f03b093c
AC
469 (long)sim_events_time(sd),
470 (long)new_event,
471 (long)new_event->time_of_event,
472 (long)new_event->handler,
473 (long)new_event->data));
f03b093c 474}
8517f62b 475
8517f62b 476
f03b093c
AC
477EXTERN_SIM_EVENTS\
478(sim_event *)
479sim_events_watch_clock (SIM_DESC sd,
50a2a691 480 unsigned delta_ms_time,
f03b093c
AC
481 sim_event_handler *handler,
482 void *data)
483{
484 sim_events *events = STATE_EVENTS (sd);
50a2a691 485 sim_event *new_event = sim_events_zalloc (sd);
f03b093c
AC
486 /* type */
487 new_event->watching = watch_clock;
488 /* handler */
489 new_event->data = data;
490 new_event->handler = handler;
491 /* data */
fdd64f95
AC
492 if (events->resume_wallclock == 0)
493 new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
494 else
495 new_event->wallclock = (events->elapsed_wallclock
496 + sim_elapsed_time_since (events->resume_wallclock)
497 + delta_ms_time);
f03b093c
AC
498 /* insert */
499 new_event->next = events->watchpoints;
500 events->watchpoints = new_event;
501 events->work_pending = 1;
502 ETRACE ((_ETRACE,
503 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
504 (long)sim_events_time (sd),
505 (long)new_event,
506 (long)new_event->wallclock,
507 (long)new_event->handler,
508 (long)new_event->data));
8517f62b
AC
509 return new_event;
510}
511
512
f03b093c
AC
513EXTERN_SIM_EVENTS\
514(sim_event *)
515sim_events_watch_sim (SIM_DESC sd,
516 void *host_addr,
517 int nr_bytes,
518 int byte_order,
2f2e6c5d 519 int is_within,
f03b093c
AC
520 unsigned64 lb,
521 unsigned64 ub,
522 sim_event_handler *handler,
523 void *data)
524{
525 sim_events *events = STATE_EVENTS (sd);
50a2a691 526 sim_event *new_event = sim_events_zalloc (sd);
f03b093c
AC
527 /* type */
528 switch (byte_order)
529 {
530 case 0:
531 switch (nr_bytes)
532 {
533 case 1: new_event->watching = watch_sim_host_1; break;
534 case 2: new_event->watching = watch_sim_host_2; break;
535 case 4: new_event->watching = watch_sim_host_4; break;
536 case 8: new_event->watching = watch_sim_host_8; break;
537 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
538 }
539 break;
540 case BIG_ENDIAN:
541 switch (nr_bytes)
542 {
543 case 1: new_event->watching = watch_sim_be_1; break;
544 case 2: new_event->watching = watch_sim_be_2; break;
545 case 4: new_event->watching = watch_sim_be_4; break;
546 case 8: new_event->watching = watch_sim_be_8; break;
547 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
548 }
549 break;
550 case LITTLE_ENDIAN:
551 switch (nr_bytes)
552 {
553 case 1: new_event->watching = watch_sim_le_1; break;
554 case 2: new_event->watching = watch_sim_le_2; break;
555 case 4: new_event->watching = watch_sim_le_4; break;
556 case 8: new_event->watching = watch_sim_le_8; break;
557 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
558 }
559 break;
560 default:
561 sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
562 }
563 /* handler */
564 new_event->data = data;
565 new_event->handler = handler;
566 /* data */
567 new_event->host_addr = host_addr;
568 new_event->lb = lb;
569 new_event->lb64 = lb;
570 new_event->ub = ub;
571 new_event->ub64 = ub;
2f2e6c5d 572 new_event->is_within = (is_within != 0);
f03b093c
AC
573 /* insert */
574 new_event->next = events->watchpoints;
575 events->watchpoints = new_event;
576 events->work_pending = 1;
577 ETRACE ((_ETRACE,
578 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
579 (long)sim_events_time (sd),
580 (long)new_event,
581 (long)new_event->host_addr,
582 (long)new_event->lb,
583 (long)new_event->ub,
584 (long)new_event->handler,
585 (long)new_event->data));
586 return new_event;
587}
588
589
590EXTERN_SIM_EVENTS\
591(sim_event *)
592sim_events_watch_core (SIM_DESC sd,
593 address_word core_addr,
594 sim_core_maps core_map,
595 int nr_bytes,
596 int byte_order,
2f2e6c5d 597 int is_within,
f03b093c
AC
598 unsigned64 lb,
599 unsigned64 ub,
600 sim_event_handler *handler,
601 void *data)
602{
603 sim_events *events = STATE_EVENTS (sd);
50a2a691 604 sim_event *new_event = sim_events_zalloc (sd);
f03b093c
AC
605 /* type */
606 switch (byte_order)
607 {
608 case 0:
609 switch (nr_bytes)
610 {
611 case 1: new_event->watching = watch_core_targ_1; break;
612 case 2: new_event->watching = watch_core_targ_2; break;
613 case 4: new_event->watching = watch_core_targ_4; break;
614 case 8: new_event->watching = watch_core_targ_8; break;
615 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
616 }
617 break;
618 case BIG_ENDIAN:
619 switch (nr_bytes)
620 {
621 case 1: new_event->watching = watch_core_be_1; break;
622 case 2: new_event->watching = watch_core_be_2; break;
623 case 4: new_event->watching = watch_core_be_4; break;
624 case 8: new_event->watching = watch_core_be_8; break;
625 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
626 }
627 break;
628 case LITTLE_ENDIAN:
629 switch (nr_bytes)
630 {
631 case 1: new_event->watching = watch_core_le_1; break;
632 case 2: new_event->watching = watch_core_le_2; break;
633 case 4: new_event->watching = watch_core_le_4; break;
634 case 8: new_event->watching = watch_core_le_8; break;
635 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
636 }
637 break;
638 default:
639 sim_io_error (sd, "sim_events_watch_core - invalid byte order");
640 }
641 /* handler */
642 new_event->data = data;
643 new_event->handler = handler;
644 /* data */
645 new_event->core_addr = core_addr;
646 new_event->core_map = core_map;
647 new_event->lb = lb;
648 new_event->lb64 = lb;
649 new_event->ub = ub;
650 new_event->ub64 = ub;
2f2e6c5d 651 new_event->is_within = (is_within != 0);
f03b093c
AC
652 /* insert */
653 new_event->next = events->watchpoints;
654 events->watchpoints = new_event;
655 events->work_pending = 1;
656 ETRACE ((_ETRACE,
657 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
658 (long)sim_events_time (sd),
659 (long)new_event,
660 (long)new_event->host_addr,
661 (long)new_event->lb,
662 (long)new_event->ub,
663 (long)new_event->handler,
664 (long)new_event->data));
665 return new_event;
666}
667
668
669EXTERN_SIM_EVENTS\
8517f62b 670(void)
f03b093c
AC
671sim_events_deschedule (SIM_DESC sd,
672 sim_event *event_to_remove)
8517f62b 673{
f03b093c 674 sim_events *events = STATE_EVENTS (sd);
8517f62b 675 sim_event *to_remove = (sim_event*)event_to_remove;
f03b093c
AC
676 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
677 if (event_to_remove != NULL)
678 {
679 sim_event **queue = NULL;
680 while ((queue = next_event_queue (sd, queue)) != NULL)
681 {
682 sim_event **ptr_to_current;
683 for (ptr_to_current = queue;
684 *ptr_to_current != NULL && *ptr_to_current != to_remove;
685 ptr_to_current = &(*ptr_to_current)->next);
686 if (*ptr_to_current == to_remove)
687 {
688 sim_event *dead = *ptr_to_current;
689 *ptr_to_current = dead->next;
690 ETRACE ((_ETRACE,
691 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
692 (long) sim_events_time (sd),
693 (long) event_to_remove,
694 (long) dead->time_of_event,
695 (long) dead->handler,
696 (long) dead->data));
50a2a691 697 sim_events_free (sd, dead);
f03b093c
AC
698 update_time_from_event (sd);
699 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
700 return;
701 }
702 }
8517f62b 703 }
f03b093c
AC
704 ETRACE ((_ETRACE,
705 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
706 (long) sim_events_time (sd),
707 (long) event_to_remove));
8517f62b
AC
708}
709
710
f03b093c
AC
711STATIC_INLINE_SIM_EVENTS\
712(int)
713sim_watch_valid (SIM_DESC sd,
714 sim_event *to_do)
715{
716 switch (to_do->watching)
717 {
718
50a2a691 719#define WATCH_CORE(N,OP,EXT) \
1a70e182
AC
720 int ok; \
721 unsigned_##N word = 0; \
722 int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
723 to_do->core_addr, sizeof (word)); \
724 OP (word); \
725 ok = (nr_read == sizeof (unsigned_##N) \
726 && (to_do->is_within \
727 == (word >= to_do->lb##EXT \
728 && word <= to_do->ub##EXT)));
729
730 case watch_core_targ_1:
731 {
732 WATCH_CORE (1, T2H,);
733 return ok;
734 }
735 case watch_core_targ_2:
736 {
737 WATCH_CORE (2, T2H,);
738 return ok;
739 }
740 case watch_core_targ_4:
741 {
742 WATCH_CORE (4, T2H,);
743 return ok;
744 }
745 case watch_core_targ_8:
746 {
747 WATCH_CORE (8, T2H,64);
748 return ok;
749 }
750
751 case watch_core_be_1:
752 {
753 WATCH_CORE (1, BE2H,);
754 return ok;
755 }
756 case watch_core_be_2:
757 {
758 WATCH_CORE (2, BE2H,);
759 return ok;
760 }
761 case watch_core_be_4:
762 {
763 WATCH_CORE (4, BE2H,);
764 return ok;
765 }
766 case watch_core_be_8:
767 {
768 WATCH_CORE (8, BE2H,64);
769 return ok;
770 }
771
772 case watch_core_le_1:
773 {
774 WATCH_CORE (1, LE2H,);
775 return ok;
776 }
777 case watch_core_le_2:
778 {
779 WATCH_CORE (2, LE2H,);
780 return ok;
781 }
782 case watch_core_le_4:
783 {
784 WATCH_CORE (4, LE2H,);
785 return ok;
786 }
787 case watch_core_le_8:
788 {
789 WATCH_CORE (8, LE2H,64);
790 return ok;
f03b093c 791 }
f03b093c
AC
792#undef WATCH_CORE
793
50a2a691 794#define WATCH_SIM(N,OP,EXT) \
1a70e182
AC
795 int ok; \
796 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
797 OP (word); \
798 ok = (to_do->is_within \
799 == (word >= to_do->lb##EXT \
800 && word <= to_do->ub##EXT));
801
802 case watch_sim_host_1:
803 {
804 WATCH_SIM (1, word = ,);
805 return ok;
806 }
807 case watch_sim_host_2:
808 {
809 WATCH_SIM (2, word = ,);
810 return ok;
811 }
812 case watch_sim_host_4:
813 {
814 WATCH_SIM (4, word = ,);
815 return ok;
816 }
817 case watch_sim_host_8:
818 {
819 WATCH_SIM (8, word = ,64);
820 return ok;
f03b093c
AC
821 }
822
1a70e182
AC
823 case watch_sim_be_1:
824 {
825 WATCH_SIM (1, BE2H,);
826 return ok;
827 }
828 case watch_sim_be_2:
829 {
830 WATCH_SIM (2, BE2H,);
831 return ok;
832 }
833 case watch_sim_be_4:
834 {
835 WATCH_SIM (4, BE2H,);
836 return ok;
837 }
838 case watch_sim_be_8:
839 {
840 WATCH_SIM (8, BE2H,64);
841 return ok;
842 }
f03b093c 843
1a70e182
AC
844 case watch_sim_le_1:
845 {
846 WATCH_SIM (1, LE2H,);
847 return ok;
848 }
849 case watch_sim_le_2:
850 {
851 WATCH_SIM (1, LE2H,);
852 return ok;
853 }
854 case watch_sim_le_4:
855 {
856 WATCH_SIM (1, LE2H,);
857 return ok;
858 }
859 case watch_sim_le_8:
860 {
861 WATCH_SIM (1, LE2H,64);
862 return ok;
863 }
f03b093c
AC
864#undef WATCH_SIM
865
866 case watch_clock: /* wallclock */
50a2a691 867 {
fdd64f95
AC
868 unsigned long elapsed_time =
869 (sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock)
870 + STATE_EVENTS (sd)->elapsed_wallclock);
50a2a691
AC
871 return (elapsed_time >= to_do->wallclock);
872 }
f03b093c 873
50a2a691 874 default:
f03b093c
AC
875 sim_io_error (sd, "sim_watch_valid - bad switch");
876 break;
877
878 }
879 return 1;
880}
8517f62b
AC
881
882
883INLINE_SIM_EVENTS\
884(int)
f03b093c 885sim_events_tick (SIM_DESC sd)
8517f62b 886{
f03b093c 887 sim_events *events = STATE_EVENTS (sd);
8517f62b 888
50a2a691
AC
889 /* this should only be called after the previous ticks have been
890 fully processed */
891 SIM_ASSERT (events->nr_ticks_to_process == 0);
8517f62b
AC
892
893 /* Advance the time but *only* if there is nothing to process */
f03b093c
AC
894 if (events->work_pending
895 || events->time_from_event == 0)
896 {
50a2a691 897 events->nr_ticks_to_process = 1;
f03b093c
AC
898 return 1;
899 }
8517f62b
AC
900 else {
901 events->time_from_event -= 1;
902 return 0;
903 }
904}
905
906
50a2a691
AC
907INLINE_SIM_EVENTS\
908(int)
909sim_events_tickn (SIM_DESC sd,
f90b720b 910 int n)
50a2a691
AC
911{
912 sim_events *events = STATE_EVENTS (sd);
913
914 /* this should only be called after the previous ticks have been
915 fully processed */
916 SIM_ASSERT (events->nr_ticks_to_process == 0);
917 SIM_ASSERT (n > 0);
918
919 /* Advance the time but *only* if there is nothing to process */
920 if (events->work_pending
921 || events->time_from_event < n)
922 {
923 events->nr_ticks_to_process = n;
924 return 1;
925 }
926 else {
927 events->time_from_event -= n;
928 return 0;
929 }
930}
931
932
f03b093c
AC
933INLINE_SIM_EVENTS\
934(void)
935sim_events_preprocess (SIM_DESC sd,
936 int events_were_last,
937 int events_were_next)
938{
939 sim_events *events = STATE_EVENTS(sd);
50a2a691 940 if (events->nr_ticks_to_process != 0)
f03b093c
AC
941 {
942 /* Halted midway through event processing */
943 ASSERT (events_were_last && events_were_next);
944 sim_events_process (sd);
945 }
946 else if (events_were_next)
947 {
948 /* Halted by the last processor */
50a2a691 949 ASSERT (events->nr_ticks_to_process == 0 && !events_were_last);
f03b093c
AC
950 if (sim_events_tick (sd))
951 sim_events_process (sd);
952 }
953}
954
8517f62b
AC
955
956INLINE_SIM_EVENTS\
957(void)
f03b093c 958sim_events_process (SIM_DESC sd)
8517f62b 959{
f03b093c 960 sim_events *events = STATE_EVENTS(sd);
8517f62b
AC
961 signed64 event_time = sim_events_time(sd);
962
50a2a691 963 ASSERT (events->nr_ticks_to_process != 0);
8517f62b 964
f03b093c
AC
965 /* move any events that were queued by any signal handlers onto
966 the real event queue. */
50a2a691 967 if (events->nr_held > 0)
f03b093c 968 {
50a2a691 969 int i;
f03b093c 970
8517f62b 971#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
f03b093c
AC
972 /*-LOCK-*/
973 sigset_t old_mask;
974 sigset_t new_mask;
975 sigfillset(&new_mask);
976 sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
8517f62b 977#endif
f03b093c 978
50a2a691
AC
979 for (i = 0; i < events->nr_held; i++)
980 {
981 sim_event *entry = &events->held [i];
982 sim_events_schedule (sd,
983 entry->time_of_event,
984 entry->handler,
985 entry->data);
986 }
987 events->nr_held = 0;
f03b093c 988
8517f62b 989#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
f03b093c
AC
990 /*-UNLOCK-*/
991 sigprocmask(SIG_SETMASK, &old_mask, NULL);
8517f62b 992#endif
f03b093c 993
f03b093c
AC
994 }
995
996 /* Process any watchpoints. Be careful to allow a watchpoint to
997 appear/disappear under our feet.
998 To ensure that watchpoints are processed only once per cycle,
999 they are moved onto a watched queue, this returned to the
1000 watchpoint queue when all queue processing has been
1001 completed. */
1002 while (events->watchpoints != NULL)
1003 {
1004 sim_event *to_do = events->watchpoints;
1005 events->watchpoints = to_do->next;
1006 if (sim_watch_valid (sd, to_do))
1007 {
1008 sim_event_handler *handler = to_do->handler;
1009 void *data = to_do->data;
f03b093c
AC
1010 ETRACE((_ETRACE,
1011 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
1012 (long) event_time,
1013 (long) to_do,
1014 (long) handler,
1015 (long) data));
50a2a691 1016 sim_events_free (sd, to_do);
f03b093c
AC
1017 handler (sd, data);
1018 }
1019 else
1020 {
1021 to_do->next = events->watchedpoints;
1022 events->watchedpoints = to_do;
1023 }
1024 }
1025
8517f62b 1026 /* consume all events for this or earlier times. Be careful to
f03b093c 1027 allow an event to appear/disappear under our feet */
50a2a691
AC
1028 while (events->queue->time_of_event <
1029 (event_time + events->nr_ticks_to_process))
f03b093c
AC
1030 {
1031 sim_event *to_do = events->queue;
1032 sim_event_handler *handler = to_do->handler;
1033 void *data = to_do->data;
1034 events->queue = to_do->next;
1035 ETRACE((_ETRACE,
1036 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
1037 (long) event_time,
1038 (long) to_do,
1039 (long) handler,
1040 (long) data));
50a2a691 1041 sim_events_free (sd, to_do);
f03b093c
AC
1042 handler (sd, data);
1043 }
1044
1045 /* put things back where they belong ready for the next iteration */
1046 events->watchpoints = events->watchedpoints;
1047 events->watchedpoints = NULL;
1048 if (events->watchpoints != NULL)
1049 events->work_pending = 1;
1050
50a2a691 1051 /* re-caculate time for new events then advance the time */
8517f62b 1052 update_time_from_event(sd);
50a2a691
AC
1053 SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1054 SIM_ASSERT (events->queue != NULL); /* always poll event */
1055 events->time_from_event -= events->nr_ticks_to_process;
1056
1057 /* this round of processing complete */
1058 events->nr_ticks_to_process = 0;
8517f62b
AC
1059}
1060
1061#endif