14e98e3e1Schristos /* Simulator tracing/debugging support. 2*88241920Schristos Copyright (C) 1997-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Contributed by Cygnus Support. 44e98e3e1Schristos 54e98e3e1Schristos This file is part of GDB, the GNU debugger. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224b169a6bSchristos 234b169a6bSchristos #include <stdarg.h> 244b169a6bSchristos #include <stdlib.h> 254b169a6bSchristos #include <string.h> 264b169a6bSchristos 274b169a6bSchristos #include "ansidecl.h" 284b169a6bSchristos #include "bfd.h" 294b169a6bSchristos #include "dis-asm.h" 304b169a6bSchristos #include "libiberty.h" 314b169a6bSchristos 324e98e3e1Schristos #include "sim-main.h" 334b169a6bSchristos #include "sim-assert.h" 344e98e3e1Schristos #include "sim-io.h" 354e98e3e1Schristos #include "sim-options.h" 364e98e3e1Schristos #include "sim-fpu.h" 374b169a6bSchristos #include "sim/callback.h" 384e98e3e1Schristos 394e98e3e1Schristos #ifndef SIZE_PHASE 404e98e3e1Schristos #define SIZE_PHASE 8 414e98e3e1Schristos #endif 424e98e3e1Schristos 434e98e3e1Schristos #ifndef SIZE_LOCATION 444e98e3e1Schristos #define SIZE_LOCATION 20 454e98e3e1Schristos #endif 464e98e3e1Schristos 474e98e3e1Schristos #ifndef SIZE_PC 484e98e3e1Schristos #define SIZE_PC 6 494e98e3e1Schristos #endif 504e98e3e1Schristos 514e98e3e1Schristos #ifndef SIZE_LINE_NUMBER 524e98e3e1Schristos #define SIZE_LINE_NUMBER 4 534e98e3e1Schristos #endif 544e98e3e1Schristos 554e98e3e1Schristos static MODULE_INIT_FN trace_init; 564e98e3e1Schristos static MODULE_UNINSTALL_FN trace_uninstall; 574e98e3e1Schristos 584e98e3e1Schristos static DECLARE_OPTION_HANDLER (trace_option_handler); 594e98e3e1Schristos 604e98e3e1Schristos enum { 614e98e3e1Schristos OPTION_TRACE_INSN = OPTION_START, 62ba340e45Schristos OPTION_TRACE_DISASM, 634e98e3e1Schristos OPTION_TRACE_DECODE, 644e98e3e1Schristos OPTION_TRACE_EXTRACT, 654e98e3e1Schristos OPTION_TRACE_LINENUM, 664e98e3e1Schristos OPTION_TRACE_MEMORY, 674e98e3e1Schristos OPTION_TRACE_MODEL, 684e98e3e1Schristos OPTION_TRACE_ALU, 694e98e3e1Schristos OPTION_TRACE_CORE, 704e98e3e1Schristos OPTION_TRACE_EVENTS, 714e98e3e1Schristos OPTION_TRACE_FPU, 724e98e3e1Schristos OPTION_TRACE_BRANCH, 734e98e3e1Schristos OPTION_TRACE_SEMANTICS, 744e98e3e1Schristos OPTION_TRACE_RANGE, 754e98e3e1Schristos OPTION_TRACE_FUNCTION, 764e98e3e1Schristos OPTION_TRACE_DEBUG, 774e98e3e1Schristos OPTION_TRACE_FILE, 78a2e2270fSchristos OPTION_TRACE_VPU, 79212397c6Schristos OPTION_TRACE_SYSCALL, 80212397c6Schristos OPTION_TRACE_REGISTER 814e98e3e1Schristos }; 824e98e3e1Schristos 834e98e3e1Schristos static const OPTION trace_options[] = 844e98e3e1Schristos { 854e98e3e1Schristos /* This table is organized to group related instructions together. */ 864e98e3e1Schristos { {"trace", optional_argument, NULL, 't'}, 874e98e3e1Schristos 't', "on|off", "Trace useful things", 884e98e3e1Schristos trace_option_handler, NULL }, 894e98e3e1Schristos { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN}, 904e98e3e1Schristos '\0', "on|off", "Perform instruction tracing", 914e98e3e1Schristos trace_option_handler, NULL }, 92ba340e45Schristos { {"trace-disasm", optional_argument, NULL, OPTION_TRACE_DISASM}, 93ba340e45Schristos '\0', "on|off", "Disassemble instructions (slower, but more accurate)", 94ba340e45Schristos trace_option_handler, NULL }, 954e98e3e1Schristos { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE}, 964e98e3e1Schristos '\0', "on|off", "Trace instruction decoding", 974e98e3e1Schristos trace_option_handler, NULL }, 984e98e3e1Schristos { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT}, 994e98e3e1Schristos '\0', "on|off", "Trace instruction extraction", 1004e98e3e1Schristos trace_option_handler, NULL }, 1014e98e3e1Schristos { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM}, 1024e98e3e1Schristos '\0', "on|off", "Perform line number tracing (implies --trace-insn)", 1034e98e3e1Schristos trace_option_handler, NULL }, 1044e98e3e1Schristos { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY}, 1054e98e3e1Schristos '\0', "on|off", "Trace memory operations", 1064e98e3e1Schristos trace_option_handler, NULL }, 1074e98e3e1Schristos { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU}, 108212397c6Schristos '\0', "on|off", "Trace ALU (Arithmetic Logic Unit) operations", 1094e98e3e1Schristos trace_option_handler, NULL }, 1104e98e3e1Schristos { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU}, 111212397c6Schristos '\0', "on|off", "Trace FPU (Floating Point Unit) operations", 1124e98e3e1Schristos trace_option_handler, NULL }, 1134e98e3e1Schristos { {"trace-vpu", optional_argument, NULL, OPTION_TRACE_VPU}, 114212397c6Schristos '\0', "on|off", "Trace VPU (Vector Processing Unit) operations", 1154e98e3e1Schristos trace_option_handler, NULL }, 1164e98e3e1Schristos { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH}, 1174e98e3e1Schristos '\0', "on|off", "Trace branching", 1184e98e3e1Schristos trace_option_handler, NULL }, 1194e98e3e1Schristos { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS}, 120212397c6Schristos '\0', "on|off", "Perform ALU, FPU, VPU, MEMORY, and BRANCH tracing", 1214e98e3e1Schristos trace_option_handler, NULL }, 1224e98e3e1Schristos { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL}, 1234e98e3e1Schristos '\0', "on|off", "Include model performance data", 1244e98e3e1Schristos trace_option_handler, NULL }, 1254e98e3e1Schristos { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE}, 1264e98e3e1Schristos '\0', "on|off", "Trace core operations", 1274e98e3e1Schristos trace_option_handler, NULL }, 1284e98e3e1Schristos { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS}, 1294e98e3e1Schristos '\0', "on|off", "Trace events", 1304e98e3e1Schristos trace_option_handler, NULL }, 131a2e2270fSchristos { {"trace-syscall", optional_argument, NULL, OPTION_TRACE_SYSCALL}, 132a2e2270fSchristos '\0', "on|off", "Trace system calls", 133a2e2270fSchristos trace_option_handler, NULL }, 134212397c6Schristos { {"trace-register", optional_argument, NULL, OPTION_TRACE_REGISTER}, 135212397c6Schristos '\0', "on|off", "Trace cpu register accesses", 136212397c6Schristos trace_option_handler, NULL }, 1374e98e3e1Schristos #ifdef SIM_HAVE_ADDR_RANGE 1384e98e3e1Schristos { {"trace-range", required_argument, NULL, OPTION_TRACE_RANGE}, 1394e98e3e1Schristos '\0', "START,END", "Specify range of addresses for instruction tracing", 1404e98e3e1Schristos trace_option_handler, NULL }, 1414e98e3e1Schristos #if 0 /*wip*/ 1424e98e3e1Schristos { {"trace-function", required_argument, NULL, OPTION_TRACE_FUNCTION}, 1434e98e3e1Schristos '\0', "FUNCTION", "Specify function to trace", 1444e98e3e1Schristos trace_option_handler, NULL }, 1454e98e3e1Schristos #endif 1464e98e3e1Schristos #endif 1474e98e3e1Schristos { {"trace-debug", optional_argument, NULL, OPTION_TRACE_DEBUG}, 1484e98e3e1Schristos '\0', "on|off", "Add information useful for debugging the simulator to the tracing output", 1494e98e3e1Schristos trace_option_handler, NULL }, 1504e98e3e1Schristos { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE}, 1514e98e3e1Schristos '\0', "FILE NAME", "Specify tracing output file", 1524e98e3e1Schristos trace_option_handler, NULL }, 1534e98e3e1Schristos { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } 1544e98e3e1Schristos }; 1554e98e3e1Schristos 1564e98e3e1Schristos /* Set/reset the trace options indicated in MASK. */ 1574e98e3e1Schristos 1584e98e3e1Schristos static SIM_RC 1594e98e3e1Schristos set_trace_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg) 1604e98e3e1Schristos { 1614e98e3e1Schristos int trace_nr; 1624e98e3e1Schristos int cpu_nr; 1634e98e3e1Schristos int trace_val = 1; 1644e98e3e1Schristos 1654e98e3e1Schristos if (arg != NULL) 1664e98e3e1Schristos { 1674e98e3e1Schristos if (strcmp (arg, "yes") == 0 1684e98e3e1Schristos || strcmp (arg, "on") == 0 1694e98e3e1Schristos || strcmp (arg, "1") == 0) 1704e98e3e1Schristos trace_val = 1; 1714e98e3e1Schristos else if (strcmp (arg, "no") == 0 1724e98e3e1Schristos || strcmp (arg, "off") == 0 1734e98e3e1Schristos || strcmp (arg, "0") == 0) 1744e98e3e1Schristos trace_val = 0; 1754e98e3e1Schristos else 1764e98e3e1Schristos { 1774e98e3e1Schristos sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name); 1784e98e3e1Schristos return SIM_RC_FAIL; 1794e98e3e1Schristos } 1804e98e3e1Schristos } 1814e98e3e1Schristos 182212397c6Schristos /* Update applicable trace bits. */ 1834e98e3e1Schristos for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) 1844e98e3e1Schristos { 1854e98e3e1Schristos if ((mask & (1 << trace_nr)) == 0) 1864e98e3e1Schristos continue; 1874e98e3e1Schristos 1884e98e3e1Schristos /* Set non-cpu specific values. */ 1894e98e3e1Schristos STATE_TRACE_FLAGS (sd)[trace_nr] = trace_val; 1904e98e3e1Schristos 1914e98e3e1Schristos /* Set cpu values. */ 1924e98e3e1Schristos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 1934e98e3e1Schristos { 1944e98e3e1Schristos CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val; 1954e98e3e1Schristos } 1964e98e3e1Schristos } 1974e98e3e1Schristos 1984e98e3e1Schristos /* Re-compute the cpu trace summary. */ 1994e98e3e1Schristos if (trace_val) 2004e98e3e1Schristos { 2014e98e3e1Schristos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 2024e98e3e1Schristos CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; 2034e98e3e1Schristos } 2044e98e3e1Schristos else 2054e98e3e1Schristos { 2064e98e3e1Schristos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 2074e98e3e1Schristos { 2084e98e3e1Schristos CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 0; 2094e98e3e1Schristos for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) 2104e98e3e1Schristos { 2114e98e3e1Schristos if (CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr]) 2124e98e3e1Schristos { 2134e98e3e1Schristos CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; 2144e98e3e1Schristos break; 2154e98e3e1Schristos } 2164e98e3e1Schristos } 2174e98e3e1Schristos } 2184e98e3e1Schristos } 2194e98e3e1Schristos 2204e98e3e1Schristos return SIM_RC_OK; 2214e98e3e1Schristos } 2224e98e3e1Schristos 2234e98e3e1Schristos /* Set one trace option based on its IDX value. */ 2244e98e3e1Schristos 2254e98e3e1Schristos static SIM_RC 2264e98e3e1Schristos set_trace_option (SIM_DESC sd, const char *name, int idx, const char *arg) 2274e98e3e1Schristos { 2284e98e3e1Schristos return set_trace_option_mask (sd, name, 1 << idx, arg); 2294e98e3e1Schristos } 2304e98e3e1Schristos 2314e98e3e1Schristos 2324e98e3e1Schristos static SIM_RC 2334e98e3e1Schristos trace_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, 2344e98e3e1Schristos char *arg, int is_command) 2354e98e3e1Schristos { 2364e98e3e1Schristos int n; 2374e98e3e1Schristos 2384e98e3e1Schristos switch (opt) 2394e98e3e1Schristos { 2404e98e3e1Schristos case 't' : 241212397c6Schristos if (!WITH_TRACE_ANY_P) 2424e98e3e1Schristos sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n"); 2434e98e3e1Schristos else 2444e98e3e1Schristos return set_trace_option_mask (sd, "trace", TRACE_USEFUL_MASK, arg); 2454e98e3e1Schristos break; 2464e98e3e1Schristos 2474e98e3e1Schristos case OPTION_TRACE_INSN : 2484e98e3e1Schristos if (WITH_TRACE_INSN_P) 2494e98e3e1Schristos return set_trace_option (sd, "-insn", TRACE_INSN_IDX, arg); 2504e98e3e1Schristos else 2514e98e3e1Schristos sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n"); 2524e98e3e1Schristos break; 2534e98e3e1Schristos 254ba340e45Schristos case OPTION_TRACE_DISASM : 255ba340e45Schristos if (WITH_TRACE_DISASM_P) 256ba340e45Schristos return set_trace_option (sd, "-disasm", TRACE_DISASM_IDX, arg); 257ba340e45Schristos else 258ba340e45Schristos sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-disasm' ignored\n"); 259ba340e45Schristos break; 260ba340e45Schristos 2614e98e3e1Schristos case OPTION_TRACE_DECODE : 2624e98e3e1Schristos if (WITH_TRACE_DECODE_P) 2634e98e3e1Schristos return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg); 2644e98e3e1Schristos else 2654e98e3e1Schristos sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n"); 2664e98e3e1Schristos break; 2674e98e3e1Schristos 2684e98e3e1Schristos case OPTION_TRACE_EXTRACT : 2694e98e3e1Schristos if (WITH_TRACE_EXTRACT_P) 2704e98e3e1Schristos return set_trace_option (sd, "-extract", TRACE_EXTRACT_IDX, arg); 2714e98e3e1Schristos else 2724e98e3e1Schristos sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n"); 2734e98e3e1Schristos break; 2744e98e3e1Schristos 2754e98e3e1Schristos case OPTION_TRACE_LINENUM : 2764e98e3e1Schristos if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P) 2774e98e3e1Schristos { 2784e98e3e1Schristos if (set_trace_option (sd, "-linenum", TRACE_LINENUM_IDX, arg) != SIM_RC_OK 2794e98e3e1Schristos || set_trace_option (sd, "-linenum", TRACE_INSN_IDX, arg) != SIM_RC_OK) 2804e98e3e1Schristos return SIM_RC_FAIL; 2814e98e3e1Schristos } 2824e98e3e1Schristos else 2834e98e3e1Schristos sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n"); 2844e98e3e1Schristos break; 2854e98e3e1Schristos 2864e98e3e1Schristos case OPTION_TRACE_MEMORY : 2874e98e3e1Schristos if (WITH_TRACE_MEMORY_P) 2884e98e3e1Schristos return set_trace_option (sd, "-memory", TRACE_MEMORY_IDX, arg); 2894e98e3e1Schristos else 2904e98e3e1Schristos sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n"); 2914e98e3e1Schristos break; 2924e98e3e1Schristos 2934e98e3e1Schristos case OPTION_TRACE_MODEL : 2944e98e3e1Schristos if (WITH_TRACE_MODEL_P) 2954e98e3e1Schristos return set_trace_option (sd, "-model", TRACE_MODEL_IDX, arg); 2964e98e3e1Schristos else 2974e98e3e1Schristos sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n"); 2984e98e3e1Schristos break; 2994e98e3e1Schristos 3004e98e3e1Schristos case OPTION_TRACE_ALU : 3014e98e3e1Schristos if (WITH_TRACE_ALU_P) 3024e98e3e1Schristos return set_trace_option (sd, "-alu", TRACE_ALU_IDX, arg); 3034e98e3e1Schristos else 3044e98e3e1Schristos sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n"); 3054e98e3e1Schristos break; 3064e98e3e1Schristos 3074e98e3e1Schristos case OPTION_TRACE_CORE : 3084e98e3e1Schristos if (WITH_TRACE_CORE_P) 3094e98e3e1Schristos return set_trace_option (sd, "-core", TRACE_CORE_IDX, arg); 3104e98e3e1Schristos else 3114e98e3e1Schristos sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n"); 3124e98e3e1Schristos break; 3134e98e3e1Schristos 3144e98e3e1Schristos case OPTION_TRACE_EVENTS : 3154e98e3e1Schristos if (WITH_TRACE_EVENTS_P) 3164e98e3e1Schristos return set_trace_option (sd, "-events", TRACE_EVENTS_IDX, arg); 3174e98e3e1Schristos else 3184e98e3e1Schristos sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n"); 3194e98e3e1Schristos break; 3204e98e3e1Schristos 3214e98e3e1Schristos case OPTION_TRACE_FPU : 3224e98e3e1Schristos if (WITH_TRACE_FPU_P) 3234e98e3e1Schristos return set_trace_option (sd, "-fpu", TRACE_FPU_IDX, arg); 3244e98e3e1Schristos else 3254e98e3e1Schristos sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n"); 3264e98e3e1Schristos break; 3274e98e3e1Schristos 3284e98e3e1Schristos case OPTION_TRACE_VPU : 3294e98e3e1Schristos if (WITH_TRACE_VPU_P) 3304e98e3e1Schristos return set_trace_option (sd, "-vpu", TRACE_VPU_IDX, arg); 3314e98e3e1Schristos else 3324e98e3e1Schristos sim_io_eprintf (sd, "VPU tracing not compiled in, `--trace-vpu' ignored\n"); 3334e98e3e1Schristos break; 3344e98e3e1Schristos 3354e98e3e1Schristos case OPTION_TRACE_BRANCH : 3364e98e3e1Schristos if (WITH_TRACE_BRANCH_P) 3374e98e3e1Schristos return set_trace_option (sd, "-branch", TRACE_BRANCH_IDX, arg); 3384e98e3e1Schristos else 3394e98e3e1Schristos sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n"); 3404e98e3e1Schristos break; 3414e98e3e1Schristos 342a2e2270fSchristos case OPTION_TRACE_SYSCALL : 343a2e2270fSchristos if (WITH_TRACE_SYSCALL_P) 344a2e2270fSchristos return set_trace_option (sd, "-syscall", TRACE_SYSCALL_IDX, arg); 345a2e2270fSchristos else 346a2e2270fSchristos sim_io_eprintf (sd, "System call tracing not compiled in, `--trace-syscall' ignored\n"); 347a2e2270fSchristos break; 348a2e2270fSchristos 349212397c6Schristos case OPTION_TRACE_REGISTER : 350212397c6Schristos if (WITH_TRACE_REGISTER_P) 351212397c6Schristos return set_trace_option (sd, "-register", TRACE_REGISTER_IDX, arg); 352212397c6Schristos else 353212397c6Schristos sim_io_eprintf (sd, "Register tracing not compiled in, `--trace-register' ignored\n"); 354212397c6Schristos break; 355212397c6Schristos 3564e98e3e1Schristos case OPTION_TRACE_SEMANTICS : 3574e98e3e1Schristos if (WITH_TRACE_ALU_P 3584e98e3e1Schristos && WITH_TRACE_FPU_P 3594e98e3e1Schristos && WITH_TRACE_MEMORY_P 3604e98e3e1Schristos && WITH_TRACE_BRANCH_P) 3614e98e3e1Schristos { 3624e98e3e1Schristos if (set_trace_option (sd, "-semantics", TRACE_ALU_IDX, arg) != SIM_RC_OK 3634e98e3e1Schristos || set_trace_option (sd, "-semantics", TRACE_FPU_IDX, arg) != SIM_RC_OK 3644e98e3e1Schristos || set_trace_option (sd, "-semantics", TRACE_VPU_IDX, arg) != SIM_RC_OK 3654e98e3e1Schristos || set_trace_option (sd, "-semantics", TRACE_MEMORY_IDX, arg) != SIM_RC_OK 3664e98e3e1Schristos || set_trace_option (sd, "-semantics", TRACE_BRANCH_IDX, arg) != SIM_RC_OK) 3674e98e3e1Schristos return SIM_RC_FAIL; 3684e98e3e1Schristos } 3694e98e3e1Schristos else 3704e98e3e1Schristos sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n"); 3714e98e3e1Schristos break; 3724e98e3e1Schristos 3734e98e3e1Schristos #ifdef SIM_HAVE_ADDR_RANGE 3744e98e3e1Schristos case OPTION_TRACE_RANGE : 375212397c6Schristos if (WITH_TRACE_ANY_P) 3764e98e3e1Schristos { 3774e98e3e1Schristos int cpu_nr; 3784e98e3e1Schristos char *chp = arg; 3794e98e3e1Schristos unsigned long start,end; 3804e98e3e1Schristos start = strtoul (chp, &chp, 0); 3814e98e3e1Schristos if (*chp != ',') 3824e98e3e1Schristos { 3834e98e3e1Schristos sim_io_eprintf (sd, "--trace-range missing END argument\n"); 3844e98e3e1Schristos return SIM_RC_FAIL; 3854e98e3e1Schristos } 3864e98e3e1Schristos end = strtoul (chp + 1, NULL, 0); 3874e98e3e1Schristos /* FIXME: Argument validation. */ 3884e98e3e1Schristos if (cpu != NULL) 3894e98e3e1Schristos sim_addr_range_add (TRACE_RANGE (CPU_PROFILE_DATA (cpu)), 3904e98e3e1Schristos start, end); 3914e98e3e1Schristos else 3924e98e3e1Schristos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) 3934e98e3e1Schristos sim_addr_range_add (TRACE_RANGE (CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))), 3944e98e3e1Schristos start, end); 3954e98e3e1Schristos } 3964e98e3e1Schristos else 3974e98e3e1Schristos sim_io_eprintf (sd, "Tracing not compiled in, `--trace-range' ignored\n"); 3984e98e3e1Schristos break; 3994e98e3e1Schristos 4004e98e3e1Schristos case OPTION_TRACE_FUNCTION : 401212397c6Schristos if (WITH_TRACE_ANY_P) 4024e98e3e1Schristos { 4034e98e3e1Schristos /*wip: need to compute function range given name*/ 4044e98e3e1Schristos } 4054e98e3e1Schristos else 4064e98e3e1Schristos sim_io_eprintf (sd, "Tracing not compiled in, `--trace-function' ignored\n"); 4074e98e3e1Schristos break; 4084e98e3e1Schristos #endif /* SIM_HAVE_ADDR_RANGE */ 4094e98e3e1Schristos 4104e98e3e1Schristos case OPTION_TRACE_DEBUG : 4114e98e3e1Schristos if (WITH_TRACE_DEBUG_P) 4124e98e3e1Schristos return set_trace_option (sd, "-debug", TRACE_DEBUG_IDX, arg); 4134e98e3e1Schristos else 4144e98e3e1Schristos sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n"); 4154e98e3e1Schristos break; 4164e98e3e1Schristos 4174e98e3e1Schristos case OPTION_TRACE_FILE : 418212397c6Schristos if (!WITH_TRACE_ANY_P) 4194e98e3e1Schristos sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n"); 4204e98e3e1Schristos else 4214e98e3e1Schristos { 4224e98e3e1Schristos FILE *f = fopen (arg, "w"); 4234e98e3e1Schristos 4244e98e3e1Schristos if (f == NULL) 4254e98e3e1Schristos { 4264e98e3e1Schristos sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg); 4274e98e3e1Schristos return SIM_RC_FAIL; 4284e98e3e1Schristos } 4294e98e3e1Schristos for (n = 0; n < MAX_NR_PROCESSORS; ++n) 4304e98e3e1Schristos TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f; 4314e98e3e1Schristos TRACE_FILE (STATE_TRACE_DATA (sd)) = f; 4324e98e3e1Schristos } 4334e98e3e1Schristos break; 4344e98e3e1Schristos } 4354e98e3e1Schristos 4364e98e3e1Schristos return SIM_RC_OK; 4374e98e3e1Schristos } 4384e98e3e1Schristos 4394b169a6bSchristos /* Provide a prototype to silence -Wmissing-prototypes. */ 4404b169a6bSchristos SIM_RC sim_install_trace (SIM_DESC sd); 4414e98e3e1Schristos 4424b169a6bSchristos /* Install tracing support. */ 4434e98e3e1Schristos SIM_RC 4444b169a6bSchristos sim_install_trace (SIM_DESC sd) 4454e98e3e1Schristos { 4464e98e3e1Schristos int i; 4474e98e3e1Schristos 4484e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 4494e98e3e1Schristos 4504e98e3e1Schristos sim_add_option_table (sd, NULL, trace_options); 4514e98e3e1Schristos memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd))); 4524e98e3e1Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 4534e98e3e1Schristos memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0, 4544e98e3e1Schristos sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i)))); 4554e98e3e1Schristos sim_module_add_init_fn (sd, trace_init); 4564e98e3e1Schristos sim_module_add_uninstall_fn (sd, trace_uninstall); 4574e98e3e1Schristos return SIM_RC_OK; 4584e98e3e1Schristos } 4594e98e3e1Schristos 4604e98e3e1Schristos static SIM_RC 4614e98e3e1Schristos trace_init (SIM_DESC sd) 4624e98e3e1Schristos { 4634e98e3e1Schristos #ifdef SIM_HAVE_ADDR_RANGE 4644e98e3e1Schristos /* Check if a range has been specified without specifying what to 4654e98e3e1Schristos collect. */ 4664e98e3e1Schristos { 4674e98e3e1Schristos int i; 4684e98e3e1Schristos 4694e98e3e1Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 4704e98e3e1Schristos { 4714e98e3e1Schristos sim_cpu *cpu = STATE_CPU (sd, i); 4724e98e3e1Schristos 4734e98e3e1Schristos if (ADDR_RANGE_RANGES (TRACE_RANGE (CPU_TRACE_DATA (cpu))) 4744e98e3e1Schristos && ! TRACE_INSN_P (cpu)) 4754e98e3e1Schristos { 4764e98e3e1Schristos sim_io_eprintf_cpu (cpu, "Tracing address range specified without --trace-insn.\n"); 4774e98e3e1Schristos sim_io_eprintf_cpu (cpu, "Address range ignored.\n"); 4784e98e3e1Schristos sim_addr_range_delete (TRACE_RANGE (CPU_TRACE_DATA (cpu)), 4794e98e3e1Schristos 0, ~ (address_word) 0); 4804e98e3e1Schristos } 4814e98e3e1Schristos } 4824e98e3e1Schristos } 4834e98e3e1Schristos #endif 4844e98e3e1Schristos 4854e98e3e1Schristos return SIM_RC_OK; 4864e98e3e1Schristos } 4874e98e3e1Schristos 4884e98e3e1Schristos static void 4894e98e3e1Schristos trace_uninstall (SIM_DESC sd) 4904e98e3e1Schristos { 4914e98e3e1Schristos int i,j; 4924e98e3e1Schristos FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd)); 4934e98e3e1Schristos 4944e98e3e1Schristos if (sfile != NULL) 4954e98e3e1Schristos fclose (sfile); 4964e98e3e1Schristos 4974e98e3e1Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 4984e98e3e1Schristos { 4994e98e3e1Schristos FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i))); 5004e98e3e1Schristos if (cfile != NULL && cfile != sfile) 5014e98e3e1Schristos { 5024e98e3e1Schristos /* If output from different cpus is going to the same file, 5034e98e3e1Schristos avoid closing the file twice. */ 5044e98e3e1Schristos for (j = 0; j < i; ++j) 5054e98e3e1Schristos if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile) 5064e98e3e1Schristos break; 5074e98e3e1Schristos if (i == j) 5084e98e3e1Schristos fclose (cfile); 5094e98e3e1Schristos } 5104e98e3e1Schristos } 511796c32c9Schristos 512796c32c9Schristos if (STATE_PROG_SYMS (sd)) 513796c32c9Schristos free (STATE_PROG_SYMS (sd)); 5144e98e3e1Schristos } 5154e98e3e1Schristos 5164e98e3e1Schristos /* compute the nr of trace data units consumed by data */ 5174e98e3e1Schristos static int 5184e98e3e1Schristos save_data_size (TRACE_DATA *data, 5194e98e3e1Schristos long size) 5204e98e3e1Schristos { 5214e98e3e1Schristos return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1) 5224e98e3e1Schristos / sizeof (TRACE_INPUT_DATA (data) [0])); 5234e98e3e1Schristos } 5244e98e3e1Schristos 5254e98e3e1Schristos 5264e98e3e1Schristos /* Archive DATA into the trace buffer */ 527a2e2270fSchristos void 5284e98e3e1Schristos save_data (SIM_DESC sd, 5294e98e3e1Schristos TRACE_DATA *data, 5304e98e3e1Schristos data_fmt fmt, 5314e98e3e1Schristos long size, 5324e98e3e1Schristos const void *buf) 5334e98e3e1Schristos { 5344e98e3e1Schristos int i = TRACE_INPUT_IDX (data); 5354e98e3e1Schristos if (i == sizeof (TRACE_INPUT_FMT (data))) 5364e98e3e1Schristos sim_io_error (sd, "trace buffer overflow"); 5374e98e3e1Schristos TRACE_INPUT_FMT (data) [i] = fmt; 5384e98e3e1Schristos TRACE_INPUT_SIZE (data) [i] = size; 5394e98e3e1Schristos memcpy (&TRACE_INPUT_DATA (data) [i], buf, size); 5404e98e3e1Schristos i += save_data_size (data, size); 5414e98e3e1Schristos TRACE_INPUT_IDX (data) = i; 5424e98e3e1Schristos } 5434e98e3e1Schristos 5444e98e3e1Schristos static void 5454e98e3e1Schristos print_data (SIM_DESC sd, 5464e98e3e1Schristos sim_cpu *cpu, 5474e98e3e1Schristos data_fmt fmt, 5484e98e3e1Schristos long size, 5494e98e3e1Schristos void *data) 5504e98e3e1Schristos { 5514e98e3e1Schristos switch (fmt) 5524e98e3e1Schristos { 5534e98e3e1Schristos case trace_fmt_instruction_incomplete: 5544e98e3e1Schristos trace_printf (sd, cpu, " (instruction incomplete)"); 5554e98e3e1Schristos break; 5564e98e3e1Schristos case trace_fmt_word: 5574e98e3e1Schristos case trace_fmt_addr: 5584e98e3e1Schristos { 5594e98e3e1Schristos switch (size) 5604e98e3e1Schristos { 5614b169a6bSchristos case sizeof (uint32_t): 5624b169a6bSchristos trace_printf (sd, cpu, " 0x%08lx", (long) * (uint32_t*) data); 5634e98e3e1Schristos break; 5644b169a6bSchristos case sizeof (uint64_t): 5654e98e3e1Schristos trace_printf (sd, cpu, " 0x%08lx%08lx", 5664b169a6bSchristos (long) ((* (uint64_t*) data) >> 32), 5674b169a6bSchristos (long) * (uint64_t*) data); 5684e98e3e1Schristos break; 5694e98e3e1Schristos default: 5704e98e3e1Schristos abort (); 5714e98e3e1Schristos } 5724e98e3e1Schristos break; 5734e98e3e1Schristos } 5744e98e3e1Schristos case trace_fmt_bool: 5754e98e3e1Schristos { 5764e98e3e1Schristos SIM_ASSERT (size == sizeof (int)); 5774e98e3e1Schristos trace_printf (sd, cpu, " %-8s", 5784e98e3e1Schristos (* (int*) data) ? "true" : "false"); 5794e98e3e1Schristos break; 5804e98e3e1Schristos } 5814e98e3e1Schristos case trace_fmt_fp: 5824e98e3e1Schristos { 5834e98e3e1Schristos sim_fpu fp; 5844e98e3e1Schristos switch (size) 5854e98e3e1Schristos { 5864e98e3e1Schristos /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */ 5874e98e3e1Schristos case 4: 5884b169a6bSchristos sim_fpu_32to (&fp, *(uint32_t*)data); 5894e98e3e1Schristos break; 5904e98e3e1Schristos case 8: 5914b169a6bSchristos sim_fpu_64to (&fp, *(uint64_t*)data); 5924e98e3e1Schristos break; 5934e98e3e1Schristos default: 5944e98e3e1Schristos abort (); 5954e98e3e1Schristos } 5964e98e3e1Schristos trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp)); 5974e98e3e1Schristos switch (size) 5984e98e3e1Schristos { 5994e98e3e1Schristos case 4: 6004e98e3e1Schristos trace_printf (sd, cpu, " (0x%08lx)", 6014b169a6bSchristos (long) *(uint32_t*)data); 6024e98e3e1Schristos break; 6034e98e3e1Schristos case 8: 6044e98e3e1Schristos trace_printf (sd, cpu, " (0x%08lx%08lx)", 6054b169a6bSchristos (long) (*(uint64_t*)data >> 32), 6064b169a6bSchristos (long) (*(uint64_t*)data)); 6074e98e3e1Schristos break; 6084e98e3e1Schristos default: 6094e98e3e1Schristos abort (); 6104e98e3e1Schristos } 6114e98e3e1Schristos break; 6124e98e3e1Schristos } 6134e98e3e1Schristos case trace_fmt_fpu: 6144e98e3e1Schristos /* FIXME: At present sim_fpu data is stored as a double */ 6154e98e3e1Schristos trace_printf (sd, cpu, " %8g", * (double*) data); 6164e98e3e1Schristos break; 6174e98e3e1Schristos case trace_fmt_string: 6184e98e3e1Schristos trace_printf (sd, cpu, " %-8s", (char*) data); 6194e98e3e1Schristos break; 6204e98e3e1Schristos default: 6214e98e3e1Schristos abort (); 6224e98e3e1Schristos } 6234e98e3e1Schristos } 6244e98e3e1Schristos 6254e98e3e1Schristos static const char * 6264e98e3e1Schristos trace_idx_to_str (int trace_idx) 6274e98e3e1Schristos { 6284e98e3e1Schristos static char num[8]; 6294e98e3e1Schristos switch (trace_idx) 6304e98e3e1Schristos { 6314e98e3e1Schristos case TRACE_ALU_IDX: return "alu: "; 6324e98e3e1Schristos case TRACE_INSN_IDX: return "insn: "; 633ba340e45Schristos case TRACE_DISASM_IDX: return "disasm: "; 6344e98e3e1Schristos case TRACE_DECODE_IDX: return "decode: "; 6354e98e3e1Schristos case TRACE_EXTRACT_IDX: return "extract: "; 6364e98e3e1Schristos case TRACE_MEMORY_IDX: return "memory: "; 6374e98e3e1Schristos case TRACE_CORE_IDX: return "core: "; 6384e98e3e1Schristos case TRACE_EVENTS_IDX: return "events: "; 6394e98e3e1Schristos case TRACE_FPU_IDX: return "fpu: "; 6404e98e3e1Schristos case TRACE_BRANCH_IDX: return "branch: "; 641a2e2270fSchristos case TRACE_SYSCALL_IDX: return "syscall: "; 642212397c6Schristos case TRACE_REGISTER_IDX: return "reg: "; 6434e98e3e1Schristos case TRACE_VPU_IDX: return "vpu: "; 6444e98e3e1Schristos default: 6454e98e3e1Schristos sprintf (num, "?%d?", trace_idx); 6464e98e3e1Schristos return num; 6474e98e3e1Schristos } 6484e98e3e1Schristos } 6494e98e3e1Schristos 6504e98e3e1Schristos static void 6514e98e3e1Schristos trace_results (SIM_DESC sd, 6524e98e3e1Schristos sim_cpu *cpu, 6534e98e3e1Schristos int trace_idx, 6544e98e3e1Schristos int last_input) 6554e98e3e1Schristos { 6564e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 6574e98e3e1Schristos int nr_out; 6584e98e3e1Schristos int i; 6594e98e3e1Schristos 6604e98e3e1Schristos /* cross check trace_idx against TRACE_IDX (data)? */ 6614e98e3e1Schristos 6624e98e3e1Schristos /* prefix */ 6634e98e3e1Schristos trace_printf (sd, cpu, "%s %s", 6644e98e3e1Schristos trace_idx_to_str (TRACE_IDX (data)), 6654e98e3e1Schristos TRACE_PREFIX (data)); 6664e98e3e1Schristos TRACE_IDX (data) = 0; 6674e98e3e1Schristos 6684e98e3e1Schristos for (i = 0, nr_out = 0; 6694e98e3e1Schristos i < TRACE_INPUT_IDX (data); 6704e98e3e1Schristos i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++) 6714e98e3e1Schristos { 6724e98e3e1Schristos if (i == last_input) 6734e98e3e1Schristos { 6744e98e3e1Schristos int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2); 6754e98e3e1Schristos int padding = pad * (3 - nr_out); 6764e98e3e1Schristos if (padding < 0) 6774e98e3e1Schristos padding = 0; 6784e98e3e1Schristos padding += strlen (" ::"); 6794e98e3e1Schristos trace_printf (sd, cpu, "%*s", padding, " ::"); 6804e98e3e1Schristos } 6814e98e3e1Schristos print_data (sd, cpu, 6824e98e3e1Schristos TRACE_INPUT_FMT (data) [i], 6834e98e3e1Schristos TRACE_INPUT_SIZE (data) [i], 6844e98e3e1Schristos &TRACE_INPUT_DATA (data) [i]); 6854e98e3e1Schristos } 6864e98e3e1Schristos trace_printf (sd, cpu, "\n"); 6874e98e3e1Schristos } 6884e98e3e1Schristos 689796c32c9Schristos int 690796c32c9Schristos trace_load_symbols (SIM_DESC sd) 691796c32c9Schristos { 692796c32c9Schristos bfd *abfd; 693796c32c9Schristos asymbol **asymbols; 694796c32c9Schristos long symsize; 695796c32c9Schristos long symbol_count; 696796c32c9Schristos 697796c32c9Schristos /* Already loaded, so nothing to do. */ 698796c32c9Schristos if (STATE_PROG_SYMS (sd)) 699796c32c9Schristos return 1; 700796c32c9Schristos 701796c32c9Schristos abfd = STATE_PROG_BFD (sd); 702796c32c9Schristos if (abfd == NULL) 703796c32c9Schristos return 0; 704796c32c9Schristos 705796c32c9Schristos symsize = bfd_get_symtab_upper_bound (abfd); 706796c32c9Schristos if (symsize < 0) 707796c32c9Schristos return 0; 708796c32c9Schristos 709796c32c9Schristos asymbols = xmalloc (symsize); 710796c32c9Schristos symbol_count = bfd_canonicalize_symtab (abfd, asymbols); 711796c32c9Schristos if (symbol_count < 0) 712796c32c9Schristos { 713796c32c9Schristos free (asymbols); 714796c32c9Schristos return 0; 715796c32c9Schristos } 716796c32c9Schristos 717796c32c9Schristos STATE_PROG_SYMS (sd) = asymbols; 718796c32c9Schristos STATE_PROG_SYMS_COUNT (sd) = symbol_count; 719796c32c9Schristos return 1; 720796c32c9Schristos } 721796c32c9Schristos 722796c32c9Schristos bfd_vma 723796c32c9Schristos trace_sym_value (SIM_DESC sd, const char *name) 724796c32c9Schristos { 725796c32c9Schristos asymbol **asymbols; 726796c32c9Schristos long i; 727796c32c9Schristos 728796c32c9Schristos if (!trace_load_symbols (sd)) 729796c32c9Schristos return -1; 730796c32c9Schristos 731796c32c9Schristos asymbols = STATE_PROG_SYMS (sd); 732796c32c9Schristos 733796c32c9Schristos for (i = 0; i < STATE_PROG_SYMS_COUNT (sd); ++i) 734796c32c9Schristos if (strcmp (asymbols[i]->name, name) == 0) 735796c32c9Schristos return bfd_asymbol_value (asymbols[i]); 736796c32c9Schristos 737796c32c9Schristos return -1; 738796c32c9Schristos } 739796c32c9Schristos 7404e98e3e1Schristos void 7414e98e3e1Schristos trace_prefix (SIM_DESC sd, 7424e98e3e1Schristos sim_cpu *cpu, 7434e98e3e1Schristos sim_cia cia, 7444e98e3e1Schristos address_word pc, 7454e98e3e1Schristos int line_p, 7464e98e3e1Schristos const char *filename, 7474e98e3e1Schristos int linenum, 7484e98e3e1Schristos const char *fmt, 7494e98e3e1Schristos ...) 7504e98e3e1Schristos { 7514e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 7524e98e3e1Schristos va_list ap; 7534e98e3e1Schristos char *prefix = TRACE_PREFIX (data); 7544e98e3e1Schristos char *chp; 7554e98e3e1Schristos /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using 7564e98e3e1Schristos known information about the disassembled instructions. */ 7574e98e3e1Schristos #ifndef TRACE_PREFIX_WIDTH 7584e98e3e1Schristos #define TRACE_PREFIX_WIDTH 48 7594e98e3e1Schristos #endif 7604e98e3e1Schristos int width = TRACE_PREFIX_WIDTH; 7614e98e3e1Schristos 7624e98e3e1Schristos /* if the previous trace data wasn't flushed, flush it now with a 7634e98e3e1Schristos note indicating that the trace was incomplete. */ 7644e98e3e1Schristos if (TRACE_IDX (data) != 0) 7654e98e3e1Schristos { 7664e98e3e1Schristos int last_input = TRACE_INPUT_IDX (data); 7674e98e3e1Schristos save_data (sd, data, trace_fmt_instruction_incomplete, 1, ""); 7684e98e3e1Schristos trace_results (sd, cpu, TRACE_IDX (data), last_input); 7694e98e3e1Schristos } 7704e98e3e1Schristos TRACE_IDX (data) = 0; 7714e98e3e1Schristos TRACE_INPUT_IDX (data) = 0; 7724e98e3e1Schristos 7734e98e3e1Schristos /* Create the text prefix for this new instruction: */ 7744e98e3e1Schristos if (!line_p) 7754e98e3e1Schristos { 7764e98e3e1Schristos if (filename) 7774e98e3e1Schristos { 7784e98e3e1Schristos sprintf (prefix, "%s:%-*d 0x%.*lx ", 7794e98e3e1Schristos filename, 7804e98e3e1Schristos SIZE_LINE_NUMBER, linenum, 7814e98e3e1Schristos SIZE_PC, (long) pc); 7824e98e3e1Schristos } 7834e98e3e1Schristos else 7844e98e3e1Schristos { 7854e98e3e1Schristos sprintf (prefix, "0x%.*lx ", 7864e98e3e1Schristos SIZE_PC, (long) pc); 7874e98e3e1Schristos /* Shrink the width by the amount that we didn't print. */ 7884e98e3e1Schristos width -= SIZE_LINE_NUMBER + SIZE_PC + 8; 7894e98e3e1Schristos } 7904e98e3e1Schristos chp = strchr (prefix, '\0'); 7914e98e3e1Schristos va_start (ap, fmt); 7924e98e3e1Schristos vsprintf (chp, fmt, ap); 7934e98e3e1Schristos va_end (ap); 7944e98e3e1Schristos } 7954e98e3e1Schristos else 7964e98e3e1Schristos { 7974e98e3e1Schristos char buf[256]; 7984e98e3e1Schristos buf[0] = 0; 799796c32c9Schristos if (STATE_TEXT_SECTION (sd) 800796c32c9Schristos && pc >= STATE_TEXT_START (sd) 801796c32c9Schristos && pc < STATE_TEXT_END (sd)) 8024e98e3e1Schristos { 8034e98e3e1Schristos const char *pc_filename = (const char *)0; 8044e98e3e1Schristos const char *pc_function = (const char *)0; 8054e98e3e1Schristos unsigned int pc_linenum = 0; 8064e98e3e1Schristos bfd *abfd; 8074e98e3e1Schristos asymbol **asymbols; 8084e98e3e1Schristos 809796c32c9Schristos if (!trace_load_symbols (sd)) 810796c32c9Schristos sim_engine_abort (sd, cpu, cia, "could not load symbols"); 8114e98e3e1Schristos 812796c32c9Schristos abfd = STATE_PROG_BFD (sd); 813796c32c9Schristos asymbols = STATE_PROG_SYMS (sd); 8144e98e3e1Schristos 815796c32c9Schristos if (bfd_find_nearest_line (abfd, STATE_TEXT_SECTION (sd), asymbols, 816796c32c9Schristos pc - STATE_TEXT_START (sd), 8174e98e3e1Schristos &pc_filename, &pc_function, &pc_linenum)) 8184e98e3e1Schristos { 8194e98e3e1Schristos char *p = buf; 8204e98e3e1Schristos if (pc_linenum) 8214e98e3e1Schristos { 8224e98e3e1Schristos sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum); 8234e98e3e1Schristos p += strlen (p); 8244e98e3e1Schristos } 8254e98e3e1Schristos else 8264e98e3e1Schristos { 8274e98e3e1Schristos sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); 8284e98e3e1Schristos p += SIZE_LINE_NUMBER+2; 8294e98e3e1Schristos } 8304e98e3e1Schristos 8314e98e3e1Schristos if (pc_function) 8324e98e3e1Schristos { 8334e98e3e1Schristos sprintf (p, "%s ", pc_function); 8344e98e3e1Schristos p += strlen (p); 8354e98e3e1Schristos } 8364e98e3e1Schristos else if (pc_filename) 8374e98e3e1Schristos { 8384e98e3e1Schristos char *q = (char *) strrchr (pc_filename, '/'); 8394e98e3e1Schristos sprintf (p, "%s ", (q) ? q+1 : pc_filename); 8404e98e3e1Schristos p += strlen (p); 8414e98e3e1Schristos } 8424e98e3e1Schristos 8434e98e3e1Schristos if (*p == ' ') 8444e98e3e1Schristos *p = '\0'; 8454e98e3e1Schristos } 8464e98e3e1Schristos } 8474e98e3e1Schristos 8484e98e3e1Schristos sprintf (prefix, "0x%.*x %-*.*s ", 8494e98e3e1Schristos SIZE_PC, (unsigned) pc, 8504e98e3e1Schristos SIZE_LOCATION, SIZE_LOCATION, buf); 8514e98e3e1Schristos chp = strchr (prefix, '\0'); 8524e98e3e1Schristos va_start (ap, fmt); 8534e98e3e1Schristos vsprintf (chp, fmt, ap); 8544e98e3e1Schristos va_end (ap); 8554e98e3e1Schristos } 8564e98e3e1Schristos 8574e98e3e1Schristos /* Pad it out to TRACE_PREFIX_WIDTH. */ 8584e98e3e1Schristos chp = strchr (prefix, '\0'); 8594e98e3e1Schristos if (chp - prefix < width) 8604e98e3e1Schristos { 8614e98e3e1Schristos memset (chp, ' ', width - (chp - prefix)); 8624e98e3e1Schristos chp = &prefix [width]; 8634e98e3e1Schristos *chp = '\0'; 8644e98e3e1Schristos } 8654e98e3e1Schristos strcpy (chp, " -"); 8664e98e3e1Schristos 8674e98e3e1Schristos /* check that we've not over flowed the prefix buffer */ 8684e98e3e1Schristos if (strlen (prefix) >= sizeof (TRACE_PREFIX (data))) 8694e98e3e1Schristos abort (); 8704e98e3e1Schristos } 8714e98e3e1Schristos 8724e98e3e1Schristos void 8734e98e3e1Schristos trace_generic (SIM_DESC sd, 8744e98e3e1Schristos sim_cpu *cpu, 8754e98e3e1Schristos int trace_idx, 8764e98e3e1Schristos const char *fmt, 8774e98e3e1Schristos ...) 8784e98e3e1Schristos { 8794e98e3e1Schristos va_list ap; 8804e98e3e1Schristos trace_printf (sd, cpu, "%s %s", 8814e98e3e1Schristos trace_idx_to_str (trace_idx), 8824e98e3e1Schristos TRACE_PREFIX (CPU_TRACE_DATA (cpu))); 8834e98e3e1Schristos va_start (ap, fmt); 8844e98e3e1Schristos trace_vprintf (sd, cpu, fmt, ap); 8854e98e3e1Schristos va_end (ap); 8864e98e3e1Schristos trace_printf (sd, cpu, "\n"); 8874e98e3e1Schristos } 8884e98e3e1Schristos 889ba340e45Schristos static int 890ba340e45Schristos dis_read (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, 891ba340e45Schristos struct disassemble_info *dinfo) 892ba340e45Schristos { 893ba340e45Schristos SIM_CPU *cpu = dinfo->application_data; 894ba340e45Schristos sim_core_read_buffer (CPU_STATE (cpu), cpu, NULL_CIA, myaddr, memaddr, length); 895ba340e45Schristos return 0; 896ba340e45Schristos } 897ba340e45Schristos 8984b169a6bSchristos static int ATTRIBUTE_PRINTF (2, 3) 899ba340e45Schristos dis_printf (SIM_CPU *cpu, const char *fmt, ...) 900ba340e45Schristos { 901ba340e45Schristos SIM_DESC sd = CPU_STATE (cpu); 902ba340e45Schristos va_list ap; 903ba340e45Schristos va_start (ap, fmt); 904ba340e45Schristos trace_vprintf (sd, cpu, fmt, ap); 905ba340e45Schristos va_end (ap); 906ba340e45Schristos return 0; 907ba340e45Schristos } 908ba340e45Schristos 9094b169a6bSchristos static int ATTRIBUTE_PRINTF (3, 4) 9104b169a6bSchristos dis_styled_printf (SIM_CPU *cpu, enum disassembler_style style, 9114b169a6bSchristos const char *fmt, ...) 9124b169a6bSchristos { 9134b169a6bSchristos SIM_DESC sd = CPU_STATE (cpu); 9144b169a6bSchristos va_list ap; 9154b169a6bSchristos va_start (ap, fmt); 9164b169a6bSchristos trace_vprintf (sd, cpu, fmt, ap); 9174b169a6bSchristos va_end (ap); 9184b169a6bSchristos return 0; 9194b169a6bSchristos } 9204b169a6bSchristos 921ba340e45Schristos void 922ba340e45Schristos trace_disasm (SIM_DESC sd, sim_cpu *cpu, address_word addr) 923ba340e45Schristos { 924ba340e45Schristos struct bfd *bfd = STATE_PROG_BFD (sd); 925ba340e45Schristos TRACE_DATA *trace_data = CPU_TRACE_DATA (cpu); 926ba340e45Schristos disassemble_info *info = &trace_data->dis_info; 927ba340e45Schristos 928ba340e45Schristos /* See if we need to set up the disassembly func. */ 929ba340e45Schristos if (trace_data->dis_bfd != bfd) 930ba340e45Schristos { 931ba340e45Schristos trace_data->dis_bfd = bfd; 9324559860eSchristos trace_data->disassembler 9334559860eSchristos = disassembler (bfd_get_arch (trace_data->dis_bfd), 9344559860eSchristos bfd_big_endian (trace_data->dis_bfd), 9354559860eSchristos bfd_get_mach (trace_data->dis_bfd), 9364559860eSchristos trace_data->dis_bfd); 9374b169a6bSchristos INIT_DISASSEMBLE_INFO (*info, cpu, dis_printf, dis_styled_printf); 938ba340e45Schristos info->read_memory_func = dis_read; 939ba340e45Schristos info->arch = bfd_get_arch (bfd); 940ba340e45Schristos info->mach = bfd_get_mach (bfd); 941ba340e45Schristos disassemble_init_for_target (info); 942ba340e45Schristos } 943ba340e45Schristos 944ba340e45Schristos info->application_data = cpu; 945ba340e45Schristos 946ba340e45Schristos trace_printf (sd, cpu, "%s %s", 947ba340e45Schristos trace_idx_to_str (TRACE_DISASM_IDX), 948ba340e45Schristos TRACE_PREFIX (trace_data)); 949ba340e45Schristos trace_data->disassembler (addr, info); 950ba340e45Schristos trace_printf (sd, cpu, "\n"); 951ba340e45Schristos } 952ba340e45Schristos 9534e98e3e1Schristos void 9544e98e3e1Schristos trace_input0 (SIM_DESC sd, 9554e98e3e1Schristos sim_cpu *cpu, 9564e98e3e1Schristos int trace_idx) 9574e98e3e1Schristos { 9584e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 9594e98e3e1Schristos TRACE_IDX (data) = trace_idx; 9604e98e3e1Schristos } 9614e98e3e1Schristos 9624e98e3e1Schristos void 9634e98e3e1Schristos trace_input_word1 (SIM_DESC sd, 9644e98e3e1Schristos sim_cpu *cpu, 9654e98e3e1Schristos int trace_idx, 9664e98e3e1Schristos unsigned_word d0) 9674e98e3e1Schristos { 9684e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 9694e98e3e1Schristos TRACE_IDX (data) = trace_idx; 9704e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); 9714e98e3e1Schristos } 9724e98e3e1Schristos 9734e98e3e1Schristos void 9744e98e3e1Schristos trace_input_word2 (SIM_DESC sd, 9754e98e3e1Schristos sim_cpu *cpu, 9764e98e3e1Schristos int trace_idx, 9774e98e3e1Schristos unsigned_word d0, 9784e98e3e1Schristos unsigned_word d1) 9794e98e3e1Schristos { 9804e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 9814e98e3e1Schristos TRACE_IDX (data) = trace_idx; 9824e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); 9834e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1); 9844e98e3e1Schristos } 9854e98e3e1Schristos 9864e98e3e1Schristos void 9874e98e3e1Schristos trace_input_word3 (SIM_DESC sd, 9884e98e3e1Schristos sim_cpu *cpu, 9894e98e3e1Schristos int trace_idx, 9904e98e3e1Schristos unsigned_word d0, 9914e98e3e1Schristos unsigned_word d1, 9924e98e3e1Schristos unsigned_word d2) 9934e98e3e1Schristos { 9944e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 9954e98e3e1Schristos TRACE_IDX (data) = trace_idx; 9964e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); 9974e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1); 9984e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2); 9994e98e3e1Schristos } 10004e98e3e1Schristos 10014e98e3e1Schristos void 10024e98e3e1Schristos trace_input_word4 (SIM_DESC sd, 10034e98e3e1Schristos sim_cpu *cpu, 10044e98e3e1Schristos int trace_idx, 10054e98e3e1Schristos unsigned_word d0, 10064e98e3e1Schristos unsigned_word d1, 10074e98e3e1Schristos unsigned_word d2, 10084e98e3e1Schristos unsigned_word d3) 10094e98e3e1Schristos { 10104e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 10114e98e3e1Schristos TRACE_IDX (data) = trace_idx; 10124e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (d0), &d0); 10134e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (d1), &d1); 10144e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (d2), &d2); 10154e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (d3), &d3); 10164e98e3e1Schristos } 10174e98e3e1Schristos 10184e98e3e1Schristos void 10194e98e3e1Schristos trace_input_bool1 (SIM_DESC sd, 10204e98e3e1Schristos sim_cpu *cpu, 10214e98e3e1Schristos int trace_idx, 10224e98e3e1Schristos int d0) 10234e98e3e1Schristos { 10244e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 10254e98e3e1Schristos TRACE_IDX (data) = trace_idx; 10264e98e3e1Schristos save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0); 10274e98e3e1Schristos } 10284e98e3e1Schristos 10294e98e3e1Schristos void 10304e98e3e1Schristos trace_input_addr1 (SIM_DESC sd, 10314e98e3e1Schristos sim_cpu *cpu, 10324e98e3e1Schristos int trace_idx, 10334e98e3e1Schristos address_word d0) 10344e98e3e1Schristos { 10354e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 10364e98e3e1Schristos TRACE_IDX (data) = trace_idx; 10374e98e3e1Schristos save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0); 10384e98e3e1Schristos } 10394e98e3e1Schristos 10404e98e3e1Schristos void 10414e98e3e1Schristos trace_input_fp1 (SIM_DESC sd, 10424e98e3e1Schristos sim_cpu *cpu, 10434e98e3e1Schristos int trace_idx, 10444e98e3e1Schristos fp_word f0) 10454e98e3e1Schristos { 10464e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 10474e98e3e1Schristos TRACE_IDX (data) = trace_idx; 10484e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 10494e98e3e1Schristos } 10504e98e3e1Schristos 10514e98e3e1Schristos void 10524e98e3e1Schristos trace_input_fp2 (SIM_DESC sd, 10534e98e3e1Schristos sim_cpu *cpu, 10544e98e3e1Schristos int trace_idx, 10554e98e3e1Schristos fp_word f0, 10564e98e3e1Schristos fp_word f1) 10574e98e3e1Schristos { 10584e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 10594e98e3e1Schristos TRACE_IDX (data) = trace_idx; 10604e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 10614e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1); 10624e98e3e1Schristos } 10634e98e3e1Schristos 10644e98e3e1Schristos void 10654e98e3e1Schristos trace_input_fp3 (SIM_DESC sd, 10664e98e3e1Schristos sim_cpu *cpu, 10674e98e3e1Schristos int trace_idx, 10684e98e3e1Schristos fp_word f0, 10694e98e3e1Schristos fp_word f1, 10704e98e3e1Schristos fp_word f2) 10714e98e3e1Schristos { 10724e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 10734e98e3e1Schristos TRACE_IDX (data) = trace_idx; 10744e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 10754e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1); 10764e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2); 10774e98e3e1Schristos } 10784e98e3e1Schristos 10794e98e3e1Schristos void 10804e98e3e1Schristos trace_input_fpu1 (SIM_DESC sd, 10814e98e3e1Schristos sim_cpu *cpu, 10824e98e3e1Schristos int trace_idx, 10834e98e3e1Schristos sim_fpu *f0) 10844e98e3e1Schristos { 10854e98e3e1Schristos double d; 10864e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 10874e98e3e1Schristos TRACE_IDX (data) = trace_idx; 10884e98e3e1Schristos d = sim_fpu_2d (f0); 10894e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 10904e98e3e1Schristos } 10914e98e3e1Schristos 10924e98e3e1Schristos void 10934e98e3e1Schristos trace_input_fpu2 (SIM_DESC sd, 10944e98e3e1Schristos sim_cpu *cpu, 10954e98e3e1Schristos int trace_idx, 10964e98e3e1Schristos sim_fpu *f0, 10974e98e3e1Schristos sim_fpu *f1) 10984e98e3e1Schristos { 10994e98e3e1Schristos double d; 11004e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 11014e98e3e1Schristos TRACE_IDX (data) = trace_idx; 11024e98e3e1Schristos d = sim_fpu_2d (f0); 11034e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 11044e98e3e1Schristos d = sim_fpu_2d (f1); 11054e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 11064e98e3e1Schristos } 11074e98e3e1Schristos 11084e98e3e1Schristos void 11094e98e3e1Schristos trace_input_fpu3 (SIM_DESC sd, 11104e98e3e1Schristos sim_cpu *cpu, 11114e98e3e1Schristos int trace_idx, 11124e98e3e1Schristos sim_fpu *f0, 11134e98e3e1Schristos sim_fpu *f1, 11144e98e3e1Schristos sim_fpu *f2) 11154e98e3e1Schristos { 11164e98e3e1Schristos double d; 11174e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 11184e98e3e1Schristos TRACE_IDX (data) = trace_idx; 11194e98e3e1Schristos d = sim_fpu_2d (f0); 11204e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 11214e98e3e1Schristos d = sim_fpu_2d (f1); 11224e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 11234e98e3e1Schristos d = sim_fpu_2d (f2); 11244e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 11254e98e3e1Schristos } 11264e98e3e1Schristos 11274e98e3e1Schristos void 11284e98e3e1Schristos trace_result_word1 (SIM_DESC sd, 11294e98e3e1Schristos sim_cpu *cpu, 11304e98e3e1Schristos int trace_idx, 11314e98e3e1Schristos unsigned_word r0) 11324e98e3e1Schristos { 11334e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 11344e98e3e1Schristos int last_input; 11354e98e3e1Schristos 11364e98e3e1Schristos /* Append any results to the end of the inputs */ 11374e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 11384e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0); 11394e98e3e1Schristos 11404e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 11414e98e3e1Schristos } 11424e98e3e1Schristos 11434e98e3e1Schristos void 11444e98e3e1Schristos trace_result0 (SIM_DESC sd, 11454e98e3e1Schristos sim_cpu *cpu, 11464e98e3e1Schristos int trace_idx) 11474e98e3e1Schristos { 11484e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 11494e98e3e1Schristos int last_input; 11504e98e3e1Schristos 11514e98e3e1Schristos /* Append any results to the end of the inputs */ 11524e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 11534e98e3e1Schristos 11544e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 11554e98e3e1Schristos } 11564e98e3e1Schristos 11574e98e3e1Schristos void 11584e98e3e1Schristos trace_result_word2 (SIM_DESC sd, 11594e98e3e1Schristos sim_cpu *cpu, 11604e98e3e1Schristos int trace_idx, 11614e98e3e1Schristos unsigned_word r0, 11624e98e3e1Schristos unsigned_word r1) 11634e98e3e1Schristos { 11644e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 11654e98e3e1Schristos int last_input; 11664e98e3e1Schristos 11674e98e3e1Schristos /* Append any results to the end of the inputs */ 11684e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 11694e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (r0), &r0); 11704e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (r1), &r1); 11714e98e3e1Schristos 11724e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 11734e98e3e1Schristos } 11744e98e3e1Schristos 11754e98e3e1Schristos void 11764e98e3e1Schristos trace_result_word4 (SIM_DESC sd, 11774e98e3e1Schristos sim_cpu *cpu, 11784e98e3e1Schristos int trace_idx, 11794e98e3e1Schristos unsigned_word r0, 11804e98e3e1Schristos unsigned_word r1, 11814e98e3e1Schristos unsigned_word r2, 11824e98e3e1Schristos unsigned_word r3) 11834e98e3e1Schristos { 11844e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 11854e98e3e1Schristos int last_input; 11864e98e3e1Schristos 11874e98e3e1Schristos /* Append any results to the end of the inputs */ 11884e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 11894e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (r0), &r0); 11904e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (r1), &r1); 11914e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (r2), &r2); 11924e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (r3), &r3); 11934e98e3e1Schristos 11944e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 11954e98e3e1Schristos } 11964e98e3e1Schristos 11974e98e3e1Schristos void 11984e98e3e1Schristos trace_result_bool1 (SIM_DESC sd, 11994e98e3e1Schristos sim_cpu *cpu, 12004e98e3e1Schristos int trace_idx, 12014e98e3e1Schristos int r0) 12024e98e3e1Schristos { 12034e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 12044e98e3e1Schristos int last_input; 12054e98e3e1Schristos 12064e98e3e1Schristos /* Append any results to the end of the inputs */ 12074e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 12084e98e3e1Schristos save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0); 12094e98e3e1Schristos 12104e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 12114e98e3e1Schristos } 12124e98e3e1Schristos 12134e98e3e1Schristos void 12144e98e3e1Schristos trace_result_addr1 (SIM_DESC sd, 12154e98e3e1Schristos sim_cpu *cpu, 12164e98e3e1Schristos int trace_idx, 12174e98e3e1Schristos address_word r0) 12184e98e3e1Schristos { 12194e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 12204e98e3e1Schristos int last_input; 12214e98e3e1Schristos 12224e98e3e1Schristos /* Append any results to the end of the inputs */ 12234e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 12244e98e3e1Schristos save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0); 12254e98e3e1Schristos 12264e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 12274e98e3e1Schristos } 12284e98e3e1Schristos 12294e98e3e1Schristos void 12304e98e3e1Schristos trace_result_fp1 (SIM_DESC sd, 12314e98e3e1Schristos sim_cpu *cpu, 12324e98e3e1Schristos int trace_idx, 12334e98e3e1Schristos fp_word f0) 12344e98e3e1Schristos { 12354e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 12364e98e3e1Schristos int last_input; 12374e98e3e1Schristos 12384e98e3e1Schristos /* Append any results to the end of the inputs */ 12394e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 12404e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); 12414e98e3e1Schristos 12424e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 12434e98e3e1Schristos } 12444e98e3e1Schristos 12454e98e3e1Schristos void 12464e98e3e1Schristos trace_result_fp2 (SIM_DESC sd, 12474e98e3e1Schristos sim_cpu *cpu, 12484e98e3e1Schristos int trace_idx, 12494e98e3e1Schristos fp_word f0, 12504e98e3e1Schristos fp_word f1) 12514e98e3e1Schristos { 12524e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 12534e98e3e1Schristos int last_input; 12544e98e3e1Schristos 12554e98e3e1Schristos /* Append any results to the end of the inputs */ 12564e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 12574e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (f0), &f0); 12584e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1); 12594e98e3e1Schristos 12604e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 12614e98e3e1Schristos } 12624e98e3e1Schristos 12634e98e3e1Schristos void 12644e98e3e1Schristos trace_result_fpu1 (SIM_DESC sd, 12654e98e3e1Schristos sim_cpu *cpu, 12664e98e3e1Schristos int trace_idx, 12674e98e3e1Schristos sim_fpu *f0) 12684e98e3e1Schristos { 12694e98e3e1Schristos double d; 12704e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 12714e98e3e1Schristos int last_input; 12724e98e3e1Schristos 12734e98e3e1Schristos /* Append any results to the end of the inputs */ 12744e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 12754e98e3e1Schristos d = sim_fpu_2d (f0); 12764e98e3e1Schristos save_data (sd, data, trace_fmt_fp, sizeof (double), &d); 12774e98e3e1Schristos 12784e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 12794e98e3e1Schristos } 12804e98e3e1Schristos 12814e98e3e1Schristos void 12824e98e3e1Schristos trace_result_string1 (SIM_DESC sd, 12834e98e3e1Schristos sim_cpu *cpu, 12844e98e3e1Schristos int trace_idx, 12854e98e3e1Schristos char *s0) 12864e98e3e1Schristos { 12874e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 12884e98e3e1Schristos int last_input; 12894e98e3e1Schristos 12904e98e3e1Schristos /* Append any results to the end of the inputs */ 12914e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 12924e98e3e1Schristos save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0); 12934e98e3e1Schristos 12944e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 12954e98e3e1Schristos } 12964e98e3e1Schristos 12974e98e3e1Schristos void 12984e98e3e1Schristos trace_result_word1_string1 (SIM_DESC sd, 12994e98e3e1Schristos sim_cpu *cpu, 13004e98e3e1Schristos int trace_idx, 13014e98e3e1Schristos unsigned_word r0, 13024e98e3e1Schristos char *s0) 13034e98e3e1Schristos { 13044e98e3e1Schristos TRACE_DATA *data = CPU_TRACE_DATA (cpu); 13054e98e3e1Schristos int last_input; 13064e98e3e1Schristos 13074e98e3e1Schristos /* Append any results to the end of the inputs */ 13084e98e3e1Schristos last_input = TRACE_INPUT_IDX (data); 13094e98e3e1Schristos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0); 13104e98e3e1Schristos save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0); 13114e98e3e1Schristos 13124e98e3e1Schristos trace_results (sd, cpu, trace_idx, last_input); 13134e98e3e1Schristos } 13144e98e3e1Schristos 13154e98e3e1Schristos void 13164e98e3e1Schristos trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap) 13174e98e3e1Schristos { 13184e98e3e1Schristos if (cpu != NULL) 13194e98e3e1Schristos { 13204e98e3e1Schristos if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL) 13214e98e3e1Schristos vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap); 13224e98e3e1Schristos else 13234e98e3e1Schristos sim_io_evprintf (sd, fmt, ap); 13244e98e3e1Schristos } 13254e98e3e1Schristos else 13264e98e3e1Schristos { 13274e98e3e1Schristos if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL) 13284e98e3e1Schristos vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap); 13294e98e3e1Schristos else 13304e98e3e1Schristos sim_io_evprintf (sd, fmt, ap); 13314e98e3e1Schristos } 13324e98e3e1Schristos } 13334e98e3e1Schristos 13344e98e3e1Schristos void 133503467a24Schristos trace_printf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...) 13364e98e3e1Schristos { 13374e98e3e1Schristos va_list ap; 13384e98e3e1Schristos 133903467a24Schristos va_start (ap, fmt); 13404e98e3e1Schristos 13414e98e3e1Schristos trace_vprintf (sd, cpu, fmt, ap); 13424e98e3e1Schristos 13434e98e3e1Schristos va_end (ap); 13444e98e3e1Schristos } 13454e98e3e1Schristos 13464e98e3e1Schristos void 1347212397c6Schristos sim_debug_printf (sim_cpu *cpu, const char *fmt, ...) 13484e98e3e1Schristos { 13494e98e3e1Schristos va_list ap; 13504e98e3e1Schristos 135103467a24Schristos va_start (ap, fmt); 13524e98e3e1Schristos 13534e98e3e1Schristos if (CPU_DEBUG_FILE (cpu) == NULL) 13544e98e3e1Schristos (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered) 13554e98e3e1Schristos (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap); 13564e98e3e1Schristos else 13574e98e3e1Schristos vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap); 13584e98e3e1Schristos 13594e98e3e1Schristos va_end (ap); 13604e98e3e1Schristos } 1361