b4f7704e37a9ce9f2be13ab07969a9c8e48a6a37
[platform/upstream/binutils.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
25 #ifdef HAVE_STRING_H
26 #include <string.h>
27 #else
28 #ifdef HAVE_STRINGS_H
29 #include <strings.h>
30 #endif
31 #endif
32
33 static MODULE_UNINSTALL_FN trace_uninstall;
34
35 static DECLARE_OPTION_HANDLER (trace_option_handler);
36
37 #define OPTION_TRACE_INSN       (OPTION_START + 0)
38 #define OPTION_TRACE_DECODE     (OPTION_START + 1)
39 #define OPTION_TRACE_EXTRACT    (OPTION_START + 2)
40 #define OPTION_TRACE_LINENUM    (OPTION_START + 3)
41 #define OPTION_TRACE_MEMORY     (OPTION_START + 4)
42 #define OPTION_TRACE_MODEL      (OPTION_START + 5)
43 #define OPTION_TRACE_ALU        (OPTION_START + 6)
44 #define OPTION_TRACE_CORE       (OPTION_START + 7)
45 #define OPTION_TRACE_EVENTS     (OPTION_START + 8)
46 #define OPTION_TRACE_FPU        (OPTION_START + 9)
47 #define OPTION_TRACE_FILE       (OPTION_START + 10)
48
49 static const OPTION trace_options[] =
50 {
51   { {"trace", no_argument, NULL, 't'},
52       't', NULL, "Perform tracing",
53       trace_option_handler },
54   { {"trace-insn", no_argument, NULL, OPTION_TRACE_INSN},
55       '\0', NULL, "Perform instruction tracing",
56       trace_option_handler },
57   { {"trace-decode", no_argument, NULL, OPTION_TRACE_DECODE},
58       '\0', NULL, "Perform instruction decoding tracing",
59       trace_option_handler },
60   { {"trace-extract", no_argument, NULL, OPTION_TRACE_EXTRACT},
61       '\0', NULL, "Perform instruction extraction tracing",
62       trace_option_handler },
63   { {"trace-linenum", no_argument, NULL, OPTION_TRACE_LINENUM},
64       '\0', NULL, "Perform line number tracing",
65       trace_option_handler },
66   { {"trace-memory", no_argument, NULL, OPTION_TRACE_MEMORY},
67       '\0', NULL, "Perform memory tracing",
68       trace_option_handler },
69   { {"trace-model", no_argument, NULL, OPTION_TRACE_MODEL},
70       '\0', NULL, "Perform model tracing",
71       trace_option_handler },
72   { {"trace-alu", no_argument, NULL, OPTION_TRACE_ALU},
73       '\0', NULL, "Perform ALU tracing",
74       trace_option_handler },
75   { {"trace-core", no_argument, NULL, OPTION_TRACE_CORE},
76       '\0', NULL, "Perform CORE tracing",
77       trace_option_handler },
78   { {"trace-events", no_argument, NULL, OPTION_TRACE_EVENTS},
79       '\0', NULL, "Perform EVENTS tracing",
80       trace_option_handler },
81   { {"trace-fpu", no_argument, NULL, OPTION_TRACE_FPU},
82       '\0', NULL, "Perform FPU tracing",
83       trace_option_handler },
84   { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE},
85       '\0', "FILE NAME", "Specify tracing output file",
86       trace_option_handler },
87   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
88 };
89
90 static SIM_RC
91 trace_option_handler (sd, opt, arg)
92      SIM_DESC sd;
93      int opt;
94      char *arg;
95 {
96   int i,n;
97
98   switch (opt)
99     {
100     case 't' :
101       if (! WITH_TRACE)
102         sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
103       else
104         {
105           for (n = 0; n < MAX_NR_PROCESSORS; ++n)
106             for (i = 0; i < MAX_TRACE_VALUES; ++i)
107               CPU_TRACE_FLAGS (STATE_CPU (sd, n))[i] = 1;
108           STATE_CORE(sd)->trace = 1;
109           STATE_EVENTS(sd)->trace = 1;
110         }
111       break;
112
113     case OPTION_TRACE_INSN :
114       if (WITH_TRACE_INSN_P)
115         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
116           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
117       else
118         sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
119       break;
120
121     case OPTION_TRACE_DECODE :
122       if (WITH_TRACE_DECODE_P)
123         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
124           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_DECODE_IDX] = 1;
125       else
126         sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
127       break;
128
129     case OPTION_TRACE_EXTRACT :
130       if (WITH_TRACE_EXTRACT_P)
131         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
132           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EXTRACT_IDX] = 1;
133       else
134         sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
135       break;
136
137     case OPTION_TRACE_LINENUM :
138       if (WITH_TRACE_LINENUM_P)
139         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
140           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_LINENUM_IDX] = 1;
141       else
142         sim_io_eprintf (sd, "Line number tracing not compiled in, `--trace-linenum' ignored\n");
143       break;
144
145     case OPTION_TRACE_MEMORY :
146       if (WITH_TRACE_MEMORY_P)
147         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
148           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1;
149       else
150         sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
151       break;
152
153     case OPTION_TRACE_MODEL :
154       if (WITH_TRACE_MODEL_P)
155         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
156           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MODEL_IDX] = 1;
157       else
158         sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
159       break;
160
161     case OPTION_TRACE_ALU :
162       if (WITH_TRACE_ALU_P)
163         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
164           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1;
165       else
166         sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
167       break;
168
169     case OPTION_TRACE_CORE :
170       if (WITH_TRACE_CORE_P)
171         {
172           for (n = 0; n < MAX_NR_PROCESSORS; ++n)
173             CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_CORE_IDX] = 1;
174           STATE_CORE(sd)->trace = 1;
175         }
176       else
177         sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
178       break;
179
180     case OPTION_TRACE_EVENTS :
181       if (WITH_TRACE_EVENTS_P)
182         {
183           for (n = 0; n < MAX_NR_PROCESSORS; ++n)
184             CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EVENTS_IDX] = 1;
185           STATE_EVENTS(sd)->trace = 1;
186         }
187       else
188         sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
189       break;
190
191     case OPTION_TRACE_FPU :
192       if (WITH_TRACE_FPU_P)
193         for (n = 0; n < MAX_NR_PROCESSORS; ++n)
194           CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
195       else
196         sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
197       break;
198
199     case OPTION_TRACE_FILE :
200       if (! WITH_TRACE)
201         sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
202       else
203         {
204           FILE *f = fopen (arg, "w");
205
206           if (f == NULL)
207             {
208               sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
209               return SIM_RC_FAIL;
210             }
211           for (n = 0; n < MAX_NR_PROCESSORS; ++n)
212             TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f;
213         }
214       break;
215     }
216
217   return SIM_RC_OK;
218 }
219 \f
220 /* Install tracing support.  */
221
222 SIM_RC
223 trace_install (SIM_DESC sd)
224 {
225   int i;
226
227   sim_add_option_table (sd, trace_options);
228   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
229     memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
230             sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i))));
231   sim_module_add_uninstall_fn (sd, trace_uninstall);
232   return SIM_RC_OK;
233 }
234
235 static void
236 trace_uninstall (SIM_DESC sd)
237 {
238   int i;
239
240   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
241     {
242       TRACE_DATA *data = CPU_TRACE_DATA (STATE_CPU (sd, i));
243       if (TRACE_FILE (data) != NULL)
244         fclose (TRACE_FILE (data));
245     }
246 }
247 \f
248 void
249 trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...))
250 {
251 #ifndef __STDC__
252   SIM_DESC sd;
253   sim_cpu *cpu;
254   const char *fmt;
255 #endif
256   va_list ap;
257
258   VA_START (ap, fmt);
259 #ifndef __STDC__
260   sd = va_arg (ap, SIM_DESC);
261   cpu = va_arg (ap, sim_cpu *);
262   fmt = va_arg (ap, const char *);
263 #endif
264
265   if (cpu != NULL && TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
266     vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
267   else
268     sim_io_evprintf (sd, fmt, ap);
269
270   va_end (ap);
271 }
272
273 void
274 debug_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...))
275 {
276 #ifndef __STDC__
277   sim_cpu *cpu;
278   const char *fmt;
279 #endif
280   va_list ap;
281
282   VA_START (ap, fmt);
283 #ifndef __STDC__
284   cpu = va_arg (ap, sim_cpu *);
285   fmt = va_arg (ap, const char *);
286 #endif
287
288   if (CPU_DEBUG_FILE (cpu) == NULL)
289     (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
290       (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
291   else
292     vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
293
294   va_end (ap);
295 }