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