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