aboutsummaryrefslogtreecommitdiff
path: root/sim/common/cgen-trace.c
diff options
context:
space:
mode:
authorDoug Evans <dje@google.com>1999-01-06 00:42:34 +0000
committerDoug Evans <dje@google.com>1999-01-06 00:42:34 +0000
commitf5cd4d758c52b6746046da1fafd0e70b41022178 (patch)
tree3eb8c2ebe80f7fb26095862240191e4ae138adc6 /sim/common/cgen-trace.c
parent5730d39d2cd1974c77899555dac466babc316589 (diff)
downloadfsf-binutils-gdb-f5cd4d758c52b6746046da1fafd0e70b41022178.zip
fsf-binutils-gdb-f5cd4d758c52b6746046da1fafd0e70b41022178.tar.gz
fsf-binutils-gdb-f5cd4d758c52b6746046da1fafd0e70b41022178.tar.bz2
* Make-common.in (CGEN_INCLUDE_DEPS): Add cgen-defs.h, cgen-engine.h.
(CGEN_MAIN_SCM): Add rtx-funcs.scm. (cgen-arch): Pass $(mach) to cgen.sh. * cgen-engine.h (SEM_BRANCH_FINI): New arg pcvar, all uses updated. (SEM_BRANCH_INIT_EXTRACT): New macro. (SEM_BRANCH_INIT): Add taken_p. (TARGET_SEM_BRANCH_FINI): Provide default definition. (SEM_BRANCH_FINI): Use it. (SEM_INSN): Update. * cgen-run.c (sim_resume): Handle tracing of last insn. * cgen-scache.h (WITH_SCACHE): Define as 0 if not defined. * cgen-trace.c (current_abuf): New static global. (trace_insn_init): Initialize it. (trace_insn_fini): Use it. (trace_insn): Set it. * cgen.sh (arch case): Pass -m ${mach} to cgen. * genmloop.sh (@cpu@_emit_before): Only define if WITH_SCACHE_PBB. (@cpu@_emit_after): Ditto. (simple @cpu@_engine_run_full): New local `pc'. Initialize semantic labels if WITH_SEM_SWITCH_FULL. * sim-model.c: Include bfd.h. (sim_model_init): New function. (sim_model_install): Record init fn. * sim-model.h (MACH): New member bfd_name. * sim-module.c (modules): Initialize model before scache.
Diffstat (limited to 'sim/common/cgen-trace.c')
-rw-r--r--sim/common/cgen-trace.c196
1 files changed, 110 insertions, 86 deletions
diff --git a/sim/common/cgen-trace.c b/sim/common/cgen-trace.c
index c389014..f95f837 100644
--- a/sim/common/cgen-trace.c
+++ b/sim/common/cgen-trace.c
@@ -1,5 +1,5 @@
/* Tracing support for CGEN-based simulators.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB, the GNU debugger.
@@ -46,118 +46,136 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define SIZE_TOTAL_CYCLE_COUNT 9
#endif
+#ifndef SIZE_TRACE_BUF
+#define SIZE_TRACE_BUF 256
+#endif
+
/* Text is queued in TRACE_BUF because we want to output the insn's cycle
- count first but that isn't known until after the insn has executed. */
-static char trace_buf[1024];
+ count first but that isn't known until after the insn has executed.
+ This also handles the queueing of trace results, TRACE_RESULT may be
+ called multiple times for one insn. */
+static char trace_buf[SIZE_TRACE_BUF];
/* If NULL, output to stdout directly. */
static char *bufptr;
-/* For computing an instruction's cycle count.
- FIXME: Need to move into cpu struct for smp case. */
-static unsigned long last_cycle_count;
+/* Non-zero if this is the first insn in a set of parallel insns. */
+static int first_insn_p;
+
+/* For communication between trace_insn and trace_result. */
+static int printed_result_p;
+
+/* Insn and its extracted fields.
+ Set by trace_insn, used by trace_insn_fini.
+ ??? Move to SIM_CPU to support heterogeneous multi-cpu case. */
+static const struct cgen_insn *current_insn;
+static CGEN_FIELDS insn_fields;
+static const struct argbuf *current_abuf;
void
trace_insn_init (SIM_CPU *cpu, int first_p)
{
bufptr = trace_buf;
*bufptr = 0;
+ first_insn_p = first_p;
+
+ /* Set to NULL so trace_insn_fini can know if trace_insn was called. */
+ current_insn = NULL;
+ current_abuf = NULL;
}
void
-trace_insn_fini (SIM_CPU *cpu, int last_p)
+trace_insn_fini (SIM_CPU *cpu, const struct argbuf *abuf, int last_p)
{
- if (CPU_PROFILE_FLAGS (cpu) [PROFILE_MODEL_IDX])
- {
- unsigned long total = PROFILE_TOTAL_CYCLE_COUNT (CPU_PROFILE_DATA (cpu));
- trace_printf (CPU_STATE (cpu), cpu, "%-*ld %-*ld ",
- SIZE_CYCLE_COUNT, total - last_cycle_count,
- SIZE_TOTAL_CYCLE_COUNT, total);
- last_cycle_count = total;
- }
+ SIM_DESC sd = CPU_STATE (cpu);
- trace_printf (CPU_STATE (cpu), cpu, "%s\n", trace_buf);
-}
+ /* Was insn traced? It might not be if trace ranges are in effect. */
+ if (current_insn == NULL)
+ return;
-/* For communication between trace_insn and trace_result. */
-static int printed_result_p;
+ /* The first thing printed is current and total cycle counts. */
-void
-trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
- const struct argbuf *abuf, PCADDR pc)
-{
- const char *filename;
- const char *functionname;
- unsigned int linenumber;
- char *p, buf[256], disasm_buf[50];
-
- if (! TRACE_P (cpu, TRACE_LINENUM_IDX))
+ if (PROFILE_MODEL_P (cpu)
+ && ARGBUF_PROFILE_P (current_abuf))
{
- cgen_trace_printf (cpu, "0x%.*x %-*s ",
- SIZE_PC, (unsigned) pc,
- SIZE_INSTRUCTION,
- CGEN_INSN_MNEMONIC (opcode));
- printed_result_p = 0;
- return;
- }
+ unsigned long total = PROFILE_MODEL_TOTAL_CYCLES (CPU_PROFILE_DATA (cpu));
+ unsigned long this_insn = PROFILE_MODEL_CUR_INSN_CYCLES (CPU_PROFILE_DATA (cpu));
- buf[0] = 0;
-
- if (STATE_TEXT_SECTION (CPU_STATE (cpu))
- && pc >= STATE_TEXT_START (CPU_STATE (cpu))
- && pc < STATE_TEXT_END (CPU_STATE (cpu)))
- {
- filename = (const char *) 0;
- functionname = (const char *) 0;
- linenumber = 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)),
- &filename, &functionname, &linenumber))
+ if (last_p)
+ {
+ trace_printf (sd, cpu, "%-*ld %-*ld ",
+ SIZE_CYCLE_COUNT, this_insn,
+ SIZE_TOTAL_CYCLE_COUNT, total);
+ }
+ else
{
- p = buf;
- if (linenumber)
- {
- sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber);
- p += strlen (p);
- }
- else
- {
- sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
- p += SIZE_LINE_NUMBER+2;
- }
-
- if (functionname)
- {
- sprintf (p, "%s ", functionname);
- p += strlen (p);
- }
- else if (filename)
- {
- char *q = (char *) strrchr (filename, '/');
- sprintf (p, "%s ", (q) ? q+1 : filename);
- p += strlen (p);
- }
-
- if (*p == ' ')
- *p = '\0';
+ trace_printf (sd, cpu, "%-*ld %-*s ",
+ SIZE_CYCLE_COUNT, this_insn,
+ SIZE_TOTAL_CYCLE_COUNT, "---");
}
}
- sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf);
+ /* Print the disassembled insn. */
+
+ trace_printf (sd, cpu, "%s", TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
- cgen_trace_printf (cpu, "0x%.*x %-*.*s %-*s ",
- SIZE_PC, (unsigned) pc,
- SIZE_LOCATION, SIZE_LOCATION, buf,
- SIZE_INSTRUCTION,
#if 0
- CGEN_INSN_NAME (opcode)
-#else
- disasm_buf
+ /* Print insn results. */
+ {
+ const CGEN_OPERAND_INSTANCE *opinst = CGEN_INSN_OPERANDS (current_insn);
+
+ if (opinst)
+ {
+ int i;
+ int indices[MAX_OPERAND_INSTANCES];
+
+ /* Fetch the operands used by the insn. */
+ /* FIXME: Add fn ptr to CGEN_OPCODE_DESC. */
+ CGEN_SYM (get_insn_operands) (STATE_OPCODE_TABLE (sd), current_insn,
+ 0, CGEN_FIELDS_BITSIZE (&insn_fields),
+ indices);
+
+ for (i = 0;
+ CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
+ ++i, ++opinst)
+ {
+ if (CGEN_OPERAND_INSTANCE_TYPE (opinst) == CGEN_OPERAND_INSTANCE_OUTPUT)
+ trace_result (cpu, current_insn, opinst, indices[i]);
+ }
+ }
+ }
#endif
- );
+
+ /* Print anything else requested. */
+
+ if (*trace_buf)
+ trace_printf (sd, cpu, " %s\n", trace_buf);
+ else
+ trace_printf (sd, cpu, "\n");
+}
+
+void
+trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
+ const struct argbuf *abuf, PCADDR pc)
+{
+ char disasm_buf[50];
printed_result_p = 0;
+ current_insn = opcode;
+ current_abuf = abuf;
+
+ if (CGEN_INSN_VIRTUAL_P (opcode))
+ {
+ trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, (address_word) 0, 0,
+ NULL, 0, CGEN_INSN_NAME (opcode));
+ return;
+ }
+
+ sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf, &insn_fields);
+ trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
+ NULL, 0,
+ "%s%-*s",
+ first_insn_p ? " " : "|",
+ SIZE_INSTRUCTION, disasm_buf);
}
void
@@ -169,7 +187,8 @@ trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
va_start (args, name);
- trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*x: %s ", SIZE_PC, pc, name);
+ trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*lx: %s ",
+ SIZE_PC, pc, name);
do {
int type,ival;
@@ -206,6 +225,7 @@ trace_result (SIM_CPU *cpu, char *name, int type, ...)
va_start (args, type);
if (printed_result_p)
cgen_trace_printf (cpu, ", ");
+
switch (type)
{
case 'x' :
@@ -222,6 +242,7 @@ trace_result (SIM_CPU *cpu, char *name, int type, ...)
break;
}
}
+
printed_result_p = 1;
va_end (args);
}
@@ -248,6 +269,9 @@ cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...)
{
vsprintf (bufptr, fmt, args);
bufptr += strlen (bufptr);
+ /* ??? Need version of SIM_ASSERT that is always enabled. */
+ if (bufptr - trace_buf > SIZE_TRACE_BUF)
+ abort ();
}
va_end (args);