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