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