Commit | Line | Data |
---|---|---|
381f42ef AC |
1 | /* TIc80 Simulator. |
2 | Copyright (C) 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 | ||
22 | #include "sim-main.h" | |
23 | ||
24 | #ifdef HAVE_STRING_H | |
25 | #include <string.h> | |
26 | #else | |
27 | #ifdef HAVE_STRINGS_H | |
28 | #include <strings.h> | |
29 | #endif | |
30 | #endif | |
31 | ||
32 | ||
33 | tic80_control_regs | |
34 | tic80_index2cr (int index) | |
35 | { | |
36 | switch (index) | |
37 | { | |
38 | case 0x0000: return EPC_CR; | |
39 | case 0x0001: return EIP_CR; | |
40 | case 0x0002: return CONFIG_CR; | |
41 | case 0x0004: return INTPEN_CR; | |
42 | case 0x0006: return IE_CR; | |
43 | case 0x0008: return FPST_CR; | |
44 | case 0x000A: return PPERROR_CR; | |
45 | case 0x000D: return PKTREQ_CR; | |
46 | case 0x000E: return TCOUNT_CR; | |
47 | case 0x000F: return TSCALE_CR; | |
48 | case 0x0010: return FLTOP_CR; | |
49 | case 0x0011: return FLTADR_CR; | |
50 | case 0x0012: return FLTTAG_CR; | |
51 | case 0x0013: return FLTDLT_CR; | |
52 | case 0x0014: return FLTDTH_CR; | |
53 | case 0x0015: return FLT005_CR; | |
54 | case 0x0016: return FLT006_CR; | |
55 | case 0x0017: return FLT007_CR; | |
56 | case 0x0018: return FLT008_CR; | |
57 | case 0x0019: return FLT009_CR; | |
58 | case 0x001a: return FLT010_CR; | |
59 | case 0x001b: return FLT011_CR; | |
60 | case 0x001c: return FLT012_CR; | |
61 | case 0x001d: return FLT013_CR; | |
62 | case 0x001e: return FLT014_CR; | |
63 | case 0x001f: return FLT015_CR; | |
64 | case 0x0020: return SYSSTK_CR; | |
65 | case 0x0021: return SYSTMP_CR; | |
66 | case 0x0030: return MPC_CR; | |
67 | case 0x0031: return MIP_CR; | |
68 | case 0x0033: return ECOMCNTL_CR; | |
69 | case 0x0034: return ANASTAT_CR; | |
70 | case 0x0039: return BRK1_CR; | |
71 | case 0x003A: return BRK2_CR; | |
72 | case 0x0200: return ITAG0_CR; | |
73 | case 0x0201: return ITAG1_CR; | |
74 | case 0x0202: return ITAG2_CR; | |
75 | case 0x0203: return ITAG3_CR; | |
76 | case 0x0204: return ITAG4_CR; | |
77 | case 0x0205: return ITAG5_CR; | |
78 | case 0x0206: return ITAG6_CR; | |
79 | case 0x0207: return ITAG7_CR; | |
80 | case 0x0208: return ITAG8_CR; | |
81 | case 0x0209: return ITAG9_CR; | |
82 | case 0x020a: return ITAG10_CR; | |
83 | case 0x020b: return ITAG11_CR; | |
84 | case 0x020c: return ITAG12_CR; | |
85 | case 0x020d: return ITAG13_CR; | |
86 | case 0x020e: return ITAG14_CR; | |
87 | case 0x020f: return ITAG15_CR; | |
88 | case 0x0300: return ILRU_CR; | |
89 | case 0x0400: return DTAG0_CR; | |
90 | case 0x0401: return DTAG1_CR; | |
91 | case 0x0402: return DTAG2_CR; | |
92 | case 0x0403: return DTAG3_CR; | |
93 | case 0x0404: return DTAG4_CR; | |
94 | case 0x0405: return DTAG5_CR; | |
95 | case 0x0406: return DTAG6_CR; | |
96 | case 0x0407: return DTAG7_CR; | |
97 | case 0x0408: return DTAG8_CR; | |
98 | case 0x0409: return DTAG9_CR; | |
99 | case 0x040a: return DTAG10_CR; | |
100 | case 0x040b: return DTAG11_CR; | |
101 | case 0x040c: return DTAG12_CR; | |
102 | case 0x040d: return DTAG13_CR; | |
103 | case 0x040e: return DTAG14_CR; | |
104 | case 0x040f: return DTAG15_CR; | |
105 | case 0x0500: return DLRU_CR; | |
106 | case 0x4000: return IN0P_CR; | |
107 | case 0x4001: return IN1P_CR; | |
108 | case 0x4002: return OUTP_CR; | |
109 | default: return SCRATCH_CR; | |
110 | } | |
111 | } | |
112 | ||
113 | ||
114 | \f | |
115 | #if defined(WITH_TRACE) | |
116 | /* Tracing support routines */ | |
117 | ||
118 | static char tic80_trace_buffer[1024]; | |
119 | static int tic80_size_name; | |
120 | ||
121 | #define SIZE_HEX 8 | |
8c3b5af1 | 122 | #define SIZE_DECIMAL 11 |
381f42ef AC |
123 | |
124 | /* Initialize tracing by calculating the maximum name size */ | |
125 | static void | |
126 | tic80_init_trace (void) | |
127 | { | |
128 | int i; | |
129 | int len, max_len = 0; | |
130 | ||
131 | for (i = 0; i < (int)nr_itable_entries; i++) { | |
132 | len = strlen (itable[i].name); | |
133 | if (len > max_len) | |
134 | max_len = len; | |
135 | } | |
136 | ||
137 | tic80_size_name = max_len + sizeof(":m") - 1 + sizeof (":s") - 1; | |
138 | } | |
139 | ||
140 | /* Trace the result of an ALU operation with 2 integer inputs and an integer output */ | |
141 | char * | |
142 | tic80_trace_alu3 (int indx, | |
143 | unsigned32 result, | |
144 | unsigned32 input1, | |
145 | unsigned32 input2) | |
146 | { | |
381f42ef AC |
147 | if (!tic80_size_name) |
148 | tic80_init_trace (); | |
149 | ||
8c3b5af1 | 150 | sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld => 0x%.*lx/%*ld", |
381f42ef | 151 | tic80_size_name, itable[indx].name, |
8c3b5af1 MM |
152 | SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1, |
153 | SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2, | |
154 | SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result); | |
381f42ef AC |
155 | |
156 | return tic80_trace_buffer; | |
157 | } | |
158 | ||
159 | /* Trace the result of an ALU operation with 1 integer input and an integer output */ | |
160 | char * | |
161 | tic80_trace_alu2 (int indx, | |
162 | unsigned32 result, | |
163 | unsigned32 input) | |
164 | { | |
381f42ef AC |
165 | if (!tic80_size_name) |
166 | tic80_init_trace (); | |
167 | ||
8c3b5af1 | 168 | sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld %*s => 0x%.*lx/%*ld", |
381f42ef | 169 | tic80_size_name, itable[indx].name, |
8c3b5af1 | 170 | SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input, |
450be234 | 171 | SIZE_HEX + SIZE_DECIMAL + 3, "", |
8c3b5af1 | 172 | SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result); |
381f42ef AC |
173 | |
174 | return tic80_trace_buffer; | |
175 | } | |
176 | ||
450be234 MM |
177 | /* Trace the result of a shift instruction */ |
178 | char * | |
179 | tic80_trace_shift (int indx, | |
180 | unsigned32 result, | |
181 | unsigned32 input, | |
182 | int i, | |
183 | int n, | |
184 | int merge, | |
185 | int endmask, | |
186 | int rotate) | |
187 | { | |
188 | const char *merge_name; | |
189 | char name[40]; | |
190 | char *p; | |
191 | ||
192 | if (!tic80_size_name) | |
193 | tic80_init_trace (); | |
194 | ||
195 | switch (merge) | |
196 | { | |
197 | default: merge_name = ".??"; break; | |
198 | case 0: merge_name = ".dz"; break; | |
199 | case 1: merge_name = ".dm"; break; | |
200 | case 2: merge_name = ".ds"; break; | |
201 | case 3: merge_name = ".ez"; break; | |
202 | case 4: merge_name = ".em"; break; | |
203 | case 5: merge_name = ".es"; break; | |
204 | case 6: merge_name = ".iz"; break; | |
205 | case 7: merge_name = ".im"; break; | |
206 | } | |
207 | ||
208 | /* Don't use itable[indx].name, which is just sl {r,i}. Instead reconstruct | |
209 | the name, using the i and n fields. */ | |
210 | p = strchr (itable[indx].name, ' '); | |
211 | sprintf (name, "s%s%s%s%s", | |
212 | (n) ? "r" : "l", | |
213 | (i) ? "i" : "", | |
214 | merge_name, | |
215 | (p) ? p : ""); | |
216 | ||
217 | sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld %*s%2d,%2d => 0x%.*lx/%*ld", | |
218 | tic80_size_name, name, | |
219 | SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input, | |
220 | SIZE_HEX + SIZE_DECIMAL - 2, "", | |
221 | rotate, endmask, | |
222 | SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result); | |
223 | ||
224 | return tic80_trace_buffer; | |
225 | } | |
226 | ||
8c3b5af1 | 227 | /* Trace the result of an FPU operation with 2 floating point inputs and a floating point output */ |
381f42ef AC |
228 | void |
229 | tic80_trace_fpu3 (SIM_DESC sd, | |
230 | sim_cpu *cpu, | |
231 | sim_cia cia, | |
232 | int indx, | |
233 | sim_fpu result, | |
234 | sim_fpu input1, | |
235 | sim_fpu input2) | |
236 | { | |
237 | if (!tic80_size_name) | |
238 | tic80_init_trace (); | |
239 | ||
240 | trace_one_insn (sd, cpu, cia.ip, 1, | |
241 | itable[indx].file, itable[indx].line_nr, "fpu", | |
93555c3b | 242 | "%-*s %*g %*g => %*g", |
381f42ef | 243 | tic80_size_name, itable[indx].name, |
93555c3b MM |
244 | SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input1), |
245 | SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input2), | |
246 | SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (result)); | |
381f42ef AC |
247 | } |
248 | ||
8c3b5af1 | 249 | /* Trace the result of an FPU operation with 1 floating point input and a floating point output */ |
381f42ef AC |
250 | void |
251 | tic80_trace_fpu2 (SIM_DESC sd, | |
252 | sim_cpu *cpu, | |
253 | sim_cia cia, | |
254 | int indx, | |
255 | sim_fpu result, | |
256 | sim_fpu input) | |
257 | { | |
258 | if (!tic80_size_name) | |
259 | tic80_init_trace (); | |
260 | ||
261 | trace_one_insn (sd, cpu, cia.ip, 1, | |
262 | itable[indx].file, itable[indx].line_nr, "fpu", | |
93555c3b | 263 | "%-*s %*g %-*s => %*g", |
381f42ef | 264 | tic80_size_name, itable[indx].name, |
93555c3b MM |
265 | SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input), |
266 | SIZE_HEX + SIZE_DECIMAL + 3, "", | |
381f42ef AC |
267 | SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (result)); |
268 | } | |
269 | ||
aa3a0447 AC |
270 | /* Trace the result of an FPU operation with 1 floating point input and a floating point output */ |
271 | void | |
272 | tic80_trace_fpu1 (SIM_DESC sd, | |
273 | sim_cpu *cpu, | |
274 | sim_cia cia, | |
275 | int indx, | |
276 | sim_fpu result) | |
277 | { | |
278 | if (!tic80_size_name) | |
279 | tic80_init_trace (); | |
280 | ||
281 | trace_one_insn (sd, cpu, cia.ip, 1, | |
282 | itable[indx].file, itable[indx].line_nr, "fpu", | |
283 | "%-*s %-*s %-*s => %*g", | |
284 | tic80_size_name, itable[indx].name, | |
285 | SIZE_HEX + SIZE_DECIMAL + 3, "", | |
286 | SIZE_HEX + SIZE_DECIMAL + 3, "", | |
287 | SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (result)); | |
288 | } | |
289 | ||
381f42ef AC |
290 | /* Trace the result of an FPU operation with 1 integer input and an integer output */ |
291 | void | |
292 | tic80_trace_fpu2i (SIM_DESC sd, | |
293 | sim_cpu *cpu, | |
294 | sim_cia cia, | |
295 | int indx, | |
296 | unsigned32 result, | |
297 | sim_fpu input1, | |
298 | sim_fpu input2) | |
299 | { | |
381f42ef AC |
300 | if (!tic80_size_name) |
301 | tic80_init_trace (); | |
302 | ||
381f42ef AC |
303 | trace_one_insn (sd, cpu, cia.ip, 1, |
304 | itable[indx].file, itable[indx].line_nr, "fpu", | |
c445af5a | 305 | "%-*s %*f %*f => 0x%.*lx %-*ld", |
381f42ef AC |
306 | tic80_size_name, itable[indx].name, |
307 | SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input1), | |
308 | SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input2), | |
8c3b5af1 | 309 | SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result); |
381f42ef AC |
310 | } |
311 | ||
312 | /* Trace the result of a NOP operation */ | |
313 | char * | |
314 | tic80_trace_nop (int indx) | |
315 | { | |
316 | if (!tic80_size_name) | |
317 | tic80_init_trace (); | |
318 | ||
319 | sprintf (tic80_trace_buffer, "%s", itable[indx].name); | |
320 | return tic80_trace_buffer; | |
321 | } | |
322 | ||
323 | /* Trace the result of a data sink with one input */ | |
324 | char * | |
325 | tic80_trace_sink1 (int indx, unsigned32 input) | |
326 | { | |
381f42ef AC |
327 | if (!tic80_size_name) |
328 | tic80_init_trace (); | |
329 | ||
8c3b5af1 | 330 | sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld", |
381f42ef | 331 | tic80_size_name, itable[indx].name, |
8c3b5af1 | 332 | SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input); |
381f42ef AC |
333 | |
334 | return tic80_trace_buffer; | |
335 | } | |
336 | ||
337 | /* Trace the result of a data sink with two inputs */ | |
338 | char * | |
339 | tic80_trace_sink2 (int indx, unsigned32 input1, unsigned32 input2) | |
340 | { | |
381f42ef AC |
341 | if (!tic80_size_name) |
342 | tic80_init_trace (); | |
343 | ||
8c3b5af1 | 344 | sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld", |
381f42ef | 345 | tic80_size_name, itable[indx].name, |
8c3b5af1 MM |
346 | SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1, |
347 | SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2); | |
381f42ef AC |
348 | |
349 | return tic80_trace_buffer; | |
350 | } | |
351 | ||
8c3b5af1 | 352 | /* Trace the result of a data sink with three inputs */ |
381f42ef AC |
353 | char * |
354 | tic80_trace_sink3 (int indx, unsigned32 input1, unsigned32 input2, unsigned32 input3) | |
355 | { | |
381f42ef AC |
356 | if (!tic80_size_name) |
357 | tic80_init_trace (); | |
358 | ||
8c3b5af1 | 359 | sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld 0x%.*lx/%*ld", |
381f42ef | 360 | tic80_size_name, itable[indx].name, |
8c3b5af1 MM |
361 | SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1, |
362 | SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2, | |
363 | SIZE_HEX, input3, SIZE_DECIMAL, (long)(signed32)input3); | |
381f42ef AC |
364 | |
365 | return tic80_trace_buffer; | |
366 | } | |
367 | ||
368 | /* Trace the result of a conditional branch operation */ | |
369 | char * | |
370 | tic80_trace_cond_br (int indx, | |
371 | int jump_p, | |
372 | unsigned32 cond, | |
373 | unsigned32 target) | |
374 | { | |
381f42ef AC |
375 | if (!tic80_size_name) |
376 | tic80_init_trace (); | |
377 | ||
381f42ef AC |
378 | if (jump_p) |
379 | sprintf (tic80_trace_buffer, | |
8c3b5af1 | 380 | "%-*s 0x%.*lx %*s 0x%.*lx/%*ld => 0x%.*lx", |
381f42ef AC |
381 | tic80_size_name, itable[indx].name, |
382 | SIZE_HEX, target, SIZE_DECIMAL, "", | |
8c3b5af1 | 383 | SIZE_HEX, cond, SIZE_DECIMAL, (long)(signed32)cond, |
381f42ef AC |
384 | SIZE_HEX, target); |
385 | else | |
386 | sprintf (tic80_trace_buffer, | |
8c3b5af1 | 387 | "%-*s 0x%.*lx %*s 0x%.*lx/%*ld => [fallthrough]", |
381f42ef AC |
388 | tic80_size_name, itable[indx].name, |
389 | SIZE_HEX, target, SIZE_DECIMAL, "", | |
8c3b5af1 | 390 | SIZE_HEX, cond, SIZE_DECIMAL, (long)(signed32)cond); |
381f42ef AC |
391 | |
392 | return tic80_trace_buffer; | |
393 | } | |
394 | ||
395 | /* Trace the result of a unconditional branch operation */ | |
396 | char * | |
397 | tic80_trace_ucond_br (int indx, | |
398 | unsigned32 target) | |
399 | { | |
400 | if (!tic80_size_name) | |
401 | tic80_init_trace (); | |
402 | ||
403 | sprintf (tic80_trace_buffer, | |
404 | "%-*s 0x%.*lx %*s => 0x%.*lx", | |
405 | tic80_size_name, itable[indx].name, | |
406 | SIZE_HEX, target, (SIZE_DECIMAL*2) + SIZE_HEX + 4, "", | |
407 | SIZE_HEX, target); | |
408 | ||
409 | return tic80_trace_buffer; | |
410 | } | |
411 | ||
412 | /* Trace the result of a load or store operation with 2 integer addresses | |
413 | and an integer output or input */ | |
414 | char * | |
415 | tic80_trace_ldst (int indx, | |
416 | int st_p, | |
417 | int m_p, | |
418 | int s_p, | |
419 | unsigned32 value, | |
420 | unsigned32 input1, | |
421 | unsigned32 input2) | |
422 | { | |
381f42ef AC |
423 | char name[40]; |
424 | ||
425 | if (!tic80_size_name) | |
426 | tic80_init_trace (); | |
427 | ||
428 | strcpy (name, itable[indx].name); | |
429 | if (m_p) | |
430 | strcat (name, ":m"); | |
431 | ||
432 | if (s_p) | |
433 | strcat (name, ":s"); | |
434 | ||
8c3b5af1 | 435 | sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld %s 0x%.*lx/%*ld", |
381f42ef | 436 | tic80_size_name, name, |
8c3b5af1 MM |
437 | SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1, |
438 | SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2, | |
381f42ef | 439 | (!st_p) ? "=>" : "<=", |
8c3b5af1 | 440 | SIZE_HEX, value, SIZE_DECIMAL, (long)(signed32)value); |
381f42ef AC |
441 | |
442 | return tic80_trace_buffer; | |
443 | } | |
444 | ||
445 | #endif /* WITH_TRACE */ |