Add semantic tracing to the tic80
[deliverable/binutils-gdb.git] / sim / tic80 / interp.c
1 /* This file is part of the GDB simulators.
2
3 Copyright (C) 1997, Free Software Foundation
4 Condtributed by Cyngnus Solutions.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22
23
24 #include "sim-main.h"
25
26 #include "idecode.h"
27 #include "itable.h"
28
29 #include <signal.h>
30
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #else
34 #ifdef HAVE_STRINGS_H
35 #include <strings.h>
36 #endif
37 #endif
38
39 void
40 engine_init (SIM_DESC sd)
41 {
42 memset (&STATE_CPU (sd, 0)->reg, 0, sizeof STATE_CPU (sd, 0)->reg);
43 memset (&STATE_CPU (sd, 0)->cia, 0, sizeof STATE_CPU (sd, 0)->cia);
44 CPU_STATE (STATE_CPU (sd, 0)) = sd;
45 }
46
47
48 /* Mechanisms for stopping/restarting the simulation */
49
50 void
51 engine_error (SIM_DESC sd,
52 sim_cpu *cpu,
53 instruction_address cia,
54 const char *fmt,
55 ...)
56 {
57 va_list ap;
58 va_start (ap, fmt);
59 sim_io_evprintf (sd, fmt, ap);
60 va_end (ap);
61
62 if (sd->halt_ok)
63 {
64 sim_io_eprintf (sd, "\n");
65 engine_halt (sd, cpu, cia, sim_signalled, SIGABRT);
66 }
67 else
68 sim_io_error (sd, " - aborting simulation");
69 }
70
71 void
72 engine_halt (SIM_DESC sd,
73 sim_cpu *cpu,
74 instruction_address cia,
75 enum sim_stop reason,
76 int siggnal)
77 {
78 if (!sd->halt_ok)
79 sim_io_error (sd, "engine_halt - bad longjmp");
80 sd->reason = reason;
81 sd->siggnal = siggnal;
82 sd->halt_ok = 0;
83 sd->restart_ok = 0;
84 if (cpu != NULL)
85 cpu->cia = cia;
86 longjmp (sd->path_to_halt, 1);
87 }
88
89 void
90 engine_restart (SIM_DESC sd,
91 sim_cpu *cpu,
92 instruction_address cia)
93 {
94 if (!sd->restart_ok)
95 sim_io_error (sd, "engine_restart - bad longjmp");
96 sd->restart_ok = 0;
97 cpu->cia = cia;
98 longjmp(sd->path_to_restart, 1);
99 }
100
101
102 void
103 engine_run_until_stop (SIM_DESC sd,
104 volatile int *keep_running)
105 {
106 if (!setjmp (sd->path_to_halt))
107 {
108 instruction_address cia;
109 sim_cpu *cpu = STATE_CPU (sd, 0);
110 sd->halt_ok = 1;
111 setjmp (sd->path_to_restart);
112 sd->restart_ok = 1;
113 cia = cpu->cia;
114 do
115 {
116 if (cia.ip == -1)
117 {
118 /* anulled instruction */
119 cia.ip = cia.dp;
120 cia.dp = cia.dp + sizeof (instruction_word);
121 }
122 else
123 {
124 instruction_word insn = IMEM (cia.ip);
125 cia = idecode_issue (sd, insn, cia);
126 }
127 }
128 while (*keep_running);
129 engine_halt (sd, cpu, cia, sim_stopped, SIGINT);
130 }
131 }
132
133 \f
134 #if defined(WITH_TRACE)
135 /* Tracing support routines */
136
137 static char tic80_trace_buffer[1024];
138 static int tic80_size_name;
139
140 #define SIZE_HEX 8
141 #define SIZE_DECIMAL 12
142
143 /* Initialize tracing by calculating the maximum name size */
144 static void
145 tic80_init_trace (void)
146 {
147 int i;
148 int len, max_len = 0;
149
150 for (i = 0; i < (int)nr_itable_entries; i++) {
151 len = strlen (itable[i].name);
152 if (len > max_len)
153 max_len = len;
154 }
155
156 tic80_size_name = max_len + sizeof(":m") - 1 + sizeof (":s") - 1;
157 }
158
159 /* Trace the result of an ALU operation with 2 integer inputs and an integer output */
160 char *
161 tic80_trace_alu3 (int indx,
162 unsigned32 result,
163 unsigned32 input1,
164 unsigned32 input2)
165 {
166 char buf1[SIZE_DECIMAL+10], buf2[SIZE_DECIMAL+10], bufr[SIZE_DECIMAL+10];
167
168 if (!tic80_size_name)
169 tic80_init_trace ();
170
171 sprintf (bufr, "(%ld)", (long) (signed32) result);
172 sprintf (buf1, "(%ld)", (long) (signed32) input1);
173 sprintf (buf2, "(%ld)", (long) (signed32) input2);
174
175 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx %-*s 0x%.*lx %-*s => 0x%.*lx %-*s",
176 tic80_size_name, itable[indx].name,
177 SIZE_HEX, input1, SIZE_DECIMAL, buf1,
178 SIZE_HEX, input2, SIZE_DECIMAL, buf2,
179 SIZE_HEX, result, SIZE_DECIMAL, bufr);
180
181 return tic80_trace_buffer;
182 }
183
184 /* Trace the result of an ALU operation with 1 integer input and an integer output */
185 char *
186 tic80_trace_alu2 (int indx,
187 unsigned32 result,
188 unsigned32 input)
189 {
190 char bufi[SIZE_DECIMAL+10], bufr[SIZE_DECIMAL+10];
191
192 if (!tic80_size_name)
193 tic80_init_trace ();
194
195 sprintf (bufr, "(%ld)", (long) (signed32) result);
196 sprintf (bufi, "(%ld)", (long) (signed32) input);
197
198 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx %-*s %*s => 0x%.*lx %-*s",
199 tic80_size_name, itable[indx].name,
200 SIZE_HEX, input, SIZE_DECIMAL, bufi,
201 SIZE_HEX + SIZE_DECIMAL + 3, "",
202 SIZE_HEX, result, SIZE_DECIMAL, bufr);
203
204 return tic80_trace_buffer;
205 }
206
207 /* Trace the result of a NOP operation */
208 char *
209 tic80_trace_nop (int indx)
210 {
211 if (!tic80_size_name)
212 tic80_init_trace ();
213
214 sprintf (tic80_trace_buffer, "%s:", itable[indx].name);
215 return tic80_trace_buffer;
216 }
217
218 /* Trace the result of a data sink with one input */
219 char *
220 tic80_trace_sink1 (int indx, unsigned32 input)
221 {
222 char buf[SIZE_DECIMAL+10];
223
224 if (!tic80_size_name)
225 tic80_init_trace ();
226
227 sprintf (buf, "(%ld)", (long) (signed32) input);
228 sprintf (tic80_trace_buffer, "%-*s: 0x%.*lx %-*s",
229 tic80_size_name, itable[indx].name,
230 SIZE_HEX, input, SIZE_DECIMAL, buf);
231
232 return tic80_trace_buffer;
233 }
234
235 /* Trace the result of a data sink with two inputs */
236 char *
237 tic80_trace_sink2 (int indx, unsigned32 input1, unsigned32 input2)
238 {
239 char buf1[SIZE_DECIMAL+10], buf2[SIZE_DECIMAL+10];
240
241 if (!tic80_size_name)
242 tic80_init_trace ();
243
244 sprintf (buf1, "(%ld)", (long) (signed32) input1);
245 sprintf (buf2, "(%ld)", (long) (signed32) input2);
246 sprintf (tic80_trace_buffer, "%-*s: 0x%.*lx %-*s 0x%.*lx %-*s",
247 tic80_size_name, itable[indx].name,
248 SIZE_HEX, input1, SIZE_DECIMAL, buf1,
249 SIZE_HEX, input2, SIZE_DECIMAL, buf2);
250
251 return tic80_trace_buffer;
252 }
253
254 /* Trace the result of a conditional branch operation */
255 char *
256 tic80_trace_cond_br (int indx,
257 int jump_p,
258 unsigned32 cond,
259 unsigned32 target)
260 {
261 char buf[SIZE_DECIMAL+10];
262
263 if (!tic80_size_name)
264 tic80_init_trace ();
265
266 sprintf (buf, "(%ld)", (long) (signed32) cond);
267
268 if (jump_p)
269 sprintf (tic80_trace_buffer,
270 "%-*s 0x%.*lx %*s 0x%.*lx %-*s => 0x%.*lx",
271 tic80_size_name, itable[indx].name,
272 SIZE_HEX, target, SIZE_DECIMAL, "",
273 SIZE_HEX, cond, SIZE_DECIMAL, buf,
274 SIZE_HEX, target);
275 else
276 sprintf (tic80_trace_buffer,
277 "%-*s 0x%.*lx %*s 0x%.*lx %-*s => [fallthrough]",
278 tic80_size_name, itable[indx].name,
279 SIZE_HEX, target, SIZE_DECIMAL, "",
280 SIZE_HEX, cond, SIZE_DECIMAL, buf);
281
282 return tic80_trace_buffer;
283 }
284
285 /* Trace the result of a unconditional branch operation */
286 char *
287 tic80_trace_ucond_br (int indx,
288 unsigned32 target)
289 {
290 if (!tic80_size_name)
291 tic80_init_trace ();
292
293 sprintf (tic80_trace_buffer,
294 "%-*s 0x%.*lx %*s => 0x%.*lx",
295 tic80_size_name, itable[indx].name,
296 SIZE_HEX, target, (SIZE_DECIMAL*2) + SIZE_HEX + 4, "",
297 SIZE_HEX, target);
298
299 return tic80_trace_buffer;
300 }
301
302 /* Trace the result of a load or store operation with 2 integer addresses
303 and an integer output or input */
304 char *
305 tic80_trace_ldst (int indx,
306 int st_p,
307 int m_p,
308 int s_p,
309 unsigned32 value,
310 unsigned32 input1,
311 unsigned32 input2)
312 {
313 char buf1[SIZE_DECIMAL+10], buf2[SIZE_DECIMAL+10], bufr[SIZE_DECIMAL+10];
314 char name[40];
315
316 if (!tic80_size_name)
317 tic80_init_trace ();
318
319 strcpy (name, itable[indx].name);
320 if (m_p)
321 strcat (name, ":m");
322
323 if (s_p)
324 strcat (name, ":s");
325
326 sprintf (bufr, "(%ld)", (long) (signed32) value);
327 sprintf (buf1, "(%ld)", (long) (signed32) input1);
328 sprintf (buf2, "(%ld)", (long) (signed32) input2);
329
330 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx %-*s 0x%.*lx %-*s %s 0x%.*lx %-*s",
331 tic80_size_name, name,
332 SIZE_HEX, input1, SIZE_DECIMAL, buf1,
333 SIZE_HEX, input2, SIZE_DECIMAL, buf2,
334 (!st_p) ? "=>" : "<=",
335 SIZE_HEX, value, SIZE_DECIMAL, bufr);
336
337 return tic80_trace_buffer;
338 }
339 #endif /* WITH_TRACE */
This page took 0.036005 seconds and 4 git commands to generate.