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