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