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