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