Commit | Line | Data |
---|---|---|
b9c8cd10 DE |
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 | |
c967f187 | 50 | count first but that isn't known until after the insn has executed. */ |
b9c8cd10 DE |
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)); | |
ef13d3e3 | 72 | trace_printf (CPU_STATE (cpu), cpu, "%-*ld %-*ld ", |
c967f187 DE |
73 | SIZE_CYCLE_COUNT, total - last_cycle_count, |
74 | SIZE_TOTAL_CYCLE_COUNT, total); | |
b9c8cd10 DE |
75 | last_cycle_count = total; |
76 | } | |
77 | ||
ef13d3e3 | 78 | trace_printf (CPU_STATE (cpu), cpu, "%s\n", trace_buf); |
b9c8cd10 DE |
79 | } |
80 | ||
81 | /* For communication between trace_insn and trace_result. */ | |
82 | static int printed_result_p; | |
83 | ||
84 | void | |
85 | trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode, | |
86 | const struct argbuf *abuf, PCADDR pc) | |
87 | { | |
88 | const char *filename; | |
89 | const char *functionname; | |
90 | unsigned int linenumber; | |
91 | char *p, buf[256], disasm_buf[50]; | |
92 | ||
93 | if (! TRACE_P (cpu, TRACE_LINENUM_IDX)) | |
94 | { | |
95 | cgen_trace_printf (cpu, "0x%.*x %-*s ", | |
96 | SIZE_PC, (unsigned) pc, | |
97 | SIZE_INSTRUCTION, | |
ef13d3e3 | 98 | CGEN_INSN_MNEMONIC (opcode)); |
b9c8cd10 DE |
99 | return; |
100 | } | |
101 | ||
102 | buf[0] = 0; | |
103 | ||
104 | if (STATE_TEXT_SECTION (CPU_STATE (cpu)) | |
105 | && pc >= STATE_TEXT_START (CPU_STATE (cpu)) | |
106 | && pc < STATE_TEXT_END (CPU_STATE (cpu))) | |
107 | { | |
108 | filename = (const char *) 0; | |
109 | functionname = (const char *) 0; | |
110 | linenumber = 0; | |
111 | if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)), | |
112 | STATE_TEXT_SECTION (CPU_STATE (cpu)), | |
113 | (struct symbol_cache_entry **) 0, | |
114 | pc - STATE_TEXT_START (CPU_STATE (cpu)), | |
115 | &filename, &functionname, &linenumber)) | |
116 | { | |
117 | p = buf; | |
118 | if (linenumber) | |
119 | { | |
120 | sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber); | |
121 | p += strlen (p); | |
122 | } | |
123 | else | |
124 | { | |
125 | sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); | |
126 | p += SIZE_LINE_NUMBER+2; | |
127 | } | |
128 | ||
129 | if (functionname) | |
130 | { | |
131 | sprintf (p, "%s ", functionname); | |
132 | p += strlen (p); | |
133 | } | |
134 | else if (filename) | |
135 | { | |
136 | char *q = (char *) strrchr (filename, '/'); | |
137 | sprintf (p, "%s ", (q) ? q+1 : filename); | |
138 | p += strlen (p); | |
139 | } | |
140 | ||
141 | if (*p == ' ') | |
142 | *p = '\0'; | |
143 | } | |
144 | } | |
145 | ||
ef13d3e3 | 146 | sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf); |
b9c8cd10 DE |
147 | |
148 | cgen_trace_printf (cpu, "0x%.*x %-*.*s %-*s ", | |
149 | SIZE_PC, (unsigned) pc, | |
150 | SIZE_LOCATION, SIZE_LOCATION, buf, | |
151 | SIZE_INSTRUCTION, | |
152 | #if 0 | |
153 | CGEN_INSN_SYNTAX (opcode)->mnemonic | |
154 | #else | |
155 | disasm_buf | |
156 | #endif | |
157 | ); | |
158 | ||
159 | printed_result_p = 0; | |
160 | } | |
161 | ||
162 | void | |
163 | trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...) | |
164 | { | |
165 | va_list args; | |
166 | int printed_one_p = 0; | |
167 | char *fmt; | |
168 | ||
169 | va_start (args, name); | |
170 | ||
ef13d3e3 | 171 | trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*x: %s ", SIZE_PC, pc, name); |
b9c8cd10 DE |
172 | |
173 | do { | |
174 | int type,ival; | |
175 | ||
176 | fmt = va_arg (args, char *); | |
177 | ||
178 | if (fmt) | |
179 | { | |
180 | if (printed_one_p) | |
ef13d3e3 | 181 | trace_printf (CPU_STATE (cpu), cpu, ", "); |
b9c8cd10 DE |
182 | printed_one_p = 1; |
183 | type = va_arg (args, int); | |
184 | switch (type) | |
185 | { | |
186 | case 'x' : | |
187 | ival = va_arg (args, int); | |
ef13d3e3 | 188 | trace_printf (CPU_STATE (cpu), cpu, fmt, ival); |
b9c8cd10 DE |
189 | break; |
190 | default : | |
191 | abort (); | |
192 | } | |
193 | } | |
194 | } while (fmt); | |
195 | ||
196 | va_end (args); | |
ef13d3e3 | 197 | trace_printf (CPU_STATE (cpu), cpu, "\n"); |
b9c8cd10 DE |
198 | } |
199 | ||
200 | void | |
201 | trace_result (SIM_CPU *cpu, char *name, int type, ...) | |
202 | { | |
203 | va_list args; | |
204 | ||
205 | va_start (args, type); | |
206 | if (printed_result_p) | |
207 | cgen_trace_printf (cpu, ", "); | |
208 | switch (type) | |
209 | { | |
210 | case 'x' : | |
211 | default : | |
212 | cgen_trace_printf (cpu, "%s <- 0x%x", name, va_arg (args, int)); | |
213 | break; | |
214 | case 'D' : | |
215 | { | |
216 | DI di; | |
217 | /* this is separated from previous line for sunos cc */ | |
218 | di = va_arg (args, DI); | |
219 | cgen_trace_printf (cpu, "%s <- 0x%x%08x", name, | |
220 | GETHIDI(di), GETLODI (di)); | |
221 | break; | |
222 | } | |
223 | } | |
224 | printed_result_p = 1; | |
225 | va_end (args); | |
226 | } | |
227 | ||
c967f187 DE |
228 | /* Print trace output to BUFPTR if active, otherwise print normally. |
229 | This is only for tracing semantic code. */ | |
230 | ||
b9c8cd10 DE |
231 | void |
232 | cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...) | |
233 | { | |
234 | va_list args; | |
235 | ||
236 | va_start (args, fmt); | |
237 | ||
238 | if (bufptr == NULL) | |
239 | { | |
240 | if (TRACE_FILE (CPU_TRACE_DATA (cpu)) == NULL) | |
241 | (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered) | |
242 | (STATE_CALLBACK (CPU_STATE (cpu)), fmt, args); | |
243 | else | |
244 | vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, args); | |
245 | } | |
246 | else | |
247 | { | |
248 | vsprintf (bufptr, fmt, args); | |
249 | bufptr += strlen (bufptr); | |
250 | } | |
251 | ||
252 | va_end (args); | |
253 | } |