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