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 | |
bcb829fd | 60 | trace_insn_init (SIM_CPU *cpu, int first_p) |
b9c8cd10 DE |
61 | { |
62 | bufptr = trace_buf; | |
63 | *bufptr = 0; | |
64 | } | |
65 | ||
66 | void | |
bcb829fd | 67 | trace_insn_fini (SIM_CPU *cpu, int last_p) |
b9c8cd10 DE |
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)); |
bcb829fd | 99 | printed_result_p = 0; |
b9c8cd10 DE |
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 | ||
ef13d3e3 | 147 | sim_disassemble_insn (cpu, opcode, abuf, pc, disasm_buf); |
b9c8cd10 DE |
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 | |
bcb829fd | 154 | CGEN_INSN_NAME (opcode) |
b9c8cd10 DE |
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 | ||
ef13d3e3 | 172 | trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*x: %s ", SIZE_PC, pc, name); |
b9c8cd10 DE |
173 | |
174 | do { | |
175 | int type,ival; | |
176 | ||
177 | fmt = va_arg (args, char *); | |
178 | ||
179 | if (fmt) | |
180 | { | |
181 | if (printed_one_p) | |
ef13d3e3 | 182 | trace_printf (CPU_STATE (cpu), cpu, ", "); |
b9c8cd10 DE |
183 | printed_one_p = 1; |
184 | type = va_arg (args, int); | |
185 | switch (type) | |
186 | { | |
187 | case 'x' : | |
188 | ival = va_arg (args, int); | |
ef13d3e3 | 189 | trace_printf (CPU_STATE (cpu), cpu, fmt, ival); |
b9c8cd10 DE |
190 | break; |
191 | default : | |
192 | abort (); | |
193 | } | |
194 | } | |
195 | } while (fmt); | |
196 | ||
197 | va_end (args); | |
ef13d3e3 | 198 | trace_printf (CPU_STATE (cpu), cpu, "\n"); |
b9c8cd10 DE |
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 | ||
c967f187 DE |
229 | /* Print trace output to BUFPTR if active, otherwise print normally. |
230 | This is only for tracing semantic code. */ | |
231 | ||
b9c8cd10 DE |
232 | void |
233 | cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...) | |
234 | { | |
235 | va_list args; | |
236 | ||
237 | va_start (args, fmt); | |
238 | ||
239 | if (bufptr == NULL) | |
240 | { | |
241 | if (TRACE_FILE (CPU_TRACE_DATA (cpu)) == NULL) | |
242 | (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered) | |
243 | (STATE_CALLBACK (CPU_STATE (cpu)), fmt, args); | |
244 | else | |
245 | vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, args); | |
246 | } | |
247 | else | |
248 | { | |
249 | vsprintf (bufptr, fmt, args); | |
250 | bufptr += strlen (bufptr); | |
251 | } | |
252 | ||
253 | va_end (args); | |
254 | } |