xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/sim-trace.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /* Simulator tracing/debugging support.
2    Copyright (C) 1997-2020 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   if (STATE_PROG_SYMS (sd))
515     free (STATE_PROG_SYMS (sd));
516 }
517 
518 /* compute the nr of trace data units consumed by data */
519 static int
520 save_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 */
529 void
530 save_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 
546 static void
547 print_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 
627 static const char *
628 trace_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 
652 static void
653 trace_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 
691 int
692 trace_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 
724 bfd_vma
725 trace_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 
742 void
743 trace_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 
874 void
875 trace_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 
891 static int
892 dis_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 
900 static int
901 dis_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 
911 void
912 trace_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 
943 void
944 trace_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 
952 void
953 trace_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 
963 void
964 trace_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 
976 void
977 trace_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 
991 void
992 trace_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 
1008 void
1009 trace_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 
1019 void
1020 trace_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 
1030 void
1031 trace_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 
1041 void
1042 trace_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 
1054 void
1055 trace_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 
1069 void
1070 trace_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 
1082 void
1083 trace_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 
1098 void
1099 trace_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 
1117 void
1118 trace_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 
1133 void
1134 trace_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 
1147 void
1148 trace_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 
1165 void
1166 trace_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 
1187 void
1188 trace_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 
1203 void
1204 trace_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 
1219 void
1220 trace_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 
1235 void
1236 trace_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 
1253 void
1254 trace_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 
1271 void
1272 trace_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 
1287 void
1288 trace_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 
1305 void
1306 trace_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 
1324 void
1325 trace_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 
1336 void
1337 sim_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