sim-trace.c revision 1.1.1.5 1 1.1 christos /* Simulator tracing/debugging support.
2 1.1.1.4 christos Copyright (C) 1997-2015 Free Software Foundation, Inc.
3 1.1 christos Contributed by Cygnus Support.
4 1.1 christos
5 1.1 christos This file is part of GDB, the GNU debugger.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos #include "sim-main.h"
21 1.1 christos #include "sim-io.h"
22 1.1 christos #include "sim-options.h"
23 1.1 christos #include "sim-fpu.h"
24 1.1 christos
25 1.1 christos #include "bfd.h"
26 1.1 christos #include "libiberty.h"
27 1.1 christos
28 1.1 christos #include "sim-assert.h"
29 1.1 christos
30 1.1 christos #ifdef HAVE_STRING_H
31 1.1 christos #include <string.h>
32 1.1 christos #else
33 1.1 christos #ifdef HAVE_STRINGS_H
34 1.1 christos #include <strings.h>
35 1.1 christos #endif
36 1.1 christos #endif
37 1.1 christos #ifdef HAVE_STDLIB_H
38 1.1 christos #include <stdlib.h>
39 1.1 christos #endif
40 1.1 christos
41 1.1 christos #ifndef SIZE_PHASE
42 1.1 christos #define SIZE_PHASE 8
43 1.1 christos #endif
44 1.1 christos
45 1.1 christos #ifndef SIZE_LOCATION
46 1.1 christos #define SIZE_LOCATION 20
47 1.1 christos #endif
48 1.1 christos
49 1.1 christos #ifndef SIZE_PC
50 1.1 christos #define SIZE_PC 6
51 1.1 christos #endif
52 1.1 christos
53 1.1 christos #ifndef SIZE_LINE_NUMBER
54 1.1 christos #define SIZE_LINE_NUMBER 4
55 1.1 christos #endif
56 1.1 christos
57 1.1 christos static MODULE_INIT_FN trace_init;
58 1.1 christos static MODULE_UNINSTALL_FN trace_uninstall;
59 1.1 christos
60 1.1 christos static DECLARE_OPTION_HANDLER (trace_option_handler);
61 1.1 christos
62 1.1 christos enum {
63 1.1 christos OPTION_TRACE_INSN = OPTION_START,
64 1.1 christos OPTION_TRACE_DECODE,
65 1.1 christos OPTION_TRACE_EXTRACT,
66 1.1 christos OPTION_TRACE_LINENUM,
67 1.1 christos OPTION_TRACE_MEMORY,
68 1.1 christos OPTION_TRACE_MODEL,
69 1.1 christos OPTION_TRACE_ALU,
70 1.1 christos OPTION_TRACE_CORE,
71 1.1 christos OPTION_TRACE_EVENTS,
72 1.1 christos OPTION_TRACE_FPU,
73 1.1 christos OPTION_TRACE_BRANCH,
74 1.1 christos OPTION_TRACE_SEMANTICS,
75 1.1 christos OPTION_TRACE_RANGE,
76 1.1 christos OPTION_TRACE_FUNCTION,
77 1.1 christos OPTION_TRACE_DEBUG,
78 1.1 christos OPTION_TRACE_FILE,
79 1.1.1.2 christos OPTION_TRACE_VPU,
80 1.1.1.5 christos OPTION_TRACE_SYSCALL,
81 1.1.1.5 christos OPTION_TRACE_REGISTER
82 1.1 christos };
83 1.1 christos
84 1.1 christos static const OPTION trace_options[] =
85 1.1 christos {
86 1.1 christos /* This table is organized to group related instructions together. */
87 1.1 christos { {"trace", optional_argument, NULL, 't'},
88 1.1 christos 't', "on|off", "Trace useful things",
89 1.1 christos trace_option_handler, NULL },
90 1.1 christos { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN},
91 1.1 christos '\0', "on|off", "Perform instruction tracing",
92 1.1 christos trace_option_handler, NULL },
93 1.1 christos { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE},
94 1.1 christos '\0', "on|off", "Trace instruction decoding",
95 1.1 christos trace_option_handler, NULL },
96 1.1 christos { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT},
97 1.1 christos '\0', "on|off", "Trace instruction extraction",
98 1.1 christos trace_option_handler, NULL },
99 1.1 christos { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM},
100 1.1 christos '\0', "on|off", "Perform line number tracing (implies --trace-insn)",
101 1.1 christos trace_option_handler, NULL },
102 1.1 christos { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY},
103 1.1 christos '\0', "on|off", "Trace memory operations",
104 1.1 christos trace_option_handler, NULL },
105 1.1 christos { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU},
106 1.1.1.5 christos '\0', "on|off", "Trace ALU (Arithmetic Logic Unit) operations",
107 1.1 christos trace_option_handler, NULL },
108 1.1 christos { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU},
109 1.1.1.5 christos '\0', "on|off", "Trace FPU (Floating Point Unit) operations",
110 1.1 christos trace_option_handler, NULL },
111 1.1 christos { {"trace-vpu", optional_argument, NULL, OPTION_TRACE_VPU},
112 1.1.1.5 christos '\0', "on|off", "Trace VPU (Vector Processing Unit) operations",
113 1.1 christos trace_option_handler, NULL },
114 1.1 christos { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH},
115 1.1 christos '\0', "on|off", "Trace branching",
116 1.1 christos trace_option_handler, NULL },
117 1.1 christos { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS},
118 1.1.1.5 christos '\0', "on|off", "Perform ALU, FPU, VPU, MEMORY, and BRANCH tracing",
119 1.1 christos trace_option_handler, NULL },
120 1.1 christos { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL},
121 1.1 christos '\0', "on|off", "Include model performance data",
122 1.1 christos trace_option_handler, NULL },
123 1.1 christos { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE},
124 1.1 christos '\0', "on|off", "Trace core operations",
125 1.1 christos trace_option_handler, NULL },
126 1.1 christos { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS},
127 1.1 christos '\0', "on|off", "Trace events",
128 1.1 christos trace_option_handler, NULL },
129 1.1.1.2 christos { {"trace-syscall", optional_argument, NULL, OPTION_TRACE_SYSCALL},
130 1.1.1.2 christos '\0', "on|off", "Trace system calls",
131 1.1.1.2 christos trace_option_handler, NULL },
132 1.1.1.5 christos { {"trace-register", optional_argument, NULL, OPTION_TRACE_REGISTER},
133 1.1.1.5 christos '\0', "on|off", "Trace cpu register accesses",
134 1.1.1.5 christos trace_option_handler, NULL },
135 1.1 christos #ifdef SIM_HAVE_ADDR_RANGE
136 1.1 christos { {"trace-range", required_argument, NULL, OPTION_TRACE_RANGE},
137 1.1 christos '\0', "START,END", "Specify range of addresses for instruction tracing",
138 1.1 christos trace_option_handler, NULL },
139 1.1 christos #if 0 /*wip*/
140 1.1 christos { {"trace-function", required_argument, NULL, OPTION_TRACE_FUNCTION},
141 1.1 christos '\0', "FUNCTION", "Specify function to trace",
142 1.1 christos trace_option_handler, NULL },
143 1.1 christos #endif
144 1.1 christos #endif
145 1.1 christos { {"trace-debug", optional_argument, NULL, OPTION_TRACE_DEBUG},
146 1.1 christos '\0', "on|off", "Add information useful for debugging the simulator to the tracing output",
147 1.1 christos trace_option_handler, NULL },
148 1.1 christos { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE},
149 1.1 christos '\0', "FILE NAME", "Specify tracing output file",
150 1.1 christos trace_option_handler, NULL },
151 1.1 christos { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
152 1.1 christos };
153 1.1 christos
154 1.1 christos /* Set/reset the trace options indicated in MASK. */
155 1.1 christos
156 1.1 christos static SIM_RC
157 1.1 christos set_trace_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg)
158 1.1 christos {
159 1.1 christos int trace_nr;
160 1.1 christos int cpu_nr;
161 1.1 christos int trace_val = 1;
162 1.1 christos
163 1.1 christos if (arg != NULL)
164 1.1 christos {
165 1.1 christos if (strcmp (arg, "yes") == 0
166 1.1 christos || strcmp (arg, "on") == 0
167 1.1 christos || strcmp (arg, "1") == 0)
168 1.1 christos trace_val = 1;
169 1.1 christos else if (strcmp (arg, "no") == 0
170 1.1 christos || strcmp (arg, "off") == 0
171 1.1 christos || strcmp (arg, "0") == 0)
172 1.1 christos trace_val = 0;
173 1.1 christos else
174 1.1 christos {
175 1.1 christos sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name);
176 1.1 christos return SIM_RC_FAIL;
177 1.1 christos }
178 1.1 christos }
179 1.1 christos
180 1.1.1.5 christos /* Update applicable trace bits. */
181 1.1 christos for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr)
182 1.1 christos {
183 1.1 christos if ((mask & (1 << trace_nr)) == 0)
184 1.1 christos continue;
185 1.1 christos
186 1.1 christos /* Set non-cpu specific values. */
187 1.1.1.5 christos STATE_TRACE_FLAGS (sd)[trace_nr] = trace_val;
188 1.1 christos
189 1.1 christos /* Set cpu values. */
190 1.1 christos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
191 1.1 christos {
192 1.1 christos CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val;
193 1.1 christos }
194 1.1 christos }
195 1.1 christos
196 1.1 christos /* Re-compute the cpu trace summary. */
197 1.1 christos if (trace_val)
198 1.1 christos {
199 1.1 christos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
200 1.1 christos CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1;
201 1.1 christos }
202 1.1 christos else
203 1.1 christos {
204 1.1 christos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
205 1.1 christos {
206 1.1 christos CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 0;
207 1.1 christos for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr)
208 1.1 christos {
209 1.1 christos if (CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr])
210 1.1 christos {
211 1.1 christos CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1;
212 1.1 christos break;
213 1.1 christos }
214 1.1 christos }
215 1.1 christos }
216 1.1 christos }
217 1.1 christos
218 1.1 christos return SIM_RC_OK;
219 1.1 christos }
220 1.1 christos
221 1.1 christos /* Set one trace option based on its IDX value. */
222 1.1 christos
223 1.1 christos static SIM_RC
224 1.1 christos set_trace_option (SIM_DESC sd, const char *name, int idx, const char *arg)
225 1.1 christos {
226 1.1 christos return set_trace_option_mask (sd, name, 1 << idx, arg);
227 1.1 christos }
228 1.1 christos
229 1.1 christos
230 1.1 christos static SIM_RC
231 1.1 christos trace_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
232 1.1 christos char *arg, int is_command)
233 1.1 christos {
234 1.1 christos int n;
235 1.1 christos
236 1.1 christos switch (opt)
237 1.1 christos {
238 1.1 christos case 't' :
239 1.1.1.5 christos if (!WITH_TRACE_ANY_P)
240 1.1 christos sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
241 1.1 christos else
242 1.1 christos return set_trace_option_mask (sd, "trace", TRACE_USEFUL_MASK, arg);
243 1.1 christos break;
244 1.1 christos
245 1.1 christos case OPTION_TRACE_INSN :
246 1.1 christos if (WITH_TRACE_INSN_P)
247 1.1 christos return set_trace_option (sd, "-insn", TRACE_INSN_IDX, arg);
248 1.1 christos else
249 1.1 christos sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
250 1.1 christos break;
251 1.1 christos
252 1.1 christos case OPTION_TRACE_DECODE :
253 1.1 christos if (WITH_TRACE_DECODE_P)
254 1.1 christos return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg);
255 1.1 christos else
256 1.1 christos sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
257 1.1 christos break;
258 1.1 christos
259 1.1 christos case OPTION_TRACE_EXTRACT :
260 1.1 christos if (WITH_TRACE_EXTRACT_P)
261 1.1 christos return set_trace_option (sd, "-extract", TRACE_EXTRACT_IDX, arg);
262 1.1 christos else
263 1.1 christos sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
264 1.1 christos break;
265 1.1 christos
266 1.1 christos case OPTION_TRACE_LINENUM :
267 1.1 christos if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P)
268 1.1 christos {
269 1.1 christos if (set_trace_option (sd, "-linenum", TRACE_LINENUM_IDX, arg) != SIM_RC_OK
270 1.1 christos || set_trace_option (sd, "-linenum", TRACE_INSN_IDX, arg) != SIM_RC_OK)
271 1.1 christos return SIM_RC_FAIL;
272 1.1 christos }
273 1.1 christos else
274 1.1 christos sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
275 1.1 christos break;
276 1.1 christos
277 1.1 christos case OPTION_TRACE_MEMORY :
278 1.1 christos if (WITH_TRACE_MEMORY_P)
279 1.1 christos return set_trace_option (sd, "-memory", TRACE_MEMORY_IDX, arg);
280 1.1 christos else
281 1.1 christos sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
282 1.1 christos break;
283 1.1 christos
284 1.1 christos case OPTION_TRACE_MODEL :
285 1.1 christos if (WITH_TRACE_MODEL_P)
286 1.1 christos return set_trace_option (sd, "-model", TRACE_MODEL_IDX, arg);
287 1.1 christos else
288 1.1 christos sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
289 1.1 christos break;
290 1.1 christos
291 1.1 christos case OPTION_TRACE_ALU :
292 1.1 christos if (WITH_TRACE_ALU_P)
293 1.1 christos return set_trace_option (sd, "-alu", TRACE_ALU_IDX, arg);
294 1.1 christos else
295 1.1 christos sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
296 1.1 christos break;
297 1.1 christos
298 1.1 christos case OPTION_TRACE_CORE :
299 1.1 christos if (WITH_TRACE_CORE_P)
300 1.1 christos return set_trace_option (sd, "-core", TRACE_CORE_IDX, arg);
301 1.1 christos else
302 1.1 christos sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
303 1.1 christos break;
304 1.1 christos
305 1.1 christos case OPTION_TRACE_EVENTS :
306 1.1 christos if (WITH_TRACE_EVENTS_P)
307 1.1 christos return set_trace_option (sd, "-events", TRACE_EVENTS_IDX, arg);
308 1.1 christos else
309 1.1 christos sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
310 1.1 christos break;
311 1.1 christos
312 1.1 christos case OPTION_TRACE_FPU :
313 1.1 christos if (WITH_TRACE_FPU_P)
314 1.1 christos return set_trace_option (sd, "-fpu", TRACE_FPU_IDX, arg);
315 1.1 christos else
316 1.1 christos sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
317 1.1 christos break;
318 1.1 christos
319 1.1 christos case OPTION_TRACE_VPU :
320 1.1 christos if (WITH_TRACE_VPU_P)
321 1.1 christos return set_trace_option (sd, "-vpu", TRACE_VPU_IDX, arg);
322 1.1 christos else
323 1.1 christos sim_io_eprintf (sd, "VPU tracing not compiled in, `--trace-vpu' ignored\n");
324 1.1 christos break;
325 1.1 christos
326 1.1 christos case OPTION_TRACE_BRANCH :
327 1.1 christos if (WITH_TRACE_BRANCH_P)
328 1.1 christos return set_trace_option (sd, "-branch", TRACE_BRANCH_IDX, arg);
329 1.1 christos else
330 1.1 christos sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n");
331 1.1 christos break;
332 1.1 christos
333 1.1.1.2 christos case OPTION_TRACE_SYSCALL :
334 1.1.1.2 christos if (WITH_TRACE_SYSCALL_P)
335 1.1.1.2 christos return set_trace_option (sd, "-syscall", TRACE_SYSCALL_IDX, arg);
336 1.1.1.2 christos else
337 1.1.1.2 christos sim_io_eprintf (sd, "System call tracing not compiled in, `--trace-syscall' ignored\n");
338 1.1.1.2 christos break;
339 1.1.1.2 christos
340 1.1.1.5 christos case OPTION_TRACE_REGISTER :
341 1.1.1.5 christos if (WITH_TRACE_REGISTER_P)
342 1.1.1.5 christos return set_trace_option (sd, "-register", TRACE_REGISTER_IDX, arg);
343 1.1.1.5 christos else
344 1.1.1.5 christos sim_io_eprintf (sd, "Register tracing not compiled in, `--trace-register' ignored\n");
345 1.1.1.5 christos break;
346 1.1.1.5 christos
347 1.1 christos case OPTION_TRACE_SEMANTICS :
348 1.1 christos if (WITH_TRACE_ALU_P
349 1.1 christos && WITH_TRACE_FPU_P
350 1.1 christos && WITH_TRACE_MEMORY_P
351 1.1 christos && WITH_TRACE_BRANCH_P)
352 1.1 christos {
353 1.1 christos if (set_trace_option (sd, "-semantics", TRACE_ALU_IDX, arg) != SIM_RC_OK
354 1.1 christos || set_trace_option (sd, "-semantics", TRACE_FPU_IDX, arg) != SIM_RC_OK
355 1.1 christos || set_trace_option (sd, "-semantics", TRACE_VPU_IDX, arg) != SIM_RC_OK
356 1.1 christos || set_trace_option (sd, "-semantics", TRACE_MEMORY_IDX, arg) != SIM_RC_OK
357 1.1 christos || set_trace_option (sd, "-semantics", TRACE_BRANCH_IDX, arg) != SIM_RC_OK)
358 1.1 christos return SIM_RC_FAIL;
359 1.1 christos }
360 1.1 christos else
361 1.1 christos sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n");
362 1.1 christos break;
363 1.1 christos
364 1.1 christos #ifdef SIM_HAVE_ADDR_RANGE
365 1.1 christos case OPTION_TRACE_RANGE :
366 1.1.1.5 christos if (WITH_TRACE_ANY_P)
367 1.1 christos {
368 1.1 christos int cpu_nr;
369 1.1 christos char *chp = arg;
370 1.1 christos unsigned long start,end;
371 1.1 christos start = strtoul (chp, &chp, 0);
372 1.1 christos if (*chp != ',')
373 1.1 christos {
374 1.1 christos sim_io_eprintf (sd, "--trace-range missing END argument\n");
375 1.1 christos return SIM_RC_FAIL;
376 1.1 christos }
377 1.1 christos end = strtoul (chp + 1, NULL, 0);
378 1.1 christos /* FIXME: Argument validation. */
379 1.1 christos if (cpu != NULL)
380 1.1 christos sim_addr_range_add (TRACE_RANGE (CPU_PROFILE_DATA (cpu)),
381 1.1 christos start, end);
382 1.1 christos else
383 1.1 christos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
384 1.1 christos sim_addr_range_add (TRACE_RANGE (CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))),
385 1.1 christos start, end);
386 1.1 christos }
387 1.1 christos else
388 1.1 christos sim_io_eprintf (sd, "Tracing not compiled in, `--trace-range' ignored\n");
389 1.1 christos break;
390 1.1 christos
391 1.1 christos case OPTION_TRACE_FUNCTION :
392 1.1.1.5 christos if (WITH_TRACE_ANY_P)
393 1.1 christos {
394 1.1 christos /*wip: need to compute function range given name*/
395 1.1 christos }
396 1.1 christos else
397 1.1 christos sim_io_eprintf (sd, "Tracing not compiled in, `--trace-function' ignored\n");
398 1.1 christos break;
399 1.1 christos #endif /* SIM_HAVE_ADDR_RANGE */
400 1.1 christos
401 1.1 christos case OPTION_TRACE_DEBUG :
402 1.1 christos if (WITH_TRACE_DEBUG_P)
403 1.1 christos return set_trace_option (sd, "-debug", TRACE_DEBUG_IDX, arg);
404 1.1 christos else
405 1.1 christos sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n");
406 1.1 christos break;
407 1.1 christos
408 1.1 christos case OPTION_TRACE_FILE :
409 1.1.1.5 christos if (!WITH_TRACE_ANY_P)
410 1.1 christos sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
411 1.1 christos else
412 1.1 christos {
413 1.1 christos FILE *f = fopen (arg, "w");
414 1.1 christos
415 1.1 christos if (f == NULL)
416 1.1 christos {
417 1.1 christos sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
418 1.1 christos return SIM_RC_FAIL;
419 1.1 christos }
420 1.1 christos for (n = 0; n < MAX_NR_PROCESSORS; ++n)
421 1.1 christos TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f;
422 1.1 christos TRACE_FILE (STATE_TRACE_DATA (sd)) = f;
423 1.1 christos }
424 1.1 christos break;
425 1.1 christos }
426 1.1 christos
427 1.1 christos return SIM_RC_OK;
428 1.1 christos }
429 1.1 christos
430 1.1 christos /* Install tracing support. */
432 1.1 christos
433 1.1 christos SIM_RC
434 1.1 christos trace_install (SIM_DESC sd)
435 1.1 christos {
436 1.1 christos int i;
437 1.1 christos
438 1.1 christos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
439 1.1 christos
440 1.1 christos sim_add_option_table (sd, NULL, trace_options);
441 1.1 christos memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd)));
442 1.1 christos for (i = 0; i < MAX_NR_PROCESSORS; ++i)
443 1.1 christos memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
444 1.1 christos sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i))));
445 1.1 christos sim_module_add_init_fn (sd, trace_init);
446 1.1 christos sim_module_add_uninstall_fn (sd, trace_uninstall);
447 1.1 christos return SIM_RC_OK;
448 1.1 christos }
449 1.1 christos
450 1.1 christos static SIM_RC
451 1.1 christos trace_init (SIM_DESC sd)
452 1.1 christos {
453 1.1 christos #ifdef SIM_HAVE_ADDR_RANGE
454 1.1 christos /* Check if a range has been specified without specifying what to
455 1.1 christos collect. */
456 1.1 christos {
457 1.1 christos int i;
458 1.1 christos
459 1.1 christos for (i = 0; i < MAX_NR_PROCESSORS; ++i)
460 1.1 christos {
461 1.1 christos sim_cpu *cpu = STATE_CPU (sd, i);
462 1.1 christos
463 1.1 christos if (ADDR_RANGE_RANGES (TRACE_RANGE (CPU_TRACE_DATA (cpu)))
464 1.1 christos && ! TRACE_INSN_P (cpu))
465 1.1 christos {
466 1.1 christos sim_io_eprintf_cpu (cpu, "Tracing address range specified without --trace-insn.\n");
467 1.1 christos sim_io_eprintf_cpu (cpu, "Address range ignored.\n");
468 1.1 christos sim_addr_range_delete (TRACE_RANGE (CPU_TRACE_DATA (cpu)),
469 1.1 christos 0, ~ (address_word) 0);
470 1.1 christos }
471 1.1 christos }
472 1.1 christos }
473 1.1 christos #endif
474 1.1 christos
475 1.1 christos return SIM_RC_OK;
476 1.1 christos }
477 1.1 christos
478 1.1 christos static void
479 1.1 christos trace_uninstall (SIM_DESC sd)
480 1.1 christos {
481 1.1 christos int i,j;
482 1.1 christos FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd));
483 1.1 christos
484 1.1 christos if (sfile != NULL)
485 1.1 christos fclose (sfile);
486 1.1 christos
487 1.1 christos for (i = 0; i < MAX_NR_PROCESSORS; ++i)
488 1.1 christos {
489 1.1 christos FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i)));
490 1.1 christos if (cfile != NULL && cfile != sfile)
491 1.1 christos {
492 1.1 christos /* If output from different cpus is going to the same file,
493 1.1 christos avoid closing the file twice. */
494 1.1 christos for (j = 0; j < i; ++j)
495 1.1 christos if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile)
496 1.1 christos break;
497 1.1 christos if (i == j)
498 1.1 christos fclose (cfile);
499 1.1 christos }
500 1.1 christos }
501 1.1 christos }
502 1.1 christos
503 1.1 christos /* compute the nr of trace data units consumed by data */
505 1.1 christos static int
506 1.1 christos save_data_size (TRACE_DATA *data,
507 1.1 christos long size)
508 1.1 christos {
509 1.1 christos return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1)
510 1.1 christos / sizeof (TRACE_INPUT_DATA (data) [0]));
511 1.1 christos }
512 1.1 christos
513 1.1.1.2 christos
514 1.1 christos /* Archive DATA into the trace buffer */
515 1.1 christos void
516 1.1 christos save_data (SIM_DESC sd,
517 1.1 christos TRACE_DATA *data,
518 1.1 christos data_fmt fmt,
519 1.1 christos long size,
520 1.1 christos const void *buf)
521 1.1 christos {
522 1.1 christos int i = TRACE_INPUT_IDX (data);
523 1.1 christos if (i == sizeof (TRACE_INPUT_FMT (data)))
524 1.1 christos sim_io_error (sd, "trace buffer overflow");
525 1.1 christos TRACE_INPUT_FMT (data) [i] = fmt;
526 1.1 christos TRACE_INPUT_SIZE (data) [i] = size;
527 1.1 christos memcpy (&TRACE_INPUT_DATA (data) [i], buf, size);
528 1.1 christos i += save_data_size (data, size);
529 1.1 christos TRACE_INPUT_IDX (data) = i;
530 1.1 christos }
531 1.1 christos
532 1.1 christos static void
533 1.1 christos print_data (SIM_DESC sd,
534 1.1 christos sim_cpu *cpu,
535 1.1 christos data_fmt fmt,
536 1.1 christos long size,
537 1.1 christos void *data)
538 1.1 christos {
539 1.1 christos switch (fmt)
540 1.1 christos {
541 1.1 christos case trace_fmt_instruction_incomplete:
542 1.1 christos trace_printf (sd, cpu, " (instruction incomplete)");
543 1.1 christos break;
544 1.1 christos case trace_fmt_word:
545 1.1 christos case trace_fmt_addr:
546 1.1 christos {
547 1.1 christos switch (size)
548 1.1 christos {
549 1.1 christos case sizeof (unsigned32):
550 1.1 christos trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned32*) data);
551 1.1 christos break;
552 1.1 christos case sizeof (unsigned64):
553 1.1 christos trace_printf (sd, cpu, " 0x%08lx%08lx",
554 1.1 christos (long) ((* (unsigned64*) data) >> 32),
555 1.1 christos (long) * (unsigned64*) data);
556 1.1 christos break;
557 1.1 christos default:
558 1.1 christos abort ();
559 1.1 christos }
560 1.1 christos break;
561 1.1 christos }
562 1.1 christos case trace_fmt_bool:
563 1.1 christos {
564 1.1 christos SIM_ASSERT (size == sizeof (int));
565 1.1 christos trace_printf (sd, cpu, " %-8s",
566 1.1 christos (* (int*) data) ? "true" : "false");
567 1.1 christos break;
568 1.1 christos }
569 1.1 christos case trace_fmt_fp:
570 1.1 christos {
571 1.1 christos sim_fpu fp;
572 1.1 christos switch (size)
573 1.1 christos {
574 1.1 christos /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */
575 1.1 christos case 4:
576 1.1 christos sim_fpu_32to (&fp, *(unsigned32*)data);
577 1.1 christos break;
578 1.1 christos case 8:
579 1.1 christos sim_fpu_64to (&fp, *(unsigned64*)data);
580 1.1 christos break;
581 1.1 christos default:
582 1.1 christos abort ();
583 1.1 christos }
584 1.1 christos trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp));
585 1.1 christos switch (size)
586 1.1 christos {
587 1.1 christos case 4:
588 1.1 christos trace_printf (sd, cpu, " (0x%08lx)",
589 1.1 christos (long) *(unsigned32*)data);
590 1.1 christos break;
591 1.1 christos case 8:
592 1.1 christos trace_printf (sd, cpu, " (0x%08lx%08lx)",
593 1.1 christos (long) (*(unsigned64*)data >> 32),
594 1.1 christos (long) (*(unsigned64*)data));
595 1.1 christos break;
596 1.1 christos default:
597 1.1 christos abort ();
598 1.1 christos }
599 1.1 christos break;
600 1.1 christos }
601 1.1 christos case trace_fmt_fpu:
602 1.1 christos /* FIXME: At present sim_fpu data is stored as a double */
603 1.1 christos trace_printf (sd, cpu, " %8g", * (double*) data);
604 1.1 christos break;
605 1.1 christos case trace_fmt_string:
606 1.1 christos trace_printf (sd, cpu, " %-8s", (char*) data);
607 1.1 christos break;
608 1.1 christos default:
609 1.1 christos abort ();
610 1.1 christos }
611 1.1 christos }
612 1.1 christos
613 1.1 christos static const char *
614 1.1 christos trace_idx_to_str (int trace_idx)
615 1.1 christos {
616 1.1 christos static char num[8];
617 1.1.1.5 christos switch (trace_idx)
618 1.1.1.5 christos {
619 1.1.1.5 christos case TRACE_ALU_IDX: return "alu: ";
620 1.1.1.5 christos case TRACE_INSN_IDX: return "insn: ";
621 1.1.1.5 christos case TRACE_DECODE_IDX: return "decode: ";
622 1.1.1.5 christos case TRACE_EXTRACT_IDX: return "extract: ";
623 1.1.1.5 christos case TRACE_MEMORY_IDX: return "memory: ";
624 1.1.1.5 christos case TRACE_CORE_IDX: return "core: ";
625 1.1.1.5 christos case TRACE_EVENTS_IDX: return "events: ";
626 1.1.1.5 christos case TRACE_FPU_IDX: return "fpu: ";
627 1.1.1.5 christos case TRACE_BRANCH_IDX: return "branch: ";
628 1.1.1.5 christos case TRACE_SYSCALL_IDX: return "syscall: ";
629 1.1 christos case TRACE_REGISTER_IDX: return "reg: ";
630 1.1 christos case TRACE_VPU_IDX: return "vpu: ";
631 1.1 christos default:
632 1.1 christos sprintf (num, "?%d?", trace_idx);
633 1.1 christos return num;
634 1.1 christos }
635 1.1 christos }
636 1.1 christos
637 1.1 christos static void
638 1.1 christos trace_results (SIM_DESC sd,
639 1.1 christos sim_cpu *cpu,
640 1.1 christos int trace_idx,
641 1.1 christos int last_input)
642 1.1 christos {
643 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
644 1.1 christos int nr_out;
645 1.1 christos int i;
646 1.1 christos
647 1.1 christos /* cross check trace_idx against TRACE_IDX (data)? */
648 1.1 christos
649 1.1 christos /* prefix */
650 1.1 christos trace_printf (sd, cpu, "%s %s",
651 1.1 christos trace_idx_to_str (TRACE_IDX (data)),
652 1.1 christos TRACE_PREFIX (data));
653 1.1 christos TRACE_IDX (data) = 0;
654 1.1 christos
655 1.1 christos for (i = 0, nr_out = 0;
656 1.1 christos i < TRACE_INPUT_IDX (data);
657 1.1 christos i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++)
658 1.1 christos {
659 1.1 christos if (i == last_input)
660 1.1 christos {
661 1.1 christos int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2);
662 1.1 christos int padding = pad * (3 - nr_out);
663 1.1 christos if (padding < 0)
664 1.1 christos padding = 0;
665 1.1 christos padding += strlen (" ::");
666 1.1 christos trace_printf (sd, cpu, "%*s", padding, " ::");
667 1.1 christos }
668 1.1 christos print_data (sd, cpu,
669 1.1 christos TRACE_INPUT_FMT (data) [i],
670 1.1 christos TRACE_INPUT_SIZE (data) [i],
671 1.1 christos &TRACE_INPUT_DATA (data) [i]);
672 1.1 christos }
673 1.1 christos trace_printf (sd, cpu, "\n");
674 1.1 christos }
675 1.1 christos
676 1.1 christos void
677 1.1 christos trace_prefix (SIM_DESC sd,
678 1.1 christos sim_cpu *cpu,
679 1.1 christos sim_cia cia,
680 1.1 christos address_word pc,
681 1.1 christos int line_p,
682 1.1 christos const char *filename,
683 1.1 christos int linenum,
684 1.1 christos const char *fmt,
685 1.1 christos ...)
686 1.1 christos {
687 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
688 1.1 christos va_list ap;
689 1.1 christos char *prefix = TRACE_PREFIX (data);
690 1.1 christos char *chp;
691 1.1 christos /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using
692 1.1 christos known information about the disassembled instructions. */
693 1.1 christos #ifndef TRACE_PREFIX_WIDTH
694 1.1 christos #define TRACE_PREFIX_WIDTH 48
695 1.1 christos #endif
696 1.1 christos int width = TRACE_PREFIX_WIDTH;
697 1.1 christos
698 1.1 christos /* if the previous trace data wasn't flushed, flush it now with a
699 1.1 christos note indicating that the trace was incomplete. */
700 1.1 christos if (TRACE_IDX (data) != 0)
701 1.1 christos {
702 1.1 christos int last_input = TRACE_INPUT_IDX (data);
703 1.1 christos save_data (sd, data, trace_fmt_instruction_incomplete, 1, "");
704 1.1 christos trace_results (sd, cpu, TRACE_IDX (data), last_input);
705 1.1 christos }
706 1.1 christos TRACE_IDX (data) = 0;
707 1.1 christos TRACE_INPUT_IDX (data) = 0;
708 1.1 christos
709 1.1 christos /* Create the text prefix for this new instruction: */
710 1.1 christos if (!line_p)
711 1.1 christos {
712 1.1 christos if (filename)
713 1.1 christos {
714 1.1 christos sprintf (prefix, "%s:%-*d 0x%.*lx ",
715 1.1 christos filename,
716 1.1 christos SIZE_LINE_NUMBER, linenum,
717 1.1 christos SIZE_PC, (long) pc);
718 1.1 christos }
719 1.1 christos else
720 1.1 christos {
721 1.1 christos sprintf (prefix, "0x%.*lx ",
722 1.1 christos SIZE_PC, (long) pc);
723 1.1 christos /* Shrink the width by the amount that we didn't print. */
724 1.1 christos width -= SIZE_LINE_NUMBER + SIZE_PC + 8;
725 1.1 christos }
726 1.1 christos chp = strchr (prefix, '\0');
727 1.1 christos va_start (ap, fmt);
728 1.1 christos vsprintf (chp, fmt, ap);
729 1.1 christos va_end (ap);
730 1.1 christos }
731 1.1 christos else
732 1.1 christos {
733 1.1 christos char buf[256];
734 1.1 christos buf[0] = 0;
735 1.1 christos if (STATE_TEXT_SECTION (CPU_STATE (cpu))
736 1.1 christos && pc >= STATE_TEXT_START (CPU_STATE (cpu))
737 1.1 christos && pc < STATE_TEXT_END (CPU_STATE (cpu)))
738 1.1 christos {
739 1.1 christos const char *pc_filename = (const char *)0;
740 1.1 christos const char *pc_function = (const char *)0;
741 1.1 christos unsigned int pc_linenum = 0;
742 1.1 christos bfd *abfd;
743 1.1 christos asymbol **asymbols;
744 1.1 christos
745 1.1 christos abfd = STATE_PROG_BFD (CPU_STATE (cpu));
746 1.1 christos asymbols = STATE_PROG_SYMS (CPU_STATE (cpu));
747 1.1 christos if (asymbols == NULL)
748 1.1 christos {
749 1.1 christos long symsize;
750 1.1 christos long symbol_count;
751 1.1 christos
752 1.1 christos symsize = bfd_get_symtab_upper_bound (abfd);
753 1.1 christos if (symsize < 0)
754 1.1 christos {
755 1.1 christos sim_engine_abort (sd, cpu, cia, "could not read symbols");
756 1.1 christos }
757 1.1 christos asymbols = (asymbol **) xmalloc (symsize);
758 1.1 christos symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
759 1.1 christos if (symbol_count < 0)
760 1.1 christos {
761 1.1 christos sim_engine_abort (sd, cpu, cia, "could not canonicalize symbols");
762 1.1 christos }
763 1.1 christos STATE_PROG_SYMS (CPU_STATE (cpu)) = asymbols;
764 1.1 christos }
765 1.1 christos
766 1.1 christos if (bfd_find_nearest_line (abfd,
767 1.1 christos STATE_TEXT_SECTION (CPU_STATE (cpu)),
768 1.1 christos asymbols,
769 1.1 christos pc - STATE_TEXT_START (CPU_STATE (cpu)),
770 1.1 christos &pc_filename, &pc_function, &pc_linenum))
771 1.1 christos {
772 1.1 christos char *p = buf;
773 1.1 christos if (pc_linenum)
774 1.1 christos {
775 1.1 christos sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
776 1.1 christos p += strlen (p);
777 1.1 christos }
778 1.1 christos else
779 1.1 christos {
780 1.1 christos sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
781 1.1 christos p += SIZE_LINE_NUMBER+2;
782 1.1 christos }
783 1.1 christos
784 1.1 christos if (pc_function)
785 1.1 christos {
786 1.1 christos sprintf (p, "%s ", pc_function);
787 1.1 christos p += strlen (p);
788 1.1 christos }
789 1.1 christos else if (pc_filename)
790 1.1 christos {
791 1.1 christos char *q = (char *) strrchr (pc_filename, '/');
792 1.1 christos sprintf (p, "%s ", (q) ? q+1 : pc_filename);
793 1.1 christos p += strlen (p);
794 1.1 christos }
795 1.1 christos
796 1.1 christos if (*p == ' ')
797 1.1 christos *p = '\0';
798 1.1 christos }
799 1.1 christos }
800 1.1 christos
801 1.1 christos sprintf (prefix, "0x%.*x %-*.*s ",
802 1.1 christos SIZE_PC, (unsigned) pc,
803 1.1 christos SIZE_LOCATION, SIZE_LOCATION, buf);
804 1.1 christos chp = strchr (prefix, '\0');
805 1.1 christos va_start (ap, fmt);
806 1.1 christos vsprintf (chp, fmt, ap);
807 1.1 christos va_end (ap);
808 1.1 christos }
809 1.1 christos
810 1.1 christos /* Pad it out to TRACE_PREFIX_WIDTH. */
811 1.1 christos chp = strchr (prefix, '\0');
812 1.1 christos if (chp - prefix < width)
813 1.1 christos {
814 1.1 christos memset (chp, ' ', width - (chp - prefix));
815 1.1 christos chp = &prefix [width];
816 1.1 christos *chp = '\0';
817 1.1 christos }
818 1.1 christos strcpy (chp, " -");
819 1.1 christos
820 1.1 christos /* check that we've not over flowed the prefix buffer */
821 1.1 christos if (strlen (prefix) >= sizeof (TRACE_PREFIX (data)))
822 1.1 christos abort ();
823 1.1 christos }
824 1.1 christos
825 1.1 christos void
826 1.1 christos trace_generic (SIM_DESC sd,
827 1.1 christos sim_cpu *cpu,
828 1.1 christos int trace_idx,
829 1.1 christos const char *fmt,
830 1.1 christos ...)
831 1.1 christos {
832 1.1 christos va_list ap;
833 1.1 christos trace_printf (sd, cpu, "%s %s",
834 1.1 christos trace_idx_to_str (trace_idx),
835 1.1 christos TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
836 1.1 christos va_start (ap, fmt);
837 1.1 christos trace_vprintf (sd, cpu, fmt, ap);
838 1.1 christos va_end (ap);
839 1.1 christos trace_printf (sd, cpu, "\n");
840 1.1 christos }
841 1.1 christos
842 1.1 christos void
843 1.1 christos trace_input0 (SIM_DESC sd,
844 1.1 christos sim_cpu *cpu,
845 1.1 christos int trace_idx)
846 1.1 christos {
847 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
848 1.1 christos TRACE_IDX (data) = trace_idx;
849 1.1 christos }
850 1.1 christos
851 1.1 christos void
852 1.1 christos trace_input_word1 (SIM_DESC sd,
853 1.1 christos sim_cpu *cpu,
854 1.1 christos int trace_idx,
855 1.1 christos unsigned_word d0)
856 1.1 christos {
857 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
858 1.1 christos TRACE_IDX (data) = trace_idx;
859 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
860 1.1 christos }
861 1.1 christos
862 1.1 christos void
863 1.1 christos trace_input_word2 (SIM_DESC sd,
864 1.1 christos sim_cpu *cpu,
865 1.1 christos int trace_idx,
866 1.1 christos unsigned_word d0,
867 1.1 christos unsigned_word d1)
868 1.1 christos {
869 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
870 1.1 christos TRACE_IDX (data) = trace_idx;
871 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
872 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
873 1.1 christos }
874 1.1 christos
875 1.1 christos void
876 1.1 christos trace_input_word3 (SIM_DESC sd,
877 1.1 christos sim_cpu *cpu,
878 1.1 christos int trace_idx,
879 1.1 christos unsigned_word d0,
880 1.1 christos unsigned_word d1,
881 1.1 christos unsigned_word d2)
882 1.1 christos {
883 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
884 1.1 christos TRACE_IDX (data) = trace_idx;
885 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);
886 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);
887 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);
888 1.1 christos }
889 1.1 christos
890 1.1 christos void
891 1.1 christos trace_input_word4 (SIM_DESC sd,
892 1.1 christos sim_cpu *cpu,
893 1.1 christos int trace_idx,
894 1.1 christos unsigned_word d0,
895 1.1 christos unsigned_word d1,
896 1.1 christos unsigned_word d2,
897 1.1 christos unsigned_word d3)
898 1.1 christos {
899 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
900 1.1 christos TRACE_IDX (data) = trace_idx;
901 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (d0), &d0);
902 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (d1), &d1);
903 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (d2), &d2);
904 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (d3), &d3);
905 1.1 christos }
906 1.1 christos
907 1.1 christos void
908 1.1 christos trace_input_bool1 (SIM_DESC sd,
909 1.1 christos sim_cpu *cpu,
910 1.1 christos int trace_idx,
911 1.1 christos int d0)
912 1.1 christos {
913 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
914 1.1 christos TRACE_IDX (data) = trace_idx;
915 1.1 christos save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0);
916 1.1 christos }
917 1.1 christos
918 1.1 christos void
919 1.1 christos trace_input_addr1 (SIM_DESC sd,
920 1.1 christos sim_cpu *cpu,
921 1.1 christos int trace_idx,
922 1.1 christos address_word d0)
923 1.1 christos {
924 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
925 1.1 christos TRACE_IDX (data) = trace_idx;
926 1.1 christos save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0);
927 1.1 christos }
928 1.1 christos
929 1.1 christos void
930 1.1 christos trace_input_fp1 (SIM_DESC sd,
931 1.1 christos sim_cpu *cpu,
932 1.1 christos int trace_idx,
933 1.1 christos fp_word f0)
934 1.1 christos {
935 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
936 1.1 christos TRACE_IDX (data) = trace_idx;
937 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
938 1.1 christos }
939 1.1 christos
940 1.1 christos void
941 1.1 christos trace_input_fp2 (SIM_DESC sd,
942 1.1 christos sim_cpu *cpu,
943 1.1 christos int trace_idx,
944 1.1 christos fp_word f0,
945 1.1 christos fp_word f1)
946 1.1 christos {
947 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
948 1.1 christos TRACE_IDX (data) = trace_idx;
949 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
950 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
951 1.1 christos }
952 1.1 christos
953 1.1 christos void
954 1.1 christos trace_input_fp3 (SIM_DESC sd,
955 1.1 christos sim_cpu *cpu,
956 1.1 christos int trace_idx,
957 1.1 christos fp_word f0,
958 1.1 christos fp_word f1,
959 1.1 christos fp_word f2)
960 1.1 christos {
961 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
962 1.1 christos TRACE_IDX (data) = trace_idx;
963 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
964 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1);
965 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2);
966 1.1 christos }
967 1.1 christos
968 1.1 christos void
969 1.1 christos trace_input_fpu1 (SIM_DESC sd,
970 1.1 christos sim_cpu *cpu,
971 1.1 christos int trace_idx,
972 1.1 christos sim_fpu *f0)
973 1.1 christos {
974 1.1 christos double d;
975 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
976 1.1 christos TRACE_IDX (data) = trace_idx;
977 1.1 christos d = sim_fpu_2d (f0);
978 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
979 1.1 christos }
980 1.1 christos
981 1.1 christos void
982 1.1 christos trace_input_fpu2 (SIM_DESC sd,
983 1.1 christos sim_cpu *cpu,
984 1.1 christos int trace_idx,
985 1.1 christos sim_fpu *f0,
986 1.1 christos sim_fpu *f1)
987 1.1 christos {
988 1.1 christos double d;
989 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
990 1.1 christos TRACE_IDX (data) = trace_idx;
991 1.1 christos d = sim_fpu_2d (f0);
992 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
993 1.1 christos d = sim_fpu_2d (f1);
994 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
995 1.1 christos }
996 1.1 christos
997 1.1 christos void
998 1.1 christos trace_input_fpu3 (SIM_DESC sd,
999 1.1 christos sim_cpu *cpu,
1000 1.1 christos int trace_idx,
1001 1.1 christos sim_fpu *f0,
1002 1.1 christos sim_fpu *f1,
1003 1.1 christos sim_fpu *f2)
1004 1.1 christos {
1005 1.1 christos double d;
1006 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1007 1.1 christos TRACE_IDX (data) = trace_idx;
1008 1.1 christos d = sim_fpu_2d (f0);
1009 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1010 1.1 christos d = sim_fpu_2d (f1);
1011 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1012 1.1 christos d = sim_fpu_2d (f2);
1013 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1014 1.1 christos }
1015 1.1 christos
1016 1.1 christos void
1017 1.1 christos trace_result_word1 (SIM_DESC sd,
1018 1.1 christos sim_cpu *cpu,
1019 1.1 christos int trace_idx,
1020 1.1 christos unsigned_word r0)
1021 1.1 christos {
1022 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1023 1.1 christos int last_input;
1024 1.1 christos
1025 1.1 christos /* Append any results to the end of the inputs */
1026 1.1 christos last_input = TRACE_INPUT_IDX (data);
1027 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
1028 1.1 christos
1029 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1030 1.1 christos }
1031 1.1 christos
1032 1.1 christos void
1033 1.1 christos trace_result0 (SIM_DESC sd,
1034 1.1 christos sim_cpu *cpu,
1035 1.1 christos int trace_idx)
1036 1.1 christos {
1037 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1038 1.1 christos int last_input;
1039 1.1 christos
1040 1.1 christos /* Append any results to the end of the inputs */
1041 1.1 christos last_input = TRACE_INPUT_IDX (data);
1042 1.1 christos
1043 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1044 1.1 christos }
1045 1.1 christos
1046 1.1 christos void
1047 1.1 christos trace_result_word2 (SIM_DESC sd,
1048 1.1 christos sim_cpu *cpu,
1049 1.1 christos int trace_idx,
1050 1.1 christos unsigned_word r0,
1051 1.1 christos unsigned_word r1)
1052 1.1 christos {
1053 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1054 1.1 christos int last_input;
1055 1.1 christos
1056 1.1 christos /* Append any results to the end of the inputs */
1057 1.1 christos last_input = TRACE_INPUT_IDX (data);
1058 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
1059 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
1060 1.1 christos
1061 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1062 1.1 christos }
1063 1.1 christos
1064 1.1 christos void
1065 1.1 christos trace_result_word4 (SIM_DESC sd,
1066 1.1 christos sim_cpu *cpu,
1067 1.1 christos int trace_idx,
1068 1.1 christos unsigned_word r0,
1069 1.1 christos unsigned_word r1,
1070 1.1 christos unsigned_word r2,
1071 1.1 christos unsigned_word r3)
1072 1.1 christos {
1073 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1074 1.1 christos int last_input;
1075 1.1 christos
1076 1.1 christos /* Append any results to the end of the inputs */
1077 1.1 christos last_input = TRACE_INPUT_IDX (data);
1078 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (r0), &r0);
1079 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
1080 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (r2), &r2);
1081 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (r3), &r3);
1082 1.1 christos
1083 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1084 1.1 christos }
1085 1.1 christos
1086 1.1 christos void
1087 1.1 christos trace_result_bool1 (SIM_DESC sd,
1088 1.1 christos sim_cpu *cpu,
1089 1.1 christos int trace_idx,
1090 1.1 christos int r0)
1091 1.1 christos {
1092 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1093 1.1 christos int last_input;
1094 1.1 christos
1095 1.1 christos /* Append any results to the end of the inputs */
1096 1.1 christos last_input = TRACE_INPUT_IDX (data);
1097 1.1 christos save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0);
1098 1.1 christos
1099 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1100 1.1 christos }
1101 1.1 christos
1102 1.1 christos void
1103 1.1 christos trace_result_addr1 (SIM_DESC sd,
1104 1.1 christos sim_cpu *cpu,
1105 1.1 christos int trace_idx,
1106 1.1 christos address_word r0)
1107 1.1 christos {
1108 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1109 1.1 christos int last_input;
1110 1.1 christos
1111 1.1 christos /* Append any results to the end of the inputs */
1112 1.1 christos last_input = TRACE_INPUT_IDX (data);
1113 1.1 christos save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0);
1114 1.1 christos
1115 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1116 1.1 christos }
1117 1.1 christos
1118 1.1 christos void
1119 1.1 christos trace_result_fp1 (SIM_DESC sd,
1120 1.1 christos sim_cpu *cpu,
1121 1.1 christos int trace_idx,
1122 1.1 christos fp_word f0)
1123 1.1 christos {
1124 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1125 1.1 christos int last_input;
1126 1.1 christos
1127 1.1 christos /* Append any results to the end of the inputs */
1128 1.1 christos last_input = TRACE_INPUT_IDX (data);
1129 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
1130 1.1 christos
1131 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1132 1.1 christos }
1133 1.1 christos
1134 1.1 christos void
1135 1.1 christos trace_result_fp2 (SIM_DESC sd,
1136 1.1 christos sim_cpu *cpu,
1137 1.1 christos int trace_idx,
1138 1.1 christos fp_word f0,
1139 1.1 christos fp_word f1)
1140 1.1 christos {
1141 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1142 1.1 christos int last_input;
1143 1.1 christos
1144 1.1 christos /* Append any results to the end of the inputs */
1145 1.1 christos last_input = TRACE_INPUT_IDX (data);
1146 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (f0), &f0);
1147 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1);
1148 1.1 christos
1149 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1150 1.1 christos }
1151 1.1 christos
1152 1.1 christos void
1153 1.1 christos trace_result_fpu1 (SIM_DESC sd,
1154 1.1 christos sim_cpu *cpu,
1155 1.1 christos int trace_idx,
1156 1.1 christos sim_fpu *f0)
1157 1.1 christos {
1158 1.1 christos double d;
1159 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1160 1.1 christos int last_input;
1161 1.1 christos
1162 1.1 christos /* Append any results to the end of the inputs */
1163 1.1 christos last_input = TRACE_INPUT_IDX (data);
1164 1.1 christos d = sim_fpu_2d (f0);
1165 1.1 christos save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
1166 1.1 christos
1167 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1168 1.1 christos }
1169 1.1 christos
1170 1.1 christos void
1171 1.1 christos trace_result_string1 (SIM_DESC sd,
1172 1.1 christos sim_cpu *cpu,
1173 1.1 christos int trace_idx,
1174 1.1 christos char *s0)
1175 1.1 christos {
1176 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1177 1.1 christos int last_input;
1178 1.1 christos
1179 1.1 christos /* Append any results to the end of the inputs */
1180 1.1 christos last_input = TRACE_INPUT_IDX (data);
1181 1.1 christos save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
1182 1.1 christos
1183 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1184 1.1 christos }
1185 1.1 christos
1186 1.1 christos void
1187 1.1 christos trace_result_word1_string1 (SIM_DESC sd,
1188 1.1 christos sim_cpu *cpu,
1189 1.1 christos int trace_idx,
1190 1.1 christos unsigned_word r0,
1191 1.1 christos char *s0)
1192 1.1 christos {
1193 1.1 christos TRACE_DATA *data = CPU_TRACE_DATA (cpu);
1194 1.1 christos int last_input;
1195 1.1 christos
1196 1.1 christos /* Append any results to the end of the inputs */
1197 1.1 christos last_input = TRACE_INPUT_IDX (data);
1198 1.1 christos save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
1199 1.1 christos save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
1200 1.1 christos
1201 1.1 christos trace_results (sd, cpu, trace_idx, last_input);
1202 1.1 christos }
1203 1.1 christos
1204 1.1 christos void
1206 1.1 christos trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
1207 1.1 christos {
1208 1.1 christos if (cpu != NULL)
1209 1.1 christos {
1210 1.1 christos if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
1211 1.1 christos vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
1212 1.1 christos else
1213 1.1 christos sim_io_evprintf (sd, fmt, ap);
1214 1.1 christos }
1215 1.1 christos else
1216 1.1 christos {
1217 1.1 christos if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
1218 1.1 christos vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
1219 1.1 christos else
1220 1.1 christos sim_io_evprintf (sd, fmt, ap);
1221 1.1 christos }
1222 1.1.1.3 christos }
1223 1.1 christos
1224 1.1 christos void
1225 1.1 christos trace_printf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...)
1226 1.1.1.3 christos {
1227 1.1 christos va_list ap;
1228 1.1 christos
1229 1.1 christos va_start (ap, fmt);
1230 1.1 christos
1231 1.1 christos trace_vprintf (sd, cpu, fmt, ap);
1232 1.1 christos
1233 1.1 christos va_end (ap);
1234 1.1.1.5 christos }
1235 1.1 christos
1236 1.1 christos void
1237 1.1 christos sim_debug_printf (sim_cpu *cpu, const char *fmt, ...)
1238 1.1.1.3 christos {
1239 1.1 christos va_list ap;
1240 1.1 christos
1241 1.1 christos va_start (ap, fmt);
1242 1.1 christos
1243 1.1 christos if (CPU_DEBUG_FILE (cpu) == NULL)
1244 1.1 christos (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
1245 1.1 christos (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
1246 1.1 christos else
1247 1.1 christos vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
1248
1249 va_end (ap);
1250 }
1251