* sim-bits.h (EXTEND24): Define.
[external/binutils.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 }