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