]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-trace.c
Add semantic tracing to the tic80
[thirdparty/binutils-gdb.git] / sim / common / sim-trace.c
1 /* Simulator tracing/debugging support.
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5 This file is part of GDB, the GNU debugger.
6
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.
11
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.
16
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. */
20
21 #include "sim-main.h"
22 #include "sim-io.h"
23 #include "sim-options.h"
24 #include "bfd.h"
25
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #else
29 #ifdef HAVE_STRINGS_H
30 #include <strings.h>
31 #endif
32 #endif
33
34 #ifndef SIZE_PHASE
35 #define SIZE_PHASE 8
36 #endif
37
38 #ifndef SIZE_LOCATION
39 #define SIZE_LOCATION 20
40 #endif
41
42 #ifndef SIZE_PC
43 #define SIZE_PC 6
44 #endif
45
46 #ifndef SIZE_LINE_NUMBER
47 #define SIZE_LINE_NUMBER 4
48 #endif
49
50 static MODULE_UNINSTALL_FN trace_uninstall;
51
52 static DECLARE_OPTION_HANDLER (trace_option_handler);
53
54 enum {
55 OPTION_TRACE_INSN = OPTION_START,
56 OPTION_TRACE_DECODE,
57 OPTION_TRACE_EXTRACT,
58 OPTION_TRACE_LINENUM,
59 OPTION_TRACE_MEMORY,
60 OPTION_TRACE_MODEL,
61 OPTION_TRACE_ALU,
62 OPTION_TRACE_CORE,
63 OPTION_TRACE_EVENTS,
64 OPTION_TRACE_FPU,
65 OPTION_TRACE_BRANCH,
66 OPTION_TRACE_SEMANTICS,
67 OPTION_TRACE_FILE
68 };
69
70 static const OPTION trace_options[] =
71 {
72 { {"trace", no_argument, NULL, 't'},
73 't', NULL, "Perform tracing",
74 trace_option_handler },
75 { {"trace-insn", no_argument, NULL, OPTION_TRACE_INSN},
76 '\0', NULL, "Perform instruction tracing",
77 trace_option_handler },
78 { {"trace-decode", no_argument, NULL, OPTION_TRACE_DECODE},
79 '\0', NULL, "Perform instruction decoding tracing",
80 trace_option_handler },
81 { {"trace-extract", no_argument, NULL, OPTION_TRACE_EXTRACT},
82 '\0', NULL, "Perform instruction extraction tracing",
83 trace_option_handler },
84 { {"trace-linenum", no_argument, NULL, OPTION_TRACE_LINENUM},
85 '\0', NULL, "Perform line number tracing (implies --trace-insn)",
86 trace_option_handler },
87 { {"trace-memory", no_argument, NULL, OPTION_TRACE_MEMORY},
88 '\0', NULL, "Perform memory tracing",
89 trace_option_handler },
90 { {"trace-model", no_argument, NULL, OPTION_TRACE_MODEL},
91 '\0', NULL, "Perform model tracing",
92 trace_option_handler },
93 { {"trace-alu", no_argument, NULL, OPTION_TRACE_ALU},
94 '\0', NULL, "Perform ALU tracing",
95 trace_option_handler },
96 { {"trace-core", no_argument, NULL, OPTION_TRACE_CORE},
97 '\0', NULL, "Perform CORE tracing",
98 trace_option_handler },
99 { {"trace-events", no_argument, NULL, OPTION_TRACE_EVENTS},
100 '\0', NULL, "Perform EVENTS tracing",
101 trace_option_handler },
102 { {"trace-fpu", no_argument, NULL, OPTION_TRACE_FPU},
103 '\0', NULL, "Perform FPU tracing",
104 trace_option_handler },
105 { {"trace-branch", no_argument, NULL, OPTION_TRACE_BRANCH},
106 '\0', NULL, "Perform branch tracing",
107 trace_option_handler },
108 { {"trace-semantics", no_argument, NULL, OPTION_TRACE_SEMANTICS},
109 '\0', NULL, "Perform ALU, FPU, and MEMORY tracing",
110 trace_option_handler },
111 { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE},
112 '\0', "FILE NAME", "Specify tracing output file",
113 trace_option_handler },
114 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
115 };
116
117 static SIM_RC
118 trace_option_handler (sd, opt, arg)
119 SIM_DESC sd;
120 int opt;
121 char *arg;
122 {
123 int i,n;
124
125 switch (opt)
126 {
127 case 't' :
128 if (! WITH_TRACE)
129 sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
130 else
131 {
132 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
133 for (i = 0; i < MAX_TRACE_VALUES; ++i)
134 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[i] = 1;
135 STATE_CORE(sd)->trace = 1;
136 STATE_EVENTS(sd)->trace = 1;
137 }
138 break;
139
140 case OPTION_TRACE_INSN :
141 if (WITH_TRACE_INSN_P)
142 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
143 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
144 else
145 sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
146 break;
147
148 case OPTION_TRACE_DECODE :
149 if (WITH_TRACE_DECODE_P)
150 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
151 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_DECODE_IDX] = 1;
152 else
153 sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
154 break;
155
156 case OPTION_TRACE_EXTRACT :
157 if (WITH_TRACE_EXTRACT_P)
158 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
159 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EXTRACT_IDX] = 1;
160 else
161 sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
162 break;
163
164 case OPTION_TRACE_LINENUM :
165 if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P)
166 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
167 {
168 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_LINENUM_IDX] = 1;
169 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
170 }
171 else
172 sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
173 break;
174
175 case OPTION_TRACE_MEMORY :
176 if (WITH_TRACE_MEMORY_P)
177 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
178 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1;
179 else
180 sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
181 break;
182
183 case OPTION_TRACE_MODEL :
184 if (WITH_TRACE_MODEL_P)
185 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
186 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MODEL_IDX] = 1;
187 else
188 sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
189 break;
190
191 case OPTION_TRACE_ALU :
192 if (WITH_TRACE_ALU_P)
193 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
194 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1;
195 else
196 sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
197 break;
198
199 case OPTION_TRACE_CORE :
200 if (WITH_TRACE_CORE_P)
201 {
202 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
203 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_CORE_IDX] = 1;
204 STATE_CORE(sd)->trace = 1;
205 }
206 else
207 sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
208 break;
209
210 case OPTION_TRACE_EVENTS :
211 if (WITH_TRACE_EVENTS_P)
212 {
213 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
214 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EVENTS_IDX] = 1;
215 STATE_EVENTS(sd)->trace = 1;
216 }
217 else
218 sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
219 break;
220
221 case OPTION_TRACE_FPU :
222 if (WITH_TRACE_FPU_P)
223 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
224 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
225 else
226 sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
227 break;
228
229 case OPTION_TRACE_BRANCH :
230 if (WITH_TRACE_BRANCH_P)
231 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
232 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
233 else
234 sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n");
235 break;
236
237 case OPTION_TRACE_SEMANTICS :
238 if (WITH_TRACE_ALU_P && WITH_TRACE_FPU_P && WITH_TRACE_MEMORY_P)
239 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
240 {
241 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1;
242 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
243 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1;
244 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_BRANCH_IDX] = 1;
245 }
246 else
247 sim_io_eprintf (sd, "Alu, fpu, and/or memory tracing not compiled in, `--trace-semantics' ignored\n");
248 break;
249
250 case OPTION_TRACE_FILE :
251 if (! WITH_TRACE)
252 sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
253 else
254 {
255 FILE *f = fopen (arg, "w");
256
257 if (f == NULL)
258 {
259 sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
260 return SIM_RC_FAIL;
261 }
262 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
263 TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f;
264 }
265 break;
266 }
267
268 return SIM_RC_OK;
269 }
270 \f
271 /* Install tracing support. */
272
273 SIM_RC
274 trace_install (SIM_DESC sd)
275 {
276 int i;
277
278 sim_add_option_table (sd, trace_options);
279 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
280 memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
281 sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i))));
282 sim_module_add_uninstall_fn (sd, trace_uninstall);
283 return SIM_RC_OK;
284 }
285
286 static void
287 trace_uninstall (SIM_DESC sd)
288 {
289 int i;
290
291 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
292 {
293 TRACE_DATA *data = CPU_TRACE_DATA (STATE_CPU (sd, i));
294 if (TRACE_FILE (data) != NULL)
295 fclose (TRACE_FILE (data));
296 }
297 }
298 \f
299 void
300 trace_one_insn (SIM_DESC sd, sim_cpu *cpu, address_word pc,
301 int line_p, const char *filename, int linenum,
302 const char *phase_wo_colon, const char *name)
303 {
304 char phase[SIZE_PHASE+2];
305
306 strncpy (phase, phase_wo_colon, SIZE_PHASE);
307 strcat (phase, ":");
308
309 if (!line_p)
310 trace_printf(sd, cpu, "%-*s %s:%-*d 0x%.*lx %s\n",
311 SIZE_PHASE+1, phase,
312 filename,
313 SIZE_LINE_NUMBER, linenum,
314 SIZE_PC, (long)pc,
315 name);
316
317 else
318 {
319 char buf[256];
320
321 buf[0] = 0;
322 if (STATE_TEXT_SECTION (CPU_STATE (cpu))
323 && pc >= STATE_TEXT_START (CPU_STATE (cpu))
324 && pc < STATE_TEXT_END (CPU_STATE (cpu)))
325 {
326 const char *pc_filename = (const char *)0;
327 const char *pc_function = (const char *)0;
328 unsigned int pc_linenum = 0;
329
330 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
331 STATE_TEXT_SECTION (CPU_STATE (cpu)),
332 (struct symbol_cache_entry **) 0,
333 pc - STATE_TEXT_START (CPU_STATE (cpu)),
334 &pc_filename, &pc_function, &pc_linenum))
335 {
336 char *p = buf;
337 if (pc_linenum)
338 {
339 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
340 p += strlen (p);
341 }
342 else
343 {
344 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
345 p += SIZE_LINE_NUMBER+2;
346 }
347
348 if (pc_function)
349 {
350 sprintf (p, "%s ", pc_function);
351 p += strlen (p);
352 }
353 else if (pc_filename)
354 {
355 char *q = (char *) strrchr (pc_filename, '/');
356 sprintf (p, "%s ", (q) ? q+1 : pc_filename);
357 p += strlen (p);
358 }
359
360 if (*p == ' ')
361 *p = '\0';
362 }
363 }
364
365 trace_printf (sd, cpu, "%-*s 0x%.*x %-*.*s %s\n",
366 SIZE_PHASE+1, phase,
367 SIZE_PC, (unsigned) pc,
368 SIZE_LOCATION, SIZE_LOCATION, buf,
369 name);
370 }
371 }
372 \f
373 void
374 trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...))
375 {
376 #ifndef __STDC__
377 SIM_DESC sd;
378 sim_cpu *cpu;
379 const char *fmt;
380 #endif
381 va_list ap;
382
383 VA_START (ap, fmt);
384 #ifndef __STDC__
385 sd = va_arg (ap, SIM_DESC);
386 cpu = va_arg (ap, sim_cpu *);
387 fmt = va_arg (ap, const char *);
388 #endif
389
390 if (cpu != NULL && TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
391 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
392 else
393 sim_io_evprintf (sd, fmt, ap);
394
395 va_end (ap);
396 }
397
398 void
399 debug_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...))
400 {
401 #ifndef __STDC__
402 sim_cpu *cpu;
403 const char *fmt;
404 #endif
405 va_list ap;
406
407 VA_START (ap, fmt);
408 #ifndef __STDC__
409 cpu = va_arg (ap, sim_cpu *);
410 fmt = va_arg (ap, const char *);
411 #endif
412
413 if (CPU_DEBUG_FILE (cpu) == NULL)
414 (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
415 (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
416 else
417 vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
418
419 va_end (ap);
420 }