Home | History | Annotate | Line # | Download | only in common
sim-trace.c revision 1.1.1.7
      1 /* Simulator tracing/debugging support.
      2    Copyright (C) 1997-2017 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.  */
    445 
    446 SIM_RC
    447 trace_install (SIM_DESC sd)
    448 {
    449   int i;
    450 
    451   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
    452 
    453   sim_add_option_table (sd, NULL, trace_options);
    454   memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd)));
    455   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
    456     memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
    457 	    sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i))));
    458   sim_module_add_init_fn (sd, trace_init);
    459   sim_module_add_uninstall_fn (sd, trace_uninstall);
    460   return SIM_RC_OK;
    461 }
    462 
    463 static SIM_RC
    464 trace_init (SIM_DESC sd)
    465 {
    466 #ifdef SIM_HAVE_ADDR_RANGE
    467   /* Check if a range has been specified without specifying what to
    468      collect.  */
    469   {
    470     int i;
    471 
    472     for (i = 0; i < MAX_NR_PROCESSORS; ++i)
    473       {
    474 	sim_cpu *cpu = STATE_CPU (sd, i);
    475 
    476 	if (ADDR_RANGE_RANGES (TRACE_RANGE (CPU_TRACE_DATA (cpu)))
    477 	    && ! TRACE_INSN_P (cpu))
    478 	  {
    479 	    sim_io_eprintf_cpu (cpu, "Tracing address range specified without --trace-insn.\n");
    480 	    sim_io_eprintf_cpu (cpu, "Address range ignored.\n");
    481 	    sim_addr_range_delete (TRACE_RANGE (CPU_TRACE_DATA (cpu)),
    482 				   0, ~ (address_word) 0);
    483 	  }
    484       }
    485   }
    486 #endif
    487 
    488   return SIM_RC_OK;
    489 }
    490 
    491 static void
    492 trace_uninstall (SIM_DESC sd)
    493 {
    494   int i,j;
    495   FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd));
    496 
    497   if (sfile != NULL)
    498     fclose (sfile);
    499 
    500   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
    501     {
    502       FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i)));
    503       if (cfile != NULL && cfile != sfile)
    504 	{
    505 	  /* If output from different cpus is going to the same file,
    506 	     avoid closing the file twice.  */
    507 	  for (j = 0; j < i; ++j)
    508 	    if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile)
    509 	      break;
    510 	  if (i == j)
    511 	    fclose (cfile);
    512 	}
    513     }
    514 
    515   if (STATE_PROG_SYMS (sd))
    516     free (STATE_PROG_SYMS (sd));
    517 }
    518 
    519 /* compute the nr of trace data units consumed by data */
    521 static int
    522 save_data_size (TRACE_DATA *data,
    523 		long size)
    524 {
    525   return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1)
    526 	  / sizeof (TRACE_INPUT_DATA (data) [0]));
    527 }
    528 
    529 
    530 /* Archive DATA into the trace buffer */
    531 void
    532 save_data (SIM_DESC sd,
    533 	   TRACE_DATA *data,
    534 	   data_fmt fmt,
    535 	   long size,
    536 	   const void *buf)
    537 {
    538   int i = TRACE_INPUT_IDX (data);
    539   if (i == sizeof (TRACE_INPUT_FMT (data)))
    540     sim_io_error (sd, "trace buffer overflow");
    541   TRACE_INPUT_FMT (data) [i] = fmt;
    542   TRACE_INPUT_SIZE (data) [i] = size;
    543   memcpy (&TRACE_INPUT_DATA (data) [i], buf, size);
    544   i += save_data_size (data, size);
    545   TRACE_INPUT_IDX (data) = i;
    546 }
    547 
    548 static void
    549 print_data (SIM_DESC sd,
    550 	    sim_cpu *cpu,
    551 	    data_fmt fmt,
    552 	    long size,
    553 	    void *data)
    554 {
    555   switch (fmt)
    556     {
    557     case trace_fmt_instruction_incomplete:
    558       trace_printf (sd, cpu, " (instruction incomplete)");
    559       break;
    560     case trace_fmt_word:
    561     case trace_fmt_addr:
    562       {
    563 	switch (size)
    564 	  {
    565 	  case sizeof (unsigned32):
    566 	    trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned32*) data);
    567 	    break;
    568 	  case sizeof (unsigned64):
    569 	    trace_printf (sd, cpu, " 0x%08lx%08lx",
    570 			  (long) ((* (unsigned64*) data) >> 32),
    571 			  (long) * (unsigned64*) data);
    572 	    break;
    573 	  default:
    574 	    abort ();
    575 	  }
    576 	break;
    577       }
    578     case trace_fmt_bool:
    579       {
    580 	SIM_ASSERT (size == sizeof (int));
    581 	trace_printf (sd, cpu, " %-8s",
    582 		      (* (int*) data) ? "true" : "false");
    583 	break;
    584       }
    585     case trace_fmt_fp:
    586       {
    587 	sim_fpu fp;
    588 	switch (size)
    589 	  {
    590 	    /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */
    591 	  case 4:
    592 	    sim_fpu_32to (&fp, *(unsigned32*)data);
    593 	    break;
    594 	  case 8:
    595 	    sim_fpu_64to (&fp, *(unsigned64*)data);
    596 	    break;
    597 	  default:
    598 	    abort ();
    599 	  }
    600 	trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp));
    601 	switch (size)
    602 	  {
    603 	  case 4:
    604 	    trace_printf (sd, cpu, " (0x%08lx)",
    605 			  (long) *(unsigned32*)data);
    606 	    break;
    607 	  case 8:
    608 	    trace_printf (sd, cpu, " (0x%08lx%08lx)",
    609 			  (long) (*(unsigned64*)data >> 32),
    610 			  (long) (*(unsigned64*)data));
    611 	    break;
    612 	  default:
    613 	    abort ();
    614 	  }
    615 	break;
    616       }
    617     case trace_fmt_fpu:
    618       /* FIXME: At present sim_fpu data is stored as a double */
    619       trace_printf (sd, cpu, " %8g", * (double*) data);
    620       break;
    621     case trace_fmt_string:
    622       trace_printf (sd, cpu, " %-8s", (char*) data);
    623       break;
    624     default:
    625       abort ();
    626     }
    627 }
    628 
    629 static const char *
    630 trace_idx_to_str (int trace_idx)
    631 {
    632   static char num[8];
    633   switch (trace_idx)
    634     {
    635     case TRACE_ALU_IDX:      return "alu:     ";
    636     case TRACE_INSN_IDX:     return "insn:    ";
    637     case TRACE_DISASM_IDX:   return "disasm:  ";
    638     case TRACE_DECODE_IDX:   return "decode:  ";
    639     case TRACE_EXTRACT_IDX:  return "extract: ";
    640     case TRACE_MEMORY_IDX:   return "memory:  ";
    641     case TRACE_CORE_IDX:     return "core:    ";
    642     case TRACE_EVENTS_IDX:   return "events:  ";
    643     case TRACE_FPU_IDX:      return "fpu:     ";
    644     case TRACE_BRANCH_IDX:   return "branch:  ";
    645     case TRACE_SYSCALL_IDX:  return "syscall: ";
    646     case TRACE_REGISTER_IDX: return "reg:     ";
    647     case TRACE_VPU_IDX:      return "vpu:     ";
    648     default:
    649       sprintf (num, "?%d?", trace_idx);
    650       return num;
    651     }
    652 }
    653 
    654 static void
    655 trace_results (SIM_DESC sd,
    656 	       sim_cpu *cpu,
    657 	       int trace_idx,
    658 	       int last_input)
    659 {
    660   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
    661   int nr_out;
    662   int i;
    663 
    664   /* cross check trace_idx against TRACE_IDX (data)? */
    665 
    666   /* prefix */
    667   trace_printf (sd, cpu, "%s %s",
    668 		trace_idx_to_str (TRACE_IDX (data)),
    669 		TRACE_PREFIX (data));
    670   TRACE_IDX (data) = 0;
    671 
    672   for (i = 0, nr_out = 0;
    673        i < TRACE_INPUT_IDX (data);
    674        i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++)
    675     {
    676       if (i == last_input)
    677 	{
    678 	  int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2);
    679 	  int padding = pad * (3 - nr_out);
    680 	  if (padding < 0)
    681 	    padding = 0;
    682 	  padding += strlen (" ::");
    683 	  trace_printf (sd, cpu, "%*s", padding, " ::");
    684 	}
    685       print_data (sd, cpu,
    686 		  TRACE_INPUT_FMT (data) [i],
    687 		  TRACE_INPUT_SIZE (data) [i],
    688 		  &TRACE_INPUT_DATA (data) [i]);
    689     }
    690   trace_printf (sd, cpu, "\n");
    691 }
    692 
    693 int
    694 trace_load_symbols (SIM_DESC sd)
    695 {
    696   bfd *abfd;
    697   asymbol **asymbols;
    698   long symsize;
    699   long symbol_count;
    700 
    701   /* Already loaded, so nothing to do.  */
    702   if (STATE_PROG_SYMS (sd))
    703     return 1;
    704 
    705   abfd = STATE_PROG_BFD (sd);
    706   if (abfd == NULL)
    707     return 0;
    708 
    709   symsize = bfd_get_symtab_upper_bound (abfd);
    710   if (symsize < 0)
    711     return 0;
    712 
    713   asymbols = xmalloc (symsize);
    714   symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
    715   if (symbol_count < 0)
    716     {
    717       free (asymbols);
    718       return 0;
    719     }
    720 
    721   STATE_PROG_SYMS (sd) = asymbols;
    722   STATE_PROG_SYMS_COUNT (sd) = symbol_count;
    723   return 1;
    724 }
    725 
    726 bfd_vma
    727 trace_sym_value (SIM_DESC sd, const char *name)
    728 {
    729   asymbol **asymbols;
    730   long i;
    731 
    732   if (!trace_load_symbols (sd))
    733     return -1;
    734 
    735   asymbols = STATE_PROG_SYMS (sd);
    736 
    737   for (i = 0; i < STATE_PROG_SYMS_COUNT (sd); ++i)
    738     if (strcmp (asymbols[i]->name, name) == 0)
    739       return bfd_asymbol_value (asymbols[i]);
    740 
    741   return -1;
    742 }
    743 
    744 void
    745 trace_prefix (SIM_DESC sd,
    746 	      sim_cpu *cpu,
    747 	      sim_cia cia,
    748 	      address_word pc,
    749 	      int line_p,
    750 	      const char *filename,
    751 	      int linenum,
    752 	      const char *fmt,
    753 	      ...)
    754 {
    755   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
    756   va_list ap;
    757   char *prefix = TRACE_PREFIX (data);
    758   char *chp;
    759  /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using
    760     known information about the disassembled instructions. */
    761 #ifndef TRACE_PREFIX_WIDTH
    762 #define TRACE_PREFIX_WIDTH 48
    763 #endif
    764   int width = TRACE_PREFIX_WIDTH;
    765 
    766   /* if the previous trace data wasn't flushed, flush it now with a
    767      note indicating that the trace was incomplete. */
    768   if (TRACE_IDX (data) != 0)
    769     {
    770       int last_input = TRACE_INPUT_IDX (data);
    771       save_data (sd, data, trace_fmt_instruction_incomplete, 1, "");
    772       trace_results (sd, cpu, TRACE_IDX (data), last_input);
    773     }
    774   TRACE_IDX (data) = 0;
    775   TRACE_INPUT_IDX (data) = 0;
    776 
    777   /* Create the text prefix for this new instruction: */
    778   if (!line_p)
    779     {
    780       if (filename)
    781 	{
    782 	  sprintf (prefix, "%s:%-*d 0x%.*lx ",
    783 		   filename,
    784 		   SIZE_LINE_NUMBER, linenum,
    785 		   SIZE_PC, (long) pc);
    786 	}
    787       else
    788 	{
    789 	  sprintf (prefix, "0x%.*lx ",
    790 		   SIZE_PC, (long) pc);
    791 	  /* Shrink the width by the amount that we didn't print.  */
    792 	  width -= SIZE_LINE_NUMBER + SIZE_PC + 8;
    793 	}
    794       chp = strchr (prefix, '\0');
    795       va_start (ap, fmt);
    796       vsprintf (chp, fmt, ap);
    797       va_end (ap);
    798     }
    799   else
    800     {
    801       char buf[256];
    802       buf[0] = 0;
    803       if (STATE_TEXT_SECTION (sd)
    804 	  && pc >= STATE_TEXT_START (sd)
    805 	  && pc < STATE_TEXT_END (sd))
    806 	{
    807 	  const char *pc_filename = (const char *)0;
    808 	  const char *pc_function = (const char *)0;
    809 	  unsigned int pc_linenum = 0;
    810 	  bfd *abfd;
    811 	  asymbol **asymbols;
    812 
    813 	  if (!trace_load_symbols (sd))
    814 	    sim_engine_abort (sd, cpu, cia, "could not load symbols");
    815 
    816 	  abfd = STATE_PROG_BFD (sd);
    817 	  asymbols = STATE_PROG_SYMS (sd);
    818 
    819 	  if (bfd_find_nearest_line (abfd, STATE_TEXT_SECTION (sd), asymbols,
    820 				     pc - STATE_TEXT_START (sd),
    821 				     &pc_filename, &pc_function, &pc_linenum))
    822 	    {
    823 	      char *p = buf;
    824 	      if (pc_linenum)
    825 		{
    826 		  sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
    827 		  p += strlen (p);
    828 		}
    829 	      else
    830 		{
    831 		  sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
    832 		  p += SIZE_LINE_NUMBER+2;
    833 		}
    834 
    835 	      if (pc_function)
    836 		{
    837 		  sprintf (p, "%s ", pc_function);
    838 		  p += strlen (p);
    839 		}
    840 	      else if (pc_filename)
    841 		{
    842 		  char *q = (char *) strrchr (pc_filename, '/');
    843 		  sprintf (p, "%s ", (q) ? q+1 : pc_filename);
    844 		  p += strlen (p);
    845 		}
    846 
    847 	      if (*p == ' ')
    848 		*p = '\0';
    849 	    }
    850 	}
    851 
    852       sprintf (prefix, "0x%.*x %-*.*s ",
    853 	       SIZE_PC, (unsigned) pc,
    854 	       SIZE_LOCATION, SIZE_LOCATION, buf);
    855       chp = strchr (prefix, '\0');
    856       va_start (ap, fmt);
    857       vsprintf (chp, fmt, ap);
    858       va_end (ap);
    859     }
    860 
    861   /* Pad it out to TRACE_PREFIX_WIDTH.  */
    862   chp = strchr (prefix, '\0');
    863   if (chp - prefix < width)
    864     {
    865       memset (chp, ' ', width - (chp - prefix));
    866       chp = &prefix [width];
    867       *chp = '\0';
    868     }
    869   strcpy (chp, " -");
    870 
    871   /* check that we've not over flowed the prefix buffer */
    872   if (strlen (prefix) >= sizeof (TRACE_PREFIX (data)))
    873     abort ();
    874 }
    875 
    876 void
    877 trace_generic (SIM_DESC sd,
    878 	       sim_cpu *cpu,
    879 	       int trace_idx,
    880 	       const char *fmt,
    881 	       ...)
    882 {
    883   va_list ap;
    884   trace_printf (sd, cpu, "%s %s",
    885 		trace_idx_to_str (trace_idx),
    886 		TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
    887   va_start (ap, fmt);
    888   trace_vprintf (sd, cpu, fmt, ap);
    889   va_end (ap);
    890   trace_printf (sd, cpu, "\n");
    891 }
    892 
    893 static int
    894 dis_read (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
    895 	  struct disassemble_info *dinfo)
    896 {
    897   SIM_CPU *cpu = dinfo->application_data;
    898   sim_core_read_buffer (CPU_STATE (cpu), cpu, NULL_CIA, myaddr, memaddr, length);
    899   return 0;
    900 }
    901 
    902 static int
    903 dis_printf (SIM_CPU *cpu, const char *fmt, ...)
    904 {
    905   SIM_DESC sd = CPU_STATE (cpu);
    906   va_list ap;
    907   va_start (ap, fmt);
    908   trace_vprintf (sd, cpu, fmt, ap);
    909   va_end (ap);
    910   return 0;
    911 }
    912 
    913 void
    914 trace_disasm (SIM_DESC sd, sim_cpu *cpu, address_word addr)
    915 {
    916   struct bfd *bfd = STATE_PROG_BFD (sd);
    917   TRACE_DATA *trace_data = CPU_TRACE_DATA (cpu);
    918   disassemble_info *info = &trace_data->dis_info;
    919 
    920   /* See if we need to set up the disassembly func.  */
    921   if (trace_data->dis_bfd != bfd)
    922     {
    923       trace_data->dis_bfd = bfd;
    924       trace_data->disassembler = disassembler (trace_data->dis_bfd);
    925       INIT_DISASSEMBLE_INFO (*info, cpu, dis_printf);
    926       info->read_memory_func = dis_read;
    927       info->arch = bfd_get_arch (bfd);
    928       info->mach = bfd_get_mach (bfd);
    929       disassemble_init_for_target (info);
    930     }
    931 
    932   info->application_data = cpu;
    933 
    934   trace_printf (sd, cpu, "%s %s",
    935 		trace_idx_to_str (TRACE_DISASM_IDX),
    936 		TRACE_PREFIX (trace_data));
    937   trace_data->disassembler (addr, info);
    938   trace_printf (sd, cpu, "\n");
    939 }
    940 
    941 void
    942 trace_input0 (SIM_DESC sd,
    943 	      sim_cpu *cpu,
    944 	      int trace_idx)
    945 {
    946   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
    947   TRACE_IDX (data) = trace_idx;
    948 }
    949 
    950 void
    951 trace_input_word1 (SIM_DESC sd,
    952 		   sim_cpu *cpu,
    953 		   int trace_idx,
    954 		   unsigned_word d0)
    955 {
    956   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
    957   TRACE_IDX (data) = trace_idx;
    958   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
    959 }
    960 
    961 void
    962 trace_input_word2 (SIM_DESC sd,
    963 		   sim_cpu *cpu,
    964 		   int trace_idx,
    965 		   unsigned_word d0,
    966 		   unsigned_word d1)
    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   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
    972 }
    973 
    974 void
    975 trace_input_word3 (SIM_DESC sd,
    976 		   sim_cpu *cpu,
    977 		   int trace_idx,
    978 		   unsigned_word d0,
    979 		   unsigned_word d1,
    980 		   unsigned_word d2)
    981 {
    982   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
    983   TRACE_IDX (data) = trace_idx;
    984   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
    985   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
    986   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);
    987 }
    988 
    989 void
    990 trace_input_word4 (SIM_DESC sd,
    991 		   sim_cpu *cpu,
    992 		   int trace_idx,
    993 		   unsigned_word d0,
    994 		   unsigned_word d1,
    995 		   unsigned_word d2,
    996 		   unsigned_word d3)
    997 {
    998   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
    999   TRACE_IDX (data) = trace_idx;
   1000   save_data (sd, data, trace_fmt_word, sizeof (d0), &d0);
   1001   save_data (sd, data, trace_fmt_word, sizeof (d1), &d1);
   1002   save_data (sd, data, trace_fmt_word, sizeof (d2), &d2);
   1003   save_data (sd, data, trace_fmt_word, sizeof (d3), &d3);
   1004 }
   1005 
   1006 void
   1007 trace_input_bool1 (SIM_DESC sd,
   1008 		   sim_cpu *cpu,
   1009 		   int trace_idx,
   1010 		   int d0)
   1011 {
   1012   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1013   TRACE_IDX (data) = trace_idx;
   1014   save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0);
   1015 }
   1016 
   1017 void
   1018 trace_input_addr1 (SIM_DESC sd,
   1019 		   sim_cpu *cpu,
   1020 		   int trace_idx,
   1021 		   address_word d0)
   1022 {
   1023   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1024   TRACE_IDX (data) = trace_idx;
   1025   save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0);
   1026 }
   1027 
   1028 void
   1029 trace_input_fp1 (SIM_DESC sd,
   1030 		 sim_cpu *cpu,
   1031 		 int trace_idx,
   1032 		 fp_word f0)
   1033 {
   1034   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1035   TRACE_IDX (data) = trace_idx;
   1036   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
   1037 }
   1038 
   1039 void
   1040 trace_input_fp2 (SIM_DESC sd,
   1041 		 sim_cpu *cpu,
   1042 		 int trace_idx,
   1043 		 fp_word f0,
   1044 		 fp_word f1)
   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   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
   1050 }
   1051 
   1052 void
   1053 trace_input_fp3 (SIM_DESC sd,
   1054 		 sim_cpu *cpu,
   1055 		 int trace_idx,
   1056 		 fp_word f0,
   1057 		 fp_word f1,
   1058 		 fp_word f2)
   1059 {
   1060   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1061   TRACE_IDX (data) = trace_idx;
   1062   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
   1063   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
   1064   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2);
   1065 }
   1066 
   1067 void
   1068 trace_input_fpu1 (SIM_DESC sd,
   1069 		  sim_cpu *cpu,
   1070 		  int trace_idx,
   1071 		  sim_fpu *f0)
   1072 {
   1073   double d;
   1074   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1075   TRACE_IDX (data) = trace_idx;
   1076   d = sim_fpu_2d (f0);
   1077   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
   1078 }
   1079 
   1080 void
   1081 trace_input_fpu2 (SIM_DESC sd,
   1082 		  sim_cpu *cpu,
   1083 		  int trace_idx,
   1084 		  sim_fpu *f0,
   1085 		  sim_fpu *f1)
   1086 {
   1087   double d;
   1088   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1089   TRACE_IDX (data) = trace_idx;
   1090   d = sim_fpu_2d (f0);
   1091   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
   1092   d = sim_fpu_2d (f1);
   1093   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
   1094 }
   1095 
   1096 void
   1097 trace_input_fpu3 (SIM_DESC sd,
   1098 		  sim_cpu *cpu,
   1099 		  int trace_idx,
   1100 		  sim_fpu *f0,
   1101 		  sim_fpu *f1,
   1102 		  sim_fpu *f2)
   1103 {
   1104   double d;
   1105   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1106   TRACE_IDX (data) = trace_idx;
   1107   d = sim_fpu_2d (f0);
   1108   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
   1109   d = sim_fpu_2d (f1);
   1110   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
   1111   d = sim_fpu_2d (f2);
   1112   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
   1113 }
   1114 
   1115 void
   1116 trace_result_word1 (SIM_DESC sd,
   1117 		    sim_cpu *cpu,
   1118 		    int trace_idx,
   1119 		    unsigned_word r0)
   1120 {
   1121   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1122   int last_input;
   1123 
   1124   /* Append any results to the end of the inputs */
   1125   last_input = TRACE_INPUT_IDX (data);
   1126   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
   1127 
   1128   trace_results (sd, cpu, trace_idx, last_input);
   1129 }
   1130 
   1131 void
   1132 trace_result0 (SIM_DESC sd,
   1133 	       sim_cpu *cpu,
   1134 	       int trace_idx)
   1135 {
   1136   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1137   int last_input;
   1138 
   1139   /* Append any results to the end of the inputs */
   1140   last_input = TRACE_INPUT_IDX (data);
   1141 
   1142   trace_results (sd, cpu, trace_idx, last_input);
   1143 }
   1144 
   1145 void
   1146 trace_result_word2 (SIM_DESC sd,
   1147 		    sim_cpu *cpu,
   1148 		    int trace_idx,
   1149 		    unsigned_word r0,
   1150 		    unsigned_word r1)
   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_word, sizeof (r0), &r0);
   1158   save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
   1159 
   1160   trace_results (sd, cpu, trace_idx, last_input);
   1161 }
   1162 
   1163 void
   1164 trace_result_word4 (SIM_DESC sd,
   1165 		    sim_cpu *cpu,
   1166 		    int trace_idx,
   1167 		    unsigned_word r0,
   1168 		    unsigned_word r1,
   1169 		    unsigned_word r2,
   1170 		    unsigned_word r3)
   1171 {
   1172   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1173   int last_input;
   1174 
   1175   /* Append any results to the end of the inputs */
   1176   last_input = TRACE_INPUT_IDX (data);
   1177   save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
   1178   save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
   1179   save_data (sd, data, trace_fmt_word, sizeof (r2), &r2);
   1180   save_data (sd, data, trace_fmt_word, sizeof (r3), &r3);
   1181 
   1182   trace_results (sd, cpu, trace_idx, last_input);
   1183 }
   1184 
   1185 void
   1186 trace_result_bool1 (SIM_DESC sd,
   1187 		    sim_cpu *cpu,
   1188 		    int trace_idx,
   1189 		    int r0)
   1190 {
   1191   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1192   int last_input;
   1193 
   1194   /* Append any results to the end of the inputs */
   1195   last_input = TRACE_INPUT_IDX (data);
   1196   save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0);
   1197 
   1198   trace_results (sd, cpu, trace_idx, last_input);
   1199 }
   1200 
   1201 void
   1202 trace_result_addr1 (SIM_DESC sd,
   1203 		    sim_cpu *cpu,
   1204 		    int trace_idx,
   1205 		    address_word r0)
   1206 {
   1207   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1208   int last_input;
   1209 
   1210   /* Append any results to the end of the inputs */
   1211   last_input = TRACE_INPUT_IDX (data);
   1212   save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0);
   1213 
   1214   trace_results (sd, cpu, trace_idx, last_input);
   1215 }
   1216 
   1217 void
   1218 trace_result_fp1 (SIM_DESC sd,
   1219 		  sim_cpu *cpu,
   1220 		  int trace_idx,
   1221 		  fp_word f0)
   1222 {
   1223   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1224   int last_input;
   1225 
   1226   /* Append any results to the end of the inputs */
   1227   last_input = TRACE_INPUT_IDX (data);
   1228   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
   1229 
   1230   trace_results (sd, cpu, trace_idx, last_input);
   1231 }
   1232 
   1233 void
   1234 trace_result_fp2 (SIM_DESC sd,
   1235 		  sim_cpu *cpu,
   1236 		  int trace_idx,
   1237 		  fp_word f0,
   1238 		  fp_word f1)
   1239 {
   1240   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1241   int last_input;
   1242 
   1243   /* Append any results to the end of the inputs */
   1244   last_input = TRACE_INPUT_IDX (data);
   1245   save_data (sd, data, trace_fmt_fp, sizeof (f0), &f0);
   1246   save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1);
   1247 
   1248   trace_results (sd, cpu, trace_idx, last_input);
   1249 }
   1250 
   1251 void
   1252 trace_result_fpu1 (SIM_DESC sd,
   1253 		   sim_cpu *cpu,
   1254 		   int trace_idx,
   1255 		   sim_fpu *f0)
   1256 {
   1257   double d;
   1258   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1259   int last_input;
   1260 
   1261   /* Append any results to the end of the inputs */
   1262   last_input = TRACE_INPUT_IDX (data);
   1263   d = sim_fpu_2d (f0);
   1264   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
   1265 
   1266   trace_results (sd, cpu, trace_idx, last_input);
   1267 }
   1268 
   1269 void
   1270 trace_result_string1 (SIM_DESC sd,
   1271 		      sim_cpu *cpu,
   1272 		      int trace_idx,
   1273 		      char *s0)
   1274 {
   1275   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1276   int last_input;
   1277 
   1278   /* Append any results to the end of the inputs */
   1279   last_input = TRACE_INPUT_IDX (data);
   1280   save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
   1281 
   1282   trace_results (sd, cpu, trace_idx, last_input);
   1283 }
   1284 
   1285 void
   1286 trace_result_word1_string1 (SIM_DESC sd,
   1287 			    sim_cpu *cpu,
   1288 			    int trace_idx,
   1289 			    unsigned_word r0,
   1290 			    char *s0)
   1291 {
   1292   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
   1293   int last_input;
   1294 
   1295   /* Append any results to the end of the inputs */
   1296   last_input = TRACE_INPUT_IDX (data);
   1297   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
   1298   save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
   1299 
   1300   trace_results (sd, cpu, trace_idx, last_input);
   1301 }
   1302 
   1303 void
   1305 trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
   1306 {
   1307   if (cpu != NULL)
   1308     {
   1309       if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
   1310 	vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
   1311       else
   1312 	sim_io_evprintf (sd, fmt, ap);
   1313     }
   1314   else
   1315     {
   1316       if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
   1317 	vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
   1318       else
   1319 	sim_io_evprintf (sd, fmt, ap);
   1320     }
   1321 }
   1322 
   1323 void
   1324 trace_printf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...)
   1325 {
   1326   va_list ap;
   1327 
   1328   va_start (ap, fmt);
   1329 
   1330   trace_vprintf (sd, cpu, fmt, ap);
   1331 
   1332   va_end (ap);
   1333 }
   1334 
   1335 void
   1336 sim_debug_printf (sim_cpu *cpu, const char *fmt, ...)
   1337 {
   1338   va_list ap;
   1339 
   1340   va_start (ap, fmt);
   1341 
   1342   if (CPU_DEBUG_FILE (cpu) == NULL)
   1343     (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
   1344       (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
   1345   else
   1346     vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
   1347 
   1348   va_end (ap);
   1349 }
   1350