xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/sim-trace.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
14e98e3e1Schristos /* Simulator tracing/debugging support.
2*88241920Schristos    Copyright (C) 1997-2024 Free Software Foundation, Inc.
34e98e3e1Schristos    Contributed by Cygnus Support.
44e98e3e1Schristos 
54e98e3e1Schristos This file is part of GDB, the GNU debugger.
64e98e3e1Schristos 
74e98e3e1Schristos This program is free software; you can redistribute it and/or modify
84e98e3e1Schristos it under the terms of the GNU General Public License as published by
94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or
104e98e3e1Schristos (at your option) any later version.
114e98e3e1Schristos 
124e98e3e1Schristos This program is distributed in the hope that it will be useful,
134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
154e98e3e1Schristos GNU General Public License for more details.
164e98e3e1Schristos 
174e98e3e1Schristos You should have received a copy of the GNU General Public License
184e98e3e1Schristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
194e98e3e1Schristos 
204b169a6bSchristos /* This must come before any other includes.  */
214b169a6bSchristos #include "defs.h"
224b169a6bSchristos 
234b169a6bSchristos #include <stdarg.h>
244b169a6bSchristos #include <stdlib.h>
254b169a6bSchristos #include <string.h>
264b169a6bSchristos 
274b169a6bSchristos #include "ansidecl.h"
284b169a6bSchristos #include "bfd.h"
294b169a6bSchristos #include "dis-asm.h"
304b169a6bSchristos #include "libiberty.h"
314b169a6bSchristos 
324e98e3e1Schristos #include "sim-main.h"
334b169a6bSchristos #include "sim-assert.h"
344e98e3e1Schristos #include "sim-io.h"
354e98e3e1Schristos #include "sim-options.h"
364e98e3e1Schristos #include "sim-fpu.h"
374b169a6bSchristos #include "sim/callback.h"
384e98e3e1Schristos 
394e98e3e1Schristos #ifndef SIZE_PHASE
404e98e3e1Schristos #define SIZE_PHASE 8
414e98e3e1Schristos #endif
424e98e3e1Schristos 
434e98e3e1Schristos #ifndef SIZE_LOCATION
444e98e3e1Schristos #define SIZE_LOCATION 20
454e98e3e1Schristos #endif
464e98e3e1Schristos 
474e98e3e1Schristos #ifndef SIZE_PC
484e98e3e1Schristos #define SIZE_PC 6
494e98e3e1Schristos #endif
504e98e3e1Schristos 
514e98e3e1Schristos #ifndef SIZE_LINE_NUMBER
524e98e3e1Schristos #define SIZE_LINE_NUMBER 4
534e98e3e1Schristos #endif
544e98e3e1Schristos 
554e98e3e1Schristos static MODULE_INIT_FN trace_init;
564e98e3e1Schristos static MODULE_UNINSTALL_FN trace_uninstall;
574e98e3e1Schristos 
584e98e3e1Schristos static DECLARE_OPTION_HANDLER (trace_option_handler);
594e98e3e1Schristos 
604e98e3e1Schristos enum {
614e98e3e1Schristos   OPTION_TRACE_INSN	= OPTION_START,
62ba340e45Schristos   OPTION_TRACE_DISASM,
634e98e3e1Schristos   OPTION_TRACE_DECODE,
644e98e3e1Schristos   OPTION_TRACE_EXTRACT,
654e98e3e1Schristos   OPTION_TRACE_LINENUM,
664e98e3e1Schristos   OPTION_TRACE_MEMORY,
674e98e3e1Schristos   OPTION_TRACE_MODEL,
684e98e3e1Schristos   OPTION_TRACE_ALU,
694e98e3e1Schristos   OPTION_TRACE_CORE,
704e98e3e1Schristos   OPTION_TRACE_EVENTS,
714e98e3e1Schristos   OPTION_TRACE_FPU,
724e98e3e1Schristos   OPTION_TRACE_BRANCH,
734e98e3e1Schristos   OPTION_TRACE_SEMANTICS,
744e98e3e1Schristos   OPTION_TRACE_RANGE,
754e98e3e1Schristos   OPTION_TRACE_FUNCTION,
764e98e3e1Schristos   OPTION_TRACE_DEBUG,
774e98e3e1Schristos   OPTION_TRACE_FILE,
78a2e2270fSchristos   OPTION_TRACE_VPU,
79212397c6Schristos   OPTION_TRACE_SYSCALL,
80212397c6Schristos   OPTION_TRACE_REGISTER
814e98e3e1Schristos };
824e98e3e1Schristos 
834e98e3e1Schristos static const OPTION trace_options[] =
844e98e3e1Schristos {
854e98e3e1Schristos   /* This table is organized to group related instructions together.  */
864e98e3e1Schristos   { {"trace", optional_argument, NULL, 't'},
874e98e3e1Schristos       't', "on|off", "Trace useful things",
884e98e3e1Schristos       trace_option_handler, NULL },
894e98e3e1Schristos   { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN},
904e98e3e1Schristos       '\0', "on|off", "Perform instruction tracing",
914e98e3e1Schristos       trace_option_handler, NULL },
92ba340e45Schristos   { {"trace-disasm", optional_argument, NULL, OPTION_TRACE_DISASM},
93ba340e45Schristos       '\0', "on|off", "Disassemble instructions (slower, but more accurate)",
94ba340e45Schristos       trace_option_handler, NULL },
954e98e3e1Schristos   { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE},
964e98e3e1Schristos       '\0', "on|off", "Trace instruction decoding",
974e98e3e1Schristos       trace_option_handler, NULL },
984e98e3e1Schristos   { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT},
994e98e3e1Schristos       '\0', "on|off", "Trace instruction extraction",
1004e98e3e1Schristos       trace_option_handler, NULL },
1014e98e3e1Schristos   { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM},
1024e98e3e1Schristos       '\0', "on|off", "Perform line number tracing (implies --trace-insn)",
1034e98e3e1Schristos       trace_option_handler, NULL },
1044e98e3e1Schristos   { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY},
1054e98e3e1Schristos       '\0', "on|off", "Trace memory operations",
1064e98e3e1Schristos       trace_option_handler, NULL },
1074e98e3e1Schristos   { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU},
108212397c6Schristos       '\0', "on|off", "Trace ALU (Arithmetic Logic Unit) operations",
1094e98e3e1Schristos       trace_option_handler, NULL },
1104e98e3e1Schristos   { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU},
111212397c6Schristos       '\0', "on|off", "Trace FPU (Floating Point Unit) operations",
1124e98e3e1Schristos       trace_option_handler, NULL },
1134e98e3e1Schristos   { {"trace-vpu", optional_argument, NULL, OPTION_TRACE_VPU},
114212397c6Schristos       '\0', "on|off", "Trace VPU (Vector Processing Unit) operations",
1154e98e3e1Schristos       trace_option_handler, NULL },
1164e98e3e1Schristos   { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH},
1174e98e3e1Schristos       '\0', "on|off", "Trace branching",
1184e98e3e1Schristos       trace_option_handler, NULL },
1194e98e3e1Schristos   { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS},
120212397c6Schristos       '\0', "on|off", "Perform ALU, FPU, VPU, MEMORY, and BRANCH tracing",
1214e98e3e1Schristos       trace_option_handler, NULL },
1224e98e3e1Schristos   { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL},
1234e98e3e1Schristos       '\0', "on|off", "Include model performance data",
1244e98e3e1Schristos       trace_option_handler, NULL },
1254e98e3e1Schristos   { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE},
1264e98e3e1Schristos       '\0', "on|off", "Trace core operations",
1274e98e3e1Schristos       trace_option_handler, NULL },
1284e98e3e1Schristos   { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS},
1294e98e3e1Schristos       '\0', "on|off", "Trace events",
1304e98e3e1Schristos       trace_option_handler, NULL },
131a2e2270fSchristos   { {"trace-syscall", optional_argument, NULL, OPTION_TRACE_SYSCALL},
132a2e2270fSchristos       '\0', "on|off", "Trace system calls",
133a2e2270fSchristos       trace_option_handler, NULL },
134212397c6Schristos   { {"trace-register", optional_argument, NULL, OPTION_TRACE_REGISTER},
135212397c6Schristos       '\0', "on|off", "Trace cpu register accesses",
136212397c6Schristos       trace_option_handler, NULL },
1374e98e3e1Schristos #ifdef SIM_HAVE_ADDR_RANGE
1384e98e3e1Schristos   { {"trace-range", required_argument, NULL, OPTION_TRACE_RANGE},
1394e98e3e1Schristos       '\0', "START,END", "Specify range of addresses for instruction tracing",
1404e98e3e1Schristos       trace_option_handler, NULL },
1414e98e3e1Schristos #if 0 /*wip*/
1424e98e3e1Schristos   { {"trace-function", required_argument, NULL, OPTION_TRACE_FUNCTION},
1434e98e3e1Schristos       '\0', "FUNCTION", "Specify function to trace",
1444e98e3e1Schristos       trace_option_handler, NULL },
1454e98e3e1Schristos #endif
1464e98e3e1Schristos #endif
1474e98e3e1Schristos   { {"trace-debug", optional_argument, NULL, OPTION_TRACE_DEBUG},
1484e98e3e1Schristos       '\0', "on|off", "Add information useful for debugging the simulator to the tracing output",
1494e98e3e1Schristos       trace_option_handler, NULL },
1504e98e3e1Schristos   { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE},
1514e98e3e1Schristos       '\0', "FILE NAME", "Specify tracing output file",
1524e98e3e1Schristos       trace_option_handler, NULL },
1534e98e3e1Schristos   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
1544e98e3e1Schristos };
1554e98e3e1Schristos 
1564e98e3e1Schristos /* Set/reset the trace options indicated in MASK.  */
1574e98e3e1Schristos 
1584e98e3e1Schristos static SIM_RC
1594e98e3e1Schristos set_trace_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg)
1604e98e3e1Schristos {
1614e98e3e1Schristos   int trace_nr;
1624e98e3e1Schristos   int cpu_nr;
1634e98e3e1Schristos   int trace_val = 1;
1644e98e3e1Schristos 
1654e98e3e1Schristos   if (arg != NULL)
1664e98e3e1Schristos     {
1674e98e3e1Schristos       if (strcmp (arg, "yes") == 0
1684e98e3e1Schristos 	  || strcmp (arg, "on") == 0
1694e98e3e1Schristos 	  || strcmp (arg, "1") == 0)
1704e98e3e1Schristos 	trace_val = 1;
1714e98e3e1Schristos       else if (strcmp (arg, "no") == 0
1724e98e3e1Schristos 	       || strcmp (arg, "off") == 0
1734e98e3e1Schristos 	       || strcmp (arg, "0") == 0)
1744e98e3e1Schristos 	trace_val = 0;
1754e98e3e1Schristos       else
1764e98e3e1Schristos 	{
1774e98e3e1Schristos 	  sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name);
1784e98e3e1Schristos 	  return SIM_RC_FAIL;
1794e98e3e1Schristos 	}
1804e98e3e1Schristos     }
1814e98e3e1Schristos 
182212397c6Schristos   /* Update applicable trace bits.  */
1834e98e3e1Schristos   for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr)
1844e98e3e1Schristos     {
1854e98e3e1Schristos       if ((mask & (1 << trace_nr)) == 0)
1864e98e3e1Schristos 	continue;
1874e98e3e1Schristos 
1884e98e3e1Schristos       /* Set non-cpu specific values.  */
1894e98e3e1Schristos       STATE_TRACE_FLAGS (sd)[trace_nr] = trace_val;
1904e98e3e1Schristos 
1914e98e3e1Schristos       /* Set cpu values.  */
1924e98e3e1Schristos       for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
1934e98e3e1Schristos 	{
1944e98e3e1Schristos 	  CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val;
1954e98e3e1Schristos 	}
1964e98e3e1Schristos     }
1974e98e3e1Schristos 
1984e98e3e1Schristos   /* Re-compute the cpu trace summary.  */
1994e98e3e1Schristos   if (trace_val)
2004e98e3e1Schristos     {
2014e98e3e1Schristos       for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
2024e98e3e1Schristos 	CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1;
2034e98e3e1Schristos     }
2044e98e3e1Schristos   else
2054e98e3e1Schristos     {
2064e98e3e1Schristos       for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
2074e98e3e1Schristos 	{
2084e98e3e1Schristos 	  CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 0;
2094e98e3e1Schristos 	  for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr)
2104e98e3e1Schristos 	    {
2114e98e3e1Schristos 	      if (CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr])
2124e98e3e1Schristos 		{
2134e98e3e1Schristos 		  CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1;
2144e98e3e1Schristos 		  break;
2154e98e3e1Schristos 		}
2164e98e3e1Schristos 	    }
2174e98e3e1Schristos 	}
2184e98e3e1Schristos     }
2194e98e3e1Schristos 
2204e98e3e1Schristos   return SIM_RC_OK;
2214e98e3e1Schristos }
2224e98e3e1Schristos 
2234e98e3e1Schristos /* Set one trace option based on its IDX value.  */
2244e98e3e1Schristos 
2254e98e3e1Schristos static SIM_RC
2264e98e3e1Schristos set_trace_option (SIM_DESC sd, const char *name, int idx, const char *arg)
2274e98e3e1Schristos {
2284e98e3e1Schristos   return set_trace_option_mask (sd, name, 1 << idx, arg);
2294e98e3e1Schristos }
2304e98e3e1Schristos 
2314e98e3e1Schristos 
2324e98e3e1Schristos static SIM_RC
2334e98e3e1Schristos trace_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
2344e98e3e1Schristos 		      char *arg, int is_command)
2354e98e3e1Schristos {
2364e98e3e1Schristos   int n;
2374e98e3e1Schristos 
2384e98e3e1Schristos   switch (opt)
2394e98e3e1Schristos     {
2404e98e3e1Schristos     case 't' :
241212397c6Schristos       if (!WITH_TRACE_ANY_P)
2424e98e3e1Schristos 	sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
2434e98e3e1Schristos       else
2444e98e3e1Schristos 	return set_trace_option_mask (sd, "trace", TRACE_USEFUL_MASK, arg);
2454e98e3e1Schristos       break;
2464e98e3e1Schristos 
2474e98e3e1Schristos     case OPTION_TRACE_INSN :
2484e98e3e1Schristos       if (WITH_TRACE_INSN_P)
2494e98e3e1Schristos 	return set_trace_option (sd, "-insn", TRACE_INSN_IDX, arg);
2504e98e3e1Schristos       else
2514e98e3e1Schristos 	sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
2524e98e3e1Schristos       break;
2534e98e3e1Schristos 
254ba340e45Schristos     case OPTION_TRACE_DISASM :
255ba340e45Schristos       if (WITH_TRACE_DISASM_P)
256ba340e45Schristos 	return set_trace_option (sd, "-disasm", TRACE_DISASM_IDX, arg);
257ba340e45Schristos       else
258ba340e45Schristos 	sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-disasm' ignored\n");
259ba340e45Schristos       break;
260ba340e45Schristos 
2614e98e3e1Schristos     case OPTION_TRACE_DECODE :
2624e98e3e1Schristos       if (WITH_TRACE_DECODE_P)
2634e98e3e1Schristos 	return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg);
2644e98e3e1Schristos       else
2654e98e3e1Schristos 	sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
2664e98e3e1Schristos       break;
2674e98e3e1Schristos 
2684e98e3e1Schristos     case OPTION_TRACE_EXTRACT :
2694e98e3e1Schristos       if (WITH_TRACE_EXTRACT_P)
2704e98e3e1Schristos 	return set_trace_option (sd, "-extract", TRACE_EXTRACT_IDX, arg);
2714e98e3e1Schristos       else
2724e98e3e1Schristos 	sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
2734e98e3e1Schristos       break;
2744e98e3e1Schristos 
2754e98e3e1Schristos     case OPTION_TRACE_LINENUM :
2764e98e3e1Schristos       if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P)
2774e98e3e1Schristos 	{
2784e98e3e1Schristos 	  if (set_trace_option (sd, "-linenum", TRACE_LINENUM_IDX, arg) != SIM_RC_OK
2794e98e3e1Schristos 	      || set_trace_option (sd, "-linenum", TRACE_INSN_IDX, arg) != SIM_RC_OK)
2804e98e3e1Schristos 	    return SIM_RC_FAIL;
2814e98e3e1Schristos 	}
2824e98e3e1Schristos       else
2834e98e3e1Schristos 	sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
2844e98e3e1Schristos       break;
2854e98e3e1Schristos 
2864e98e3e1Schristos     case OPTION_TRACE_MEMORY :
2874e98e3e1Schristos       if (WITH_TRACE_MEMORY_P)
2884e98e3e1Schristos 	return set_trace_option (sd, "-memory", TRACE_MEMORY_IDX, arg);
2894e98e3e1Schristos       else
2904e98e3e1Schristos 	sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
2914e98e3e1Schristos       break;
2924e98e3e1Schristos 
2934e98e3e1Schristos     case OPTION_TRACE_MODEL :
2944e98e3e1Schristos       if (WITH_TRACE_MODEL_P)
2954e98e3e1Schristos 	return set_trace_option (sd, "-model", TRACE_MODEL_IDX, arg);
2964e98e3e1Schristos       else
2974e98e3e1Schristos 	sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
2984e98e3e1Schristos       break;
2994e98e3e1Schristos 
3004e98e3e1Schristos     case OPTION_TRACE_ALU :
3014e98e3e1Schristos       if (WITH_TRACE_ALU_P)
3024e98e3e1Schristos 	return set_trace_option (sd, "-alu", TRACE_ALU_IDX, arg);
3034e98e3e1Schristos       else
3044e98e3e1Schristos 	sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
3054e98e3e1Schristos       break;
3064e98e3e1Schristos 
3074e98e3e1Schristos     case OPTION_TRACE_CORE :
3084e98e3e1Schristos       if (WITH_TRACE_CORE_P)
3094e98e3e1Schristos 	return set_trace_option (sd, "-core", TRACE_CORE_IDX, arg);
3104e98e3e1Schristos       else
3114e98e3e1Schristos 	sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
3124e98e3e1Schristos       break;
3134e98e3e1Schristos 
3144e98e3e1Schristos     case OPTION_TRACE_EVENTS :
3154e98e3e1Schristos       if (WITH_TRACE_EVENTS_P)
3164e98e3e1Schristos 	return set_trace_option (sd, "-events", TRACE_EVENTS_IDX, arg);
3174e98e3e1Schristos       else
3184e98e3e1Schristos 	sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
3194e98e3e1Schristos       break;
3204e98e3e1Schristos 
3214e98e3e1Schristos     case OPTION_TRACE_FPU :
3224e98e3e1Schristos       if (WITH_TRACE_FPU_P)
3234e98e3e1Schristos 	return set_trace_option (sd, "-fpu", TRACE_FPU_IDX, arg);
3244e98e3e1Schristos       else
3254e98e3e1Schristos 	sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
3264e98e3e1Schristos       break;
3274e98e3e1Schristos 
3284e98e3e1Schristos     case OPTION_TRACE_VPU :
3294e98e3e1Schristos       if (WITH_TRACE_VPU_P)
3304e98e3e1Schristos 	return set_trace_option (sd, "-vpu", TRACE_VPU_IDX, arg);
3314e98e3e1Schristos       else
3324e98e3e1Schristos 	sim_io_eprintf (sd, "VPU tracing not compiled in, `--trace-vpu' ignored\n");
3334e98e3e1Schristos       break;
3344e98e3e1Schristos 
3354e98e3e1Schristos     case OPTION_TRACE_BRANCH :
3364e98e3e1Schristos       if (WITH_TRACE_BRANCH_P)
3374e98e3e1Schristos 	return set_trace_option (sd, "-branch", TRACE_BRANCH_IDX, arg);
3384e98e3e1Schristos       else
3394e98e3e1Schristos 	sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n");
3404e98e3e1Schristos       break;
3414e98e3e1Schristos 
342a2e2270fSchristos     case OPTION_TRACE_SYSCALL :
343a2e2270fSchristos       if (WITH_TRACE_SYSCALL_P)
344a2e2270fSchristos 	return set_trace_option (sd, "-syscall", TRACE_SYSCALL_IDX, arg);
345a2e2270fSchristos       else
346a2e2270fSchristos 	sim_io_eprintf (sd, "System call tracing not compiled in, `--trace-syscall' ignored\n");
347a2e2270fSchristos       break;
348a2e2270fSchristos 
349212397c6Schristos     case OPTION_TRACE_REGISTER :
350212397c6Schristos       if (WITH_TRACE_REGISTER_P)
351212397c6Schristos 	return set_trace_option (sd, "-register", TRACE_REGISTER_IDX, arg);
352212397c6Schristos       else
353212397c6Schristos 	sim_io_eprintf (sd, "Register tracing not compiled in, `--trace-register' ignored\n");
354212397c6Schristos       break;
355212397c6Schristos 
3564e98e3e1Schristos     case OPTION_TRACE_SEMANTICS :
3574e98e3e1Schristos       if (WITH_TRACE_ALU_P
3584e98e3e1Schristos 	  && WITH_TRACE_FPU_P
3594e98e3e1Schristos 	  && WITH_TRACE_MEMORY_P
3604e98e3e1Schristos 	  && WITH_TRACE_BRANCH_P)
3614e98e3e1Schristos 	{
3624e98e3e1Schristos 	  if (set_trace_option (sd, "-semantics", TRACE_ALU_IDX, arg) != SIM_RC_OK
3634e98e3e1Schristos 	      || set_trace_option (sd, "-semantics", TRACE_FPU_IDX, arg) != SIM_RC_OK
3644e98e3e1Schristos 	      || set_trace_option (sd, "-semantics", TRACE_VPU_IDX, arg) != SIM_RC_OK
3654e98e3e1Schristos 	      || set_trace_option (sd, "-semantics", TRACE_MEMORY_IDX, arg) != SIM_RC_OK
3664e98e3e1Schristos 	      || set_trace_option (sd, "-semantics", TRACE_BRANCH_IDX, arg) != SIM_RC_OK)
3674e98e3e1Schristos 	    return SIM_RC_FAIL;
3684e98e3e1Schristos 	}
3694e98e3e1Schristos       else
3704e98e3e1Schristos 	sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n");
3714e98e3e1Schristos       break;
3724e98e3e1Schristos 
3734e98e3e1Schristos #ifdef SIM_HAVE_ADDR_RANGE
3744e98e3e1Schristos     case OPTION_TRACE_RANGE :
375212397c6Schristos       if (WITH_TRACE_ANY_P)
3764e98e3e1Schristos 	{
3774e98e3e1Schristos 	  int cpu_nr;
3784e98e3e1Schristos 	  char *chp = arg;
3794e98e3e1Schristos 	  unsigned long start,end;
3804e98e3e1Schristos 	  start = strtoul (chp, &chp, 0);
3814e98e3e1Schristos 	  if (*chp != ',')
3824e98e3e1Schristos 	    {
3834e98e3e1Schristos 	      sim_io_eprintf (sd, "--trace-range missing END argument\n");
3844e98e3e1Schristos 	      return SIM_RC_FAIL;
3854e98e3e1Schristos 	    }
3864e98e3e1Schristos 	  end = strtoul (chp + 1, NULL, 0);
3874e98e3e1Schristos 	  /* FIXME: Argument validation.  */
3884e98e3e1Schristos 	  if (cpu != NULL)
3894e98e3e1Schristos 	    sim_addr_range_add (TRACE_RANGE (CPU_PROFILE_DATA (cpu)),
3904e98e3e1Schristos 				start, end);
3914e98e3e1Schristos 	  else
3924e98e3e1Schristos 	    for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
3934e98e3e1Schristos 	      sim_addr_range_add (TRACE_RANGE (CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))),
3944e98e3e1Schristos 				  start, end);
3954e98e3e1Schristos 	}
3964e98e3e1Schristos       else
3974e98e3e1Schristos 	sim_io_eprintf (sd, "Tracing not compiled in, `--trace-range' ignored\n");
3984e98e3e1Schristos       break;
3994e98e3e1Schristos 
4004e98e3e1Schristos     case OPTION_TRACE_FUNCTION :
401212397c6Schristos       if (WITH_TRACE_ANY_P)
4024e98e3e1Schristos 	{
4034e98e3e1Schristos 	  /*wip: need to compute function range given name*/
4044e98e3e1Schristos 	}
4054e98e3e1Schristos       else
4064e98e3e1Schristos 	sim_io_eprintf (sd, "Tracing not compiled in, `--trace-function' ignored\n");
4074e98e3e1Schristos       break;
4084e98e3e1Schristos #endif /* SIM_HAVE_ADDR_RANGE */
4094e98e3e1Schristos 
4104e98e3e1Schristos     case OPTION_TRACE_DEBUG :
4114e98e3e1Schristos       if (WITH_TRACE_DEBUG_P)
4124e98e3e1Schristos 	return set_trace_option (sd, "-debug", TRACE_DEBUG_IDX, arg);
4134e98e3e1Schristos       else
4144e98e3e1Schristos 	sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n");
4154e98e3e1Schristos       break;
4164e98e3e1Schristos 
4174e98e3e1Schristos     case OPTION_TRACE_FILE :
418212397c6Schristos       if (!WITH_TRACE_ANY_P)
4194e98e3e1Schristos 	sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
4204e98e3e1Schristos       else
4214e98e3e1Schristos 	{
4224e98e3e1Schristos 	  FILE *f = fopen (arg, "w");
4234e98e3e1Schristos 
4244e98e3e1Schristos 	  if (f == NULL)
4254e98e3e1Schristos 	    {
4264e98e3e1Schristos 	      sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
4274e98e3e1Schristos 	      return SIM_RC_FAIL;
4284e98e3e1Schristos 	    }
4294e98e3e1Schristos 	  for (n = 0; n < MAX_NR_PROCESSORS; ++n)
4304e98e3e1Schristos 	    TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f;
4314e98e3e1Schristos 	  TRACE_FILE (STATE_TRACE_DATA (sd)) = f;
4324e98e3e1Schristos 	}
4334e98e3e1Schristos       break;
4344e98e3e1Schristos     }
4354e98e3e1Schristos 
4364e98e3e1Schristos   return SIM_RC_OK;
4374e98e3e1Schristos }
4384e98e3e1Schristos 
4394b169a6bSchristos /* Provide a prototype to silence -Wmissing-prototypes.  */
4404b169a6bSchristos SIM_RC sim_install_trace (SIM_DESC sd);
4414e98e3e1Schristos 
4424b169a6bSchristos /* Install tracing support.  */
4434e98e3e1Schristos SIM_RC
4444b169a6bSchristos sim_install_trace (SIM_DESC sd)
4454e98e3e1Schristos {
4464e98e3e1Schristos   int i;
4474e98e3e1Schristos 
4484e98e3e1Schristos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
4494e98e3e1Schristos 
4504e98e3e1Schristos   sim_add_option_table (sd, NULL, trace_options);
4514e98e3e1Schristos   memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd)));
4524e98e3e1Schristos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
4534e98e3e1Schristos     memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
4544e98e3e1Schristos 	    sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i))));
4554e98e3e1Schristos   sim_module_add_init_fn (sd, trace_init);
4564e98e3e1Schristos   sim_module_add_uninstall_fn (sd, trace_uninstall);
4574e98e3e1Schristos   return SIM_RC_OK;
4584e98e3e1Schristos }
4594e98e3e1Schristos 
4604e98e3e1Schristos static SIM_RC
4614e98e3e1Schristos trace_init (SIM_DESC sd)
4624e98e3e1Schristos {
4634e98e3e1Schristos #ifdef SIM_HAVE_ADDR_RANGE
4644e98e3e1Schristos   /* Check if a range has been specified without specifying what to
4654e98e3e1Schristos      collect.  */
4664e98e3e1Schristos   {
4674e98e3e1Schristos     int i;
4684e98e3e1Schristos 
4694e98e3e1Schristos     for (i = 0; i < MAX_NR_PROCESSORS; ++i)
4704e98e3e1Schristos       {
4714e98e3e1Schristos 	sim_cpu *cpu = STATE_CPU (sd, i);
4724e98e3e1Schristos 
4734e98e3e1Schristos 	if (ADDR_RANGE_RANGES (TRACE_RANGE (CPU_TRACE_DATA (cpu)))
4744e98e3e1Schristos 	    && ! TRACE_INSN_P (cpu))
4754e98e3e1Schristos 	  {
4764e98e3e1Schristos 	    sim_io_eprintf_cpu (cpu, "Tracing address range specified without --trace-insn.\n");
4774e98e3e1Schristos 	    sim_io_eprintf_cpu (cpu, "Address range ignored.\n");
4784e98e3e1Schristos 	    sim_addr_range_delete (TRACE_RANGE (CPU_TRACE_DATA (cpu)),
4794e98e3e1Schristos 				   0, ~ (address_word) 0);
4804e98e3e1Schristos 	  }
4814e98e3e1Schristos       }
4824e98e3e1Schristos   }
4834e98e3e1Schristos #endif
4844e98e3e1Schristos 
4854e98e3e1Schristos   return SIM_RC_OK;
4864e98e3e1Schristos }
4874e98e3e1Schristos 
4884e98e3e1Schristos static void
4894e98e3e1Schristos trace_uninstall (SIM_DESC sd)
4904e98e3e1Schristos {
4914e98e3e1Schristos   int i,j;
4924e98e3e1Schristos   FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd));
4934e98e3e1Schristos 
4944e98e3e1Schristos   if (sfile != NULL)
4954e98e3e1Schristos     fclose (sfile);
4964e98e3e1Schristos 
4974e98e3e1Schristos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
4984e98e3e1Schristos     {
4994e98e3e1Schristos       FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i)));
5004e98e3e1Schristos       if (cfile != NULL && cfile != sfile)
5014e98e3e1Schristos 	{
5024e98e3e1Schristos 	  /* If output from different cpus is going to the same file,
5034e98e3e1Schristos 	     avoid closing the file twice.  */
5044e98e3e1Schristos 	  for (j = 0; j < i; ++j)
5054e98e3e1Schristos 	    if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile)
5064e98e3e1Schristos 	      break;
5074e98e3e1Schristos 	  if (i == j)
5084e98e3e1Schristos 	    fclose (cfile);
5094e98e3e1Schristos 	}
5104e98e3e1Schristos     }
511796c32c9Schristos 
512796c32c9Schristos   if (STATE_PROG_SYMS (sd))
513796c32c9Schristos     free (STATE_PROG_SYMS (sd));
5144e98e3e1Schristos }
5154e98e3e1Schristos 
5164e98e3e1Schristos /* compute the nr of trace data units consumed by data */
5174e98e3e1Schristos static int
5184e98e3e1Schristos save_data_size (TRACE_DATA *data,
5194e98e3e1Schristos 		long size)
5204e98e3e1Schristos {
5214e98e3e1Schristos   return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1)
5224e98e3e1Schristos 	  / sizeof (TRACE_INPUT_DATA (data) [0]));
5234e98e3e1Schristos }
5244e98e3e1Schristos 
5254e98e3e1Schristos 
5264e98e3e1Schristos /* Archive DATA into the trace buffer */
527a2e2270fSchristos void
5284e98e3e1Schristos save_data (SIM_DESC sd,
5294e98e3e1Schristos 	   TRACE_DATA *data,
5304e98e3e1Schristos 	   data_fmt fmt,
5314e98e3e1Schristos 	   long size,
5324e98e3e1Schristos 	   const void *buf)
5334e98e3e1Schristos {
5344e98e3e1Schristos   int i = TRACE_INPUT_IDX (data);
5354e98e3e1Schristos   if (i == sizeof (TRACE_INPUT_FMT (data)))
5364e98e3e1Schristos     sim_io_error (sd, "trace buffer overflow");
5374e98e3e1Schristos   TRACE_INPUT_FMT (data) [i] = fmt;
5384e98e3e1Schristos   TRACE_INPUT_SIZE (data) [i] = size;
5394e98e3e1Schristos   memcpy (&TRACE_INPUT_DATA (data) [i], buf, size);
5404e98e3e1Schristos   i += save_data_size (data, size);
5414e98e3e1Schristos   TRACE_INPUT_IDX (data) = i;
5424e98e3e1Schristos }
5434e98e3e1Schristos 
5444e98e3e1Schristos static void
5454e98e3e1Schristos print_data (SIM_DESC sd,
5464e98e3e1Schristos 	    sim_cpu *cpu,
5474e98e3e1Schristos 	    data_fmt fmt,
5484e98e3e1Schristos 	    long size,
5494e98e3e1Schristos 	    void *data)
5504e98e3e1Schristos {
5514e98e3e1Schristos   switch (fmt)
5524e98e3e1Schristos     {
5534e98e3e1Schristos     case trace_fmt_instruction_incomplete:
5544e98e3e1Schristos       trace_printf (sd, cpu, " (instruction incomplete)");
5554e98e3e1Schristos       break;
5564e98e3e1Schristos     case trace_fmt_word:
5574e98e3e1Schristos     case trace_fmt_addr:
5584e98e3e1Schristos       {
5594e98e3e1Schristos 	switch (size)
5604e98e3e1Schristos 	  {
5614b169a6bSchristos 	  case sizeof (uint32_t):
5624b169a6bSchristos 	    trace_printf (sd, cpu, " 0x%08lx", (long) * (uint32_t*) data);
5634e98e3e1Schristos 	    break;
5644b169a6bSchristos 	  case sizeof (uint64_t):
5654e98e3e1Schristos 	    trace_printf (sd, cpu, " 0x%08lx%08lx",
5664b169a6bSchristos 			  (long) ((* (uint64_t*) data) >> 32),
5674b169a6bSchristos 			  (long) * (uint64_t*) data);
5684e98e3e1Schristos 	    break;
5694e98e3e1Schristos 	  default:
5704e98e3e1Schristos 	    abort ();
5714e98e3e1Schristos 	  }
5724e98e3e1Schristos 	break;
5734e98e3e1Schristos       }
5744e98e3e1Schristos     case trace_fmt_bool:
5754e98e3e1Schristos       {
5764e98e3e1Schristos 	SIM_ASSERT (size == sizeof (int));
5774e98e3e1Schristos 	trace_printf (sd, cpu, " %-8s",
5784e98e3e1Schristos 		      (* (int*) data) ? "true" : "false");
5794e98e3e1Schristos 	break;
5804e98e3e1Schristos       }
5814e98e3e1Schristos     case trace_fmt_fp:
5824e98e3e1Schristos       {
5834e98e3e1Schristos 	sim_fpu fp;
5844e98e3e1Schristos 	switch (size)
5854e98e3e1Schristos 	  {
5864e98e3e1Schristos 	    /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */
5874e98e3e1Schristos 	  case 4:
5884b169a6bSchristos 	    sim_fpu_32to (&fp, *(uint32_t*)data);
5894e98e3e1Schristos 	    break;
5904e98e3e1Schristos 	  case 8:
5914b169a6bSchristos 	    sim_fpu_64to (&fp, *(uint64_t*)data);
5924e98e3e1Schristos 	    break;
5934e98e3e1Schristos 	  default:
5944e98e3e1Schristos 	    abort ();
5954e98e3e1Schristos 	  }
5964e98e3e1Schristos 	trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp));
5974e98e3e1Schristos 	switch (size)
5984e98e3e1Schristos 	  {
5994e98e3e1Schristos 	  case 4:
6004e98e3e1Schristos 	    trace_printf (sd, cpu, " (0x%08lx)",
6014b169a6bSchristos 			  (long) *(uint32_t*)data);
6024e98e3e1Schristos 	    break;
6034e98e3e1Schristos 	  case 8:
6044e98e3e1Schristos 	    trace_printf (sd, cpu, " (0x%08lx%08lx)",
6054b169a6bSchristos 			  (long) (*(uint64_t*)data >> 32),
6064b169a6bSchristos 			  (long) (*(uint64_t*)data));
6074e98e3e1Schristos 	    break;
6084e98e3e1Schristos 	  default:
6094e98e3e1Schristos 	    abort ();
6104e98e3e1Schristos 	  }
6114e98e3e1Schristos 	break;
6124e98e3e1Schristos       }
6134e98e3e1Schristos     case trace_fmt_fpu:
6144e98e3e1Schristos       /* FIXME: At present sim_fpu data is stored as a double */
6154e98e3e1Schristos       trace_printf (sd, cpu, " %8g", * (double*) data);
6164e98e3e1Schristos       break;
6174e98e3e1Schristos     case trace_fmt_string:
6184e98e3e1Schristos       trace_printf (sd, cpu, " %-8s", (char*) data);
6194e98e3e1Schristos       break;
6204e98e3e1Schristos     default:
6214e98e3e1Schristos       abort ();
6224e98e3e1Schristos     }
6234e98e3e1Schristos }
6244e98e3e1Schristos 
6254e98e3e1Schristos static const char *
6264e98e3e1Schristos trace_idx_to_str (int trace_idx)
6274e98e3e1Schristos {
6284e98e3e1Schristos   static char num[8];
6294e98e3e1Schristos   switch (trace_idx)
6304e98e3e1Schristos     {
6314e98e3e1Schristos     case TRACE_ALU_IDX:      return "alu:     ";
6324e98e3e1Schristos     case TRACE_INSN_IDX:     return "insn:    ";
633ba340e45Schristos     case TRACE_DISASM_IDX:   return "disasm:  ";
6344e98e3e1Schristos     case TRACE_DECODE_IDX:   return "decode:  ";
6354e98e3e1Schristos     case TRACE_EXTRACT_IDX:  return "extract: ";
6364e98e3e1Schristos     case TRACE_MEMORY_IDX:   return "memory:  ";
6374e98e3e1Schristos     case TRACE_CORE_IDX:     return "core:    ";
6384e98e3e1Schristos     case TRACE_EVENTS_IDX:   return "events:  ";
6394e98e3e1Schristos     case TRACE_FPU_IDX:      return "fpu:     ";
6404e98e3e1Schristos     case TRACE_BRANCH_IDX:   return "branch:  ";
641a2e2270fSchristos     case TRACE_SYSCALL_IDX:  return "syscall: ";
642212397c6Schristos     case TRACE_REGISTER_IDX: return "reg:     ";
6434e98e3e1Schristos     case TRACE_VPU_IDX:      return "vpu:     ";
6444e98e3e1Schristos     default:
6454e98e3e1Schristos       sprintf (num, "?%d?", trace_idx);
6464e98e3e1Schristos       return num;
6474e98e3e1Schristos     }
6484e98e3e1Schristos }
6494e98e3e1Schristos 
6504e98e3e1Schristos static void
6514e98e3e1Schristos trace_results (SIM_DESC sd,
6524e98e3e1Schristos 	       sim_cpu *cpu,
6534e98e3e1Schristos 	       int trace_idx,
6544e98e3e1Schristos 	       int last_input)
6554e98e3e1Schristos {
6564e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
6574e98e3e1Schristos   int nr_out;
6584e98e3e1Schristos   int i;
6594e98e3e1Schristos 
6604e98e3e1Schristos   /* cross check trace_idx against TRACE_IDX (data)? */
6614e98e3e1Schristos 
6624e98e3e1Schristos   /* prefix */
6634e98e3e1Schristos   trace_printf (sd, cpu, "%s %s",
6644e98e3e1Schristos 		trace_idx_to_str (TRACE_IDX (data)),
6654e98e3e1Schristos 		TRACE_PREFIX (data));
6664e98e3e1Schristos   TRACE_IDX (data) = 0;
6674e98e3e1Schristos 
6684e98e3e1Schristos   for (i = 0, nr_out = 0;
6694e98e3e1Schristos        i < TRACE_INPUT_IDX (data);
6704e98e3e1Schristos        i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++)
6714e98e3e1Schristos     {
6724e98e3e1Schristos       if (i == last_input)
6734e98e3e1Schristos 	{
6744e98e3e1Schristos 	  int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2);
6754e98e3e1Schristos 	  int padding = pad * (3 - nr_out);
6764e98e3e1Schristos 	  if (padding < 0)
6774e98e3e1Schristos 	    padding = 0;
6784e98e3e1Schristos 	  padding += strlen (" ::");
6794e98e3e1Schristos 	  trace_printf (sd, cpu, "%*s", padding, " ::");
6804e98e3e1Schristos 	}
6814e98e3e1Schristos       print_data (sd, cpu,
6824e98e3e1Schristos 		  TRACE_INPUT_FMT (data) [i],
6834e98e3e1Schristos 		  TRACE_INPUT_SIZE (data) [i],
6844e98e3e1Schristos 		  &TRACE_INPUT_DATA (data) [i]);
6854e98e3e1Schristos     }
6864e98e3e1Schristos   trace_printf (sd, cpu, "\n");
6874e98e3e1Schristos }
6884e98e3e1Schristos 
689796c32c9Schristos int
690796c32c9Schristos trace_load_symbols (SIM_DESC sd)
691796c32c9Schristos {
692796c32c9Schristos   bfd *abfd;
693796c32c9Schristos   asymbol **asymbols;
694796c32c9Schristos   long symsize;
695796c32c9Schristos   long symbol_count;
696796c32c9Schristos 
697796c32c9Schristos   /* Already loaded, so nothing to do.  */
698796c32c9Schristos   if (STATE_PROG_SYMS (sd))
699796c32c9Schristos     return 1;
700796c32c9Schristos 
701796c32c9Schristos   abfd = STATE_PROG_BFD (sd);
702796c32c9Schristos   if (abfd == NULL)
703796c32c9Schristos     return 0;
704796c32c9Schristos 
705796c32c9Schristos   symsize = bfd_get_symtab_upper_bound (abfd);
706796c32c9Schristos   if (symsize < 0)
707796c32c9Schristos     return 0;
708796c32c9Schristos 
709796c32c9Schristos   asymbols = xmalloc (symsize);
710796c32c9Schristos   symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
711796c32c9Schristos   if (symbol_count < 0)
712796c32c9Schristos     {
713796c32c9Schristos       free (asymbols);
714796c32c9Schristos       return 0;
715796c32c9Schristos     }
716796c32c9Schristos 
717796c32c9Schristos   STATE_PROG_SYMS (sd) = asymbols;
718796c32c9Schristos   STATE_PROG_SYMS_COUNT (sd) = symbol_count;
719796c32c9Schristos   return 1;
720796c32c9Schristos }
721796c32c9Schristos 
722796c32c9Schristos bfd_vma
723796c32c9Schristos trace_sym_value (SIM_DESC sd, const char *name)
724796c32c9Schristos {
725796c32c9Schristos   asymbol **asymbols;
726796c32c9Schristos   long i;
727796c32c9Schristos 
728796c32c9Schristos   if (!trace_load_symbols (sd))
729796c32c9Schristos     return -1;
730796c32c9Schristos 
731796c32c9Schristos   asymbols = STATE_PROG_SYMS (sd);
732796c32c9Schristos 
733796c32c9Schristos   for (i = 0; i < STATE_PROG_SYMS_COUNT (sd); ++i)
734796c32c9Schristos     if (strcmp (asymbols[i]->name, name) == 0)
735796c32c9Schristos       return bfd_asymbol_value (asymbols[i]);
736796c32c9Schristos 
737796c32c9Schristos   return -1;
738796c32c9Schristos }
739796c32c9Schristos 
7404e98e3e1Schristos void
7414e98e3e1Schristos trace_prefix (SIM_DESC sd,
7424e98e3e1Schristos 	      sim_cpu *cpu,
7434e98e3e1Schristos 	      sim_cia cia,
7444e98e3e1Schristos 	      address_word pc,
7454e98e3e1Schristos 	      int line_p,
7464e98e3e1Schristos 	      const char *filename,
7474e98e3e1Schristos 	      int linenum,
7484e98e3e1Schristos 	      const char *fmt,
7494e98e3e1Schristos 	      ...)
7504e98e3e1Schristos {
7514e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
7524e98e3e1Schristos   va_list ap;
7534e98e3e1Schristos   char *prefix = TRACE_PREFIX (data);
7544e98e3e1Schristos   char *chp;
7554e98e3e1Schristos  /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using
7564e98e3e1Schristos     known information about the disassembled instructions. */
7574e98e3e1Schristos #ifndef TRACE_PREFIX_WIDTH
7584e98e3e1Schristos #define TRACE_PREFIX_WIDTH 48
7594e98e3e1Schristos #endif
7604e98e3e1Schristos   int width = TRACE_PREFIX_WIDTH;
7614e98e3e1Schristos 
7624e98e3e1Schristos   /* if the previous trace data wasn't flushed, flush it now with a
7634e98e3e1Schristos      note indicating that the trace was incomplete. */
7644e98e3e1Schristos   if (TRACE_IDX (data) != 0)
7654e98e3e1Schristos     {
7664e98e3e1Schristos       int last_input = TRACE_INPUT_IDX (data);
7674e98e3e1Schristos       save_data (sd, data, trace_fmt_instruction_incomplete, 1, "");
7684e98e3e1Schristos       trace_results (sd, cpu, TRACE_IDX (data), last_input);
7694e98e3e1Schristos     }
7704e98e3e1Schristos   TRACE_IDX (data) = 0;
7714e98e3e1Schristos   TRACE_INPUT_IDX (data) = 0;
7724e98e3e1Schristos 
7734e98e3e1Schristos   /* Create the text prefix for this new instruction: */
7744e98e3e1Schristos   if (!line_p)
7754e98e3e1Schristos     {
7764e98e3e1Schristos       if (filename)
7774e98e3e1Schristos 	{
7784e98e3e1Schristos 	  sprintf (prefix, "%s:%-*d 0x%.*lx ",
7794e98e3e1Schristos 		   filename,
7804e98e3e1Schristos 		   SIZE_LINE_NUMBER, linenum,
7814e98e3e1Schristos 		   SIZE_PC, (long) pc);
7824e98e3e1Schristos 	}
7834e98e3e1Schristos       else
7844e98e3e1Schristos 	{
7854e98e3e1Schristos 	  sprintf (prefix, "0x%.*lx ",
7864e98e3e1Schristos 		   SIZE_PC, (long) pc);
7874e98e3e1Schristos 	  /* Shrink the width by the amount that we didn't print.  */
7884e98e3e1Schristos 	  width -= SIZE_LINE_NUMBER + SIZE_PC + 8;
7894e98e3e1Schristos 	}
7904e98e3e1Schristos       chp = strchr (prefix, '\0');
7914e98e3e1Schristos       va_start (ap, fmt);
7924e98e3e1Schristos       vsprintf (chp, fmt, ap);
7934e98e3e1Schristos       va_end (ap);
7944e98e3e1Schristos     }
7954e98e3e1Schristos   else
7964e98e3e1Schristos     {
7974e98e3e1Schristos       char buf[256];
7984e98e3e1Schristos       buf[0] = 0;
799796c32c9Schristos       if (STATE_TEXT_SECTION (sd)
800796c32c9Schristos 	  && pc >= STATE_TEXT_START (sd)
801796c32c9Schristos 	  && pc < STATE_TEXT_END (sd))
8024e98e3e1Schristos 	{
8034e98e3e1Schristos 	  const char *pc_filename = (const char *)0;
8044e98e3e1Schristos 	  const char *pc_function = (const char *)0;
8054e98e3e1Schristos 	  unsigned int pc_linenum = 0;
8064e98e3e1Schristos 	  bfd *abfd;
8074e98e3e1Schristos 	  asymbol **asymbols;
8084e98e3e1Schristos 
809796c32c9Schristos 	  if (!trace_load_symbols (sd))
810796c32c9Schristos 	    sim_engine_abort (sd, cpu, cia, "could not load symbols");
8114e98e3e1Schristos 
812796c32c9Schristos 	  abfd = STATE_PROG_BFD (sd);
813796c32c9Schristos 	  asymbols = STATE_PROG_SYMS (sd);
8144e98e3e1Schristos 
815796c32c9Schristos 	  if (bfd_find_nearest_line (abfd, STATE_TEXT_SECTION (sd), asymbols,
816796c32c9Schristos 				     pc - STATE_TEXT_START (sd),
8174e98e3e1Schristos 				     &pc_filename, &pc_function, &pc_linenum))
8184e98e3e1Schristos 	    {
8194e98e3e1Schristos 	      char *p = buf;
8204e98e3e1Schristos 	      if (pc_linenum)
8214e98e3e1Schristos 		{
8224e98e3e1Schristos 		  sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
8234e98e3e1Schristos 		  p += strlen (p);
8244e98e3e1Schristos 		}
8254e98e3e1Schristos 	      else
8264e98e3e1Schristos 		{
8274e98e3e1Schristos 		  sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
8284e98e3e1Schristos 		  p += SIZE_LINE_NUMBER+2;
8294e98e3e1Schristos 		}
8304e98e3e1Schristos 
8314e98e3e1Schristos 	      if (pc_function)
8324e98e3e1Schristos 		{
8334e98e3e1Schristos 		  sprintf (p, "%s ", pc_function);
8344e98e3e1Schristos 		  p += strlen (p);
8354e98e3e1Schristos 		}
8364e98e3e1Schristos 	      else if (pc_filename)
8374e98e3e1Schristos 		{
8384e98e3e1Schristos 		  char *q = (char *) strrchr (pc_filename, '/');
8394e98e3e1Schristos 		  sprintf (p, "%s ", (q) ? q+1 : pc_filename);
8404e98e3e1Schristos 		  p += strlen (p);
8414e98e3e1Schristos 		}
8424e98e3e1Schristos 
8434e98e3e1Schristos 	      if (*p == ' ')
8444e98e3e1Schristos 		*p = '\0';
8454e98e3e1Schristos 	    }
8464e98e3e1Schristos 	}
8474e98e3e1Schristos 
8484e98e3e1Schristos       sprintf (prefix, "0x%.*x %-*.*s ",
8494e98e3e1Schristos 	       SIZE_PC, (unsigned) pc,
8504e98e3e1Schristos 	       SIZE_LOCATION, SIZE_LOCATION, buf);
8514e98e3e1Schristos       chp = strchr (prefix, '\0');
8524e98e3e1Schristos       va_start (ap, fmt);
8534e98e3e1Schristos       vsprintf (chp, fmt, ap);
8544e98e3e1Schristos       va_end (ap);
8554e98e3e1Schristos     }
8564e98e3e1Schristos 
8574e98e3e1Schristos   /* Pad it out to TRACE_PREFIX_WIDTH.  */
8584e98e3e1Schristos   chp = strchr (prefix, '\0');
8594e98e3e1Schristos   if (chp - prefix < width)
8604e98e3e1Schristos     {
8614e98e3e1Schristos       memset (chp, ' ', width - (chp - prefix));
8624e98e3e1Schristos       chp = &prefix [width];
8634e98e3e1Schristos       *chp = '\0';
8644e98e3e1Schristos     }
8654e98e3e1Schristos   strcpy (chp, " -");
8664e98e3e1Schristos 
8674e98e3e1Schristos   /* check that we've not over flowed the prefix buffer */
8684e98e3e1Schristos   if (strlen (prefix) >= sizeof (TRACE_PREFIX (data)))
8694e98e3e1Schristos     abort ();
8704e98e3e1Schristos }
8714e98e3e1Schristos 
8724e98e3e1Schristos void
8734e98e3e1Schristos trace_generic (SIM_DESC sd,
8744e98e3e1Schristos 	       sim_cpu *cpu,
8754e98e3e1Schristos 	       int trace_idx,
8764e98e3e1Schristos 	       const char *fmt,
8774e98e3e1Schristos 	       ...)
8784e98e3e1Schristos {
8794e98e3e1Schristos   va_list ap;
8804e98e3e1Schristos   trace_printf (sd, cpu, "%s %s",
8814e98e3e1Schristos 		trace_idx_to_str (trace_idx),
8824e98e3e1Schristos 		TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
8834e98e3e1Schristos   va_start (ap, fmt);
8844e98e3e1Schristos   trace_vprintf (sd, cpu, fmt, ap);
8854e98e3e1Schristos   va_end (ap);
8864e98e3e1Schristos   trace_printf (sd, cpu, "\n");
8874e98e3e1Schristos }
8884e98e3e1Schristos 
889ba340e45Schristos static int
890ba340e45Schristos dis_read (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
891ba340e45Schristos 	  struct disassemble_info *dinfo)
892ba340e45Schristos {
893ba340e45Schristos   SIM_CPU *cpu = dinfo->application_data;
894ba340e45Schristos   sim_core_read_buffer (CPU_STATE (cpu), cpu, NULL_CIA, myaddr, memaddr, length);
895ba340e45Schristos   return 0;
896ba340e45Schristos }
897ba340e45Schristos 
8984b169a6bSchristos static int ATTRIBUTE_PRINTF (2, 3)
899ba340e45Schristos dis_printf (SIM_CPU *cpu, const char *fmt, ...)
900ba340e45Schristos {
901ba340e45Schristos   SIM_DESC sd = CPU_STATE (cpu);
902ba340e45Schristos   va_list ap;
903ba340e45Schristos   va_start (ap, fmt);
904ba340e45Schristos   trace_vprintf (sd, cpu, fmt, ap);
905ba340e45Schristos   va_end (ap);
906ba340e45Schristos   return 0;
907ba340e45Schristos }
908ba340e45Schristos 
9094b169a6bSchristos static int ATTRIBUTE_PRINTF (3, 4)
9104b169a6bSchristos dis_styled_printf (SIM_CPU *cpu, enum disassembler_style style,
9114b169a6bSchristos 		   const char *fmt, ...)
9124b169a6bSchristos {
9134b169a6bSchristos   SIM_DESC sd = CPU_STATE (cpu);
9144b169a6bSchristos   va_list ap;
9154b169a6bSchristos   va_start (ap, fmt);
9164b169a6bSchristos   trace_vprintf (sd, cpu, fmt, ap);
9174b169a6bSchristos   va_end (ap);
9184b169a6bSchristos   return 0;
9194b169a6bSchristos }
9204b169a6bSchristos 
921ba340e45Schristos void
922ba340e45Schristos trace_disasm (SIM_DESC sd, sim_cpu *cpu, address_word addr)
923ba340e45Schristos {
924ba340e45Schristos   struct bfd *bfd = STATE_PROG_BFD (sd);
925ba340e45Schristos   TRACE_DATA *trace_data = CPU_TRACE_DATA (cpu);
926ba340e45Schristos   disassemble_info *info = &trace_data->dis_info;
927ba340e45Schristos 
928ba340e45Schristos   /* See if we need to set up the disassembly func.  */
929ba340e45Schristos   if (trace_data->dis_bfd != bfd)
930ba340e45Schristos     {
931ba340e45Schristos       trace_data->dis_bfd = bfd;
9324559860eSchristos       trace_data->disassembler
9334559860eSchristos 	= disassembler (bfd_get_arch (trace_data->dis_bfd),
9344559860eSchristos 			bfd_big_endian (trace_data->dis_bfd),
9354559860eSchristos 			bfd_get_mach (trace_data->dis_bfd),
9364559860eSchristos 			trace_data->dis_bfd);
9374b169a6bSchristos       INIT_DISASSEMBLE_INFO (*info, cpu, dis_printf, dis_styled_printf);
938ba340e45Schristos       info->read_memory_func = dis_read;
939ba340e45Schristos       info->arch = bfd_get_arch (bfd);
940ba340e45Schristos       info->mach = bfd_get_mach (bfd);
941ba340e45Schristos       disassemble_init_for_target (info);
942ba340e45Schristos     }
943ba340e45Schristos 
944ba340e45Schristos   info->application_data = cpu;
945ba340e45Schristos 
946ba340e45Schristos   trace_printf (sd, cpu, "%s %s",
947ba340e45Schristos 		trace_idx_to_str (TRACE_DISASM_IDX),
948ba340e45Schristos 		TRACE_PREFIX (trace_data));
949ba340e45Schristos   trace_data->disassembler (addr, info);
950ba340e45Schristos   trace_printf (sd, cpu, "\n");
951ba340e45Schristos }
952ba340e45Schristos 
9534e98e3e1Schristos void
9544e98e3e1Schristos trace_input0 (SIM_DESC sd,
9554e98e3e1Schristos 	      sim_cpu *cpu,
9564e98e3e1Schristos 	      int trace_idx)
9574e98e3e1Schristos {
9584e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
9594e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
9604e98e3e1Schristos }
9614e98e3e1Schristos 
9624e98e3e1Schristos void
9634e98e3e1Schristos trace_input_word1 (SIM_DESC sd,
9644e98e3e1Schristos 		   sim_cpu *cpu,
9654e98e3e1Schristos 		   int trace_idx,
9664e98e3e1Schristos 		   unsigned_word d0)
9674e98e3e1Schristos {
9684e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
9694e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
9704e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
9714e98e3e1Schristos }
9724e98e3e1Schristos 
9734e98e3e1Schristos void
9744e98e3e1Schristos trace_input_word2 (SIM_DESC sd,
9754e98e3e1Schristos 		   sim_cpu *cpu,
9764e98e3e1Schristos 		   int trace_idx,
9774e98e3e1Schristos 		   unsigned_word d0,
9784e98e3e1Schristos 		   unsigned_word d1)
9794e98e3e1Schristos {
9804e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
9814e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
9824e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
9834e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
9844e98e3e1Schristos }
9854e98e3e1Schristos 
9864e98e3e1Schristos void
9874e98e3e1Schristos trace_input_word3 (SIM_DESC sd,
9884e98e3e1Schristos 		   sim_cpu *cpu,
9894e98e3e1Schristos 		   int trace_idx,
9904e98e3e1Schristos 		   unsigned_word d0,
9914e98e3e1Schristos 		   unsigned_word d1,
9924e98e3e1Schristos 		   unsigned_word d2)
9934e98e3e1Schristos {
9944e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
9954e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
9964e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
9974e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
9984e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);
9994e98e3e1Schristos }
10004e98e3e1Schristos 
10014e98e3e1Schristos void
10024e98e3e1Schristos trace_input_word4 (SIM_DESC sd,
10034e98e3e1Schristos 		   sim_cpu *cpu,
10044e98e3e1Schristos 		   int trace_idx,
10054e98e3e1Schristos 		   unsigned_word d0,
10064e98e3e1Schristos 		   unsigned_word d1,
10074e98e3e1Schristos 		   unsigned_word d2,
10084e98e3e1Schristos 		   unsigned_word d3)
10094e98e3e1Schristos {
10104e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
10114e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
10124e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (d0), &d0);
10134e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (d1), &d1);
10144e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (d2), &d2);
10154e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (d3), &d3);
10164e98e3e1Schristos }
10174e98e3e1Schristos 
10184e98e3e1Schristos void
10194e98e3e1Schristos trace_input_bool1 (SIM_DESC sd,
10204e98e3e1Schristos 		   sim_cpu *cpu,
10214e98e3e1Schristos 		   int trace_idx,
10224e98e3e1Schristos 		   int d0)
10234e98e3e1Schristos {
10244e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
10254e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
10264e98e3e1Schristos   save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0);
10274e98e3e1Schristos }
10284e98e3e1Schristos 
10294e98e3e1Schristos void
10304e98e3e1Schristos trace_input_addr1 (SIM_DESC sd,
10314e98e3e1Schristos 		   sim_cpu *cpu,
10324e98e3e1Schristos 		   int trace_idx,
10334e98e3e1Schristos 		   address_word d0)
10344e98e3e1Schristos {
10354e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
10364e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
10374e98e3e1Schristos   save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0);
10384e98e3e1Schristos }
10394e98e3e1Schristos 
10404e98e3e1Schristos void
10414e98e3e1Schristos trace_input_fp1 (SIM_DESC sd,
10424e98e3e1Schristos 		 sim_cpu *cpu,
10434e98e3e1Schristos 		 int trace_idx,
10444e98e3e1Schristos 		 fp_word f0)
10454e98e3e1Schristos {
10464e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
10474e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
10484e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
10494e98e3e1Schristos }
10504e98e3e1Schristos 
10514e98e3e1Schristos void
10524e98e3e1Schristos trace_input_fp2 (SIM_DESC sd,
10534e98e3e1Schristos 		 sim_cpu *cpu,
10544e98e3e1Schristos 		 int trace_idx,
10554e98e3e1Schristos 		 fp_word f0,
10564e98e3e1Schristos 		 fp_word f1)
10574e98e3e1Schristos {
10584e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
10594e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
10604e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
10614e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
10624e98e3e1Schristos }
10634e98e3e1Schristos 
10644e98e3e1Schristos void
10654e98e3e1Schristos trace_input_fp3 (SIM_DESC sd,
10664e98e3e1Schristos 		 sim_cpu *cpu,
10674e98e3e1Schristos 		 int trace_idx,
10684e98e3e1Schristos 		 fp_word f0,
10694e98e3e1Schristos 		 fp_word f1,
10704e98e3e1Schristos 		 fp_word f2)
10714e98e3e1Schristos {
10724e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
10734e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
10744e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
10754e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
10764e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2);
10774e98e3e1Schristos }
10784e98e3e1Schristos 
10794e98e3e1Schristos void
10804e98e3e1Schristos trace_input_fpu1 (SIM_DESC sd,
10814e98e3e1Schristos 		  sim_cpu *cpu,
10824e98e3e1Schristos 		  int trace_idx,
10834e98e3e1Schristos 		  sim_fpu *f0)
10844e98e3e1Schristos {
10854e98e3e1Schristos   double d;
10864e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
10874e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
10884e98e3e1Schristos   d = sim_fpu_2d (f0);
10894e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
10904e98e3e1Schristos }
10914e98e3e1Schristos 
10924e98e3e1Schristos void
10934e98e3e1Schristos trace_input_fpu2 (SIM_DESC sd,
10944e98e3e1Schristos 		  sim_cpu *cpu,
10954e98e3e1Schristos 		  int trace_idx,
10964e98e3e1Schristos 		  sim_fpu *f0,
10974e98e3e1Schristos 		  sim_fpu *f1)
10984e98e3e1Schristos {
10994e98e3e1Schristos   double d;
11004e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
11014e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
11024e98e3e1Schristos   d = sim_fpu_2d (f0);
11034e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
11044e98e3e1Schristos   d = sim_fpu_2d (f1);
11054e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
11064e98e3e1Schristos }
11074e98e3e1Schristos 
11084e98e3e1Schristos void
11094e98e3e1Schristos trace_input_fpu3 (SIM_DESC sd,
11104e98e3e1Schristos 		  sim_cpu *cpu,
11114e98e3e1Schristos 		  int trace_idx,
11124e98e3e1Schristos 		  sim_fpu *f0,
11134e98e3e1Schristos 		  sim_fpu *f1,
11144e98e3e1Schristos 		  sim_fpu *f2)
11154e98e3e1Schristos {
11164e98e3e1Schristos   double d;
11174e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
11184e98e3e1Schristos   TRACE_IDX (data) = trace_idx;
11194e98e3e1Schristos   d = sim_fpu_2d (f0);
11204e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
11214e98e3e1Schristos   d = sim_fpu_2d (f1);
11224e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
11234e98e3e1Schristos   d = sim_fpu_2d (f2);
11244e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
11254e98e3e1Schristos }
11264e98e3e1Schristos 
11274e98e3e1Schristos void
11284e98e3e1Schristos trace_result_word1 (SIM_DESC sd,
11294e98e3e1Schristos 		    sim_cpu *cpu,
11304e98e3e1Schristos 		    int trace_idx,
11314e98e3e1Schristos 		    unsigned_word r0)
11324e98e3e1Schristos {
11334e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
11344e98e3e1Schristos   int last_input;
11354e98e3e1Schristos 
11364e98e3e1Schristos   /* Append any results to the end of the inputs */
11374e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
11384e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
11394e98e3e1Schristos 
11404e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
11414e98e3e1Schristos }
11424e98e3e1Schristos 
11434e98e3e1Schristos void
11444e98e3e1Schristos trace_result0 (SIM_DESC sd,
11454e98e3e1Schristos 	       sim_cpu *cpu,
11464e98e3e1Schristos 	       int trace_idx)
11474e98e3e1Schristos {
11484e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
11494e98e3e1Schristos   int last_input;
11504e98e3e1Schristos 
11514e98e3e1Schristos   /* Append any results to the end of the inputs */
11524e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
11534e98e3e1Schristos 
11544e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
11554e98e3e1Schristos }
11564e98e3e1Schristos 
11574e98e3e1Schristos void
11584e98e3e1Schristos trace_result_word2 (SIM_DESC sd,
11594e98e3e1Schristos 		    sim_cpu *cpu,
11604e98e3e1Schristos 		    int trace_idx,
11614e98e3e1Schristos 		    unsigned_word r0,
11624e98e3e1Schristos 		    unsigned_word r1)
11634e98e3e1Schristos {
11644e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
11654e98e3e1Schristos   int last_input;
11664e98e3e1Schristos 
11674e98e3e1Schristos   /* Append any results to the end of the inputs */
11684e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
11694e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
11704e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
11714e98e3e1Schristos 
11724e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
11734e98e3e1Schristos }
11744e98e3e1Schristos 
11754e98e3e1Schristos void
11764e98e3e1Schristos trace_result_word4 (SIM_DESC sd,
11774e98e3e1Schristos 		    sim_cpu *cpu,
11784e98e3e1Schristos 		    int trace_idx,
11794e98e3e1Schristos 		    unsigned_word r0,
11804e98e3e1Schristos 		    unsigned_word r1,
11814e98e3e1Schristos 		    unsigned_word r2,
11824e98e3e1Schristos 		    unsigned_word r3)
11834e98e3e1Schristos {
11844e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
11854e98e3e1Schristos   int last_input;
11864e98e3e1Schristos 
11874e98e3e1Schristos   /* Append any results to the end of the inputs */
11884e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
11894e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
11904e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
11914e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (r2), &r2);
11924e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (r3), &r3);
11934e98e3e1Schristos 
11944e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
11954e98e3e1Schristos }
11964e98e3e1Schristos 
11974e98e3e1Schristos void
11984e98e3e1Schristos trace_result_bool1 (SIM_DESC sd,
11994e98e3e1Schristos 		    sim_cpu *cpu,
12004e98e3e1Schristos 		    int trace_idx,
12014e98e3e1Schristos 		    int r0)
12024e98e3e1Schristos {
12034e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
12044e98e3e1Schristos   int last_input;
12054e98e3e1Schristos 
12064e98e3e1Schristos   /* Append any results to the end of the inputs */
12074e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
12084e98e3e1Schristos   save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0);
12094e98e3e1Schristos 
12104e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
12114e98e3e1Schristos }
12124e98e3e1Schristos 
12134e98e3e1Schristos void
12144e98e3e1Schristos trace_result_addr1 (SIM_DESC sd,
12154e98e3e1Schristos 		    sim_cpu *cpu,
12164e98e3e1Schristos 		    int trace_idx,
12174e98e3e1Schristos 		    address_word r0)
12184e98e3e1Schristos {
12194e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
12204e98e3e1Schristos   int last_input;
12214e98e3e1Schristos 
12224e98e3e1Schristos   /* Append any results to the end of the inputs */
12234e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
12244e98e3e1Schristos   save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0);
12254e98e3e1Schristos 
12264e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
12274e98e3e1Schristos }
12284e98e3e1Schristos 
12294e98e3e1Schristos void
12304e98e3e1Schristos trace_result_fp1 (SIM_DESC sd,
12314e98e3e1Schristos 		  sim_cpu *cpu,
12324e98e3e1Schristos 		  int trace_idx,
12334e98e3e1Schristos 		  fp_word f0)
12344e98e3e1Schristos {
12354e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
12364e98e3e1Schristos   int last_input;
12374e98e3e1Schristos 
12384e98e3e1Schristos   /* Append any results to the end of the inputs */
12394e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
12404e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
12414e98e3e1Schristos 
12424e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
12434e98e3e1Schristos }
12444e98e3e1Schristos 
12454e98e3e1Schristos void
12464e98e3e1Schristos trace_result_fp2 (SIM_DESC sd,
12474e98e3e1Schristos 		  sim_cpu *cpu,
12484e98e3e1Schristos 		  int trace_idx,
12494e98e3e1Schristos 		  fp_word f0,
12504e98e3e1Schristos 		  fp_word f1)
12514e98e3e1Schristos {
12524e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
12534e98e3e1Schristos   int last_input;
12544e98e3e1Schristos 
12554e98e3e1Schristos   /* Append any results to the end of the inputs */
12564e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
12574e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (f0), &f0);
12584e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1);
12594e98e3e1Schristos 
12604e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
12614e98e3e1Schristos }
12624e98e3e1Schristos 
12634e98e3e1Schristos void
12644e98e3e1Schristos trace_result_fpu1 (SIM_DESC sd,
12654e98e3e1Schristos 		   sim_cpu *cpu,
12664e98e3e1Schristos 		   int trace_idx,
12674e98e3e1Schristos 		   sim_fpu *f0)
12684e98e3e1Schristos {
12694e98e3e1Schristos   double d;
12704e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
12714e98e3e1Schristos   int last_input;
12724e98e3e1Schristos 
12734e98e3e1Schristos   /* Append any results to the end of the inputs */
12744e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
12754e98e3e1Schristos   d = sim_fpu_2d (f0);
12764e98e3e1Schristos   save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
12774e98e3e1Schristos 
12784e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
12794e98e3e1Schristos }
12804e98e3e1Schristos 
12814e98e3e1Schristos void
12824e98e3e1Schristos trace_result_string1 (SIM_DESC sd,
12834e98e3e1Schristos 		      sim_cpu *cpu,
12844e98e3e1Schristos 		      int trace_idx,
12854e98e3e1Schristos 		      char *s0)
12864e98e3e1Schristos {
12874e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
12884e98e3e1Schristos   int last_input;
12894e98e3e1Schristos 
12904e98e3e1Schristos   /* Append any results to the end of the inputs */
12914e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
12924e98e3e1Schristos   save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
12934e98e3e1Schristos 
12944e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
12954e98e3e1Schristos }
12964e98e3e1Schristos 
12974e98e3e1Schristos void
12984e98e3e1Schristos trace_result_word1_string1 (SIM_DESC sd,
12994e98e3e1Schristos 			    sim_cpu *cpu,
13004e98e3e1Schristos 			    int trace_idx,
13014e98e3e1Schristos 			    unsigned_word r0,
13024e98e3e1Schristos 			    char *s0)
13034e98e3e1Schristos {
13044e98e3e1Schristos   TRACE_DATA *data = CPU_TRACE_DATA (cpu);
13054e98e3e1Schristos   int last_input;
13064e98e3e1Schristos 
13074e98e3e1Schristos   /* Append any results to the end of the inputs */
13084e98e3e1Schristos   last_input = TRACE_INPUT_IDX (data);
13094e98e3e1Schristos   save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
13104e98e3e1Schristos   save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
13114e98e3e1Schristos 
13124e98e3e1Schristos   trace_results (sd, cpu, trace_idx, last_input);
13134e98e3e1Schristos }
13144e98e3e1Schristos 
13154e98e3e1Schristos void
13164e98e3e1Schristos trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
13174e98e3e1Schristos {
13184e98e3e1Schristos   if (cpu != NULL)
13194e98e3e1Schristos     {
13204e98e3e1Schristos       if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
13214e98e3e1Schristos 	vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
13224e98e3e1Schristos       else
13234e98e3e1Schristos 	sim_io_evprintf (sd, fmt, ap);
13244e98e3e1Schristos     }
13254e98e3e1Schristos   else
13264e98e3e1Schristos     {
13274e98e3e1Schristos       if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
13284e98e3e1Schristos 	vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
13294e98e3e1Schristos       else
13304e98e3e1Schristos 	sim_io_evprintf (sd, fmt, ap);
13314e98e3e1Schristos     }
13324e98e3e1Schristos }
13334e98e3e1Schristos 
13344e98e3e1Schristos void
133503467a24Schristos trace_printf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...)
13364e98e3e1Schristos {
13374e98e3e1Schristos   va_list ap;
13384e98e3e1Schristos 
133903467a24Schristos   va_start (ap, fmt);
13404e98e3e1Schristos 
13414e98e3e1Schristos   trace_vprintf (sd, cpu, fmt, ap);
13424e98e3e1Schristos 
13434e98e3e1Schristos   va_end (ap);
13444e98e3e1Schristos }
13454e98e3e1Schristos 
13464e98e3e1Schristos void
1347212397c6Schristos sim_debug_printf (sim_cpu *cpu, const char *fmt, ...)
13484e98e3e1Schristos {
13494e98e3e1Schristos   va_list ap;
13504e98e3e1Schristos 
135103467a24Schristos   va_start (ap, fmt);
13524e98e3e1Schristos 
13534e98e3e1Schristos   if (CPU_DEBUG_FILE (cpu) == NULL)
13544e98e3e1Schristos     (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
13554e98e3e1Schristos       (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
13564e98e3e1Schristos   else
13574e98e3e1Schristos     vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
13584e98e3e1Schristos 
13594e98e3e1Schristos   va_end (ap);
13604e98e3e1Schristos }
1361