Commit | Line | Data |
---|---|---|
e9b2f579 DE |
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" | |
3971886a | 23 | #include "sim-options.h" |
e9b2f579 | 24 | |
3971886a AC |
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 | |
e9b2f579 | 248 | void |
3971886a | 249 | trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...)) |
e9b2f579 DE |
250 | { |
251 | #ifndef __STDC__ | |
3971886a | 252 | SIM_DESC sd; |
e9b2f579 DE |
253 | sim_cpu *cpu; |
254 | const char *fmt; | |
255 | #endif | |
256 | va_list ap; | |
257 | ||
258 | VA_START (ap, fmt); | |
259 | #ifndef __STDC__ | |
3971886a | 260 | sd = va_arg (ap, SIM_DESC); |
e9b2f579 DE |
261 | cpu = va_arg (ap, sim_cpu *); |
262 | fmt = va_arg (ap, const char *); | |
263 | #endif | |
264 | ||
3971886a AC |
265 | if (cpu != NULL && TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL) |
266 | vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap); | |
e9b2f579 | 267 | else |
3971886a | 268 | sim_io_evprintf (sd, fmt, ap); |
e9b2f579 DE |
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 | } |