2002-03-05 Chris Demetriou <cgd@broadcom.com>
[deliverable/binutils-gdb.git] / sim / tic80 / misc.c
CommitLineData
6c29acca
AC
1/* TIc80 Simulator.
2 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 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
33tic80_control_regs
34tic80_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
118static char tic80_trace_buffer[1024];
119static int tic80_size_name;
120
121#define SIZE_HEX 8
122#define SIZE_DECIMAL 11
123
124/* Initialize tracing by calculating the maximum name size */
125static void
126tic80_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/* Given an integer which is the result of a comparison, return a string
141 giving which bits are set. */
142
143static char *
144tic80_trace_cmp_internal (unsigned32 flag)
145{
146 struct cmp_bits { unsigned32 bit; char *string; };
147 static char buffer[32*8];
148 static struct cmp_bits bits[] =
149 {
150 { BIT32(29), "hs" },
151 { BIT32(28), "lo" },
152 { BIT32(27), "ls" },
153 { BIT32(26), "hi" },
154 { BIT32(25), "ge" },
155 { BIT32(24), "lt" },
156 { BIT32(23), "le" },
157 { BIT32(22), "gt" },
158 { BIT32(21), "ne" },
159 { BIT32(20), "eq" },
160
161 { BIT32(19), "hs.h" },
162 { BIT32(18), "lo.h" },
163 { BIT32(17), "ls.h" },
164 { BIT32(16), "hi.h" },
165 { BIT32(15), "ge.h" },
166 { BIT32(14), "lt.h" },
167 { BIT32(13), "le.h" },
168 { BIT32(12), "gt.h" },
169 { BIT32(11), "ne.h" },
170 { BIT32(10), "eq.h" },
171
172 { BIT32( 9), "hs.b" },
173 { BIT32( 8), "lo.b" },
174 { BIT32( 7), "ls.b" },
175 { BIT32( 6), "hi.b" },
176 { BIT32( 5), "ge.b" },
177 { BIT32( 4), "lt.b" },
178 { BIT32( 3), "le.b" },
179 { BIT32( 2), "gt.b" },
180 { BIT32( 1), "ne.b" },
181 { BIT32( 0), "eq.b" },
182 { 0, (char *)0 },
183 };
184
185 int i;
186 char *p = buffer;
187
188 for (i = 0; bits[i].bit != 0; i++)
189 {
190 if ((flag & bits[i].bit) != 0)
191 {
192 if (p != buffer)
193 *p++ = ' ';
194
195 strcpy (p, bits[i].string);
196 p += strlen (p);
197 }
198 }
199
200 *p = '\0';
201 return buffer;
202}
203
204/* Trace the result of an ALU operation with 2 integer inputs and an integer output */
205char *
206tic80_trace_alu3 (int indx,
207 unsigned32 result,
208 unsigned32 input1,
209 unsigned32 input2)
210{
211 if (!tic80_size_name)
212 tic80_init_trace ();
213
214 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld => 0x%.*lx/%*ld",
215 tic80_size_name, itable[indx].name,
216 SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
217 SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2,
218 SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);
219
220 return tic80_trace_buffer;
221}
222
223/* Trace the result of an ALU operation with 2 integer inputs and an integer output
224 that sets the bits from a compare instruction. */
225char *
226tic80_trace_cmp (int indx,
227 unsigned32 result,
228 unsigned32 input1,
229 unsigned32 input2)
230{
231 if (!tic80_size_name)
232 tic80_init_trace ();
233
234 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld => 0x%.*lx %s",
235 tic80_size_name, itable[indx].name,
236 SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
237 SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2,
238 SIZE_HEX, result, tic80_trace_cmp_internal (result));
239
240 return tic80_trace_buffer;
241}
242
243/* Trace the result of an ALU operation with 1 integer input and an integer output */
244char *
245tic80_trace_alu2 (int indx,
246 unsigned32 result,
247 unsigned32 input)
248{
249 if (!tic80_size_name)
250 tic80_init_trace ();
251
252 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld %*s => 0x%.*lx/%*ld",
253 tic80_size_name, itable[indx].name,
254 SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input,
255 SIZE_HEX + SIZE_DECIMAL + 3, "",
256 SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);
257
258 return tic80_trace_buffer;
259}
260
261/* Trace the result of a shift instruction */
262char *
263tic80_trace_shift (int indx,
264 unsigned32 result,
265 unsigned32 input,
266 int i,
267 int n,
268 int merge,
269 int endmask,
270 int rotate)
271{
272 const char *merge_name;
273 char name[40];
274 char *p;
275
276 if (!tic80_size_name)
277 tic80_init_trace ();
278
279 switch (merge)
280 {
281 default: merge_name = ".??"; break;
282 case 0: merge_name = ".dz"; break;
283 case 1: merge_name = ".dm"; break;
284 case 2: merge_name = ".ds"; break;
285 case 3: merge_name = ".ez"; break;
286 case 4: merge_name = ".em"; break;
287 case 5: merge_name = ".es"; break;
288 case 6: merge_name = ".iz"; break;
289 case 7: merge_name = ".im"; break;
290 }
291
292 /* Don't use itable[indx].name, which is just sl {r,i}. Instead reconstruct
293 the name, using the i and n fields. */
294 p = strchr (itable[indx].name, ' ');
295 sprintf (name, "s%s%s%s%s",
296 (n) ? "r" : "l",
297 (i) ? "i" : "",
298 merge_name,
299 (p) ? p : "");
300
301 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld %*s%2d,%2d => 0x%.*lx/%*ld",
302 tic80_size_name, name,
303 SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input,
304 SIZE_HEX + SIZE_DECIMAL - 2, "",
305 rotate, endmask,
306 SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);
307
308 return tic80_trace_buffer;
309}
310
311/* Trace the result of an FPU operation with 2 floating point inputs and a floating point output */
312void
313tic80_trace_fpu3 (SIM_DESC sd,
314 sim_cpu *cpu,
315 sim_cia cia,
316 int indx,
317 sim_fpu *result,
318 sim_fpu *input1,
319 sim_fpu *input2)
320{
321 if (!tic80_size_name)
322 tic80_init_trace ();
323
324 trace_one_insn (sd, cpu, cia.ip, 1,
325 itable[indx].file, itable[indx].line_nr, "fpu",
326 "%-*s %*g %*g => %*g",
327 tic80_size_name, itable[indx].name,
328 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input1),
329 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input2),
330 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (result));
331}
332
333/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
334void
335tic80_trace_fpu2 (SIM_DESC sd,
336 sim_cpu *cpu,
337 sim_cia cia,
338 int indx,
339 sim_fpu *result,
340 sim_fpu *input)
341{
342 if (!tic80_size_name)
343 tic80_init_trace ();
344
345 trace_one_insn (sd, cpu, cia.ip, 1,
346 itable[indx].file, itable[indx].line_nr, "fpu",
347 "%-*s %*g %-*s => %*g",
348 tic80_size_name, itable[indx].name,
349 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input),
350 SIZE_HEX + SIZE_DECIMAL + 3, "",
351 SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (result));
352}
353
354/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
355void
356tic80_trace_fpu1 (SIM_DESC sd,
357 sim_cpu *cpu,
358 sim_cia cia,
359 int indx,
360 sim_fpu *result)
361{
362 if (!tic80_size_name)
363 tic80_init_trace ();
364
365 trace_one_insn (sd, cpu, cia.ip, 1,
366 itable[indx].file, itable[indx].line_nr, "fpu",
367 "%-*s %-*s %-*s => %*g",
368 tic80_size_name, itable[indx].name,
369 SIZE_HEX + SIZE_DECIMAL + 3, "",
370 SIZE_HEX + SIZE_DECIMAL + 3, "",
371 SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (result));
372}
373
374/* Trace the result of an FPU operation with 2 floating point inputs and an integer output */
375void
376tic80_trace_fpu2i (SIM_DESC sd,
377 sim_cpu *cpu,
378 sim_cia cia,
379 int indx,
380 unsigned32 result,
381 sim_fpu *input1,
382 sim_fpu *input2)
383{
384 if (!tic80_size_name)
385 tic80_init_trace ();
386
387 trace_one_insn (sd, cpu, cia.ip, 1,
388 itable[indx].file, itable[indx].line_nr, "fpu",
389 "%-*s %*g %*g => 0x%.*lx %-*ld",
390 tic80_size_name, itable[indx].name,
391 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input1),
392 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input2),
393 SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);
394}
395
396/* Trace the result of an FPU operation with 2 floating point inputs and an integer output
397 that is the result of a comparison. */
398void
399tic80_trace_fpu2cmp (SIM_DESC sd,
400 sim_cpu *cpu,
401 sim_cia cia,
402 int indx,
403 unsigned32 result,
404 sim_fpu *input1,
405 sim_fpu *input2)
406{
407 if (!tic80_size_name)
408 tic80_init_trace ();
409
410 trace_one_insn (sd, cpu, cia.ip, 1,
411 itable[indx].file, itable[indx].line_nr, "fpu",
412 "%-*s %*g %*g => 0x%.*lx %s",
413 tic80_size_name, itable[indx].name,
414 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input1),
415 SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (input2),
416 SIZE_HEX, result, tic80_trace_cmp_internal (result));
417}
418
419/* Trace the result of a NOP operation */
420char *
421tic80_trace_nop (int indx)
422{
423 if (!tic80_size_name)
424 tic80_init_trace ();
425
426 sprintf (tic80_trace_buffer, "%s", itable[indx].name);
427 return tic80_trace_buffer;
428}
429
430/* Trace the result of a data sink with one input */
431char *
432tic80_trace_sink1 (int indx, unsigned32 input)
433{
434 if (!tic80_size_name)
435 tic80_init_trace ();
436
437 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld",
438 tic80_size_name, itable[indx].name,
439 SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input);
440
441 return tic80_trace_buffer;
442}
443
444/* Trace the result of a data sink with two inputs */
445char *
446tic80_trace_sink2 (int indx, unsigned32 input1, unsigned32 input2)
447{
448 if (!tic80_size_name)
449 tic80_init_trace ();
450
451 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld",
452 tic80_size_name, itable[indx].name,
453 SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
454 SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2);
455
456 return tic80_trace_buffer;
457}
458
459/* Trace the result of a data sink with three inputs */
460char *
461tic80_trace_sink3 (int indx, unsigned32 input1, unsigned32 input2, unsigned32 input3)
462{
463 if (!tic80_size_name)
464 tic80_init_trace ();
465
466 sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld 0x%.*lx/%*ld",
467 tic80_size_name, itable[indx].name,
468 SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
469 SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2,
470 SIZE_HEX, input3, SIZE_DECIMAL, (long)(signed32)input3);
471
472 return tic80_trace_buffer;
473}
474
475/* Trace the result of a conditional branch operation */
476char *
477tic80_trace_cond_br (int indx,
478 int jump_p,
479 unsigned32 cond,
480 unsigned32 target,
481 int size,
482 int code)
483{
484 char *suffix1, *suffix2;
485
486 if (!tic80_size_name)
487 tic80_init_trace ();
488
489 if (size >= 0 && code >= 0)
490 { /* BCND */
491 switch (code)
492 {
493 default: suffix1 = "???"; break;
494 case 0: suffix1 = "nev"; break;
495 case 1: suffix1 = "gt0"; break;
496 case 2: suffix1 = "eq0"; break;
497 case 3: suffix1 = "ge0"; break;
498 case 4: suffix1 = "lt0"; break;
499 case 5: suffix1 = "ne0"; break;
500 case 6: suffix1 = "le0"; break;
501 case 7: suffix1 = "alw"; break;
502 }
503
504 switch (size)
505 {
506 default: suffix2 = ".?"; break;
507 case 0: suffix2 = ".b"; break;
508 case 1: suffix2 = ".h"; break;
509 case 2: suffix2 = ".w"; break;
510 }
511
512 } else { /* BBO/BBZ */
513
514 suffix2 = "";
515 switch (cond)
516 {
517 default: suffix1 = "??.?"; break;
518 case 29: suffix1 = "hs.w"; break;
519 case 28: suffix1 = "lo.w"; break;
520 case 27: suffix1 = "ls.w"; break;
521 case 26: suffix1 = "hi.w"; break;
522 case 25: suffix1 = "ge.w"; break;
523 case 24: suffix1 = "lt.w"; break;
524 case 23: suffix1 = "le.w"; break;
525 case 22: suffix1 = "gt.w"; break;
526 case 21: suffix1 = "ne.w"; break;
527 case 20: suffix1 = "eq.w"; break;
528 case 19: suffix1 = "hs.h"; break;
529 case 18: suffix1 = "lo.h"; break;
530 case 17: suffix1 = "ls.h"; break;
531 case 16: suffix1 = "hi.h"; break;
532 case 15: suffix1 = "ge.h"; break;
533 case 14: suffix1 = "lt.h"; break;
534 case 13: suffix1 = "le.h"; break;
535 case 12: suffix1 = "gt.h"; break;
536 case 11: suffix1 = "ne.h"; break;
537 case 10: suffix1 = "eq.h"; break;
538 case 9: suffix1 = "hs.b"; break;
539 case 8: suffix1 = "lo.b"; break;
540 case 7: suffix1 = "ls.b"; break;
541 case 6: suffix1 = "hi.b"; break;
542 case 5: suffix1 = "ge.b"; break;
543 case 4: suffix1 = "lt.b"; break;
544 case 3: suffix1 = "le.b"; break;
545 case 2: suffix1 = "gt.b"; break;
546 case 1: suffix1 = "ne.b"; break;
547 case 0: suffix1 = "eq.b"; break;
548 }
549 }
550
551 if (jump_p)
552 sprintf (tic80_trace_buffer,
553 "%-*s 0x%.*lx %*s 0x%.*lx/%*ld => 0x%.*lx %s%s",
554 tic80_size_name, itable[indx].name,
555 SIZE_HEX, target, SIZE_DECIMAL, "",
556 SIZE_HEX, cond, SIZE_DECIMAL, (long)(signed32)cond,
557 SIZE_HEX, target,
558 suffix1, suffix2);
559 else
560 sprintf (tic80_trace_buffer,
561 "%-*s 0x%.*lx %*s 0x%.*lx/%*ld => %-*s %s%s",
562 tic80_size_name, itable[indx].name,
563 SIZE_HEX, target, SIZE_DECIMAL, "",
564 SIZE_HEX, cond, SIZE_DECIMAL, (long)(signed32)cond,
565 SIZE_HEX + 2, "[no jump]",
566 suffix1, suffix2);
567
568 return tic80_trace_buffer;
569}
570
571/* Trace the result of a unconditional branch operation */
572char *
573tic80_trace_ucond_br (int indx,
574 unsigned32 target)
575{
576 if (!tic80_size_name)
577 tic80_init_trace ();
578
579 sprintf (tic80_trace_buffer,
580 "%-*s 0x%.*lx %*s => 0x%.*lx",
581 tic80_size_name, itable[indx].name,
582 SIZE_HEX, target, (SIZE_DECIMAL*2) + SIZE_HEX + 4, "",
583 SIZE_HEX, target);
584
585 return tic80_trace_buffer;
586}
587
588/* Trace the result of a load or store operation with 2 integer addresses
589 and an integer output or input */
590void
591tic80_trace_ldst (SIM_DESC sd,
592 sim_cpu *cpu,
593 sim_cia cia,
594 int indx,
595 int st_p,
596 int m_p,
597 int s_p,
598 unsigned32 value,
599 unsigned32 input1,
600 unsigned32 input2)
601{
602 char name[40];
603
604 if (!tic80_size_name)
605 tic80_init_trace ();
606
607 strcpy (name, itable[indx].name);
608 if (m_p)
609 strcat (name, ":m");
610
611 if (s_p)
612 strcat (name, ":s");
613
614 trace_one_insn (sd, cpu, cia.ip, 1,
615 itable[indx].file, itable[indx].line_nr, "memory",
616 "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld %s 0x%.*lx/%*ld",
617 tic80_size_name, name,
618 SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
619 SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2,
620 (!st_p) ? "=>" : "<=",
621 SIZE_HEX, value, SIZE_DECIMAL, (long)(signed32)value);
622}
623
624#endif /* WITH_TRACE */
This page took 0.100499 seconds and 4 git commands to generate.