* cgen-mem.h, cgen-scache.[ch], cgen-sem.h, cgen-sim.h: New files.
[external/binutils.git] / sim / common / cgen-trace.c
1 /* Tracing support for CGEN-based simulators.
2    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "sim-main.h"
22 #include "bfd.h"
23 #include "cpu-opc.h"
24
25 #ifndef SIZE_INSTRUCTION
26 #define SIZE_INSTRUCTION 16
27 #endif
28
29 #ifndef SIZE_LOCATION
30 #define SIZE_LOCATION 20
31 #endif
32
33 #ifndef SIZE_PC
34 #define SIZE_PC 6
35 #endif
36
37 #ifndef SIZE_LINE_NUMBER
38 #define SIZE_LINE_NUMBER 4
39 #endif
40
41 #ifndef SIZE_CYCLE_COUNT
42 #define SIZE_CYCLE_COUNT 2
43 #endif
44
45 #ifndef SIZE_TOTAL_CYCLE_COUNT
46 #define SIZE_TOTAL_CYCLE_COUNT 9
47 #endif
48
49 /* Text is queued in TRACE_BUF because we want to output the insn's cycle
50    count first but that isn't know until after the insn has executed.  */
51 static char trace_buf[1024];
52 /* If NULL, output to stdout directly.  */
53 static char *bufptr;
54
55 /* For computing an instruction's cycle count.
56    FIXME: Need to move into cpu struct for smp case.  */
57 static unsigned long last_cycle_count;
58
59 void
60 trace_insn_init (SIM_CPU *cpu)
61 {
62   bufptr = trace_buf;
63   *bufptr = 0;
64 }
65
66 void
67 trace_insn_fini (SIM_CPU *cpu)
68 {
69   if (CPU_PROFILE_FLAGS (cpu) [PROFILE_MODEL_IDX])
70     {
71       unsigned long total = PROFILE_TOTAL_CYCLE_COUNT (CPU_PROFILE_DATA (cpu));
72       fprintf (stderr, "%-*ld %-*ld ",
73                SIZE_CYCLE_COUNT, total - last_cycle_count,
74                SIZE_TOTAL_CYCLE_COUNT, total);
75       last_cycle_count = total;
76     }
77
78   fputs (trace_buf, stderr);
79   fputc ('\n', stderr);
80 }
81
82 /* For communication between trace_insn and trace_result.  */
83 static int printed_result_p;
84
85 void
86 trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode,
87             const struct argbuf *abuf, PCADDR pc)
88 {
89   const char *filename;
90   const char *functionname;
91   unsigned int linenumber;
92   char *p, buf[256], disasm_buf[50];
93
94   if (! TRACE_P (cpu, TRACE_LINENUM_IDX))
95     {
96       cgen_trace_printf (cpu, "0x%.*x %-*s ",
97                          SIZE_PC, (unsigned) pc,
98                          SIZE_INSTRUCTION,
99                          CGEN_INSN_SYNTAX (opcode)->mnemonic);
100       return;
101     }
102
103   buf[0] = 0;
104   
105   if (STATE_TEXT_SECTION (CPU_STATE (cpu))
106       && pc >= STATE_TEXT_START (CPU_STATE (cpu))
107       && pc < STATE_TEXT_END (CPU_STATE (cpu)))
108     {
109       filename = (const char *) 0;
110       functionname = (const char *) 0;
111       linenumber = 0;
112       if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
113                                  STATE_TEXT_SECTION (CPU_STATE (cpu)),
114                                  (struct symbol_cache_entry **) 0,
115                                  pc - STATE_TEXT_START (CPU_STATE (cpu)),
116                                  &filename, &functionname, &linenumber))
117         {
118           p = buf;
119           if (linenumber)
120             {
121               sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber);
122               p += strlen (p);
123             }
124           else
125             {
126               sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
127               p += SIZE_LINE_NUMBER+2;
128             }
129
130           if (functionname)
131             {
132               sprintf (p, "%s ", functionname);
133               p += strlen (p);
134             }
135           else if (filename)
136             {
137               char *q = (char *) strrchr (filename, '/');
138               sprintf (p, "%s ", (q) ? q+1 : filename);
139               p += strlen (p);
140             }
141
142           if (*p == ' ')
143             *p = '\0';
144         }
145     }
146
147   sim_disassemble_insn (opcode, abuf, pc, disasm_buf);
148
149   cgen_trace_printf (cpu, "0x%.*x %-*.*s %-*s ",
150                      SIZE_PC, (unsigned) pc,
151                      SIZE_LOCATION, SIZE_LOCATION, buf,
152                      SIZE_INSTRUCTION,
153 #if 0
154                      CGEN_INSN_SYNTAX (opcode)->mnemonic
155 #else
156                      disasm_buf
157 #endif
158                 );
159
160   printed_result_p = 0;
161 }
162
163 void
164 trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
165 {
166   va_list args;
167   int printed_one_p = 0;
168   char *fmt;
169
170   va_start (args, name);
171
172   cgen_trace_printf (cpu, "0x%.*x: %s ", SIZE_PC, pc, name);
173
174   do {
175     int type,ival;
176
177     fmt = va_arg (args, char *);
178
179     if (fmt)
180       {
181         if (printed_one_p)
182           cgen_trace_printf (cpu, ", ");
183         printed_one_p = 1;
184         type = va_arg (args, int);
185         switch (type)
186           {
187           case 'x' :
188             ival = va_arg (args, int);
189             cgen_trace_printf (cpu, fmt, ival);
190             break;
191           default :
192             abort ();
193           }
194       }
195   } while (fmt);
196
197   va_end (args);
198   cgen_trace_printf (cpu, "\n");
199 }
200
201 void
202 trace_result (SIM_CPU *cpu, char *name, int type, ...)
203 {
204   va_list args;
205
206   va_start (args, type);
207   if (printed_result_p)
208     cgen_trace_printf (cpu, ", ");
209   switch (type)
210     {
211     case 'x' :
212     default :
213       cgen_trace_printf (cpu, "%s <- 0x%x", name, va_arg (args, int));
214       break;
215     case 'D' :
216       {
217         DI di;
218         /* this is separated from previous line for sunos cc */
219         di = va_arg (args, DI);
220         cgen_trace_printf (cpu, "%s <- 0x%x%08x", name,
221                            GETHIDI(di), GETLODI (di));
222         break;
223       }
224     }
225   printed_result_p = 1;
226   va_end (args);
227 }
228
229 void
230 cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...)
231 {
232   va_list args;
233
234   va_start (args, fmt);
235
236   if (bufptr == NULL)
237     {
238       if (TRACE_FILE (CPU_TRACE_DATA (cpu)) == NULL)
239         (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
240           (STATE_CALLBACK (CPU_STATE (cpu)), fmt, args);
241       else
242         vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, args);
243     }
244   else
245     {
246       vsprintf (bufptr, fmt, args);
247       bufptr += strlen (bufptr);
248     }
249
250   va_end (args);
251 }