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