1 /* Simulator tracing/debugging support. 2 Copyright (C) 1997-2015 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5 This file is part of GDB, the GNU debugger. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "sim-main.h" 21 #include "sim-io.h" 22 #include "sim-options.h" 23 #include "sim-fpu.h" 24 25 #include "bfd.h" 26 #include "libiberty.h" 27 28 #include "sim-assert.h" 29 30 #ifdef HAVE_STRING_H 31 #include <string.h> 32 #else 33 #ifdef HAVE_STRINGS_H 34 #include <strings.h> 35 #endif 36 #endif 37 #ifdef HAVE_STDLIB_H 38 #include <stdlib.h> 39 #endif 40 41 #ifndef SIZE_PHASE 42 #define SIZE_PHASE 8 43 #endif 44 45 #ifndef SIZE_LOCATION 46 #define SIZE_LOCATION 20 47 #endif 48 49 #ifndef SIZE_PC 50 #define SIZE_PC 6 51 #endif 52 53 #ifndef SIZE_LINE_NUMBER 54 #define SIZE_LINE_NUMBER 4 55 #endif 56 57 static MODULE_INIT_FN trace_init; 58 static MODULE_UNINSTALL_FN trace_uninstall; 59 60 static DECLARE_OPTION_HANDLER (trace_option_handler); 61 62 enum { 63 OPTION_TRACE_INSN = OPTION_START, 64 OPTION_TRACE_DECODE, 65 OPTION_TRACE_EXTRACT, 66 OPTION_TRACE_LINENUM, 67 OPTION_TRACE_MEMORY, 68 OPTION_TRACE_MODEL, 69 OPTION_TRACE_ALU, 70 OPTION_TRACE_CORE, 71 OPTION_TRACE_EVENTS, 72 OPTION_TRACE_FPU, 73 OPTION_TRACE_BRANCH, 74 OPTION_TRACE_SEMANTICS, 75 OPTION_TRACE_RANGE, 76 OPTION_TRACE_FUNCTION, 77 OPTION_TRACE_DEBUG, 78 OPTION_TRACE_FILE, 79 OPTION_TRACE_VPU, 80 OPTION_TRACE_SYSCALL, 81 OPTION_TRACE_REGISTER 82 }; 83 84 static const OPTION trace_options[] = 85 { 86 /* This table is organized to group related instructions together. */ 87 { {"trace", optional_argument, NULL, 't'}, 88 't', "on|off", "Trace useful things", 89 trace_option_handler, NULL }, 90 { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN}, 91 '\0', "on|off", "Perform instruction tracing", 92 trace_option_handler, NULL }, 93 { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE}, 94 '\0', "on|off", "Trace instruction decoding", 95 trace_option_handler, NULL }, 96 { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT}, 97 '\0', "on|off", "Trace instruction extraction", 98 trace_option_handler, NULL }, 99 { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM}, 100 '\0', "on|off", "Perform line number tracing (implies --trace-insn)", 101 trace_option_handler, NULL }, 102 { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY}, 103 '\0', "on|off", "Trace memory operations", 104 trace_option_handler, NULL }, 105 { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU}, 106 '\0', "on|off", "Trace ALU (Arithmetic Logic Unit) operations", 107 trace_option_handler, NULL }, 108 { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU}, 109 '\0', "on|off", "Trace FPU (Floating Point Unit) operations", 110 trace_option_handler, NULL }, 111 { {"trace-vpu", optional_argument, NULL, OPTION_TRACE_VPU}, 112 '\0', "on|off", "Trace VPU (Vector Processing Unit) operations", 113 trace_option_handler, NULL }, 114 { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH}, 115 '\0', "on|off", "Trace branching", 116 trace_option_handler, NULL }, 117 { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS}, 118 '\0', "on|off", "Perform ALU, FPU, VPU, MEMORY, and BRANCH tracing", 119 trace_option_handler, NULL }, 120 { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL}, 121 '\0', "on|off", "Include model performance data", 122 trace_option_handler, NULL }, 123 { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE}, 124 '\0', "on|off", "Trace core operations", 125 trace_option_handler, NULL }, 126 { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS}, 127 '\0', "on|off", "Trace events", 128 trace_option_handler, NULL }, 129 { {"trace-syscall", optional_argument, NULL, OPTION_TRACE_SYSCALL}, 130 '\0', "on|off", "Trace system calls", 131 trace_option_handler, NULL }, 132 { {"trace-register", optional_argument, NULL, OPTION_TRACE_REGISTER}, 133 '\0', "on|off", "Trace cpu register accesses", 134 trace_option_handler, NULL }, 135 #ifdef SIM_HAVE_ADDR_RANGE 136 { {"trace-range", required_argument, NULL, OPTION_TRACE_RANGE}, 137 '\0', "START,END", "Specify range of addresses for instruction tracing", 138 trace_option_handler, NULL }, 139 #if 0 /*wip*/ 140 { {"trace-function", required_argument, NULL, OPTION_TRACE_FUNCTION}, 141 '\0', "FUNCTION", "Specify function to trace", 142 trace_option_handler, NULL }, 143 #endif 144 #endif 145 { {"trace-debug", optional_argument, NULL, OPTION_TRACE_DEBUG}, 146 '\0', "on|off", "Add information useful for debugging the simulator to the tracing output", 147 trace_option_handler, NULL }, 148 { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE}, 149 '\0', "FILE NAME", "Specify tracing output file", 150 trace_option_handler, NULL }, 151 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } 152 }; 153 154 /* Set/reset the trace options indicated in MASK. */ 155 156 static SIM_RC 157 set_trace_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg) 158 { 159 int trace_nr; 160 int cpu_nr; 161 int trace_val = 1; 162 163 if (arg != NULL) 164 { 165 if (strcmp (arg, "yes") == 0 166 || strcmp (arg, "on") == 0 167 || strcmp (arg, "1") == 0) 168 trace_val = 1; 169 else if (strcmp (arg, "no") == 0 170 || strcmp (arg, "off") == 0 171 || strcmp (arg, "0") == 0) 172 trace_val = 0; 173 else 174 { 175 sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name); 176 return SIM_RC_FAIL; 177 } 178 } 179 180 /* Update applicable trace bits. */ 181 for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) 182 { 183 if ((mask & (1 << trace_nr)) == 0) 184 continue; 185 186 /* Set non-cpu specific values. */ 187 STATE_TRACE_FLAGS (sd)[trace_nr] = trace_val; 188 189 /* Set cpu values. */ 190 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 191 { 192 CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val; 193 } 194 } 195 196 /* Re-compute the cpu trace summary. */ 197 if (trace_val) 198 { 199 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 200 CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; 201 } 202 else 203 { 204 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 205 { 206 CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 0; 207 for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) 208 { 209 if (CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr]) 210 { 211 CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; 212 break; 213 } 214 } 215 } 216 } 217 218 return SIM_RC_OK; 219 } 220 221 /* Set one trace option based on its IDX value. */ 222 223 static SIM_RC 224 set_trace_option (SIM_DESC sd, const char *name, int idx, const char *arg) 225 { 226 return set_trace_option_mask (sd, name, 1 << idx, arg); 227 } 228 229 230 static SIM_RC 231 trace_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, 232 char *arg, int is_command) 233 { 234 int n; 235 236 switch (opt) 237 { 238 case 't' : 239 if (!WITH_TRACE_ANY_P) 240 sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n"); 241 else 242 return set_trace_option_mask (sd, "trace", TRACE_USEFUL_MASK, arg); 243 break; 244 245 case OPTION_TRACE_INSN : 246 if (WITH_TRACE_INSN_P) 247 return set_trace_option (sd, "-insn", TRACE_INSN_IDX, arg); 248 else 249 sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n"); 250 break; 251 252 case OPTION_TRACE_DECODE : 253 if (WITH_TRACE_DECODE_P) 254 return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg); 255 else 256 sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n"); 257 break; 258 259 case OPTION_TRACE_EXTRACT : 260 if (WITH_TRACE_EXTRACT_P) 261 return set_trace_option (sd, "-extract", TRACE_EXTRACT_IDX, arg); 262 else 263 sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n"); 264 break; 265 266 case OPTION_TRACE_LINENUM : 267 if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P) 268 { 269 if (set_trace_option (sd, "-linenum", TRACE_LINENUM_IDX, arg) != SIM_RC_OK 270 || set_trace_option (sd, "-linenum", TRACE_INSN_IDX, arg) != SIM_RC_OK) 271 return SIM_RC_FAIL; 272 } 273 else 274 sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n"); 275 break; 276 277 case OPTION_TRACE_MEMORY : 278 if (WITH_TRACE_MEMORY_P) 279 return set_trace_option (sd, "-memory", TRACE_MEMORY_IDX, arg); 280 else 281 sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n"); 282 break; 283 284 case OPTION_TRACE_MODEL : 285 if (WITH_TRACE_MODEL_P) 286 return set_trace_option (sd, "-model", TRACE_MODEL_IDX, arg); 287 else 288 sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n"); 289 break; 290 291 case OPTION_TRACE_ALU : 292 if (WITH_TRACE_ALU_P) 293 return set_trace_option (sd, "-alu", TRACE_ALU_IDX, arg); 294 else 295 sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n"); 296 break; 297 298 case OPTION_TRACE_CORE : 299 if (WITH_TRACE_CORE_P) 300 return set_trace_option (sd, "-core", TRACE_CORE_IDX, arg); 301 else 302 sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n"); 303 break; 304 305 case OPTION_TRACE_EVENTS : 306 if (WITH_TRACE_EVENTS_P) 307 return set_trace_option (sd, "-events", TRACE_EVENTS_IDX, arg); 308 else 309 sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n"); 310 break; 311 312 case OPTION_TRACE_FPU : 313 if (WITH_TRACE_FPU_P) 314 return set_trace_option (sd, "-fpu", TRACE_FPU_IDX, arg); 315 else 316 sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n"); 317 break; 318 319 case OPTION_TRACE_VPU : 320 if (WITH_TRACE_VPU_P) 321 return set_trace_option (sd, "-vpu", TRACE_VPU_IDX, arg); 322 else 323 sim_io_eprintf (sd, "VPU tracing not compiled in, `--trace-vpu' ignored\n"); 324 break; 325 326 case OPTION_TRACE_BRANCH : 327 if (WITH_TRACE_BRANCH_P) 328 return set_trace_option (sd, "-branch", TRACE_BRANCH_IDX, arg); 329 else 330 sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n"); 331 break; 332 333 case OPTION_TRACE_SYSCALL : 334 if (WITH_TRACE_SYSCALL_P) 335 return set_trace_option (sd, "-syscall", TRACE_SYSCALL_IDX, arg); 336 else 337 sim_io_eprintf (sd, "System call tracing not compiled in, `--trace-syscall' ignored\n"); 338 break; 339 340 case OPTION_TRACE_REGISTER : 341 if (WITH_TRACE_REGISTER_P) 342 return set_trace_option (sd, "-register", TRACE_REGISTER_IDX, arg); 343 else 344 sim_io_eprintf (sd, "Register tracing not compiled in, `--trace-register' ignored\n"); 345 break; 346 347 case OPTION_TRACE_SEMANTICS : 348 if (WITH_TRACE_ALU_P 349 && WITH_TRACE_FPU_P 350 && WITH_TRACE_MEMORY_P 351 && WITH_TRACE_BRANCH_P) 352 { 353 if (set_trace_option (sd, "-semantics", TRACE_ALU_IDX, arg) != SIM_RC_OK 354 || set_trace_option (sd, "-semantics", TRACE_FPU_IDX, arg) != SIM_RC_OK 355 || set_trace_option (sd, "-semantics", TRACE_VPU_IDX, arg) != SIM_RC_OK 356 || set_trace_option (sd, "-semantics", TRACE_MEMORY_IDX, arg) != SIM_RC_OK 357 || set_trace_option (sd, "-semantics", TRACE_BRANCH_IDX, arg) != SIM_RC_OK) 358 return SIM_RC_FAIL; 359 } 360 else 361 sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n"); 362 break; 363 364 #ifdef SIM_HAVE_ADDR_RANGE 365 case OPTION_TRACE_RANGE : 366 if (WITH_TRACE_ANY_P) 367 { 368 int cpu_nr; 369 char *chp = arg; 370 unsigned long start,end; 371 start = strtoul (chp, &chp, 0); 372 if (*chp != ',') 373 { 374 sim_io_eprintf (sd, "--trace-range missing END argument\n"); 375 return SIM_RC_FAIL; 376 } 377 end = strtoul (chp + 1, NULL, 0); 378 /* FIXME: Argument validation. */ 379 if (cpu != NULL) 380 sim_addr_range_add (TRACE_RANGE (CPU_PROFILE_DATA (cpu)), 381 start, end); 382 else 383 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) 384 sim_addr_range_add (TRACE_RANGE (CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))), 385 start, end); 386 } 387 else 388 sim_io_eprintf (sd, "Tracing not compiled in, `--trace-range' ignored\n"); 389 break; 390 391 case OPTION_TRACE_FUNCTION : 392 if (WITH_TRACE_ANY_P) 393 { 394 /*wip: need to compute function range given name*/ 395 } 396 else 397 sim_io_eprintf (sd, "Tracing not compiled in, `--trace-function' ignored\n"); 398 break; 399 #endif /* SIM_HAVE_ADDR_RANGE */ 400 401 case OPTION_TRACE_DEBUG : 402 if (WITH_TRACE_DEBUG_P) 403 return set_trace_option (sd, "-debug", TRACE_DEBUG_IDX, arg); 404 else 405 sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n"); 406 break; 407 408 case OPTION_TRACE_FILE : 409 if (!WITH_TRACE_ANY_P) 410 sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n"); 411 else 412 { 413 FILE *f = fopen (arg, "w"); 414 415 if (f == NULL) 416 { 417 sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg); 418 return SIM_RC_FAIL; 419 } 420 for (n = 0; n < MAX_NR_PROCESSORS; ++n) 421 TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f; 422 TRACE_FILE (STATE_TRACE_DATA (sd)) = f; 423 } 424 break; 425 } 426 427 return SIM_RC_OK; 428 } 429 430 /* Install tracing support. */ 431 432 SIM_RC 433 trace_install (SIM_DESC sd) 434 { 435 int i; 436 437 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 438 439 sim_add_option_table (sd, NULL, trace_options); 440 memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd))); 441 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 442 memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0, 443 sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i)))); 444 sim_module_add_init_fn (sd, trace_init); 445 sim_module_add_uninstall_fn (sd, trace_uninstall); 446 return SIM_RC_OK; 447 } 448 449 static SIM_RC 450 trace_init (SIM_DESC sd) 451 { 452 #ifdef SIM_HAVE_ADDR_RANGE 453 /* Check if a range has been specified without specifying what to 454 collect. */ 455 { 456 int i; 457 458 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 459 { 460 sim_cpu *cpu = STATE_CPU (sd, i); 461 462 if (ADDR_RANGE_RANGES (TRACE_RANGE (CPU_TRACE_DATA (cpu))) 463 && ! TRACE_INSN_P (cpu)) 464 { 465 sim_io_eprintf_cpu (cpu, "Tracing address range specified without --trace-insn.\n"); 466 sim_io_eprintf_cpu (cpu, "Address range ignored.\n"); 467 sim_addr_range_delete (TRACE_RANGE (CPU_TRACE_DATA (cpu)), 468 0, ~ (address_word) 0); 469 } 470 } 471 } 472 #endif 473 474 return SIM_RC_OK; 475 } 476 477 static void 478 trace_uninstall (SIM_DESC sd) 479 { 480 int i,j; 481 FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd)); 482 483 if (sfile != NULL) 484 fclose (sfile); 485 486 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 487 { 488 FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i))); 489 if (cfile != NULL && cfile != sfile) 490 { 491 /* If output from different cpus is going to the same file, 492 avoid closing the file twice. */ 493 for (j = 0; j < i; ++j) 494 if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile) 495 break; 496 if (i == j) 497 fclose (cfile); 498 } 499 } 500 } 501 502 /* compute the nr of trace data units consumed by data */ 503 static int 504 save_data_size (TRACE_DATA *data, 505 long size) 506 { 507 return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1) 508 / sizeof (TRACE_INPUT_DATA (data) [0])); 509 } 510 511 512 /* Archive DATA into the trace buffer */ 513 void 514 save_data (SIM_DESC sd, 515 TRACE_DATA *data, 516 data_fmt fmt, 517 long size, 518 const void *buf) 519 { 520 int i = TRACE_INPUT_IDX (data); 521 if (i == sizeof (TRACE_INPUT_FMT (data))) 522 sim_io_error (sd, "trace buffer overflow"); 523 TRACE_INPUT_FMT (data) [i] = fmt; 524 TRACE_INPUT_SIZE (data) [i] = size; 525 memcpy (&TRACE_INPUT_DATA (data) [i], buf, size); 526 i += save_data_size (data, size); 527 TRACE_INPUT_IDX (data) = i; 528 } 529 530 static void 531 print_data (SIM_DESC sd, 532 sim_cpu *cpu, 533 data_fmt fmt, 534 long size, 535 void *data) 536 { 537 switch (fmt) 538 { 539 case trace_fmt_instruction_incomplete: 540 trace_printf (sd, cpu, " (instruction incomplete)"); 541 break; 542 case trace_fmt_word: 543 case trace_fmt_addr: 544 { 545 switch (size) 546 { 547 case sizeof (unsigned32): 548 trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned32*) data); 549 break; 550 case sizeof (unsigned64): 551 trace_printf (sd, cpu, " 0x%08lx%08lx", 552 (long) ((* (unsigned64*) data) >> 32), 553 (long) * (unsigned64*) data); 554 break; 555 default: 556 abort (); 557 } 558 break; 559 } 560 case trace_fmt_bool: 561 { 562 SIM_ASSERT (size == sizeof (int)); 563 trace_printf (sd, cpu, " %-8s", 564 (* (int*) data) ? "true" : "false"); 565 break; 566 } 567 case trace_fmt_fp: 568 { 569 sim_fpu fp; 570 switch (size) 571 { 572 /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */ 573 case 4: 574 sim_fpu_32to (&fp, *(unsigned32*)data); 575 break; 576 case 8: 577 sim_fpu_64to (&fp, *(unsigned64*)data); 578 break; 579 default: 580 abort (); 581 } 582 trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp)); 583 switch (size) 584 { 585 case 4: 586 trace_printf (sd, cpu, " (0x%08lx)", 587 (long) *(unsigned32*)data); 588 break; 589 case 8: 590 trace_printf (sd, cpu, " (0x%08lx%08lx)", 591 (long) (*(unsigned64*)data >> 32), 592 (long) (*(unsigned64*)data)); 593 break; 594 default: 595 abort (); 596 } 597 break; 598 } 599 case trace_fmt_fpu: 600 /* FIXME: At present sim_fpu data is stored as a double */ 601 trace_printf (sd, cpu, " %8g", * (double*) data); 602 break; 603 case trace_fmt_string: 604 trace_printf (sd, cpu, " %-8s", (char*) data); 605 break; 606 default: 607 abort (); 608 } 609 } 610 611 static const char * 612 trace_idx_to_str (int trace_idx) 613 { 614 static char num[8]; 615 switch (trace_idx) 616 { 617 case TRACE_ALU_IDX: return "alu: "; 618 case TRACE_INSN_IDX: return "insn: "; 619 case TRACE_DECODE_IDX: return "decode: "; 620 case TRACE_EXTRACT_IDX: return "extract: "; 621 case TRACE_MEMORY_IDX: return "memory: "; 622 case TRACE_CORE_IDX: return "core: "; 623 case TRACE_EVENTS_IDX: return "events: "; 624 case TRACE_FPU_IDX: return "fpu: "; 625 case TRACE_BRANCH_IDX: return "branch: "; 626 case TRACE_SYSCALL_IDX: return "syscall: "; 627 case TRACE_REGISTER_IDX: return "reg: "; 628 case TRACE_VPU_IDX: return "vpu: "; 629 default: 630 sprintf (num, "?%d?", trace_idx); 631 return num; 632 } 633 } 634 635 static void 636 trace_results (SIM_DESC sd, 637 sim_cpu *cpu, 638 int trace_idx, 639 int last_input) 640 { 641 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 642 int nr_out; 643 int i; 644 645 /* cross check trace_idx against TRACE_IDX (data)? */ 646 647 /* prefix */ 648 trace_printf (sd, cpu, "%s %s", 649 trace_idx_to_str (TRACE_IDX (data)), 650 TRACE_PREFIX (data)); 651 TRACE_IDX (data) = 0; 652 653 for (i = 0, nr_out = 0; 654 i < TRACE_INPUT_IDX (data); 655 i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++) 656 { 657 if (i == last_input) 658 { 659 int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2); 660 int padding = pad * (3 - nr_out); 661 if (padding < 0) 662 padding = 0; 663 padding += strlen (" ::"); 664 trace_printf (sd, cpu, "%*s", padding, " ::"); 665 } 666 print_data (sd, cpu, 667 TRACE_INPUT_FMT (data) [i], 668 TRACE_INPUT_SIZE (data) [i], 669 &TRACE_INPUT_DATA (data) [i]); 670 } 671 trace_printf (sd, cpu, "\n"); 672 } 673 674 void 675 trace_prefix (SIM_DESC sd, 676 sim_cpu *cpu, 677 sim_cia cia, 678 address_word pc, 679 int line_p, 680 const char *filename, 681 int linenum, 682 const char *fmt, 683 ...) 684 { 685 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 686 va_list ap; 687 char *prefix = TRACE_PREFIX (data); 688 char *chp; 689 /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using 690 known information about the disassembled instructions. */ 691 #ifndef TRACE_PREFIX_WIDTH 692 #define TRACE_PREFIX_WIDTH 48 693 #endif 694 int width = TRACE_PREFIX_WIDTH; 695 696 /* if the previous trace data wasn't flushed, flush it now with a 697 note indicating that the trace was incomplete. */ 698 if (TRACE_IDX (data) != 0) 699 { 700 int last_input = TRACE_INPUT_IDX (data); 701 save_data (sd, data, trace_fmt_instruction_incomplete, 1, ""); 702 trace_results (sd, cpu, TRACE_IDX (data), last_input); 703 } 704 TRACE_IDX (data) = 0; 705 TRACE_INPUT_IDX (data) = 0; 706 707 /* Create the text prefix for this new instruction: */ 708 if (!line_p) 709 { 710 if (filename) 711 { 712 sprintf (prefix, "%s:%-*d 0x%.*lx ", 713 filename, 714 SIZE_LINE_NUMBER, linenum, 715 SIZE_PC, (long) pc); 716 } 717 else 718 { 719 sprintf (prefix, "0x%.*lx ", 720 SIZE_PC, (long) pc); 721 /* Shrink the width by the amount that we didn't print. */ 722 width -= SIZE_LINE_NUMBER + SIZE_PC + 8; 723 } 724 chp = strchr (prefix, '\0'); 725 va_start (ap, fmt); 726 vsprintf (chp, fmt, ap); 727 va_end (ap); 728 } 729 else 730 { 731 char buf[256]; 732 buf[0] = 0; 733 if (STATE_TEXT_SECTION (CPU_STATE (cpu)) 734 && pc >= STATE_TEXT_START (CPU_STATE (cpu)) 735 && pc < STATE_TEXT_END (CPU_STATE (cpu))) 736 { 737 const char *pc_filename = (const char *)0; 738 const char *pc_function = (const char *)0; 739 unsigned int pc_linenum = 0; 740 bfd *abfd; 741 asymbol **asymbols; 742 743 abfd = STATE_PROG_BFD (CPU_STATE (cpu)); 744 asymbols = STATE_PROG_SYMS (CPU_STATE (cpu)); 745 if (asymbols == NULL) 746 { 747 long symsize; 748 long symbol_count; 749 750 symsize = bfd_get_symtab_upper_bound (abfd); 751 if (symsize < 0) 752 { 753 sim_engine_abort (sd, cpu, cia, "could not read symbols"); 754 } 755 asymbols = (asymbol **) xmalloc (symsize); 756 symbol_count = bfd_canonicalize_symtab (abfd, asymbols); 757 if (symbol_count < 0) 758 { 759 sim_engine_abort (sd, cpu, cia, "could not canonicalize symbols"); 760 } 761 STATE_PROG_SYMS (CPU_STATE (cpu)) = asymbols; 762 } 763 764 if (bfd_find_nearest_line (abfd, 765 STATE_TEXT_SECTION (CPU_STATE (cpu)), 766 asymbols, 767 pc - STATE_TEXT_START (CPU_STATE (cpu)), 768 &pc_filename, &pc_function, &pc_linenum)) 769 { 770 char *p = buf; 771 if (pc_linenum) 772 { 773 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum); 774 p += strlen (p); 775 } 776 else 777 { 778 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); 779 p += SIZE_LINE_NUMBER+2; 780 } 781 782 if (pc_function) 783 { 784 sprintf (p, "%s ", pc_function); 785 p += strlen (p); 786 } 787 else if (pc_filename) 788 { 789 char *q = (char *) strrchr (pc_filename, '/'); 790 sprintf (p, "%s ", (q) ? q+1 : pc_filename); 791 p += strlen (p); 792 } 793 794 if (*p == ' ') 795 *p = '\0'; 796 } 797 } 798 799 sprintf (prefix, "0x%.*x %-*.*s ", 800 SIZE_PC, (unsigned) pc, 801 SIZE_LOCATION, SIZE_LOCATION, buf); 802 chp = strchr (prefix, '\0'); 803 va_start (ap, fmt); 804 vsprintf (chp, fmt, ap); 805 va_end (ap); 806 } 807 808 /* Pad it out to TRACE_PREFIX_WIDTH. */ 809 chp = strchr (prefix, '\0'); 810 if (chp - prefix < width) 811 { 812 memset (chp, ' ', width - (chp - prefix)); 813 chp = &prefix [width]; 814 *chp = '\0'; 815 } 816 strcpy (chp, " -"); 817 818 /* check that we've not over flowed the prefix buffer */ 819 if (strlen (prefix) >= sizeof (TRACE_PREFIX (data))) 820 abort (); 821 } 822 823 void 824 trace_generic (SIM_DESC sd, 825 sim_cpu *cpu, 826 int trace_idx, 827 const char *fmt, 828 ...) 829 { 830 va_list ap; 831 trace_printf (sd, cpu, "%s %s", 832 trace_idx_to_str (trace_idx), 833 TRACE_PREFIX (CPU_TRACE_DATA (cpu))); 834 va_start (ap, fmt); 835 trace_vprintf (sd, cpu, fmt, ap); 836 va_end (ap); 837 trace_printf (sd, cpu, "\n"); 838 } 839 840 void 841 trace_input0 (SIM_DESC sd, 842 sim_cpu *cpu, 843 int trace_idx) 844 { 845 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 846 TRACE_IDX (data) = trace_idx; 847 } 848 849 void 850 trace_input_word1 (SIM_DESC sd, 851 sim_cpu *cpu, 852 int trace_idx, 853 unsigned_word d0) 854 { 855 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 856 TRACE_IDX (data) = trace_idx; 857 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); 858 } 859 860 void 861 trace_input_word2 (SIM_DESC sd, 862 sim_cpu *cpu, 863 int trace_idx, 864 unsigned_word d0, 865 unsigned_word d1) 866 { 867 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 868 TRACE_IDX (data) = trace_idx; 869 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); 870 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1); 871 } 872 873 void 874 trace_input_word3 (SIM_DESC sd, 875 sim_cpu *cpu, 876 int trace_idx, 877 unsigned_word d0, 878 unsigned_word d1, 879 unsigned_word d2) 880 { 881 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 882 TRACE_IDX (data) = trace_idx; 883 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); 884 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1); 885 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2); 886 } 887 888 void 889 trace_input_word4 (SIM_DESC sd, 890 sim_cpu *cpu, 891 int trace_idx, 892 unsigned_word d0, 893 unsigned_word d1, 894 unsigned_word d2, 895 unsigned_word d3) 896 { 897 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 898 TRACE_IDX (data) = trace_idx; 899 save_data (sd, data, trace_fmt_word, sizeof (d0), &d0); 900 save_data (sd, data, trace_fmt_word, sizeof (d1), &d1); 901 save_data (sd, data, trace_fmt_word, sizeof (d2), &d2); 902 save_data (sd, data, trace_fmt_word, sizeof (d3), &d3); 903 } 904 905 void 906 trace_input_bool1 (SIM_DESC sd, 907 sim_cpu *cpu, 908 int trace_idx, 909 int d0) 910 { 911 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 912 TRACE_IDX (data) = trace_idx; 913 save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0); 914 } 915 916 void 917 trace_input_addr1 (SIM_DESC sd, 918 sim_cpu *cpu, 919 int trace_idx, 920 address_word d0) 921 { 922 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 923 TRACE_IDX (data) = trace_idx; 924 save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0); 925 } 926 927 void 928 trace_input_fp1 (SIM_DESC sd, 929 sim_cpu *cpu, 930 int trace_idx, 931 fp_word f0) 932 { 933 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 934 TRACE_IDX (data) = trace_idx; 935 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 936 } 937 938 void 939 trace_input_fp2 (SIM_DESC sd, 940 sim_cpu *cpu, 941 int trace_idx, 942 fp_word f0, 943 fp_word f1) 944 { 945 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 946 TRACE_IDX (data) = trace_idx; 947 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 948 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1); 949 } 950 951 void 952 trace_input_fp3 (SIM_DESC sd, 953 sim_cpu *cpu, 954 int trace_idx, 955 fp_word f0, 956 fp_word f1, 957 fp_word f2) 958 { 959 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 960 TRACE_IDX (data) = trace_idx; 961 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 962 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1); 963 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2); 964 } 965 966 void 967 trace_input_fpu1 (SIM_DESC sd, 968 sim_cpu *cpu, 969 int trace_idx, 970 sim_fpu *f0) 971 { 972 double d; 973 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 974 TRACE_IDX (data) = trace_idx; 975 d = sim_fpu_2d (f0); 976 save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 977 } 978 979 void 980 trace_input_fpu2 (SIM_DESC sd, 981 sim_cpu *cpu, 982 int trace_idx, 983 sim_fpu *f0, 984 sim_fpu *f1) 985 { 986 double d; 987 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 988 TRACE_IDX (data) = trace_idx; 989 d = sim_fpu_2d (f0); 990 save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 991 d = sim_fpu_2d (f1); 992 save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 993 } 994 995 void 996 trace_input_fpu3 (SIM_DESC sd, 997 sim_cpu *cpu, 998 int trace_idx, 999 sim_fpu *f0, 1000 sim_fpu *f1, 1001 sim_fpu *f2) 1002 { 1003 double d; 1004 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1005 TRACE_IDX (data) = trace_idx; 1006 d = sim_fpu_2d (f0); 1007 save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 1008 d = sim_fpu_2d (f1); 1009 save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 1010 d = sim_fpu_2d (f2); 1011 save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 1012 } 1013 1014 void 1015 trace_result_word1 (SIM_DESC sd, 1016 sim_cpu *cpu, 1017 int trace_idx, 1018 unsigned_word r0) 1019 { 1020 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1021 int last_input; 1022 1023 /* Append any results to the end of the inputs */ 1024 last_input = TRACE_INPUT_IDX (data); 1025 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0); 1026 1027 trace_results (sd, cpu, trace_idx, last_input); 1028 } 1029 1030 void 1031 trace_result0 (SIM_DESC sd, 1032 sim_cpu *cpu, 1033 int trace_idx) 1034 { 1035 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1036 int last_input; 1037 1038 /* Append any results to the end of the inputs */ 1039 last_input = TRACE_INPUT_IDX (data); 1040 1041 trace_results (sd, cpu, trace_idx, last_input); 1042 } 1043 1044 void 1045 trace_result_word2 (SIM_DESC sd, 1046 sim_cpu *cpu, 1047 int trace_idx, 1048 unsigned_word r0, 1049 unsigned_word r1) 1050 { 1051 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1052 int last_input; 1053 1054 /* Append any results to the end of the inputs */ 1055 last_input = TRACE_INPUT_IDX (data); 1056 save_data (sd, data, trace_fmt_word, sizeof (r0), &r0); 1057 save_data (sd, data, trace_fmt_word, sizeof (r1), &r1); 1058 1059 trace_results (sd, cpu, trace_idx, last_input); 1060 } 1061 1062 void 1063 trace_result_word4 (SIM_DESC sd, 1064 sim_cpu *cpu, 1065 int trace_idx, 1066 unsigned_word r0, 1067 unsigned_word r1, 1068 unsigned_word r2, 1069 unsigned_word r3) 1070 { 1071 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1072 int last_input; 1073 1074 /* Append any results to the end of the inputs */ 1075 last_input = TRACE_INPUT_IDX (data); 1076 save_data (sd, data, trace_fmt_word, sizeof (r0), &r0); 1077 save_data (sd, data, trace_fmt_word, sizeof (r1), &r1); 1078 save_data (sd, data, trace_fmt_word, sizeof (r2), &r2); 1079 save_data (sd, data, trace_fmt_word, sizeof (r3), &r3); 1080 1081 trace_results (sd, cpu, trace_idx, last_input); 1082 } 1083 1084 void 1085 trace_result_bool1 (SIM_DESC sd, 1086 sim_cpu *cpu, 1087 int trace_idx, 1088 int r0) 1089 { 1090 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1091 int last_input; 1092 1093 /* Append any results to the end of the inputs */ 1094 last_input = TRACE_INPUT_IDX (data); 1095 save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0); 1096 1097 trace_results (sd, cpu, trace_idx, last_input); 1098 } 1099 1100 void 1101 trace_result_addr1 (SIM_DESC sd, 1102 sim_cpu *cpu, 1103 int trace_idx, 1104 address_word r0) 1105 { 1106 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1107 int last_input; 1108 1109 /* Append any results to the end of the inputs */ 1110 last_input = TRACE_INPUT_IDX (data); 1111 save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0); 1112 1113 trace_results (sd, cpu, trace_idx, last_input); 1114 } 1115 1116 void 1117 trace_result_fp1 (SIM_DESC sd, 1118 sim_cpu *cpu, 1119 int trace_idx, 1120 fp_word f0) 1121 { 1122 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1123 int last_input; 1124 1125 /* Append any results to the end of the inputs */ 1126 last_input = TRACE_INPUT_IDX (data); 1127 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 1128 1129 trace_results (sd, cpu, trace_idx, last_input); 1130 } 1131 1132 void 1133 trace_result_fp2 (SIM_DESC sd, 1134 sim_cpu *cpu, 1135 int trace_idx, 1136 fp_word f0, 1137 fp_word f1) 1138 { 1139 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1140 int last_input; 1141 1142 /* Append any results to the end of the inputs */ 1143 last_input = TRACE_INPUT_IDX (data); 1144 save_data (sd, data, trace_fmt_fp, sizeof (f0), &f0); 1145 save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1); 1146 1147 trace_results (sd, cpu, trace_idx, last_input); 1148 } 1149 1150 void 1151 trace_result_fpu1 (SIM_DESC sd, 1152 sim_cpu *cpu, 1153 int trace_idx, 1154 sim_fpu *f0) 1155 { 1156 double d; 1157 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1158 int last_input; 1159 1160 /* Append any results to the end of the inputs */ 1161 last_input = TRACE_INPUT_IDX (data); 1162 d = sim_fpu_2d (f0); 1163 save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 1164 1165 trace_results (sd, cpu, trace_idx, last_input); 1166 } 1167 1168 void 1169 trace_result_string1 (SIM_DESC sd, 1170 sim_cpu *cpu, 1171 int trace_idx, 1172 char *s0) 1173 { 1174 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1175 int last_input; 1176 1177 /* Append any results to the end of the inputs */ 1178 last_input = TRACE_INPUT_IDX (data); 1179 save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0); 1180 1181 trace_results (sd, cpu, trace_idx, last_input); 1182 } 1183 1184 void 1185 trace_result_word1_string1 (SIM_DESC sd, 1186 sim_cpu *cpu, 1187 int trace_idx, 1188 unsigned_word r0, 1189 char *s0) 1190 { 1191 TRACE_DATA *data = CPU_TRACE_DATA (cpu); 1192 int last_input; 1193 1194 /* Append any results to the end of the inputs */ 1195 last_input = TRACE_INPUT_IDX (data); 1196 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0); 1197 save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0); 1198 1199 trace_results (sd, cpu, trace_idx, last_input); 1200 } 1201 1202 void 1203 trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap) 1204 { 1205 if (cpu != NULL) 1206 { 1207 if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL) 1208 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap); 1209 else 1210 sim_io_evprintf (sd, fmt, ap); 1211 } 1212 else 1213 { 1214 if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL) 1215 vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap); 1216 else 1217 sim_io_evprintf (sd, fmt, ap); 1218 } 1219 } 1220 1221 void 1222 trace_printf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...) 1223 { 1224 va_list ap; 1225 1226 va_start (ap, fmt); 1227 1228 trace_vprintf (sd, cpu, fmt, ap); 1229 1230 va_end (ap); 1231 } 1232 1233 void 1234 sim_debug_printf (sim_cpu *cpu, const char *fmt, ...) 1235 { 1236 va_list ap; 1237 1238 va_start (ap, fmt); 1239 1240 if (CPU_DEBUG_FILE (cpu) == NULL) 1241 (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered) 1242 (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap); 1243 else 1244 vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap); 1245 1246 va_end (ap); 1247 } 1248