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