Extend TRACE macros to include more cases.
[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_bool,
388 trace_fmt_addr,
389 trace_fmt_instruction_incomplete,
390 } data_fmt;
391
392 /* compute the nr of trace data units consumed by data */
393 static int
394 save_data_size (TRACE_DATA *data,
395 long size)
396 {
397 return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1)
398 / sizeof (TRACE_INPUT_DATA (data) [0]));
399 }
400
401
402 /* Archive DATA into the trace buffer */
403 static void
404 save_data (SIM_DESC sd,
405 TRACE_DATA *data,
406 data_fmt fmt,
407 long size,
408 void *buf)
409 {
410 int i = TRACE_INPUT_IDX (data);
411 if (i == sizeof (TRACE_INPUT_FMT (data)))
412 sim_io_error (sd, "trace buffer overflow");
413 TRACE_INPUT_FMT (data) [i] = fmt;
414 TRACE_INPUT_SIZE (data) [i] = size;
415 memcpy (&TRACE_INPUT_DATA (data) [i], buf, size);
416 i += save_data_size (data, size);
417 TRACE_INPUT_IDX (data) = i;
418 }
419
420 static void
421 print_data (SIM_DESC sd,
422 sim_cpu *cpu,
423 data_fmt fmt,
424 long size,
425 void *data)
426 {
427 switch (fmt)
428 {
429 case trace_fmt_instruction_incomplete:
430 trace_printf (sd, cpu, " (instruction incomplete)");
431 break;
432 case trace_fmt_word:
433 case trace_fmt_addr:
434 {
435 switch (size)
436 {
437 case sizeof (unsigned32):
438 trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned32*) data);
439 break;
440 case sizeof (unsigned64):
441 trace_printf (sd, cpu, " 0x%08lx%08lx",
442 (long) ((* (unsigned64*) data) >> 32),
443 (long) * (unsigned64*) data);
444 break;
445 default:
446 abort ();
447 }
448 break;
449 }
450 case trace_fmt_bool:
451 {
452 SIM_ASSERT (size == sizeof (int));
453 trace_printf (sd, cpu, " %-8s",
454 (* (int*) data) ? "true" : "false");
455 break;
456 }
457 case trace_fmt_fp:
458 {
459 sim_fpu fp;
460 switch (size)
461 {
462 /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */
463 case 4:
464 sim_fpu_32to (&fp, * (unsigned32*) data);
465 break;
466 case 8:
467 sim_fpu_64to (&fp, * (unsigned32*) data);
468 break;
469 default:
470 abort ();
471 }
472 trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp));
473 break;
474 }
475 case trace_fmt_fpu:
476 /* FIXME: At present sim_fpu data is stored as a double */
477 trace_printf (sd, cpu, " %8g", * (double*) data);
478 break;
479 case trace_fmt_string:
480 trace_printf (sd, cpu, " %-8s", (char*) data);
481 break;
482 default:
483 abort ();
484 }
485 }
486
487 static const char *
488 trace_idx_to_str (int trace_idx)
489 {
490 static char num[8];
491 switch (trace_idx)
492 {
493 case TRACE_ALU_IDX: return "alu: ";
494 case TRACE_INSN_IDX: return "insn: ";
495 case TRACE_DECODE_IDX: return "decode: ";
496 case TRACE_EXTRACT_IDX: return "extract: ";
497 case TRACE_MEMORY_IDX: return "memory: ";
498 case TRACE_CORE_IDX: return "core: ";
499 case TRACE_EVENTS_IDX: return "events: ";
500 case TRACE_FPU_IDX: return "fpu: ";
501 case TRACE_BRANCH_IDX: return "branch: ";
502 default:
503 sprintf (num, "?%d?", trace_idx);
504 return num;
505 }
506 }
507
508 static void
509 trace_results (SIM_DESC sd,
510 sim_cpu *cpu,
511 int trace_idx,
512 int last_input)
513 {
514 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
515 int nr_out;
516 int i;
517
518 /* cross check trace_idx against TRACE_IDX (data)? */
519
520 /* prefix */
521 trace_printf (sd, cpu, "%s %s",
522 trace_idx_to_str (TRACE_IDX (data)),
523 TRACE_PREFIX (data));
524 TRACE_IDX (data) = 0;
525
526 for (i = 0, nr_out = 0;
527 i < TRACE_INPUT_IDX (data);
528 i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++)
529 {
530 if (i == last_input)
531 {
532 int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2);
533 int padding = pad * (3 - nr_out);
534 if (padding < 0)
535 padding = 0;
536 padding += strlen (" ::");
537 trace_printf (sd, cpu, "%*s", padding, " ::");
538 }
539 print_data (sd, cpu,
540 TRACE_INPUT_FMT (data) [i],
541 TRACE_INPUT_SIZE (data) [i],
542 &TRACE_INPUT_DATA (data) [i]);
543 }
544 trace_printf (sd, cpu, "\n");
545 }
546
547 void
548 trace_prefix (SIM_DESC sd,
549 sim_cpu *cpu,
550 address_word pc,
551 int line_p,
552 const char *filename,
553 int linenum,
554 const char *fmt,
555 ...)
556 {
557 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
558 va_list ap;
559 char *prefix = TRACE_PREFIX (data);
560 char *chp;
561
562 /* if the previous trace data wasn't flushed, flush it now with a
563 note indicating that this occured. */
564 if (TRACE_IDX (data) != 0)
565 {
566 int last_input = TRACE_INPUT_IDX (data);
567 save_data (sd, data, trace_fmt_instruction_incomplete, 1, "");
568 trace_results (sd, cpu, TRACE_IDX (data), last_input);
569 }
570 TRACE_IDX (data) = 0;
571 TRACE_INPUT_IDX (data) = 0;
572
573 if (!line_p)
574 {
575 sprintf (prefix, "%s:%-*d 0x%.*lx ",
576 filename,
577 SIZE_LINE_NUMBER, linenum,
578 SIZE_PC, (long)pc);
579 chp = strchr (prefix, '\0');
580 va_start (ap, fmt);
581 vsprintf (chp, fmt, ap);
582 va_end (ap);
583 }
584 else
585 {
586 char buf[256];
587 buf[0] = 0;
588 if (STATE_TEXT_SECTION (CPU_STATE (cpu))
589 && pc >= STATE_TEXT_START (CPU_STATE (cpu))
590 && pc < STATE_TEXT_END (CPU_STATE (cpu)))
591 {
592 const char *pc_filename = (const char *)0;
593 const char *pc_function = (const char *)0;
594 unsigned int pc_linenum = 0;
595
596 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
597 STATE_TEXT_SECTION (CPU_STATE (cpu)),
598 (struct symbol_cache_entry **) 0,
599 pc - STATE_TEXT_START (CPU_STATE (cpu)),
600 &pc_filename, &pc_function, &pc_linenum))
601 {
602 char *p = buf;
603 if (pc_linenum)
604 {
605 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
606 p += strlen (p);
607 }
608 else
609 {
610 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
611 p += SIZE_LINE_NUMBER+2;
612 }
613
614 if (pc_function)
615 {
616 sprintf (p, "%s ", pc_function);
617 p += strlen (p);
618 }
619 else if (pc_filename)
620 {
621 char *q = (char *) strrchr (pc_filename, '/');
622 sprintf (p, "%s ", (q) ? q+1 : pc_filename);
623 p += strlen (p);
624 }
625
626 if (*p == ' ')
627 *p = '\0';
628 }
629 }
630
631 sprintf (prefix, "0x%.*x %-*.*s ",
632 SIZE_PC, (unsigned) pc,
633 SIZE_LOCATION, SIZE_LOCATION, buf);
634 chp = strchr (prefix, '\0');
635 va_start (ap, fmt);
636 vsprintf (chp, fmt, ap);
637 va_end (ap);
638 }
639
640 /* pad it out to TRACE_PREFIX_WIDTH. FIXME: The TRACE_PREFIX_WIDTH
641 should be determined at build time using known information about
642 the disassembled instructions */
643 #ifndef TRACE_PREFIX_WIDTH
644 #define TRACE_PREFIX_WIDTH 48
645 #endif
646 chp = strchr (prefix, '\0');
647 if (chp - prefix < TRACE_PREFIX_WIDTH)
648 {
649 memset (chp, ' ', TRACE_PREFIX_WIDTH - (chp - prefix));
650 chp = &prefix [TRACE_PREFIX_WIDTH];
651 *chp = '\0';
652 }
653 strcpy (chp, " -");
654
655 /* check that we've not over flowed the prefix buffer */
656 if (strlen (prefix) >= sizeof (TRACE_PREFIX (data)))
657 abort ();
658 }
659
660 void
661 trace_generic (SIM_DESC sd,
662 sim_cpu *cpu,
663 int trace_idx,
664 char *fmt,
665 ...)
666 {
667 va_list ap;
668 trace_printf (sd, cpu, "%s %s",
669 trace_idx_to_str (trace_idx),
670 TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
671 va_start (ap, fmt);
672 trace_vprintf (sd, cpu, fmt, ap);
673 va_end (ap);
674 trace_printf (sd, cpu, "\n");
675 }
676
677 void
678 trace_input0 (SIM_DESC sd,
679 sim_cpu *cpu,
680 int trace_idx)
681 {
682 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
683 TRACE_IDX (data) = trace_idx;
684 }
685
686 void
687 trace_input_word1 (SIM_DESC sd,
688 sim_cpu *cpu,
689 int trace_idx,
690 unsigned_word d0)
691 {
692 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
693 TRACE_IDX (data) = trace_idx;
694 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
695 }
696
697 void
698 trace_input_word2 (SIM_DESC sd,
699 sim_cpu *cpu,
700 int trace_idx,
701 unsigned_word d0,
702 unsigned_word d1)
703 {
704 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
705 TRACE_IDX (data) = trace_idx;
706 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
707 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
708 }
709
710 void
711 trace_input_word3 (SIM_DESC sd,
712 sim_cpu *cpu,
713 int trace_idx,
714 unsigned_word d0,
715 unsigned_word d1,
716 unsigned_word d2)
717 {
718 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
719 TRACE_IDX (data) = trace_idx;
720 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
721 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
722 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);
723 }
724
725 void
726 trace_input_word4 (SIM_DESC sd,
727 sim_cpu *cpu,
728 int trace_idx,
729 unsigned_word d0,
730 unsigned_word d1,
731 unsigned_word d2,
732 unsigned_word d3)
733 {
734 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
735 TRACE_IDX (data) = trace_idx;
736 save_data (sd, data, trace_fmt_word, sizeof (d0), &d0);
737 save_data (sd, data, trace_fmt_word, sizeof (d1), &d1);
738 save_data (sd, data, trace_fmt_word, sizeof (d2), &d2);
739 save_data (sd, data, trace_fmt_word, sizeof (d3), &d3);
740 }
741
742 void
743 trace_input_bool1 (SIM_DESC sd,
744 sim_cpu *cpu,
745 int trace_idx,
746 int d0)
747 {
748 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
749 TRACE_IDX (data) = trace_idx;
750 save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0);
751 }
752
753 void
754 trace_input_addr1 (SIM_DESC sd,
755 sim_cpu *cpu,
756 int trace_idx,
757 address_word d0)
758 {
759 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
760 TRACE_IDX (data) = trace_idx;
761 save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0);
762 }
763
764 void
765 trace_input_fp1 (SIM_DESC sd,
766 sim_cpu *cpu,
767 int trace_idx,
768 fp_word f0)
769 {
770 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
771 TRACE_IDX (data) = trace_idx;
772 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
773 }
774
775 void
776 trace_input_fp2 (SIM_DESC sd,
777 sim_cpu *cpu,
778 int trace_idx,
779 fp_word f0,
780 fp_word f1)
781 {
782 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
783 TRACE_IDX (data) = trace_idx;
784 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
785 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
786 }
787
788 void
789 trace_input_fp3 (SIM_DESC sd,
790 sim_cpu *cpu,
791 int trace_idx,
792 fp_word f0,
793 fp_word f1,
794 fp_word f2)
795 {
796 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
797 TRACE_IDX (data) = trace_idx;
798 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
799 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
800 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2);
801 }
802
803 void
804 trace_input_fpu1 (SIM_DESC sd,
805 sim_cpu *cpu,
806 int trace_idx,
807 sim_fpu *f0)
808 {
809 double d;
810 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
811 TRACE_IDX (data) = trace_idx;
812 d = sim_fpu_2d (f0);
813 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
814 }
815
816 void
817 trace_input_fpu2 (SIM_DESC sd,
818 sim_cpu *cpu,
819 int trace_idx,
820 sim_fpu *f0,
821 sim_fpu *f1)
822 {
823 double d;
824 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
825 TRACE_IDX (data) = trace_idx;
826 d = sim_fpu_2d (f0);
827 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
828 d = sim_fpu_2d (f1);
829 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
830 }
831
832 void
833 trace_input_fpu3 (SIM_DESC sd,
834 sim_cpu *cpu,
835 int trace_idx,
836 sim_fpu *f0,
837 sim_fpu *f1,
838 sim_fpu *f2)
839 {
840 double d;
841 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
842 TRACE_IDX (data) = trace_idx;
843 d = sim_fpu_2d (f0);
844 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
845 d = sim_fpu_2d (f1);
846 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
847 d = sim_fpu_2d (f2);
848 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
849 }
850
851 void
852 trace_result_word1 (SIM_DESC sd,
853 sim_cpu *cpu,
854 int trace_idx,
855 unsigned_word r0)
856 {
857 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
858 int last_input;
859
860 /* Append any results to the end of the inputs */
861 last_input = TRACE_INPUT_IDX (data);
862 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
863
864 trace_results (sd, cpu, trace_idx, last_input);
865 }
866
867 void
868 trace_result0 (SIM_DESC sd,
869 sim_cpu *cpu,
870 int trace_idx)
871 {
872 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
873 int last_input;
874
875 /* Append any results to the end of the inputs */
876 last_input = TRACE_INPUT_IDX (data);
877
878 trace_results (sd, cpu, trace_idx, last_input);
879 }
880
881 void
882 trace_result_word2 (SIM_DESC sd,
883 sim_cpu *cpu,
884 int trace_idx,
885 unsigned_word r0,
886 unsigned_word r1)
887 {
888 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
889 int last_input;
890
891 /* Append any results to the end of the inputs */
892 last_input = TRACE_INPUT_IDX (data);
893 save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
894 save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
895
896 trace_results (sd, cpu, trace_idx, last_input);
897 }
898
899 void
900 trace_result_word4 (SIM_DESC sd,
901 sim_cpu *cpu,
902 int trace_idx,
903 unsigned_word r0,
904 unsigned_word r1,
905 unsigned_word r2,
906 unsigned_word r3)
907 {
908 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
909 int last_input;
910
911 /* Append any results to the end of the inputs */
912 last_input = TRACE_INPUT_IDX (data);
913 save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
914 save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
915 save_data (sd, data, trace_fmt_word, sizeof (r2), &r2);
916 save_data (sd, data, trace_fmt_word, sizeof (r3), &r3);
917
918 trace_results (sd, cpu, trace_idx, last_input);
919 }
920
921 void
922 trace_result_bool1 (SIM_DESC sd,
923 sim_cpu *cpu,
924 int trace_idx,
925 int r0)
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_bool, sizeof (r0), &r0);
933
934 trace_results (sd, cpu, trace_idx, last_input);
935 }
936
937 void
938 trace_result_addr1 (SIM_DESC sd,
939 sim_cpu *cpu,
940 int trace_idx,
941 address_word r0)
942 {
943 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
944 int last_input;
945
946 /* Append any results to the end of the inputs */
947 last_input = TRACE_INPUT_IDX (data);
948 save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0);
949
950 trace_results (sd, cpu, trace_idx, last_input);
951 }
952
953 void
954 trace_result_fp1 (SIM_DESC sd,
955 sim_cpu *cpu,
956 int trace_idx,
957 fp_word f0)
958 {
959 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
960 int last_input;
961
962 /* Append any results to the end of the inputs */
963 last_input = TRACE_INPUT_IDX (data);
964 save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
965
966 trace_results (sd, cpu, trace_idx, last_input);
967 }
968
969 void
970 trace_result_fpu1 (SIM_DESC sd,
971 sim_cpu *cpu,
972 int trace_idx,
973 sim_fpu *f0)
974 {
975 double d;
976 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
977 int last_input;
978
979 /* Append any results to the end of the inputs */
980 last_input = TRACE_INPUT_IDX (data);
981 d = sim_fpu_2d (f0);
982 save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
983
984 trace_results (sd, cpu, trace_idx, last_input);
985 }
986
987 void
988 trace_result_string1 (SIM_DESC sd,
989 sim_cpu *cpu,
990 int trace_idx,
991 char *s0)
992 {
993 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
994 int last_input;
995
996 /* Append any results to the end of the inputs */
997 last_input = TRACE_INPUT_IDX (data);
998 save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
999
1000 trace_results (sd, cpu, trace_idx, last_input);
1001 }
1002
1003 void
1004 trace_result_word1_string1 (SIM_DESC sd,
1005 sim_cpu *cpu,
1006 int trace_idx,
1007 unsigned_word r0,
1008 char *s0)
1009 {
1010 TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1011 int last_input;
1012
1013 /* Append any results to the end of the inputs */
1014 last_input = TRACE_INPUT_IDX (data);
1015 save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
1016 save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
1017
1018 trace_results (sd, cpu, trace_idx, last_input);
1019 }
1020 \f
1021 void
1022 trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
1023 {
1024 if (cpu != NULL)
1025 {
1026 if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
1027 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
1028 else
1029 sim_io_evprintf (sd, fmt, ap);
1030 }
1031 else
1032 {
1033 if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
1034 vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
1035 else
1036 sim_io_evprintf (sd, fmt, ap);
1037 }
1038 }
1039
1040 void
1041 trace_one_insn (SIM_DESC sd, sim_cpu *cpu, address_word pc,
1042 int line_p, const char *filename, int linenum,
1043 const char *phase_wo_colon, const char *fmt,
1044 ...)
1045 {
1046 va_list ap;
1047 char phase[SIZE_PHASE+2];
1048
1049 strncpy (phase, phase_wo_colon, SIZE_PHASE);
1050 strcat (phase, ":");
1051
1052 if (!line_p)
1053 {
1054 trace_printf (sd, cpu, "%-*s %s:%-*d 0x%.*lx ",
1055 SIZE_PHASE+1, phase,
1056 filename,
1057 SIZE_LINE_NUMBER, linenum,
1058 SIZE_PC, (long)pc);
1059 va_start (ap, fmt);
1060 trace_vprintf (sd, cpu, fmt, ap);
1061 va_end (ap);
1062 trace_printf (sd, cpu, "\n");
1063 }
1064 else
1065 {
1066 char buf[256];
1067
1068 buf[0] = 0;
1069 if (STATE_TEXT_SECTION (CPU_STATE (cpu))
1070 && pc >= STATE_TEXT_START (CPU_STATE (cpu))
1071 && pc < STATE_TEXT_END (CPU_STATE (cpu)))
1072 {
1073 const char *pc_filename = (const char *)0;
1074 const char *pc_function = (const char *)0;
1075 unsigned int pc_linenum = 0;
1076
1077 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
1078 STATE_TEXT_SECTION (CPU_STATE (cpu)),
1079 (struct symbol_cache_entry **) 0,
1080 pc - STATE_TEXT_START (CPU_STATE (cpu)),
1081 &pc_filename, &pc_function, &pc_linenum))
1082 {
1083 char *p = buf;
1084 if (pc_linenum)
1085 {
1086 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
1087 p += strlen (p);
1088 }
1089 else
1090 {
1091 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
1092 p += SIZE_LINE_NUMBER+2;
1093 }
1094
1095 if (pc_function)
1096 {
1097 sprintf (p, "%s ", pc_function);
1098 p += strlen (p);
1099 }
1100 else if (pc_filename)
1101 {
1102 char *q = (char *) strrchr (pc_filename, '/');
1103 sprintf (p, "%s ", (q) ? q+1 : pc_filename);
1104 p += strlen (p);
1105 }
1106
1107 if (*p == ' ')
1108 *p = '\0';
1109 }
1110 }
1111
1112 trace_printf (sd, cpu, "%-*s 0x%.*x %-*.*s ",
1113 SIZE_PHASE+1, phase,
1114 SIZE_PC, (unsigned) pc,
1115 SIZE_LOCATION, SIZE_LOCATION, buf);
1116 va_start (ap, fmt);
1117 trace_vprintf (sd, cpu, fmt, ap);
1118 va_end (ap);
1119 trace_printf (sd, cpu, "\n");
1120 }
1121 }
1122
1123 void
1124 trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...))
1125 {
1126 #if !defined __STDC__ && !defined ALMOST_STDC
1127 SIM_DESC sd;
1128 sim_cpu *cpu;
1129 const char *fmt;
1130 #endif
1131 va_list ap;
1132
1133 VA_START (ap, fmt);
1134 #if !defined __STDC__ && !defined ALMOST_STDC
1135 sd = va_arg (ap, SIM_DESC);
1136 cpu = va_arg (ap, sim_cpu *);
1137 fmt = va_arg (ap, const char *);
1138 #endif
1139
1140 trace_vprintf (sd, cpu, fmt, ap);
1141
1142 va_end (ap);
1143 }
1144
1145 void
1146 debug_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...))
1147 {
1148 #if !defined __STDC__ && !defined ALMOST_STDC
1149 sim_cpu *cpu;
1150 const char *fmt;
1151 #endif
1152 va_list ap;
1153
1154 VA_START (ap, fmt);
1155 #if !defined __STDC__ && !defined ALMOST_STDC
1156 cpu = va_arg (ap, sim_cpu *);
1157 fmt = va_arg (ap, const char *);
1158 #endif
1159
1160 if (CPU_DEBUG_FILE (cpu) == NULL)
1161 (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
1162 (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
1163 else
1164 vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
1165
1166 va_end (ap);
1167 }