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