Extend sim-trace.[hc] to include a generic set of macro's for tracing

ALU/... inputs/outputs.
Base implementation on original v850 code.
Update igen to generate code interfacing with newer sim-trace.[hc].
This commit is contained in:
Andrew Cagney 1998-02-18 04:11:09 +00:00
parent 5871376494
commit 8dcc896d0e
3 changed files with 814 additions and 77 deletions

View 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.

View 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)
}
}
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);
}
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");
}
}
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, ...))

View 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
/* 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;
/* 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;
/* Usage macros. */
/* System tracing support. */
#define STATE_TRACE_FLAGS(sd) TRACE_FLAGS (STATE_TRACE_DATA (sd))
/* 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)
/* CPU tracing support. */
#define CPU_TRACE_FLAGS(cpu) TRACE_FLAGS (CPU_TRACE_DATA (cpu))
/* forward reference */
struct _sim_cpu;
/* Tracing support. */
/* 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)
/* 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)
/* 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 */