Extend sim-trace.[hc] to include a generic set of macro's for tracing
authorAndrew Cagney <cagney@redhat.com>
Wed, 18 Feb 1998 04:11:09 +0000 (04:11 +0000)
committerAndrew Cagney <cagney@redhat.com>
Wed, 18 Feb 1998 04:11:09 +0000 (04:11 +0000)
ALU/... inputs/outputs.
Base implementation on original v850 code.
Update igen to generate code interfacing with newer sim-trace.[hc].

sim/common/ChangeLog
sim/common/sim-trace.c
sim/common/sim-trace.h

index ffc0798..097e48a 100644 (file)
@@ -1,3 +1,22 @@
+Wed Feb 18 12:42:15 1998  Andrew Cagney  <cagney@b1.cygnus.com>
+
+       * sim-basics.h: Declare struct _sim_fpu.
+
+Tue Feb 17 16:27:46 1998  Andrew Cagney  <cagney@b1.cygnus.com>
+
+       * sim-trace.h (TRACE_ALU_INPUT*, TRACE_ALU_RESULT): Define.
+       (trace_prefix, trace_input*, trace_result*): Declare.
+       (trace_one_insn): Change declaration, assume trace_prefix called.
+       (trace_generic): Like trace_one_insn.
+       (TRACE_ALU_IDX, TRACE_*_IDX): Change #define's to enum.
+       (TRACE_alu, TRACE_[a-z]*): Update.
+       
+       * sim-trace.c (trace_prefix, trace_input*, trace_result*,
+       trace_insn, save_data, trace_idx_to_str, print_data): New
+       functions.
+       (trace_one_insn): Rewrite.
+       (trace_generic): New function.
+       
 Tue Feb 17 17:27:30 1998  Doug Evans  <devans@seba.cygnus.com>
 
        * Make-common.in (CGEN_MAIN_SCM): Update.
index 5f3dd13..d53afda 100644 (file)
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "sim-main.h"
 #include "sim-io.h"
 #include "sim-options.h"
+#include "sim-fpu.h"
 #include "bfd.h"
 
 #include "sim-assert.h"
@@ -72,45 +73,46 @@ enum {
 
 static const OPTION trace_options[] =
 {
+  /* This table is organized to group related instructions together.  */
   { {"trace", optional_argument, NULL, 't'},
-      't', "on|off", "Perform tracing",
+      't', "on|off", "Trace everything",
       trace_option_handler },
   { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN},
       '\0', "on|off", "Perform instruction tracing",
       trace_option_handler },
   { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE},
-      '\0', "on|off", "Perform instruction decoding tracing",
+      '\0', "on|off", "Trace instruction decoding",
       trace_option_handler },
   { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT},
-      '\0', "on|off", "Perform instruction extraction tracing",
+      '\0', "on|off", "Trace instruction extraction",
       trace_option_handler },
   { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM},
       '\0', "on|off", "Perform line number tracing (implies --trace-insn)",
       trace_option_handler },
   { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY},
-      '\0', "on|off", "Perform memory tracing",
-      trace_option_handler },
-  { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL},
-      '\0', "on|off", "Perform model tracing",
+      '\0', "on|off", "Trace memory operations",
       trace_option_handler },
   { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU},
-      '\0', "on|off", "Perform ALU tracing",
-      trace_option_handler },
-  { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE},
-      '\0', "on|off", "Perform CORE tracing",
-      trace_option_handler },
-  { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS},
-      '\0', "on|off", "Perform EVENTS tracing",
+      '\0', "on|off", "Trace ALU operations",
       trace_option_handler },
   { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU},
-      '\0', "on|off", "Perform FPU tracing",
+      '\0', "on|off", "Trace FPU operations",
       trace_option_handler },
   { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH},
-      '\0', "on|off", "Perform branch tracing",
+      '\0', "on|off", "Trace branching",
       trace_option_handler },
   { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS},
       '\0', "on|off", "Perform ALU, FPU, MEMORY, and BRANCH tracing",
       trace_option_handler },
+  { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL},
+      '\0', "on|off", "Include model performance data",
+      trace_option_handler },
+  { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE},
+      '\0', "on|off", "Trace core operations",
+      trace_option_handler },
+  { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS},
+      '\0', "on|off", "Trace events",
+      trace_option_handler },
   { {"trace-debug", optional_argument, NULL, OPTION_TRACE_DEBUG},
       '\0', "on|off", "Add information useful for debugging the simulator to the tracing output",
       trace_option_handler },
@@ -366,6 +368,518 @@ trace_uninstall (SIM_DESC sd)
     }
 }
 \f
+typedef enum {
+  trace_fmt_invalid,
+  trace_fmt_word,
+  trace_fmt_fp,
+  trace_fmt_fpu,
+  trace_fmt_string,
+  trace_fmt_instruction_incomplete,
+} data_fmt;
+
+/* compute the nr of trace data units consumed by data */
+static int
+save_data_size (TRACE_DATA *data,
+               long size)
+{
+  return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1)
+         / sizeof (TRACE_INPUT_DATA (data) [0]));
+}
+
+
+/* Archive DATA into the trace buffer */
+static void
+save_data (SIM_DESC sd,
+          TRACE_DATA *data,
+          data_fmt fmt,
+          long size,
+          void *buf)
+{
+  int i = TRACE_INPUT_IDX (data);
+  if (i == sizeof (TRACE_INPUT_FMT (data)))
+    sim_io_error (sd, "trace buffer overflow");
+  TRACE_INPUT_FMT (data) [i] = fmt;
+  TRACE_INPUT_SIZE (data) [i] = size;
+  memcpy (&TRACE_INPUT_DATA (data) [i], buf, size);
+  i += save_data_size (data, size);
+  TRACE_INPUT_IDX (data) = i;
+}
+
+static void
+print_data (SIM_DESC sd,
+           sim_cpu *cpu,
+           data_fmt fmt,
+           long size,
+           void *data)
+{
+  switch (fmt)
+    {
+    case trace_fmt_instruction_incomplete:
+      trace_printf (sd, cpu, " (instruction incomplete)");
+      break;
+    case trace_fmt_word:
+      switch (size)
+       {
+       case sizeof (unsigned_word):
+         trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned_word*) data);
+         break;
+       default:
+         abort ();
+       }
+      break;
+    case trace_fmt_fp:
+      switch (size)
+       {
+         /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */
+       case 4:
+         trace_printf (sd, cpu, " %8g", * (float*) data);
+         break;
+       case 8:
+         trace_printf (sd, cpu, " %8g", * (double*) data);
+         break;
+       default:
+         abort ();
+       }
+    case trace_fmt_fpu:
+      /* FIXME: At present sim_fpu data is stored as a double */
+      trace_printf (sd, cpu, " %8g", * (double*) data);
+      break;
+    case trace_fmt_string:
+      trace_printf (sd, cpu, " %-8s", (char*) data);
+      break;
+    default:
+      abort ();
+    }
+}
+                 
+static const char *
+trace_idx_to_str (int trace_idx)
+{
+  static char num[8];
+  switch (trace_idx)
+    {
+    case TRACE_ALU_IDX:     return "alu:     ";
+    case TRACE_INSN_IDX:    return "insn:    ";
+    case TRACE_DECODE_IDX:  return "decode:  ";
+    case TRACE_EXTRACT_IDX: return "extract: ";
+    case TRACE_MEMORY_IDX:  return "memory:  ";
+    case TRACE_CORE_IDX:    return "core:    ";
+    case TRACE_EVENTS_IDX:  return "events:  ";
+    case TRACE_FPU_IDX:     return "fpu:     ";
+    case TRACE_BRANCH_IDX:  return "branch:  ";
+    default:
+      sprintf (num, "?%d?", trace_idx);
+      return num;
+    }
+}
+
+static void
+trace_results (SIM_DESC sd,
+              sim_cpu *cpu,
+              int trace_idx,
+              int last_input)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  int nr_out;
+  int i;
+
+  /* cross check trace_idx against TRACE_IDX (data)? */
+
+  /* prefix */
+  trace_printf (sd, cpu, "%s %s",
+               trace_idx_to_str (TRACE_IDX (data)),
+               TRACE_PREFIX (data));
+  TRACE_IDX (data) = 0;
+
+  for (i = 0, nr_out = 0;
+       i < TRACE_INPUT_IDX (data);
+       i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++)
+    {
+      if (i == last_input)
+       {
+         int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2);
+         int padding = pad * (3 - nr_out);
+         if (padding < 0)
+           padding = 0;
+         padding += strlen (" ::");
+         trace_printf (sd, cpu, "%*s", padding, " ::");
+       }
+      print_data (sd, cpu,
+                 TRACE_INPUT_FMT (data) [i],
+                 TRACE_INPUT_SIZE (data) [i],
+                 &TRACE_INPUT_DATA (data) [i]);
+    }
+  trace_printf (sd, cpu, "\n");
+}
+
+void
+trace_prefix (SIM_DESC sd,
+             sim_cpu *cpu,
+             address_word pc,
+             int line_p,
+             const char *filename,
+             int linenum,
+             const char *fmt,
+             ...)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  va_list ap;
+  char *prefix = TRACE_PREFIX (data);
+  char *chp;
+
+  /* if the previous trace data wasn't flused, flush it now with a
+     note indicating that this occured. */
+  if (TRACE_IDX (data) != 0)
+    {
+      int last_input = TRACE_INPUT_IDX (data);
+      save_data (sd, data, trace_fmt_instruction_incomplete, 1, "");
+      trace_results (sd, cpu, TRACE_IDX (data), last_input);
+    }
+  TRACE_IDX (data) = 0;
+  TRACE_INPUT_IDX (data) = 0;
+
+  if (!line_p)
+    {
+      sprintf (prefix, "%s:%-*d 0x%.*lx ",
+              filename,
+              SIZE_LINE_NUMBER, linenum,
+              SIZE_PC, (long)pc);
+      chp = strchr (prefix, '\0');
+      va_start (ap, fmt);
+      vsprintf (chp, fmt, ap);
+      va_end (ap);
+    }
+  else
+    {
+      char buf[256];
+      buf[0] = 0;
+      if (STATE_TEXT_SECTION (CPU_STATE (cpu))
+         && pc >= STATE_TEXT_START (CPU_STATE (cpu))
+         && pc < STATE_TEXT_END (CPU_STATE (cpu)))
+       {
+         const char *pc_filename = (const char *)0;
+         const char *pc_function = (const char *)0;
+         unsigned int pc_linenum = 0;
+
+         if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
+                                    STATE_TEXT_SECTION (CPU_STATE (cpu)),
+                                    (struct symbol_cache_entry **) 0,
+                                    pc - STATE_TEXT_START (CPU_STATE (cpu)),
+                                    &pc_filename, &pc_function, &pc_linenum))
+           {
+             char *p = buf;
+             if (pc_linenum)
+               {
+                 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
+                 p += strlen (p);
+               }
+             else
+               {
+                 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
+                 p += SIZE_LINE_NUMBER+2;
+               }
+
+             if (pc_function)
+               {
+                 sprintf (p, "%s ", pc_function);
+                 p += strlen (p);
+               }
+             else if (pc_filename)
+               {
+                 char *q = (char *) strrchr (pc_filename, '/');
+                 sprintf (p, "%s ", (q) ? q+1 : pc_filename);
+                 p += strlen (p);
+               }
+
+             if (*p == ' ')
+               *p = '\0';
+           }
+       }
+
+      sprintf (prefix, "0x%.*x %-*.*s ",
+              SIZE_PC, (unsigned) pc,
+              SIZE_LOCATION, SIZE_LOCATION, buf);
+      chp = strchr (prefix, '\0');
+      va_start (ap, fmt);
+      vsprintf (chp, fmt, ap);
+      va_end (ap);
+    }
+
+  /* pad it out to TRACE_PREFIX_WIDTH.  FIXME: The TRACE_PREFIX_WIDTH
+     should be determined at build time using known information about
+     the disassembled instructions */
+#ifndef TRACE_PREFIX_WIDTH
+#define TRACE_PREFIX_WIDTH 48
+#endif
+  chp = strchr (prefix, '\0');
+  if (chp - prefix < TRACE_PREFIX_WIDTH)
+    {
+      memset (chp, ' ', TRACE_PREFIX_WIDTH - (chp - prefix));
+      chp = &prefix [TRACE_PREFIX_WIDTH];
+      *chp = '\0';
+    }
+  strcpy (chp, " -");
+
+  /* check that we've not over flowed the prefix buffer */
+  if (strlen (prefix) >= sizeof (TRACE_PREFIX (data)))
+    abort ();
+}
+
+void
+trace_generic (SIM_DESC sd,
+              sim_cpu *cpu,
+              int trace_idx,
+              char *fmt,
+              ...)
+{
+  va_list ap;
+  trace_printf (sd, cpu, "%s %s",
+               trace_idx_to_str (trace_idx),
+               TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
+  va_start (ap, fmt);
+  trace_vprintf (sd, cpu, fmt, ap);
+  va_end (ap);
+  trace_printf (sd, cpu, "\n");
+}
+
+void
+trace_input0 (SIM_DESC sd,
+             sim_cpu *cpu,
+             int trace_idx)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+}
+
+void
+trace_input_word1 (SIM_DESC sd,
+                  sim_cpu *cpu,
+                  int trace_idx,
+                  unsigned_word d0)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
+}
+
+void
+trace_input_word2 (SIM_DESC sd,
+                  sim_cpu *cpu,
+                  int trace_idx,
+                  unsigned_word d0,
+                  unsigned_word d1)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
+}
+
+void
+trace_input_word3 (SIM_DESC sd,
+                  sim_cpu *cpu,
+                  int trace_idx,
+                  unsigned_word d0,
+                  unsigned_word d1,
+                  unsigned_word d2)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);
+}
+
+void
+trace_input_fp1 (SIM_DESC sd,
+                sim_cpu *cpu,
+                int trace_idx,
+                fp_word f0)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
+}
+
+void
+trace_input_fp2 (SIM_DESC sd,
+                sim_cpu *cpu,
+                int trace_idx,
+                fp_word f0,
+                fp_word f1)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
+  save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
+}
+
+void
+trace_input_fp3 (SIM_DESC sd,
+                sim_cpu *cpu,
+                int trace_idx,
+                fp_word f0,
+                fp_word f1,
+                fp_word f2)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
+  save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
+  save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2);
+}
+
+void
+trace_input_fpu1 (SIM_DESC sd,
+                 sim_cpu *cpu,
+                 int trace_idx,
+                 sim_fpu *f0)
+{
+  double d;
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  d = sim_fpu_2d (f0);
+  save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
+}
+
+void
+trace_input_fpu2 (SIM_DESC sd,
+                 sim_cpu *cpu,
+                 int trace_idx,
+                 sim_fpu *f0,
+                 sim_fpu *f1)
+{
+  double d;
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  d = sim_fpu_2d (f0);
+  save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
+  d = sim_fpu_2d (f1);
+  save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
+}
+
+void
+trace_input_fpu3 (SIM_DESC sd,
+                 sim_cpu *cpu,
+                 int trace_idx,
+                 sim_fpu *f0,
+                 sim_fpu *f1,
+                 sim_fpu *f2)
+{
+  double d;
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  TRACE_IDX (data) = trace_idx;
+  d = sim_fpu_2d (f0);
+  save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
+  d = sim_fpu_2d (f1);
+  save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
+  d = sim_fpu_2d (f2);
+  save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
+}
+
+void
+trace_result_word1 (SIM_DESC sd,
+                   sim_cpu *cpu,
+                   int trace_idx,
+                   unsigned_word r0)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  int last_input;
+
+  /* Append any results to the end of the inputs */
+  last_input = TRACE_INPUT_IDX (data);
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
+
+  trace_results (sd, cpu, trace_idx, last_input);
+}            
+
+void
+trace_result_fp1 (SIM_DESC sd,
+                 sim_cpu *cpu,
+                 int trace_idx,
+                 fp_word f0)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  int last_input;
+
+  /* Append any results to the end of the inputs */
+  last_input = TRACE_INPUT_IDX (data);
+  save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
+
+  trace_results (sd, cpu, trace_idx, last_input);
+}            
+
+void
+trace_result_fpu1 (SIM_DESC sd,
+                  sim_cpu *cpu,
+                  int trace_idx,
+                  sim_fpu *f0)
+{
+  double d;
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  int last_input;
+
+  /* Append any results to the end of the inputs */
+  last_input = TRACE_INPUT_IDX (data);
+  d = sim_fpu_2d (f0);
+  save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
+
+  trace_results (sd, cpu, trace_idx, last_input);
+}            
+
+void
+trace_result_string1 (SIM_DESC sd,
+                     sim_cpu *cpu,
+                     int trace_idx,
+                     char *s0)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  int last_input;
+
+  /* Append any results to the end of the inputs */
+  last_input = TRACE_INPUT_IDX (data);
+  save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
+
+  trace_results (sd, cpu, trace_idx, last_input);
+}            
+
+void
+trace_result_word1_string1 (SIM_DESC sd,
+                           sim_cpu *cpu,
+                           int trace_idx,
+                           unsigned_word r0,
+                           char *s0)
+{
+  TRACE_DATA *data = CPU_TRACE_DATA (cpu);
+  int last_input;
+
+  /* Append any results to the end of the inputs */
+  last_input = TRACE_INPUT_IDX (data);
+  save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
+  save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
+
+  trace_results (sd, cpu, trace_idx, last_input);
+}            
+\f
+void
+trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
+{
+  if (cpu != NULL)
+    {
+      if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
+       vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
+      else
+       sim_io_evprintf (sd, fmt, ap);
+    }
+  else
+    {
+      if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
+       vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
+      else
+       sim_io_evprintf (sd, fmt, ap);
+    }
+}
+
 void
 trace_one_insn (SIM_DESC sd, sim_cpu *cpu, address_word pc,
                int line_p, const char *filename, int linenum,
@@ -448,25 +962,6 @@ trace_one_insn (SIM_DESC sd, sim_cpu *cpu, address_word pc,
       trace_printf (sd, cpu, "\n");
     }
 }
-\f
-void
-trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
-{
-  if (cpu != NULL)
-    {
-      if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
-       vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
-      else
-       sim_io_evprintf (sd, fmt, ap);
-    }
-  else
-    {
-      if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
-       vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
-      else
-       sim_io_evprintf (sd, fmt, ap);
-    }
-}
 
 void
 trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...))
index a22da63..e2fd4d5 100644 (file)
@@ -23,44 +23,76 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef SIM_TRACE_H
 #define SIM_TRACE_H
 
-#ifndef __attribute__
-#if !defined(__GNUC__) || (__GNUC__ < 2) || (__GNUC__ == 2 && __GNU_MINOR__ < 7)
-#define __attribute__(attr)
-#endif
-#endif
-
 /* Standard traceable entities.  */
-#define TRACE_SEMANTICS_IDX -1 /* set ALU, FPU, MEMORY tracing */
-#define TRACE_INSN_IDX 0
-#define TRACE_DECODE_IDX 1
-#define TRACE_EXTRACT_IDX 2
-#define TRACE_LINENUM_IDX 3
-#define TRACE_MEMORY_IDX 4
-#define TRACE_MODEL_IDX 5
-#define TRACE_ALU_IDX 6
-#define TRACE_CORE_IDX 7
-#define TRACE_EVENTS_IDX 8
-#define TRACE_FPU_IDX 9
-#define TRACE_BRANCH_IDX 10
-#define TRACE_NEXT_IDX 16 /* simulator specific trace bits begin here */
 
+enum {
+  /* Trace insn execution.  */
+  TRACE_INSN_IDX = 1,
+
+  /* Trace insn decoding.
+     ??? This is more of a simulator debugging operation and might best be
+     moved to --debug-decode.  */
+  TRACE_DECODE_IDX,
+
+  /* Trace insn extraction.
+     ??? This is more of a simulator debugging operation and might best be
+     moved to --debug-extract.  */
+  TRACE_EXTRACT_IDX,
+
+  /* Trace insn execution but include line numbers.  */
+  TRACE_LINENUM_IDX,
+
+  /* Trace memory operations.
+     The difference between this and TRACE_CORE_IDX is (I think) that this
+     is intended to apply to a higher level.  TRACE_CORE_IDX applies to the
+     low level core operations.  */
+  TRACE_MEMORY_IDX,
+
+  /* Include model performance data in tracing output.  */
+  TRACE_MODEL_IDX,
+
+  /* Trace ALU operations.  */
+  TRACE_ALU_IDX,
+
+  /* Trace memory core operations.  */
+  TRACE_CORE_IDX,
+
+  /* Trace events.  */
+  TRACE_EVENTS_IDX,
+
+  /* Trace fpu operations.  */
+  TRACE_FPU_IDX,
+
+  /* Trace branching.  */
+  TRACE_BRANCH_IDX,
+
+  /* Add information useful for debugging the simulator to trace output.  */
+  TRACE_DEBUG_IDX,
+
+  /* Simulator specific trace bits begin here.  */
+  TRACE_NEXT_IDX,
+
+};
 /* Maximum number of traceable entities.  */
 #ifndef MAX_TRACE_VALUES
 #define MAX_TRACE_VALUES 32
 #endif
-
-/* Masks so WITH_TRACE can have symbolic values.  */
-#define TRACE_insn 1
-#define TRACE_decode 2
-#define TRACE_extract 4
-#define TRACE_linenum 8
-#define TRACE_memory 16
-#define TRACE_model 32
-#define TRACE_alu 64
-#define TRACE_core 128
-#define TRACE_events 256
-#define TRACE_fpu 512
-#define TRACE_branch 1024
+\f
+/* Masks so WITH_TRACE can have symbolic values.
+   The case choice here is on purpose.  The lowercase parts are args to
+   --with-trace.  */
+#define TRACE_insn     (1 << TRACE_INSN_IDX)
+#define TRACE_decode   (1 << TRACE_DECODE_IDX)
+#define TRACE_extract  (1 << TRACE_EXTRACT_IDX)
+#define TRACE_linenum  (1 << TRACE_LINENUM_IDX)
+#define TRACE_memory   (1 << TRACE_MEMORY_IDX)
+#define TRACE_model    (1 << TRACE_MODEL_IDX)
+#define TRACE_alu      (1 << TRACE_ALU_IDX)
+#define TRACE_core     (1 << TRACE_CORE_IDX)
+#define TRACE_events   (1 << TRACE_EVENTS_IDX)
+#define TRACE_fpu      (1 << TRACE_FPU_IDX)
+#define TRACE_branch   (1 << TRACE_BRANCH_IDX)
+#define TRACE_debug    (1 << TRACE_DEBUG_IDX)
 
 /* Preprocessor macros to simplify tests of WITH_TRACE.  */
 #define WITH_TRACE_INSN_P      (WITH_TRACE & TRACE_insn)
@@ -74,13 +106,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define WITH_TRACE_EVENTS_P    (WITH_TRACE & TRACE_events)
 #define WITH_TRACE_FPU_P       (WITH_TRACE & TRACE_fpu)
 #define WITH_TRACE_BRANCH_P    (WITH_TRACE & TRACE_branch)
+#define WITH_TRACE_DEBUG_P     (WITH_TRACE & TRACE_debug)
 
 /* Tracing install handler.  */
 MODULE_INSTALL_FN trace_install;
 \f
-/* Struct containing all trace data.  */
+/* Struct containing all system and cpu trace data.
+
+   System trace data is stored with the associated module.
+   System and cpu tracing must share the same space of bitmasks as they
+   are arguments to --with-trace.  One could have --with-trace and
+   --with-cpu-trace or some such but that's an over-complication at this point
+   in time.  Also, there may be occasions where system and cpu tracing may
+   wish to share a name.  */
+
+typedef struct _trace_data {
 
-typedef struct {
   /* Boolean array of specified tracing flags.  */
   /* ??? It's not clear that using an array vs a bit mask is faster.
      Consider the case where one wants to test whether any of several bits
@@ -92,23 +133,57 @@ typedef struct {
      We can't store `stderr' here as stderr goes through a callback.  */
   FILE *trace_file;
 #define TRACE_FILE(t) ((t)->trace_file)
+
+  /* Buffer to store the prefix to be printed before any trace line */
+  char trace_prefix[256];
+#define TRACE_PREFIX(t) ((t)->trace_prefix)
+
+  /* Buffer to save the inputs for the current instruction.  Use a
+     union to force the buffer into correct alignment */
+  union {
+    unsigned8 i8;
+    unsigned16 i16;
+    unsigned32 i32;
+    unsigned64 i64;
+  } trace_input_data[16];
+  unsigned8 trace_input_fmt[16];
+  unsigned8 trace_input_size[16];
+  int trace_input_idx;
+#define TRACE_INPUT_DATA(t) ((t)->trace_input_data)
+#define TRACE_INPUT_FMT(t) ((t)->trace_input_fmt)
+#define TRACE_INPUT_SIZE(t) ((t)->trace_input_size)
+#define TRACE_INPUT_IDX(t) ((t)->trace_input_idx)
+  
+  /* Category of trace being performed */
+  int trace_idx;
+#define TRACE_IDX(t) ((t)->trace_idx)
+  
 } TRACE_DATA;
+
 \f
-/* Usage macros.  */
+/* System tracing support.  */
 
-#define CPU_TRACE_FLAGS(cpu) TRACE_FLAGS (CPU_TRACE_DATA (cpu))
+#define STATE_TRACE_FLAGS(sd) TRACE_FLAGS (STATE_TRACE_DATA (sd))
 
-/* forward reference */
-struct _sim_cpu;
+/* Return non-zero if tracing of IDX is enabled for non-cpu specific
+   components.  The "S" in "STRACE" refers to "System".  */
+#define STRACE_P(sd,idx) \
+((WITH_TRACE & (1 << (idx))) != 0 \
+ && STATE_TRACE_FLAGS (sd)[idx] != 0)
+
+/* Non-zero if --trace-<xxxx> was specified for SD.  */
+#define STRACE_DEBUG_P(sd)     STRACE_P (sd, TRACE_DEBUG_IDX)
+\f
+/* CPU tracing support.  */
 
-/* Tracing support.  */
+#define CPU_TRACE_FLAGS(cpu) TRACE_FLAGS (CPU_TRACE_DATA (cpu))
 
 /* Return non-zero if tracing of IDX is enabled for CPU.  */
 #define TRACE_P(cpu,idx) \
 ((WITH_TRACE & (1 << (idx))) != 0 \
  && CPU_TRACE_FLAGS (cpu)[idx] != 0)
 
-/* Non-zero if  a certain --trace-<xxxx> was specified for CPU.  */
+/* Non-zero if --trace-<xxxx> was specified for CPU.  */
 #define TRACE_INSN_P(cpu)      TRACE_P (cpu, TRACE_INSN_IDX)
 #define TRACE_DECODE_P(cpu)    TRACE_P (cpu, TRACE_DECODE_IDX)
 #define TRACE_EXTRACT_P(cpu)   TRACE_P (cpu, TRACE_EXTRACT_IDX)
@@ -120,7 +195,155 @@ struct _sim_cpu;
 #define TRACE_EVENTS_P(cpu)    TRACE_P (cpu, TRACE_EVENTS_IDX)
 #define TRACE_FPU_P(cpu)       TRACE_P (cpu, TRACE_FPU_IDX)
 #define TRACE_BRANCH_P(cpu)    TRACE_P (cpu, TRACE_BRANCH_IDX)
+#define TRACE_DEBUG_P(cpu)     TRACE_P (cpu, TRACE_DEBUG_IDX)
+\f
+/* Traceing functions.
+
+ */
+
+/* Prime the trace buffers ready for any trace output.
+   Must be called prior to any other trace operation */
+extern void trace_prefix PARAMS ((SIM_DESC sd,
+                                 sim_cpu * cpu,
+                                 address_word cia,
+                                 int print_linenum_p,
+                                 const char *file_name,
+                                 int line_nr,
+                                 const char *fmt,
+                                 ...))
+       __attribute__((format (printf, 7, 8)));
+
+/* Generic trace print, assumes trace_prefix() has been called */
+
+extern void trace_generic PARAMS ((SIM_DESC sd,
+                                  sim_cpu *cpu,
+                                  int trace_idx,
+                                  char *fmt,
+                                  ...))
+     __attribute__((format (printf, 4, 5)));
+
+/* Trace a varying number of word sized inputs/outputs.  trace_result*
+   must be called to close the trace operation. */
+
+extern void trace_input0 PARAMS ((SIM_DESC sd,
+                                 sim_cpu *cpu,
+                                 int trace_idx));
+extern void trace_input_word1 PARAMS ((SIM_DESC sd,
+                                      sim_cpu *cpu,
+                                      int trace_idx,
+                                      unsigned_word d0));
+extern void trace_input_word2 PARAMS ((SIM_DESC sd,
+                                      sim_cpu *cpu,
+                                      int trace_idx,
+                                      unsigned_word d0,
+                                      unsigned_word d1));
+extern void trace_input_word3 PARAMS ((SIM_DESC sd,
+                                      sim_cpu *cpu,
+                                      int trace_idx,
+                                      unsigned_word d0,
+                                      unsigned_word d1,
+                                      unsigned_word d2));
+
+extern void trace_input_fp1 PARAMS ((SIM_DESC sd,
+                                    sim_cpu *cpu,
+                                    int trace_idx,
+                                    fp_word f0));
+
+extern void trace_input_fp2 PARAMS ((SIM_DESC sd,
+                                    sim_cpu *cpu,
+                                    int trace_idx,
+                                    fp_word f0,
+                                    fp_word f1));
+
+extern void trace_input_fp3 PARAMS ((SIM_DESC sd,
+                                    sim_cpu *cpu,
+                                    int trace_idx,
+                                    fp_word f0,
+                                    fp_word f1,
+                                    fp_word f2));
+
+extern void trace_input_fpu1 PARAMS ((SIM_DESC sd,
+                                    sim_cpu *cpu,
+                                    int trace_idx,
+                                    struct _sim_fpu *f0));
+
+extern void trace_input_fpu2 PARAMS ((SIM_DESC sd,
+                                    sim_cpu *cpu,
+                                    int trace_idx,
+                                    struct _sim_fpu *f0,
+                                    struct _sim_fpu *f1));
+
+extern void trace_input_fpu3 PARAMS ((SIM_DESC sd,
+                                    sim_cpu *cpu,
+                                    int trace_idx,
+                                    struct _sim_fpu *f0,
+                                    struct _sim_fpu *f1,
+                                    struct _sim_fpu *f2));
 
+/* Other trace_input{_<fmt><nr-inputs>} functions can go here */
+
+extern void trace_result_word1 PARAMS ((SIM_DESC sd,
+                                       sim_cpu *cpu,
+                                       int trace_idx,
+                                       unsigned_word r0));
+
+extern void trace_result_fp1 PARAMS ((SIM_DESC sd,
+                                     sim_cpu *cpu,
+                                     int trace_idx,
+                                     fp_word f0));
+
+extern void trace_result_fpu1 PARAMS ((SIM_DESC sd,
+                                      sim_cpu *cpu,
+                                      int trace_idx,
+                                      struct _sim_fpu *f0));
+
+extern void trace_result_string1 PARAMS ((SIM_DESC sd,
+                                         sim_cpu *cpu,
+                                         int trace_idx,
+                                         char *str0));
+
+extern void trace_result_word1_string1 PARAMS ((SIM_DESC sd,
+                                               sim_cpu *cpu,
+                                               int trace_idx,
+                                               unsigned_word r0,
+                                               char *s0));
+
+/* Other trace_result{_<type><nr-results>} */
+
+
+/* Macro's for tracing ALU instructions */
+#define TRACE_ALU_INPUT0() \
+do { \
+  if (TRACE_ALU_P (CPU)) \
+    trace_input0 (SD, CPU, TRACE_ALU_IDX); \
+} while (0)
+    
+#define TRACE_ALU_INPUT1(V0) \
+do { \
+  if (TRACE_ALU_P (CPU)) \
+    trace_input_word1 (SD, CPU, TRACE_ALU_IDX, (V0)); \
+} while (0)
+
+#define TRACE_ALU_INPUT2(V0,V1) \
+do { \
+  if (TRACE_ALU_P (CPU)) \
+    trace_input_word2 (SD, CPU, TRACE_ALU_IDX, (V0), (V1)); \
+} while (0)
+
+#define TRACE_ALU_INPUT3(V0,V1,V2) \
+do { \
+  if (TRACE_ALU_P (CPU)) \
+    trace_input_word3 (SD, CPU, TRACE_ALU_IDX, (V0), (V1), (V2)); \
+} while (0)
+
+#define TRACE_ALU_RESULT(R0) \
+do { \
+  if (TRACE_ALU_P (CPU)) \
+    trace_result_word1 (SD, CPU, TRACE_ALU_IDX, (R0)); \
+} while (0)
+
+\f
+/* The function trace_one_insn has been replaced by trace_generic */
 extern void trace_one_insn PARAMS ((SIM_DESC sd,
                                    sim_cpu * cpu,
                                    address_word cia,
@@ -149,7 +372,7 @@ extern void trace_vprintf PARAMS ((SIM_DESC, sim_cpu *, const char *, va_list));
 /* Non-zero if "--debug-insn" specified.  */
 #define DEBUG_INSN_P(cpu) DEBUG_P (cpu, DEBUG_INSN_IDX)
 
-extern void debug_printf PARAMS ((struct _sim_cpu *, const char *, ...))
+extern void debug_printf PARAMS ((sim_cpu *, const char *, ...))
      __attribute__((format (printf, 2, 3)));
 
 #endif /* SIM_TRACE_H */