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