* "objcopy -O binary" warning tweak, suggested by dmoseley
[binutils-gdb.git] / sim / common / cgen-trace.c
blob82a20a5fd62803cd87cfebf6124c2c8108fddb30
1 /* Tracing support for CGEN-based simulators.
2 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
5 This file is part of GDB, the GNU debugger.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "sim-main.h"
22 #include "bfd.h"
23 #include "cpu-opc.h"
25 #ifndef SIZE_INSTRUCTION
26 #define SIZE_INSTRUCTION 16
27 #endif
29 #ifndef SIZE_LOCATION
30 #define SIZE_LOCATION 20
31 #endif
33 #ifndef SIZE_PC
34 #define SIZE_PC 6
35 #endif
37 #ifndef SIZE_LINE_NUMBER
38 #define SIZE_LINE_NUMBER 4
39 #endif
41 #ifndef SIZE_CYCLE_COUNT
42 #define SIZE_CYCLE_COUNT 2
43 #endif
45 #ifndef SIZE_TOTAL_CYCLE_COUNT
46 #define SIZE_TOTAL_CYCLE_COUNT 9
47 #endif
49 #ifndef SIZE_TRACE_BUF
50 #define SIZE_TRACE_BUF 256
51 #endif
53 /* Text is queued in TRACE_BUF because we want to output the insn's cycle
54 count first but that isn't known until after the insn has executed.
55 This also handles the queueing of trace results, TRACE_RESULT may be
56 called multiple times for one insn. */
57 static char trace_buf[SIZE_TRACE_BUF];
58 /* If NULL, output to stdout directly. */
59 static char *bufptr;
61 /* Non-zero if this is the first insn in a set of parallel insns. */
62 static int first_insn_p;
64 /* For communication between trace_insn and trace_result. */
65 static int printed_result_p;
67 /* Insn and its extracted fields.
68 Set by trace_insn, used by trace_insn_fini.
69 ??? Move to SIM_CPU to support heterogeneous multi-cpu case. */
70 static const struct cgen_insn *current_insn;
71 static CGEN_FIELDS insn_fields;
72 static const struct argbuf *current_abuf;
74 void
75 trace_insn_init (SIM_CPU *cpu, int first_p)
77 bufptr = trace_buf;
78 *bufptr = 0;
79 first_insn_p = first_p;
81 /* Set to NULL so trace_insn_fini can know if trace_insn was called. */
82 current_insn = NULL;
83 current_abuf = NULL;
86 void
87 trace_insn_fini (SIM_CPU *cpu, const struct argbuf *abuf, int last_p)
89 SIM_DESC sd = CPU_STATE (cpu);
91 /* Was insn traced? It might not be if trace ranges are in effect. */
92 if (current_insn == NULL)
93 return;
95 /* The first thing printed is current and total cycle counts. */
97 if (PROFILE_MODEL_P (cpu)
98 && ARGBUF_PROFILE_P (current_abuf))
100 unsigned long total = PROFILE_MODEL_TOTAL_CYCLES (CPU_PROFILE_DATA (cpu));
101 unsigned long this_insn = PROFILE_MODEL_CUR_INSN_CYCLES (CPU_PROFILE_DATA (cpu));
103 if (last_p)
105 trace_printf (sd, cpu, "%-*ld %-*ld ",
106 SIZE_CYCLE_COUNT, this_insn,
107 SIZE_TOTAL_CYCLE_COUNT, total);
109 else
111 trace_printf (sd, cpu, "%-*ld %-*s ",
112 SIZE_CYCLE_COUNT, this_insn,
113 SIZE_TOTAL_CYCLE_COUNT, "---");
117 /* Print the disassembled insn. */
119 trace_printf (sd, cpu, "%s", TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
121 #if 0
122 /* Print insn results. */
124 const CGEN_OPERAND_INSTANCE *opinst = CGEN_INSN_OPERANDS (current_insn);
126 if (opinst)
128 int i;
129 int indices[MAX_OPERAND_INSTANCES];
131 /* Fetch the operands used by the insn. */
132 /* FIXME: Add fn ptr to CGEN_OPCODE_DESC. */
133 CGEN_SYM (get_insn_operands) (STATE_OPCODE_TABLE (sd), current_insn,
134 0, CGEN_FIELDS_BITSIZE (&insn_fields),
135 indices);
137 for (i = 0;
138 CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
139 ++i, ++opinst)
141 if (CGEN_OPERAND_INSTANCE_TYPE (opinst) == CGEN_OPERAND_INSTANCE_OUTPUT)
142 trace_result (cpu, current_insn, opinst, indices[i]);
146 #endif
148 /* Print anything else requested. */
150 if (*trace_buf)
151 trace_printf (sd, cpu, " %s\n", trace_buf);
152 else
153 trace_printf (sd, cpu, "\n");
156 void
157 trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
158 const struct argbuf *abuf, PCADDR pc)
160 char disasm_buf[50];
162 printed_result_p = 0;
163 current_insn = opcode;
164 current_abuf = abuf;
166 if (CGEN_INSN_VIRTUAL_P (opcode))
168 trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, 0,
169 NULL, 0, CGEN_INSN_NAME (opcode));
170 return;
173 sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf, &insn_fields);
174 trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
175 NULL, 0,
176 "%s%-*s",
177 first_insn_p ? " " : "|",
178 SIZE_INSTRUCTION, disasm_buf);
181 void
182 trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
184 va_list args;
185 int printed_one_p = 0;
186 char *fmt;
188 va_start (args, name);
190 trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*lx: %s ",
191 SIZE_PC, pc, name);
193 do {
194 int type,ival;
196 fmt = va_arg (args, char *);
198 if (fmt)
200 if (printed_one_p)
201 trace_printf (CPU_STATE (cpu), cpu, ", ");
202 printed_one_p = 1;
203 type = va_arg (args, int);
204 switch (type)
206 case 'x' :
207 ival = va_arg (args, int);
208 trace_printf (CPU_STATE (cpu), cpu, fmt, ival);
209 break;
210 default :
211 abort ();
214 } while (fmt);
216 va_end (args);
217 trace_printf (CPU_STATE (cpu), cpu, "\n");
220 void
221 trace_result (SIM_CPU *cpu, char *name, int type, ...)
223 va_list args;
225 va_start (args, type);
226 if (printed_result_p)
227 cgen_trace_printf (cpu, ", ");
229 switch (type)
231 case 'x' :
232 default :
233 cgen_trace_printf (cpu, "%s <- 0x%x", name, va_arg (args, int));
234 break;
235 case 'D' :
237 DI di;
238 /* this is separated from previous line for sunos cc */
239 di = va_arg (args, DI);
240 cgen_trace_printf (cpu, "%s <- 0x%x%08x", name,
241 GETHIDI(di), GETLODI (di));
242 break;
246 printed_result_p = 1;
247 va_end (args);
250 /* Print trace output to BUFPTR if active, otherwise print normally.
251 This is only for tracing semantic code. */
253 void
254 cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...)
256 va_list args;
258 va_start (args, fmt);
260 if (bufptr == NULL)
262 if (TRACE_FILE (CPU_TRACE_DATA (cpu)) == NULL)
263 (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
264 (STATE_CALLBACK (CPU_STATE (cpu)), fmt, args);
265 else
266 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, args);
268 else
270 vsprintf (bufptr, fmt, args);
271 bufptr += strlen (bufptr);
272 /* ??? Need version of SIM_ASSERT that is always enabled. */
273 if (bufptr - trace_buf > SIZE_TRACE_BUF)
274 abort ();
277 va_end (args);