From 8dcc896d0e023cc7837370e4c186a7170400cff0 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Wed, 18 Feb 1998 04:11:09 +0000 Subject: [PATCH] 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]. --- sim/common/ChangeLog | 19 ++ sim/common/sim-trace.c | 565 ++++++++++++++++++++++++++++++++++++++--- sim/common/sim-trace.h | 305 +++++++++++++++++++--- 3 files changed, 813 insertions(+), 76 deletions(-) diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index ffc079849d..097e48a071 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,22 @@ +Wed Feb 18 12:42:15 1998 Andrew Cagney + + * sim-basics.h: Declare struct _sim_fpu. + +Tue Feb 17 16:27:46 1998 Andrew Cagney + + * 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 * Make-common.in (CGEN_MAIN_SCM): Update. diff --git a/sim/common/sim-trace.c b/sim/common/sim-trace.c index 5f3dd133f8..d53afdafee 100644 --- a/sim/common/sim-trace.c +++ b/sim/common/sim-trace.c @@ -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, ...)) diff --git a/sim/common/sim-trace.h b/sim/common/sim-trace.h index a22da63130..e2fd4d5c32 100644 --- a/sim/common/sim-trace.h +++ b/sim/common/sim-trace.h @@ -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 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- was specified for SD. */ +#define STRACE_DEBUG_P(sd) STRACE_P (sd, TRACE_DEBUG_IDX) + +/* 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- was specified for CPU. */ +/* Non-zero if --trace- 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{_} 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{_} */ + + +/* 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 */ -- 2.34.1