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