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