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