]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-trace.c
fix typo
[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 (sd, opt, arg, is_command)
196 SIM_DESC sd;
197 int opt;
198 char *arg;
199 int is_command;
200 {
201 int n;
202
203 switch (opt)
204 {
205 case 't' :
206 if (! WITH_TRACE)
207 sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
208 else
209 return set_trace_option_mask (sd, "trace", TRACE_USEFUL_MASK, arg);
210 break;
211
212 case OPTION_TRACE_INSN :
213 if (WITH_TRACE_INSN_P)
214 return set_trace_option (sd, "-insn", TRACE_INSN_IDX, arg);
215 else
216 sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
217 break;
218
219 case OPTION_TRACE_DECODE :
220 if (WITH_TRACE_DECODE_P)
221 return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg);
222 else
223 sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
224 break;
225
226 case OPTION_TRACE_EXTRACT :
227 if (WITH_TRACE_EXTRACT_P)
228 return set_trace_option (sd, "-extract", TRACE_EXTRACT_IDX, arg);
229 else
230 sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
231 break;
232
233 case OPTION_TRACE_LINENUM :
234 if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P)
235 {
236 if (set_trace_option (sd, "-linenum", TRACE_LINENUM_IDX, arg) != SIM_RC_OK
237 || set_trace_option (sd, "-linenum", TRACE_INSN_IDX, arg) != SIM_RC_OK)
238 return SIM_RC_FAIL;
239 }
240 else
241 sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
242 break;
243
244 case OPTION_TRACE_MEMORY :
245 if (WITH_TRACE_MEMORY_P)
246 return set_trace_option (sd, "-memory", TRACE_MEMORY_IDX, arg);
247 else
248 sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
249 break;
250
251 case OPTION_TRACE_MODEL :
252 if (WITH_TRACE_MODEL_P)
253 return set_trace_option (sd, "-model", TRACE_MODEL_IDX, arg);
254 else
255 sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
256 break;
257
258 case OPTION_TRACE_ALU :
259 if (WITH_TRACE_ALU_P)
260 return set_trace_option (sd, "-alu", TRACE_ALU_IDX, arg);
261 else
262 sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
263 break;
264
265 case OPTION_TRACE_CORE :
266 if (WITH_TRACE_CORE_P)
267 return set_trace_option (sd, "-core", TRACE_CORE_IDX, arg);
268 else
269 sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
270 break;
271
272 case OPTION_TRACE_EVENTS :
273 if (WITH_TRACE_EVENTS_P)
274 return set_trace_option (sd, "-events", TRACE_EVENTS_IDX, arg);
275 else
276 sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
277 break;
278
279 case OPTION_TRACE_FPU :
280 if (WITH_TRACE_FPU_P)
281 return set_trace_option (sd, "-fpu", TRACE_FPU_IDX, arg);
282 else
283 sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
284 break;
285
286 case OPTION_TRACE_BRANCH :
287 if (WITH_TRACE_BRANCH_P)
288 return set_trace_option (sd, "-branch", TRACE_BRANCH_IDX, arg);
289 else
290 sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n");
291 break;
292
293 case OPTION_TRACE_SEMANTICS :
294 if (WITH_TRACE_ALU_P
295 && WITH_TRACE_FPU_P
296 && WITH_TRACE_MEMORY_P
297 && WITH_TRACE_BRANCH_P)
298 {
299 if (set_trace_option (sd, "-semantics", TRACE_ALU_IDX, arg) != SIM_RC_OK
300 || set_trace_option (sd, "-semantics", TRACE_FPU_IDX, arg) != SIM_RC_OK
301 || set_trace_option (sd, "-semantics", TRACE_MEMORY_IDX, arg) != SIM_RC_OK
302 || set_trace_option (sd, "-semantics", TRACE_BRANCH_IDX, arg) != SIM_RC_OK)
303 return SIM_RC_FAIL;
304 }
305 else
306 sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n");
307 break;
308
309 case OPTION_TRACE_DEBUG :
310 if (WITH_TRACE_DEBUG_P)
311 return set_trace_option (sd, "-debug", TRACE_DEBUG_IDX, arg);
312 else
313 sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n");
314 break;
315
316 case OPTION_TRACE_FILE :
317 if (! WITH_TRACE)
318 sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
319 else
320 {
321 FILE *f = fopen (arg, "w");
322
323 if (f == NULL)
324 {
325 sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
326 return SIM_RC_FAIL;
327 }
328 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
329 TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f;
330 TRACE_FILE (STATE_TRACE_DATA (sd)) = f;
331 }
332 break;
333 }
334
335 return SIM_RC_OK;
336 }
337 \f
338 /* Install tracing support. */
339
340 SIM_RC
341 trace_install (SIM_DESC sd)
342 {
343 int i;
344
345 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
346
347 sim_add_option_table (sd, trace_options);
348 memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd)));
349 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
350 memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
351 sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i))));
352 sim_module_add_uninstall_fn (sd, trace_uninstall);
353 return SIM_RC_OK;
354 }
355
356 static void
357 trace_uninstall (SIM_DESC sd)
358 {
359 int i,j;
360 FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd));
361
362 if (sfile != NULL)
363 fclose (sfile);
364
365 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
366 {
367 FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i)));
368 if (cfile != NULL && cfile != sfile)
369 {
370 /* If output from different cpus is going to the same file,
371 avoid closing the file twice. */
372 for (j = 0; j < i; ++j)
373 if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile)
374 break;
375 if (i == j)
376 fclose (cfile);
377 }
378 }
379 }
380 \f
381 typedef enum {
382 trace_fmt_invalid,
383 trace_fmt_word,
384 trace_fmt_fp,
385 trace_fmt_fpu,
386 trace_fmt_string,
387 trace_fmt_instruction_incomplete,
388 } data_fmt;
389
390 /* compute the nr of trace data units consumed by data */
391 static int
392 save_data_size (TRACE_DATA *data,
393 long size)
394 {
395 return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1)
396 / sizeof (TRACE_INPUT_DATA (data) [0]));
397 }
398
399
400 /* Archive DATA into the trace buffer */
401 static void
402 save_data (SIM_DESC sd,
403 TRACE_DATA *data,
404 data_fmt fmt,
405 long size,
406 void *buf)
407 {
408 int i = TRACE_INPUT_IDX (data);
409 if (i == sizeof (TRACE_INPUT_FMT (data)))
410 sim_io_error (sd, "trace buffer overflow");
411 TRACE_INPUT_FMT (data) [i] = fmt;
412 TRACE_INPUT_SIZE (data) [i] = size;
413 memcpy (&TRACE_INPUT_DATA (data) [i], buf, size);
414 i += save_data_size (data, size);
415 TRACE_INPUT_IDX (data) = i;
416 }
417
418 static void
419 print_data (SIM_DESC sd,
420 sim_cpu *cpu,
421 data_fmt fmt,
422 long size,
423 void *data)
424 {
425 switch (fmt)
426 {
427 case trace_fmt_instruction_incomplete:
428 trace_printf (sd, cpu, " (instruction incomplete)");
429 break;
430 case trace_fmt_word:
431 switch (size)
432 {
433 case sizeof (unsigned_word):
434 trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned_word*) data);
435 break;
436 default:
437 abort ();
438 }
439 break;
440 case trace_fmt_fp:
441 switch (size)
442 {
443 /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */
444 case 4:
445 trace_printf (sd, cpu, " %8g", * (float*) data);
446 break;
447 case 8:
448 trace_printf (sd, cpu, " %8g", * (double*) data);
449 break;
450 default:
451 abort ();
452 }
453 case trace_fmt_fpu:
454 /* FIXME: At present sim_fpu data is stored as a double */
455 trace_printf (sd, cpu, " %8g", * (double*) data);
456 break;
457 case trace_fmt_string:
458 trace_printf (sd, cpu, " %-8s", (char*) data);
459 break;
460 default:
461 abort ();
462 }
463 }
464
465 static const char *
466 trace_idx_to_str (int trace_idx)
467 {
468 static char num[8];
469 switch (trace_idx)
470 {
471 case TRACE_ALU_IDX: return "alu: ";
472 case TRACE_INSN_IDX: return "insn: ";
473 case TRACE_DECODE_IDX: return "decode: ";
474 case TRACE_EXTRACT_IDX: return "extract: ";
475 case TRACE_MEMORY_IDX: return "memory: ";
476 case TRACE_CORE_IDX: return "core: ";
477 case TRACE_EVENTS_IDX: return "events: ";
478 case TRACE_FPU_IDX: return "fpu: ";
479 case TRACE_BRANCH_IDX: return "branch: ";
480 default:
481 sprintf (num, "?%d?", trace_idx);
482 return num;
483 }
484 }
485
486 static void
487 trace_results (SIM_DESC sd,
488 sim_cpu *cpu,
489 int trace_idx,
490 int last_input)
491 {
492 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
493 int nr_out;
494 int i;
495
496 /* cross check trace_idx against TRACE_IDX (data)? */
497
498 /* prefix */
499 trace_printf (sd, cpu, "%s %s",
500 trace_idx_to_str (TRACE_IDX (data)),
501 TRACE_PREFIX (data));
502 TRACE_IDX (data) = 0;
503
504 for (i = 0, nr_out = 0;
505 i < TRACE_INPUT_IDX (data);
506 i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++)
507 {
508 if (i == last_input)
509 {
510 int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2);
511 int padding = pad * (3 - nr_out);
512 if (padding < 0)
513 padding = 0;
514 padding += strlen (" ::");
515 trace_printf (sd, cpu, "%*s", padding, " ::");
516 }
517 print_data (sd, cpu,
518 TRACE_INPUT_FMT (data) [i],
519 TRACE_INPUT_SIZE (data) [i],
520 &TRACE_INPUT_DATA (data) [i]);
521 }
522 trace_printf (sd, cpu, "\n");
523 }
524
525 void
526 trace_prefix (SIM_DESC sd,
527 sim_cpu *cpu,
528 address_word pc,
529 int line_p,
530 const char *filename,
531 int linenum,
532 const char *fmt,
533 ...)
534 {
535 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
536 va_list ap;
537 char *prefix = TRACE_PREFIX (data);
538 char *chp;
539
540 /* if the previous trace data wasn't flushed, flush it now with a
541 note indicating that this occured. */
542 if (TRACE_IDX (data) != 0)
543 {
544 int last_input = TRACE_INPUT_IDX (data);
545 save_data (sd, data, trace_fmt_instruction_incomplete, 1, "");
546 trace_results (sd, cpu, TRACE_IDX (data), last_input);
547 }
548 TRACE_IDX (data) = 0;
549 TRACE_INPUT_IDX (data) = 0;
550
551 if (!line_p)
552 {
553 sprintf (prefix, "%s:%-*d 0x%.*lx ",
554 filename,
555 SIZE_LINE_NUMBER, linenum,
556 SIZE_PC, (long)pc);
557 chp = strchr (prefix, '\0');
558 va_start (ap, fmt);
559 vsprintf (chp, fmt, ap);
560 va_end (ap);
561 }
562 else
563 {
564 char buf[256];
565 buf[0] = 0;
566 if (STATE_TEXT_SECTION (CPU_STATE (cpu))
567 && pc >= STATE_TEXT_START (CPU_STATE (cpu))
568 && pc < STATE_TEXT_END (CPU_STATE (cpu)))
569 {
570 const char *pc_filename = (const char *)0;
571 const char *pc_function = (const char *)0;
572 unsigned int pc_linenum = 0;
573
574 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
575 STATE_TEXT_SECTION (CPU_STATE (cpu)),
576 (struct symbol_cache_entry **) 0,
577 pc - STATE_TEXT_START (CPU_STATE (cpu)),
578 &pc_filename, &pc_function, &pc_linenum))
579 {
580 char *p = buf;
581 if (pc_linenum)
582 {
583 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
584 p += strlen (p);
585 }
586 else
587 {
588 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
589 p += SIZE_LINE_NUMBER+2;
590 }
591
592 if (pc_function)
593 {
594 sprintf (p, "%s ", pc_function);
595 p += strlen (p);
596 }
597 else if (pc_filename)
598 {
599 char *q = (char *) strrchr (pc_filename, '/');
600 sprintf (p, "%s ", (q) ? q+1 : pc_filename);
601 p += strlen (p);
602 }
603
604 if (*p == ' ')
605 *p = '\0';
606 }
607 }
608
609 sprintf (prefix, "0x%.*x %-*.*s ",
610 SIZE_PC, (unsigned) pc,
611 SIZE_LOCATION, SIZE_LOCATION, buf);
612 chp = strchr (prefix, '\0');
613 va_start (ap, fmt);
614 vsprintf (chp, fmt, ap);
615 va_end (ap);
616 }
617
618 /* pad it out to TRACE_PREFIX_WIDTH. FIXME: The TRACE_PREFIX_WIDTH
619 should be determined at build time using known information about
620 the disassembled instructions */
621 #ifndef TRACE_PREFIX_WIDTH
622 #define TRACE_PREFIX_WIDTH 48
623 #endif
624 chp = strchr (prefix, '\0');
625 if (chp - prefix < TRACE_PREFIX_WIDTH)
626 {
627 memset (chp, ' ', TRACE_PREFIX_WIDTH - (chp - prefix));
628 chp = &prefix [TRACE_PREFIX_WIDTH];
629 *chp = '\0';
630 }
631 strcpy (chp, " -");
632
633 /* check that we've not over flowed the prefix buffer */
634 if (strlen (prefix) >= sizeof (TRACE_PREFIX (data)))
635 abort ();
636 }
637
638 void
639 trace_generic (SIM_DESC sd,
640 sim_cpu *cpu,
641 int trace_idx,
642 char *fmt,
643 ...)
644 {
645 va_list ap;
646 trace_printf (sd, cpu, "%s %s",
647 trace_idx_to_str (trace_idx),
648 TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
649 va_start (ap, fmt);
650 trace_vprintf (sd, cpu, fmt, ap);
651 va_end (ap);
652 trace_printf (sd, cpu, "\n");
653 }
654
655 void
656 trace_input0 (SIM_DESC sd,
657 sim_cpu *cpu,
658 int trace_idx)
659 {
660 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
661 TRACE_IDX (data) = trace_idx;
662 }
663
664 void
665 trace_input_word1 (SIM_DESC sd,
666 sim_cpu *cpu,
667 int trace_idx,
668 unsigned_word d0)
669 {
670 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
671 TRACE_IDX (data) = trace_idx;
672 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
673 }
674
675 void
676 trace_input_word2 (SIM_DESC sd,
677 sim_cpu *cpu,
678 int trace_idx,
679 unsigned_word d0,
680 unsigned_word d1)
681 {
682 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
683 TRACE_IDX (data) = trace_idx;
684 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
685 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
686 }
687
688 void
689 trace_input_word3 (SIM_DESC sd,
690 sim_cpu *cpu,
691 int trace_idx,
692 unsigned_word d0,
693 unsigned_word d1,
694 unsigned_word d2)
695 {
696 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
697 TRACE_IDX (data) = trace_idx;
698 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
699 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
700 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);
701 }
702
703 void
704 trace_input_fp1 (SIM_DESC sd,
705 sim_cpu *cpu,
706 int trace_idx,
707 fp_word f0)
708 {
709 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
710 TRACE_IDX (data) = trace_idx;
711 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
712 }
713
714 void
715 trace_input_fp2 (SIM_DESC sd,
716 sim_cpu *cpu,
717 int trace_idx,
718 fp_word f0,
719 fp_word f1)
720 {
721 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
722 TRACE_IDX (data) = trace_idx;
723 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
724 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
725 }
726
727 void
728 trace_input_fp3 (SIM_DESC sd,
729 sim_cpu *cpu,
730 int trace_idx,
731 fp_word f0,
732 fp_word f1,
733 fp_word f2)
734 {
735 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
736 TRACE_IDX (data) = trace_idx;
737 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
738 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
739 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2);
740 }
741
742 void
743 trace_input_fpu1 (SIM_DESC sd,
744 sim_cpu *cpu,
745 int trace_idx,
746 sim_fpu *f0)
747 {
748 double d;
749 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
750 TRACE_IDX (data) = trace_idx;
751 d = sim_fpu_2d (f0);
752 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
753 }
754
755 void
756 trace_input_fpu2 (SIM_DESC sd,
757 sim_cpu *cpu,
758 int trace_idx,
759 sim_fpu *f0,
760 sim_fpu *f1)
761 {
762 double d;
763 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
764 TRACE_IDX (data) = trace_idx;
765 d = sim_fpu_2d (f0);
766 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
767 d = sim_fpu_2d (f1);
768 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
769 }
770
771 void
772 trace_input_fpu3 (SIM_DESC sd,
773 sim_cpu *cpu,
774 int trace_idx,
775 sim_fpu *f0,
776 sim_fpu *f1,
777 sim_fpu *f2)
778 {
779 double d;
780 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
781 TRACE_IDX (data) = trace_idx;
782 d = sim_fpu_2d (f0);
783 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
784 d = sim_fpu_2d (f1);
785 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
786 d = sim_fpu_2d (f2);
787 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
788 }
789
790 void
791 trace_result_word1 (SIM_DESC sd,
792 sim_cpu *cpu,
793 int trace_idx,
794 unsigned_word r0)
795 {
796 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
797 int last_input;
798
799 /* Append any results to the end of the inputs */
800 last_input = TRACE_INPUT_IDX (data);
801 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
802
803 trace_results (sd, cpu, trace_idx, last_input);
804 }
805
806 void
807 trace_result_fp1 (SIM_DESC sd,
808 sim_cpu *cpu,
809 int trace_idx,
810 fp_word f0)
811 {
812 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
813 int last_input;
814
815 /* Append any results to the end of the inputs */
816 last_input = TRACE_INPUT_IDX (data);
817 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
818
819 trace_results (sd, cpu, trace_idx, last_input);
820 }
821
822 void
823 trace_result_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 int last_input;
831
832 /* Append any results to the end of the inputs */
833 last_input = TRACE_INPUT_IDX (data);
834 d = sim_fpu_2d (f0);
835 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
836
837 trace_results (sd, cpu, trace_idx, last_input);
838 }
839
840 void
841 trace_result_string1 (SIM_DESC sd,
842 sim_cpu *cpu,
843 int trace_idx,
844 char *s0)
845 {
846 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
847 int last_input;
848
849 /* Append any results to the end of the inputs */
850 last_input = TRACE_INPUT_IDX (data);
851 save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
852
853 trace_results (sd, cpu, trace_idx, last_input);
854 }
855
856 void
857 trace_result_word1_string1 (SIM_DESC sd,
858 sim_cpu *cpu,
859 int trace_idx,
860 unsigned_word r0,
861 char *s0)
862 {
863 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
864 int last_input;
865
866 /* Append any results to the end of the inputs */
867 last_input = TRACE_INPUT_IDX (data);
868 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
869 save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
870
871 trace_results (sd, cpu, trace_idx, last_input);
872 }
873 \f
874 void
875 trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
876 {
877 if (cpu != NULL)
878 {
879 if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
880 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
881 else
882 sim_io_evprintf (sd, fmt, ap);
883 }
884 else
885 {
886 if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
887 vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
888 else
889 sim_io_evprintf (sd, fmt, ap);
890 }
891 }
892
893 void
894 trace_one_insn (SIM_DESC sd, sim_cpu *cpu, address_word pc,
895 int line_p, const char *filename, int linenum,
896 const char *phase_wo_colon, const char *fmt,
897 ...)
898 {
899 va_list ap;
900 char phase[SIZE_PHASE+2];
901
902 strncpy (phase, phase_wo_colon, SIZE_PHASE);
903 strcat (phase, ":");
904
905 if (!line_p)
906 {
907 trace_printf (sd, cpu, "%-*s %s:%-*d 0x%.*lx ",
908 SIZE_PHASE+1, phase,
909 filename,
910 SIZE_LINE_NUMBER, linenum,
911 SIZE_PC, (long)pc);
912 va_start (ap, fmt);
913 trace_vprintf (sd, cpu, fmt, ap);
914 va_end (ap);
915 trace_printf (sd, cpu, "\n");
916 }
917 else
918 {
919 char buf[256];
920
921 buf[0] = 0;
922 if (STATE_TEXT_SECTION (CPU_STATE (cpu))
923 && pc >= STATE_TEXT_START (CPU_STATE (cpu))
924 && pc < STATE_TEXT_END (CPU_STATE (cpu)))
925 {
926 const char *pc_filename = (const char *)0;
927 const char *pc_function = (const char *)0;
928 unsigned int pc_linenum = 0;
929
930 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
931 STATE_TEXT_SECTION (CPU_STATE (cpu)),
932 (struct symbol_cache_entry **) 0,
933 pc - STATE_TEXT_START (CPU_STATE (cpu)),
934 &pc_filename, &pc_function, &pc_linenum))
935 {
936 char *p = buf;
937 if (pc_linenum)
938 {
939 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
940 p += strlen (p);
941 }
942 else
943 {
944 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
945 p += SIZE_LINE_NUMBER+2;
946 }
947
948 if (pc_function)
949 {
950 sprintf (p, "%s ", pc_function);
951 p += strlen (p);
952 }
953 else if (pc_filename)
954 {
955 char *q = (char *) strrchr (pc_filename, '/');
956 sprintf (p, "%s ", (q) ? q+1 : pc_filename);
957 p += strlen (p);
958 }
959
960 if (*p == ' ')
961 *p = '\0';
962 }
963 }
964
965 trace_printf (sd, cpu, "%-*s 0x%.*x %-*.*s ",
966 SIZE_PHASE+1, phase,
967 SIZE_PC, (unsigned) pc,
968 SIZE_LOCATION, SIZE_LOCATION, buf);
969 va_start (ap, fmt);
970 trace_vprintf (sd, cpu, fmt, ap);
971 va_end (ap);
972 trace_printf (sd, cpu, "\n");
973 }
974 }
975
976 void
977 trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...))
978 {
979 #if !defined __STDC__ && !defined ALMOST_STDC
980 SIM_DESC sd;
981 sim_cpu *cpu;
982 const char *fmt;
983 #endif
984 va_list ap;
985
986 VA_START (ap, fmt);
987 #if !defined __STDC__ && !defined ALMOST_STDC
988 sd = va_arg (ap, SIM_DESC);
989 cpu = va_arg (ap, sim_cpu *);
990 fmt = va_arg (ap, const char *);
991 #endif
992
993 trace_vprintf (sd, cpu, fmt, ap);
994
995 va_end (ap);
996 }
997
998 void
999 debug_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...))
1000 {
1001 #if !defined __STDC__ && !defined ALMOST_STDC
1002 sim_cpu *cpu;
1003 const char *fmt;
1004 #endif
1005 va_list ap;
1006
1007 VA_START (ap, fmt);
1008 #if !defined __STDC__ && !defined ALMOST_STDC
1009 cpu = va_arg (ap, sim_cpu *);
1010 fmt = va_arg (ap, const char *);
1011 #endif
1012
1013 if (CPU_DEBUG_FILE (cpu) == NULL)
1014 (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
1015 (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
1016 else
1017 vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
1018
1019 va_end (ap);
1020 }