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:
parent
5871376494
commit
8dcc896d0e
|
@ -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.
|
||||
|
|
|
@ -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, ...))
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue