xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/common/sim-trace.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* Simulator tracing/debugging support.
2    Copyright (C) 1997-2016 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.
4 
5 This file is part of GDB, the GNU debugger.
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along 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 
59 static MODULE_INIT_FN trace_init;
60 static MODULE_UNINSTALL_FN trace_uninstall;
61 
62 static DECLARE_OPTION_HANDLER (trace_option_handler);
63 
64 enum {
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 
87 static 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 
162 static SIM_RC
163 set_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 
229 static SIM_RC
230 set_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 
236 static SIM_RC
237 trace_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 
445 SIM_RC
446 trace_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 
462 static SIM_RC
463 trace_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 
490 static void
491 trace_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 
515 /* compute the nr of trace data units consumed by data */
516 static int
517 save_data_size (TRACE_DATA *data,
518 		long size)
519 {
520   return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1)
521 	  / sizeof (TRACE_INPUT_DATA (data) [0]));
522 }
523 
524 
525 /* Archive DATA into the trace buffer */
526 void
527 save_data (SIM_DESC sd,
528 	   TRACE_DATA *data,
529 	   data_fmt fmt,
530 	   long size,
531 	   const void *buf)
532 {
533   int i = TRACE_INPUT_IDX (data);
534   if (i == sizeof (TRACE_INPUT_FMT (data)))
535     sim_io_error (sd, "trace buffer overflow");
536   TRACE_INPUT_FMT (data) [i] = fmt;
537   TRACE_INPUT_SIZE (data) [i] = size;
538   memcpy (&TRACE_INPUT_DATA (data) [i], buf, size);
539   i += save_data_size (data, size);
540   TRACE_INPUT_IDX (data) = i;
541 }
542 
543 static void
544 print_data (SIM_DESC sd,
545 	    sim_cpu *cpu,
546 	    data_fmt fmt,
547 	    long size,
548 	    void *data)
549 {
550   switch (fmt)
551     {
552     case trace_fmt_instruction_incomplete:
553       trace_printf (sd, cpu, " (instruction incomplete)");
554       break;
555     case trace_fmt_word:
556     case trace_fmt_addr:
557       {
558 	switch (size)
559 	  {
560 	  case sizeof (unsigned32):
561 	    trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned32*) data);
562 	    break;
563 	  case sizeof (unsigned64):
564 	    trace_printf (sd, cpu, " 0x%08lx%08lx",
565 			  (long) ((* (unsigned64*) data) >> 32),
566 			  (long) * (unsigned64*) data);
567 	    break;
568 	  default:
569 	    abort ();
570 	  }
571 	break;
572       }
573     case trace_fmt_bool:
574       {
575 	SIM_ASSERT (size == sizeof (int));
576 	trace_printf (sd, cpu, " %-8s",
577 		      (* (int*) data) ? "true" : "false");
578 	break;
579       }
580     case trace_fmt_fp:
581       {
582 	sim_fpu fp;
583 	switch (size)
584 	  {
585 	    /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */
586 	  case 4:
587 	    sim_fpu_32to (&fp, *(unsigned32*)data);
588 	    break;
589 	  case 8:
590 	    sim_fpu_64to (&fp, *(unsigned64*)data);
591 	    break;
592 	  default:
593 	    abort ();
594 	  }
595 	trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp));
596 	switch (size)
597 	  {
598 	  case 4:
599 	    trace_printf (sd, cpu, " (0x%08lx)",
600 			  (long) *(unsigned32*)data);
601 	    break;
602 	  case 8:
603 	    trace_printf (sd, cpu, " (0x%08lx%08lx)",
604 			  (long) (*(unsigned64*)data >> 32),
605 			  (long) (*(unsigned64*)data));
606 	    break;
607 	  default:
608 	    abort ();
609 	  }
610 	break;
611       }
612     case trace_fmt_fpu:
613       /* FIXME: At present sim_fpu data is stored as a double */
614       trace_printf (sd, cpu, " %8g", * (double*) data);
615       break;
616     case trace_fmt_string:
617       trace_printf (sd, cpu, " %-8s", (char*) data);
618       break;
619     default:
620       abort ();
621     }
622 }
623 
624 static const char *
625 trace_idx_to_str (int trace_idx)
626 {
627   static char num[8];
628   switch (trace_idx)
629     {
630     case TRACE_ALU_IDX:      return "alu:     ";
631     case TRACE_INSN_IDX:     return "insn:    ";
632     case TRACE_DISASM_IDX:   return "disasm:  ";
633     case TRACE_DECODE_IDX:   return "decode:  ";
634     case TRACE_EXTRACT_IDX:  return "extract: ";
635     case TRACE_MEMORY_IDX:   return "memory:  ";
636     case TRACE_CORE_IDX:     return "core:    ";
637     case TRACE_EVENTS_IDX:   return "events:  ";
638     case TRACE_FPU_IDX:      return "fpu:     ";
639     case TRACE_BRANCH_IDX:   return "branch:  ";
640     case TRACE_SYSCALL_IDX:  return "syscall: ";
641     case TRACE_REGISTER_IDX: return "reg:     ";
642     case TRACE_VPU_IDX:      return "vpu:     ";
643     default:
644       sprintf (num, "?%d?", trace_idx);
645       return num;
646     }
647 }
648 
649 static void
650 trace_results (SIM_DESC sd,
651 	       sim_cpu *cpu,
652 	       int trace_idx,
653 	       int last_input)
654 {
655   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
656   int nr_out;
657   int i;
658 
659   /* cross check trace_idx against TRACE_IDX (data)? */
660 
661   /* prefix */
662   trace_printf (sd, cpu, "%s %s",
663 		trace_idx_to_str (TRACE_IDX (data)),
664 		TRACE_PREFIX (data));
665   TRACE_IDX (data) = 0;
666 
667   for (i = 0, nr_out = 0;
668        i < TRACE_INPUT_IDX (data);
669        i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++)
670     {
671       if (i == last_input)
672 	{
673 	  int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2);
674 	  int padding = pad * (3 - nr_out);
675 	  if (padding < 0)
676 	    padding = 0;
677 	  padding += strlen (" ::");
678 	  trace_printf (sd, cpu, "%*s", padding, " ::");
679 	}
680       print_data (sd, cpu,
681 		  TRACE_INPUT_FMT (data) [i],
682 		  TRACE_INPUT_SIZE (data) [i],
683 		  &TRACE_INPUT_DATA (data) [i]);
684     }
685   trace_printf (sd, cpu, "\n");
686 }
687 
688 void
689 trace_prefix (SIM_DESC sd,
690 	      sim_cpu *cpu,
691 	      sim_cia cia,
692 	      address_word pc,
693 	      int line_p,
694 	      const char *filename,
695 	      int linenum,
696 	      const char *fmt,
697 	      ...)
698 {
699   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
700   va_list ap;
701   char *prefix = TRACE_PREFIX (data);
702   char *chp;
703  /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using
704     known information about the disassembled instructions. */
705 #ifndef TRACE_PREFIX_WIDTH
706 #define TRACE_PREFIX_WIDTH 48
707 #endif
708   int width = TRACE_PREFIX_WIDTH;
709 
710   /* if the previous trace data wasn't flushed, flush it now with a
711      note indicating that the trace was incomplete. */
712   if (TRACE_IDX (data) != 0)
713     {
714       int last_input = TRACE_INPUT_IDX (data);
715       save_data (sd, data, trace_fmt_instruction_incomplete, 1, "");
716       trace_results (sd, cpu, TRACE_IDX (data), last_input);
717     }
718   TRACE_IDX (data) = 0;
719   TRACE_INPUT_IDX (data) = 0;
720 
721   /* Create the text prefix for this new instruction: */
722   if (!line_p)
723     {
724       if (filename)
725 	{
726 	  sprintf (prefix, "%s:%-*d 0x%.*lx ",
727 		   filename,
728 		   SIZE_LINE_NUMBER, linenum,
729 		   SIZE_PC, (long) pc);
730 	}
731       else
732 	{
733 	  sprintf (prefix, "0x%.*lx ",
734 		   SIZE_PC, (long) pc);
735 	  /* Shrink the width by the amount that we didn't print.  */
736 	  width -= SIZE_LINE_NUMBER + SIZE_PC + 8;
737 	}
738       chp = strchr (prefix, '\0');
739       va_start (ap, fmt);
740       vsprintf (chp, fmt, ap);
741       va_end (ap);
742     }
743   else
744     {
745       char buf[256];
746       buf[0] = 0;
747       if (STATE_TEXT_SECTION (CPU_STATE (cpu))
748 	  && pc >= STATE_TEXT_START (CPU_STATE (cpu))
749 	  && pc < STATE_TEXT_END (CPU_STATE (cpu)))
750 	{
751 	  const char *pc_filename = (const char *)0;
752 	  const char *pc_function = (const char *)0;
753 	  unsigned int pc_linenum = 0;
754 	  bfd *abfd;
755 	  asymbol **asymbols;
756 
757 	  abfd = STATE_PROG_BFD (CPU_STATE (cpu));
758 	  asymbols = STATE_PROG_SYMS (CPU_STATE (cpu));
759 	  if (asymbols == NULL)
760 	    {
761 	      long symsize;
762 	      long symbol_count;
763 
764 	      symsize = bfd_get_symtab_upper_bound (abfd);
765 	      if (symsize < 0)
766 		{
767 		  sim_engine_abort (sd, cpu, cia, "could not read symbols");
768 		}
769 	      asymbols = (asymbol **) xmalloc (symsize);
770 	      symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
771 	      if (symbol_count < 0)
772 		{
773 		  sim_engine_abort (sd, cpu, cia, "could not canonicalize symbols");
774 		}
775 	      STATE_PROG_SYMS (CPU_STATE (cpu)) = asymbols;
776 	    }
777 
778 	  if (bfd_find_nearest_line (abfd,
779 				     STATE_TEXT_SECTION (CPU_STATE (cpu)),
780 				     asymbols,
781 				     pc - STATE_TEXT_START (CPU_STATE (cpu)),
782 				     &pc_filename, &pc_function, &pc_linenum))
783 	    {
784 	      char *p = buf;
785 	      if (pc_linenum)
786 		{
787 		  sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
788 		  p += strlen (p);
789 		}
790 	      else
791 		{
792 		  sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
793 		  p += SIZE_LINE_NUMBER+2;
794 		}
795 
796 	      if (pc_function)
797 		{
798 		  sprintf (p, "%s ", pc_function);
799 		  p += strlen (p);
800 		}
801 	      else if (pc_filename)
802 		{
803 		  char *q = (char *) strrchr (pc_filename, '/');
804 		  sprintf (p, "%s ", (q) ? q+1 : pc_filename);
805 		  p += strlen (p);
806 		}
807 
808 	      if (*p == ' ')
809 		*p = '\0';
810 	    }
811 	}
812 
813       sprintf (prefix, "0x%.*x %-*.*s ",
814 	       SIZE_PC, (unsigned) pc,
815 	       SIZE_LOCATION, SIZE_LOCATION, buf);
816       chp = strchr (prefix, '\0');
817       va_start (ap, fmt);
818       vsprintf (chp, fmt, ap);
819       va_end (ap);
820     }
821 
822   /* Pad it out to TRACE_PREFIX_WIDTH.  */
823   chp = strchr (prefix, '\0');
824   if (chp - prefix < width)
825     {
826       memset (chp, ' ', width - (chp - prefix));
827       chp = &prefix [width];
828       *chp = '\0';
829     }
830   strcpy (chp, " -");
831 
832   /* check that we've not over flowed the prefix buffer */
833   if (strlen (prefix) >= sizeof (TRACE_PREFIX (data)))
834     abort ();
835 }
836 
837 void
838 trace_generic (SIM_DESC sd,
839 	       sim_cpu *cpu,
840 	       int trace_idx,
841 	       const char *fmt,
842 	       ...)
843 {
844   va_list ap;
845   trace_printf (sd, cpu, "%s %s",
846 		trace_idx_to_str (trace_idx),
847 		TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
848   va_start (ap, fmt);
849   trace_vprintf (sd, cpu, fmt, ap);
850   va_end (ap);
851   trace_printf (sd, cpu, "\n");
852 }
853 
854 static int
855 dis_read (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
856 	  struct disassemble_info *dinfo)
857 {
858   SIM_CPU *cpu = dinfo->application_data;
859   sim_core_read_buffer (CPU_STATE (cpu), cpu, NULL_CIA, myaddr, memaddr, length);
860   return 0;
861 }
862 
863 static int
864 dis_printf (SIM_CPU *cpu, const char *fmt, ...)
865 {
866   SIM_DESC sd = CPU_STATE (cpu);
867   va_list ap;
868   va_start (ap, fmt);
869   trace_vprintf (sd, cpu, fmt, ap);
870   va_end (ap);
871   return 0;
872 }
873 
874 void
875 trace_disasm (SIM_DESC sd, sim_cpu *cpu, address_word addr)
876 {
877   struct bfd *bfd = STATE_PROG_BFD (sd);
878   TRACE_DATA *trace_data = CPU_TRACE_DATA (cpu);
879   disassemble_info *info = &trace_data->dis_info;
880 
881   /* See if we need to set up the disassembly func.  */
882   if (trace_data->dis_bfd != bfd)
883     {
884       trace_data->dis_bfd = bfd;
885       trace_data->disassembler = disassembler (trace_data->dis_bfd);
886       INIT_DISASSEMBLE_INFO (*info, cpu, dis_printf);
887       info->read_memory_func = dis_read;
888       info->arch = bfd_get_arch (bfd);
889       info->mach = bfd_get_mach (bfd);
890       disassemble_init_for_target (info);
891     }
892 
893   info->application_data = cpu;
894 
895   trace_printf (sd, cpu, "%s %s",
896 		trace_idx_to_str (TRACE_DISASM_IDX),
897 		TRACE_PREFIX (trace_data));
898   trace_data->disassembler (addr, info);
899   trace_printf (sd, cpu, "\n");
900 }
901 
902 void
903 trace_input0 (SIM_DESC sd,
904 	      sim_cpu *cpu,
905 	      int trace_idx)
906 {
907   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
908   TRACE_IDX (data) = trace_idx;
909 }
910 
911 void
912 trace_input_word1 (SIM_DESC sd,
913 		   sim_cpu *cpu,
914 		   int trace_idx,
915 		   unsigned_word d0)
916 {
917   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
918   TRACE_IDX (data) = trace_idx;
919   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
920 }
921 
922 void
923 trace_input_word2 (SIM_DESC sd,
924 		   sim_cpu *cpu,
925 		   int trace_idx,
926 		   unsigned_word d0,
927 		   unsigned_word d1)
928 {
929   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
930   TRACE_IDX (data) = trace_idx;
931   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
932   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
933 }
934 
935 void
936 trace_input_word3 (SIM_DESC sd,
937 		   sim_cpu *cpu,
938 		   int trace_idx,
939 		   unsigned_word d0,
940 		   unsigned_word d1,
941 		   unsigned_word d2)
942 {
943   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
944   TRACE_IDX (data) = trace_idx;
945   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
946   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
947   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);
948 }
949 
950 void
951 trace_input_word4 (SIM_DESC sd,
952 		   sim_cpu *cpu,
953 		   int trace_idx,
954 		   unsigned_word d0,
955 		   unsigned_word d1,
956 		   unsigned_word d2,
957 		   unsigned_word d3)
958 {
959   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
960   TRACE_IDX (data) = trace_idx;
961   save_data (sd, data, trace_fmt_word, sizeof (d0), &d0);
962   save_data (sd, data, trace_fmt_word, sizeof (d1), &d1);
963   save_data (sd, data, trace_fmt_word, sizeof (d2), &d2);
964   save_data (sd, data, trace_fmt_word, sizeof (d3), &d3);
965 }
966 
967 void
968 trace_input_bool1 (SIM_DESC sd,
969 		   sim_cpu *cpu,
970 		   int trace_idx,
971 		   int d0)
972 {
973   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
974   TRACE_IDX (data) = trace_idx;
975   save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0);
976 }
977 
978 void
979 trace_input_addr1 (SIM_DESC sd,
980 		   sim_cpu *cpu,
981 		   int trace_idx,
982 		   address_word d0)
983 {
984   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
985   TRACE_IDX (data) = trace_idx;
986   save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0);
987 }
988 
989 void
990 trace_input_fp1 (SIM_DESC sd,
991 		 sim_cpu *cpu,
992 		 int trace_idx,
993 		 fp_word f0)
994 {
995   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
996   TRACE_IDX (data) = trace_idx;
997   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
998 }
999 
1000 void
1001 trace_input_fp2 (SIM_DESC sd,
1002 		 sim_cpu *cpu,
1003 		 int trace_idx,
1004 		 fp_word f0,
1005 		 fp_word f1)
1006 {
1007   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1008   TRACE_IDX (data) = trace_idx;
1009   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
1010   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
1011 }
1012 
1013 void
1014 trace_input_fp3 (SIM_DESC sd,
1015 		 sim_cpu *cpu,
1016 		 int trace_idx,
1017 		 fp_word f0,
1018 		 fp_word f1,
1019 		 fp_word f2)
1020 {
1021   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1022   TRACE_IDX (data) = trace_idx;
1023   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
1024   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
1025   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2);
1026 }
1027 
1028 void
1029 trace_input_fpu1 (SIM_DESC sd,
1030 		  sim_cpu *cpu,
1031 		  int trace_idx,
1032 		  sim_fpu *f0)
1033 {
1034   double d;
1035   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1036   TRACE_IDX (data) = trace_idx;
1037   d = sim_fpu_2d (f0);
1038   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1039 }
1040 
1041 void
1042 trace_input_fpu2 (SIM_DESC sd,
1043 		  sim_cpu *cpu,
1044 		  int trace_idx,
1045 		  sim_fpu *f0,
1046 		  sim_fpu *f1)
1047 {
1048   double d;
1049   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1050   TRACE_IDX (data) = trace_idx;
1051   d = sim_fpu_2d (f0);
1052   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1053   d = sim_fpu_2d (f1);
1054   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1055 }
1056 
1057 void
1058 trace_input_fpu3 (SIM_DESC sd,
1059 		  sim_cpu *cpu,
1060 		  int trace_idx,
1061 		  sim_fpu *f0,
1062 		  sim_fpu *f1,
1063 		  sim_fpu *f2)
1064 {
1065   double d;
1066   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1067   TRACE_IDX (data) = trace_idx;
1068   d = sim_fpu_2d (f0);
1069   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1070   d = sim_fpu_2d (f1);
1071   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1072   d = sim_fpu_2d (f2);
1073   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1074 }
1075 
1076 void
1077 trace_result_word1 (SIM_DESC sd,
1078 		    sim_cpu *cpu,
1079 		    int trace_idx,
1080 		    unsigned_word r0)
1081 {
1082   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1083   int last_input;
1084 
1085   /* Append any results to the end of the inputs */
1086   last_input = TRACE_INPUT_IDX (data);
1087   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
1088 
1089   trace_results (sd, cpu, trace_idx, last_input);
1090 }
1091 
1092 void
1093 trace_result0 (SIM_DESC sd,
1094 	       sim_cpu *cpu,
1095 	       int trace_idx)
1096 {
1097   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1098   int last_input;
1099 
1100   /* Append any results to the end of the inputs */
1101   last_input = TRACE_INPUT_IDX (data);
1102 
1103   trace_results (sd, cpu, trace_idx, last_input);
1104 }
1105 
1106 void
1107 trace_result_word2 (SIM_DESC sd,
1108 		    sim_cpu *cpu,
1109 		    int trace_idx,
1110 		    unsigned_word r0,
1111 		    unsigned_word r1)
1112 {
1113   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1114   int last_input;
1115 
1116   /* Append any results to the end of the inputs */
1117   last_input = TRACE_INPUT_IDX (data);
1118   save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
1119   save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
1120 
1121   trace_results (sd, cpu, trace_idx, last_input);
1122 }
1123 
1124 void
1125 trace_result_word4 (SIM_DESC sd,
1126 		    sim_cpu *cpu,
1127 		    int trace_idx,
1128 		    unsigned_word r0,
1129 		    unsigned_word r1,
1130 		    unsigned_word r2,
1131 		    unsigned_word r3)
1132 {
1133   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1134   int last_input;
1135 
1136   /* Append any results to the end of the inputs */
1137   last_input = TRACE_INPUT_IDX (data);
1138   save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
1139   save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
1140   save_data (sd, data, trace_fmt_word, sizeof (r2), &r2);
1141   save_data (sd, data, trace_fmt_word, sizeof (r3), &r3);
1142 
1143   trace_results (sd, cpu, trace_idx, last_input);
1144 }
1145 
1146 void
1147 trace_result_bool1 (SIM_DESC sd,
1148 		    sim_cpu *cpu,
1149 		    int trace_idx,
1150 		    int r0)
1151 {
1152   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1153   int last_input;
1154 
1155   /* Append any results to the end of the inputs */
1156   last_input = TRACE_INPUT_IDX (data);
1157   save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0);
1158 
1159   trace_results (sd, cpu, trace_idx, last_input);
1160 }
1161 
1162 void
1163 trace_result_addr1 (SIM_DESC sd,
1164 		    sim_cpu *cpu,
1165 		    int trace_idx,
1166 		    address_word r0)
1167 {
1168   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1169   int last_input;
1170 
1171   /* Append any results to the end of the inputs */
1172   last_input = TRACE_INPUT_IDX (data);
1173   save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0);
1174 
1175   trace_results (sd, cpu, trace_idx, last_input);
1176 }
1177 
1178 void
1179 trace_result_fp1 (SIM_DESC sd,
1180 		  sim_cpu *cpu,
1181 		  int trace_idx,
1182 		  fp_word f0)
1183 {
1184   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1185   int last_input;
1186 
1187   /* Append any results to the end of the inputs */
1188   last_input = TRACE_INPUT_IDX (data);
1189   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
1190 
1191   trace_results (sd, cpu, trace_idx, last_input);
1192 }
1193 
1194 void
1195 trace_result_fp2 (SIM_DESC sd,
1196 		  sim_cpu *cpu,
1197 		  int trace_idx,
1198 		  fp_word f0,
1199 		  fp_word f1)
1200 {
1201   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1202   int last_input;
1203 
1204   /* Append any results to the end of the inputs */
1205   last_input = TRACE_INPUT_IDX (data);
1206   save_data (sd, data, trace_fmt_fp, sizeof (f0), &f0);
1207   save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1);
1208 
1209   trace_results (sd, cpu, trace_idx, last_input);
1210 }
1211 
1212 void
1213 trace_result_fpu1 (SIM_DESC sd,
1214 		   sim_cpu *cpu,
1215 		   int trace_idx,
1216 		   sim_fpu *f0)
1217 {
1218   double d;
1219   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1220   int last_input;
1221 
1222   /* Append any results to the end of the inputs */
1223   last_input = TRACE_INPUT_IDX (data);
1224   d = sim_fpu_2d (f0);
1225   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1226 
1227   trace_results (sd, cpu, trace_idx, last_input);
1228 }
1229 
1230 void
1231 trace_result_string1 (SIM_DESC sd,
1232 		      sim_cpu *cpu,
1233 		      int trace_idx,
1234 		      char *s0)
1235 {
1236   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1237   int last_input;
1238 
1239   /* Append any results to the end of the inputs */
1240   last_input = TRACE_INPUT_IDX (data);
1241   save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
1242 
1243   trace_results (sd, cpu, trace_idx, last_input);
1244 }
1245 
1246 void
1247 trace_result_word1_string1 (SIM_DESC sd,
1248 			    sim_cpu *cpu,
1249 			    int trace_idx,
1250 			    unsigned_word r0,
1251 			    char *s0)
1252 {
1253   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1254   int last_input;
1255 
1256   /* Append any results to the end of the inputs */
1257   last_input = TRACE_INPUT_IDX (data);
1258   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
1259   save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
1260 
1261   trace_results (sd, cpu, trace_idx, last_input);
1262 }
1263 
1264 void
1265 trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
1266 {
1267   if (cpu != NULL)
1268     {
1269       if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
1270 	vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
1271       else
1272 	sim_io_evprintf (sd, fmt, ap);
1273     }
1274   else
1275     {
1276       if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
1277 	vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
1278       else
1279 	sim_io_evprintf (sd, fmt, ap);
1280     }
1281 }
1282 
1283 void
1284 trace_printf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...)
1285 {
1286   va_list ap;
1287 
1288   va_start (ap, fmt);
1289 
1290   trace_vprintf (sd, cpu, fmt, ap);
1291 
1292   va_end (ap);
1293 }
1294 
1295 void
1296 sim_debug_printf (sim_cpu *cpu, const char *fmt, ...)
1297 {
1298   va_list ap;
1299 
1300   va_start (ap, fmt);
1301 
1302   if (CPU_DEBUG_FILE (cpu) == NULL)
1303     (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
1304       (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
1305   else
1306     vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
1307 
1308   va_end (ap);
1309 }
1310