]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/mcore/interp.c
sim: avr/mcore/moxie: fill out sim-cpu pc fetch/store helpers
[thirdparty/binutils-gdb.git] / sim / mcore / interp.c
1 /* Simulator for Motorola's MCore processor
2 Copyright (C) 1999-2015 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
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 3 of the License, or
10 (at your option) 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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include <signal.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/times.h>
25 #include <sys/param.h>
26 #include <unistd.h>
27 #include "bfd.h"
28 #include "gdb/callback.h"
29 #include "libiberty.h"
30 #include "gdb/remote-sim.h"
31
32 #include "sim-main.h"
33 #include "sim-base.h"
34 #include "sim-options.h"
35
36 #ifndef NUM_ELEM
37 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
38 #endif
39
40 #define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
41
42
43 static unsigned long
44 mcore_extract_unsigned_integer (unsigned char *addr, int len)
45 {
46 unsigned long retval;
47 unsigned char * p;
48 unsigned char * startaddr = (unsigned char *)addr;
49 unsigned char * endaddr = startaddr + len;
50
51 if (len > (int) sizeof (unsigned long))
52 printf ("That operation is not available on integers of more than %zu bytes.",
53 sizeof (unsigned long));
54
55 /* Start at the most significant end of the integer, and work towards
56 the least significant. */
57 retval = 0;
58
59 if (! target_big_endian)
60 {
61 for (p = endaddr; p > startaddr;)
62 retval = (retval << 8) | * -- p;
63 }
64 else
65 {
66 for (p = startaddr; p < endaddr;)
67 retval = (retval << 8) | * p ++;
68 }
69
70 return retval;
71 }
72
73 static void
74 mcore_store_unsigned_integer (unsigned char *addr, int len, unsigned long val)
75 {
76 unsigned char * p;
77 unsigned char * startaddr = (unsigned char *)addr;
78 unsigned char * endaddr = startaddr + len;
79
80 if (! target_big_endian)
81 {
82 for (p = startaddr; p < endaddr;)
83 {
84 * p ++ = val & 0xff;
85 val >>= 8;
86 }
87 }
88 else
89 {
90 for (p = endaddr; p > startaddr;)
91 {
92 * -- p = val & 0xff;
93 val >>= 8;
94 }
95 }
96 }
97
98 /* The machine state.
99 This state is maintained in host byte order. The
100 fetch/store register functions must translate between host
101 byte order and the target processor byte order.
102 Keeping this data in target byte order simplifies the register
103 read/write functions. Keeping this data in native order improves
104 the performance of the simulator. Simulation speed is deemed more
105 important. */
106 /* TODO: Should be moved to sim-main.h:sim_cpu. */
107
108 /* The ordering of the mcore_regset structure is matched in the
109 gdb/config/mcore/tm-mcore.h file in the REGISTER_NAMES macro. */
110 struct mcore_regset
111 {
112 word gregs [16]; /* primary registers */
113 word alt_gregs [16]; /* alt register file */
114 word cregs [32]; /* control registers */
115 int ticks;
116 int stalls;
117 int cycles;
118 int insts;
119 int exception;
120 unsigned long msize;
121 unsigned char * memory;
122 word * active_gregs;
123 };
124
125 union
126 {
127 struct mcore_regset asregs;
128 word asints [1]; /* but accessed larger... */
129 } cpu;
130
131 #define LAST_VALID_CREG 32 /* only 0..12 implemented */
132 #define NUM_MCORE_REGS (16 + 16 + LAST_VALID_CREG + 1)
133
134 static int memcycles = 1;
135
136 static int issue_messages = 0;
137
138 #define gr asregs.active_gregs
139 #define cr asregs.cregs
140 #define sr asregs.cregs[0]
141 #define vbr asregs.cregs[1]
142 #define esr asregs.cregs[2]
143 #define fsr asregs.cregs[3]
144 #define epc asregs.cregs[4]
145 #define fpc asregs.cregs[5]
146 #define ss0 asregs.cregs[6]
147 #define ss1 asregs.cregs[7]
148 #define ss2 asregs.cregs[8]
149 #define ss3 asregs.cregs[9]
150 #define ss4 asregs.cregs[10]
151 #define gcr asregs.cregs[11]
152 #define gsr asregs.cregs[12]
153 #define mem asregs.memory
154
155 /* maniuplate the carry bit */
156 #define C_ON() (cpu.sr & 1)
157 #define C_VALUE() (cpu.sr & 1)
158 #define C_OFF() ((cpu.sr & 1) == 0)
159 #define SET_C() {cpu.sr |= 1;}
160 #define CLR_C() {cpu.sr &= 0xfffffffe;}
161 #define NEW_C(v) {CLR_C(); cpu.sr |= ((v) & 1);}
162
163 #define SR_AF() ((cpu.sr >> 1) & 1)
164
165 #define TRAPCODE 1 /* r1 holds which function we want */
166 #define PARM1 2 /* first parameter */
167 #define PARM2 3
168 #define PARM3 4
169 #define PARM4 5
170 #define RET1 2 /* register for return values. */
171
172 static void
173 wbat (word x, word v)
174 {
175 if (((uword)x) >= cpu.asregs.msize)
176 {
177 if (issue_messages)
178 fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
179
180 cpu.asregs.exception = SIGSEGV;
181 }
182 else
183 {
184 unsigned char *p = cpu.mem + x;
185 p[0] = v;
186 }
187 }
188
189 static void
190 wlat (word x, word v)
191 {
192 if (((uword)x) >= cpu.asregs.msize)
193 {
194 if (issue_messages)
195 fprintf (stderr, "word write to 0x%x outside memory range\n", x);
196
197 cpu.asregs.exception = SIGSEGV;
198 }
199 else
200 {
201 if ((x & 3) != 0)
202 {
203 if (issue_messages)
204 fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
205
206 cpu.asregs.exception = SIGBUS;
207 }
208 else if (! target_big_endian)
209 {
210 unsigned char * p = cpu.mem + x;
211 p[3] = v >> 24;
212 p[2] = v >> 16;
213 p[1] = v >> 8;
214 p[0] = v;
215 }
216 else
217 {
218 unsigned char * p = cpu.mem + x;
219 p[0] = v >> 24;
220 p[1] = v >> 16;
221 p[2] = v >> 8;
222 p[3] = v;
223 }
224 }
225 }
226
227 static void
228 what (word x, word v)
229 {
230 if (((uword)x) >= cpu.asregs.msize)
231 {
232 if (issue_messages)
233 fprintf (stderr, "short write to 0x%x outside memory range\n", x);
234
235 cpu.asregs.exception = SIGSEGV;
236 }
237 else
238 {
239 if ((x & 1) != 0)
240 {
241 if (issue_messages)
242 fprintf (stderr, "short write to unaligned memory address: 0x%x\n",
243 x);
244
245 cpu.asregs.exception = SIGBUS;
246 }
247 else if (! target_big_endian)
248 {
249 unsigned char * p = cpu.mem + x;
250 p[1] = v >> 8;
251 p[0] = v;
252 }
253 else
254 {
255 unsigned char * p = cpu.mem + x;
256 p[0] = v >> 8;
257 p[1] = v;
258 }
259 }
260 }
261
262 /* Read functions. */
263 static int
264 rbat (word x)
265 {
266 if (((uword)x) >= cpu.asregs.msize)
267 {
268 if (issue_messages)
269 fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
270
271 cpu.asregs.exception = SIGSEGV;
272 return 0;
273 }
274 else
275 {
276 unsigned char * p = cpu.mem + x;
277 return p[0];
278 }
279 }
280
281 static int
282 rlat (word x)
283 {
284 if (((uword) x) >= cpu.asregs.msize)
285 {
286 if (issue_messages)
287 fprintf (stderr, "word read from 0x%x outside memory range\n", x);
288
289 cpu.asregs.exception = SIGSEGV;
290 return 0;
291 }
292 else
293 {
294 if ((x & 3) != 0)
295 {
296 if (issue_messages)
297 fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
298
299 cpu.asregs.exception = SIGBUS;
300 return 0;
301 }
302 else if (! target_big_endian)
303 {
304 unsigned char * p = cpu.mem + x;
305 return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
306 }
307 else
308 {
309 unsigned char * p = cpu.mem + x;
310 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
311 }
312 }
313 }
314
315 static int
316 rhat (word x)
317 {
318 if (((uword)x) >= cpu.asregs.msize)
319 {
320 if (issue_messages)
321 fprintf (stderr, "short read from 0x%x outside memory range\n", x);
322
323 cpu.asregs.exception = SIGSEGV;
324 return 0;
325 }
326 else
327 {
328 if ((x & 1) != 0)
329 {
330 if (issue_messages)
331 fprintf (stderr, "short read from unaligned address: 0x%x\n", x);
332
333 cpu.asregs.exception = SIGBUS;
334 return 0;
335 }
336 else if (! target_big_endian)
337 {
338 unsigned char * p = cpu.mem + x;
339 return (p[1] << 8) | p[0];
340 }
341 else
342 {
343 unsigned char * p = cpu.mem + x;
344 return (p[0] << 8) | p[1];
345 }
346 }
347 }
348
349
350 /* Default to a 8 Mbyte (== 2^23) memory space. */
351 /* TODO: Delete all this custom memory logic and move to common sim helpers. */
352 static int sim_memory_size = 23;
353
354 #define MEM_SIZE_FLOOR 64
355 static void
356 sim_size (int power)
357 {
358 sim_memory_size = power;
359 cpu.asregs.msize = 1 << sim_memory_size;
360
361 if (cpu.mem)
362 free (cpu.mem);
363
364 /* Watch out for the '0 count' problem. There's probably a better
365 way.. e.g., why do we use 64 here? */
366 if (cpu.asregs.msize < 64) /* Ensure a boundary. */
367 cpu.mem = (unsigned char *) calloc (64, (64 + cpu.asregs.msize) / 64);
368 else
369 cpu.mem = (unsigned char *) calloc (64, cpu.asregs.msize / 64);
370
371 if (!cpu.mem)
372 {
373 if (issue_messages)
374 fprintf (stderr,
375 "Not enough VM for simulation of %lu bytes of RAM\n",
376 cpu.asregs.msize);
377
378 cpu.asregs.msize = 1;
379 cpu.mem = (unsigned char *) calloc (1, 1);
380 }
381 }
382
383 static void
384 init_pointers (void)
385 {
386 if (cpu.asregs.msize != (1 << sim_memory_size))
387 sim_size (sim_memory_size);
388 }
389
390 static void
391 set_initial_gprs (SIM_CPU *scpu)
392 {
393 int i;
394 long space;
395 unsigned long memsize;
396
397 init_pointers ();
398
399 /* Set up machine just out of reset. */
400 CIA_SET (scpu, 0);
401 cpu.sr = 0;
402
403 memsize = cpu.asregs.msize / (1024 * 1024);
404
405 if (issue_messages > 1)
406 fprintf (stderr, "Simulated memory of %lu Mbytes (0x0 .. 0x%08lx)\n",
407 memsize, cpu.asregs.msize - 1);
408
409 /* Clean out the GPRs and alternate GPRs. */
410 for (i = 0; i < 16; i++)
411 {
412 cpu.asregs.gregs[i] = 0;
413 cpu.asregs.alt_gregs[i] = 0;
414 }
415
416 /* Make our register set point to the right place. */
417 if (SR_AF())
418 cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0];
419 else
420 cpu.asregs.active_gregs = &cpu.asregs.gregs[0];
421
422 /* ABI specifies initial values for these registers. */
423 cpu.gr[0] = cpu.asregs.msize - 4;
424
425 /* dac fix, the stack address must be 8-byte aligned! */
426 cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
427 cpu.gr[PARM1] = 0;
428 cpu.gr[PARM2] = 0;
429 cpu.gr[PARM3] = 0;
430 cpu.gr[PARM4] = cpu.gr[0];
431 }
432
433 /* Functions so that trapped open/close don't interfere with the
434 parent's functions. We say that we can't close the descriptors
435 that we didn't open. exit() and cleanup() get in trouble here,
436 to some extent. That's the price of emulation. */
437
438 unsigned char opened[100];
439
440 static void
441 log_open (int fd)
442 {
443 if (fd < 0 || fd > NUM_ELEM (opened))
444 return;
445
446 opened[fd] = 1;
447 }
448
449 static void
450 log_close (int fd)
451 {
452 if (fd < 0 || fd > NUM_ELEM (opened))
453 return;
454
455 opened[fd] = 0;
456 }
457
458 static int
459 is_opened (int fd)
460 {
461 if (fd < 0 || fd > NUM_ELEM (opened))
462 return 0;
463
464 return opened[fd];
465 }
466
467 static void
468 handle_trap1 (SIM_DESC sd)
469 {
470 unsigned long a[3];
471 host_callback *callback = STATE_CALLBACK (sd);
472
473 switch ((unsigned long) (cpu.gr [TRAPCODE]))
474 {
475 case 3:
476 a[0] = (unsigned long) (cpu.gr[PARM1]);
477 a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
478 a[2] = (unsigned long) (cpu.gr[PARM3]);
479 cpu.gr[RET1] = callback->read (callback, a[0], (char *) a[1], a[2]);
480 break;
481
482 case 4:
483 a[0] = (unsigned long) (cpu.gr[PARM1]);
484 a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
485 a[2] = (unsigned long) (cpu.gr[PARM3]);
486 cpu.gr[RET1] = (int)callback->write (callback, a[0], (char *) a[1], a[2]);
487 break;
488
489 case 5:
490 a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
491 a[1] = (unsigned long) (cpu.gr[PARM2]);
492 /* a[2] = (unsigned long) (cpu.gr[PARM3]); */
493 cpu.gr[RET1] = callback->open (callback, (char *) a[0], a[1]);
494 log_open (cpu.gr[RET1]);
495 break;
496
497 case 6:
498 a[0] = (unsigned long) (cpu.gr[PARM1]);
499 /* Watch out for debugger's files. */
500 if (is_opened (a[0]))
501 {
502 log_close (a[0]);
503 cpu.gr[RET1] = callback->close (callback, a[0]);
504 }
505 else
506 {
507 /* Don't let him close it. */
508 cpu.gr[RET1] = (-1);
509 }
510 break;
511
512 case 9:
513 a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
514 a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
515 cpu.gr[RET1] = link ((char *) a[0], (char *) a[1]);
516 break;
517
518 case 10:
519 a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
520 cpu.gr[RET1] = callback->unlink (callback, (char *) a[0]);
521 break;
522
523 case 13:
524 /* handle time(0) vs time(&var) */
525 a[0] = (unsigned long) (cpu.gr[PARM1]);
526 if (a[0])
527 a[0] += (unsigned long) cpu.mem;
528 cpu.gr[RET1] = callback->time (callback, (time_t *) a[0]);
529 break;
530
531 case 19:
532 a[0] = (unsigned long) (cpu.gr[PARM1]);
533 a[1] = (unsigned long) (cpu.gr[PARM2]);
534 a[2] = (unsigned long) (cpu.gr[PARM3]);
535 cpu.gr[RET1] = callback->lseek (callback, a[0], a[1], a[2]);
536 break;
537
538 case 33:
539 a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
540 a[1] = (unsigned long) (cpu.gr[PARM2]);
541 cpu.gr[RET1] = access ((char *) a[0], a[1]);
542 break;
543
544 case 43:
545 a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
546 #if 0
547 cpu.gr[RET1] = times ((char *)a[0]);
548 #else
549 {
550 /* Give him simulated cycles for utime
551 and an instruction count for stime. */
552 struct tms
553 {
554 time_t tms_utime;
555 time_t tms_stime;
556 time_t tms_cutime;
557 time_t tms_cstime;
558 } t;
559
560 t.tms_utime = cpu.asregs.cycles;
561 t.tms_stime = cpu.asregs.insts;
562 t.tms_cutime = t.tms_utime;
563 t.tms_cstime = t.tms_stime;
564
565 memcpy ((struct tms *)(a[0]), &t, sizeof (t));
566
567 cpu.gr[RET1] = cpu.asregs.cycles;
568 }
569 #endif
570 break;
571
572 case 69:
573 /* Historically this was sbrk(), but no one used it, and the
574 implementation didn't actually work, so it's a stub now. */
575 a[0] = (unsigned long) (cpu.gr[PARM1]);
576 cpu.gr[RET1] = -1;
577 break;
578
579 default:
580 if (issue_messages)
581 fprintf (stderr, "WARNING: sys call %d unimplemented\n",
582 cpu.gr[TRAPCODE]);
583 break;
584 }
585 }
586
587 static void
588 process_stub (SIM_DESC sd, int what)
589 {
590 /* These values should match those in libgloss/mcore/syscalls.s. */
591 switch (what)
592 {
593 case 3: /* _read */
594 case 4: /* _write */
595 case 5: /* _open */
596 case 6: /* _close */
597 case 10: /* _unlink */
598 case 19: /* _lseek */
599 case 43: /* _times */
600 cpu.gr [TRAPCODE] = what;
601 handle_trap1 (sd);
602 break;
603
604 default:
605 if (issue_messages)
606 fprintf (stderr, "Unhandled stub opcode: %d\n", what);
607 break;
608 }
609 }
610
611 static void
612 util (SIM_DESC sd, unsigned what)
613 {
614 switch (what)
615 {
616 case 0: /* exit */
617 cpu.asregs.exception = SIGQUIT;
618 break;
619
620 case 1: /* printf */
621 {
622 unsigned long a[6];
623 unsigned char *s;
624 int i;
625
626 a[0] = (unsigned long)(cpu.mem + cpu.gr[PARM1]);
627
628 for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++)
629 {
630 if (*s == '%')
631 {
632 if (*++s == 's')
633 a[i] = (unsigned long)(cpu.mem + cpu.gr[PARM1+i]);
634 else
635 a[i] = cpu.gr[i+PARM1];
636 i++;
637 }
638 }
639
640 cpu.gr[RET1] = printf ((char *)a[0], a[1], a[2], a[3], a[4], a[5]);
641 }
642 break;
643
644 case 2: /* scanf */
645 if (issue_messages)
646 fprintf (stderr, "WARNING: scanf unimplemented\n");
647 break;
648
649 case 3: /* utime */
650 cpu.gr[RET1] = cpu.asregs.insts;
651 break;
652
653 case 0xFF:
654 process_stub (sd, cpu.gr[1]);
655 break;
656
657 default:
658 if (issue_messages)
659 fprintf (stderr, "Unhandled util code: %x\n", what);
660 break;
661 }
662 }
663
664 /* For figuring out whether we carried; addc/subc use this. */
665 static int
666 iu_carry (unsigned long a, unsigned long b, int cin)
667 {
668 unsigned long x;
669
670 x = (a & 0xffff) + (b & 0xffff) + cin;
671 x = (x >> 16) + (a >> 16) + (b >> 16);
672 x >>= 16;
673
674 return (x != 0);
675 }
676
677 #define WATCHFUNCTIONS 1
678 #ifdef WATCHFUNCTIONS
679
680 #define MAXWL 80
681 word WL[MAXWL];
682 char * WLstr[MAXWL];
683
684 int ENDWL=0;
685 int WLincyc;
686 int WLcyc[MAXWL];
687 int WLcnts[MAXWL];
688 int WLmax[MAXWL];
689 int WLmin[MAXWL];
690 word WLendpc;
691 int WLbcyc;
692 int WLW;
693 #endif
694
695 #define RD (inst & 0xF)
696 #define RS ((inst >> 4) & 0xF)
697 #define RX ((inst >> 8) & 0xF)
698 #define IMM5 ((inst >> 4) & 0x1F)
699 #define IMM4 ((inst) & 0xF)
700
701 static int tracing = 0;
702
703 void
704 sim_resume (SIM_DESC sd, int step, int siggnal)
705 {
706 SIM_CPU *scpu = STATE_CPU (sd, 0);
707 int needfetch;
708 word ibuf;
709 word pc;
710 unsigned short inst;
711 int memops;
712 int bonus_cycles;
713 int insts;
714 int w;
715 int cycs;
716 word WLhash;
717
718 cpu.asregs.exception = step ? SIGTRAP: 0;
719 pc = CIA_GET (scpu);
720
721 /* Fetch the initial instructions that we'll decode. */
722 ibuf = rlat (pc & 0xFFFFFFFC);
723 needfetch = 0;
724
725 memops = 0;
726 bonus_cycles = 0;
727 insts = 0;
728
729 /* make our register set point to the right place */
730 if (SR_AF ())
731 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
732 else
733 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
734
735 /* make a hash to speed exec loop, hope it's nonzero */
736 WLhash = 0xFFFFFFFF;
737
738 for (w = 1; w <= ENDWL; w++)
739 WLhash = WLhash & WL[w];
740
741 do
742 {
743 word oldpc;
744
745 insts ++;
746
747 if (pc & 02)
748 {
749 if (! target_big_endian)
750 inst = ibuf >> 16;
751 else
752 inst = ibuf & 0xFFFF;
753 needfetch = 1;
754 }
755 else
756 {
757 if (! target_big_endian)
758 inst = ibuf & 0xFFFF;
759 else
760 inst = ibuf >> 16;
761 }
762
763 #ifdef WATCHFUNCTIONS
764 /* now scan list of watch addresses, if match, count it and
765 note return address and count cycles until pc=return address */
766
767 if ((WLincyc == 1) && (pc == WLendpc))
768 {
769 cycs = (cpu.asregs.cycles + (insts + bonus_cycles +
770 (memops * memcycles)) - WLbcyc);
771
772 if (WLcnts[WLW] == 1)
773 {
774 WLmax[WLW] = cycs;
775 WLmin[WLW] = cycs;
776 WLcyc[WLW] = 0;
777 }
778
779 if (cycs > WLmax[WLW])
780 {
781 WLmax[WLW] = cycs;
782 }
783
784 if (cycs < WLmin[WLW])
785 {
786 WLmin[WLW] = cycs;
787 }
788
789 WLcyc[WLW] += cycs;
790 WLincyc = 0;
791 WLendpc = 0;
792 }
793
794 /* Optimize with a hash to speed loop. */
795 if (WLincyc == 0)
796 {
797 if ((WLhash == 0) || ((WLhash & pc) != 0))
798 {
799 for (w=1; w <= ENDWL; w++)
800 {
801 if (pc == WL[w])
802 {
803 WLcnts[w]++;
804 WLbcyc = cpu.asregs.cycles + insts
805 + bonus_cycles + (memops * memcycles);
806 WLendpc = cpu.gr[15];
807 WLincyc = 1;
808 WLW = w;
809 break;
810 }
811 }
812 }
813 }
814 #endif
815
816 if (tracing)
817 fprintf (stderr, "%.4x: inst = %.4x ", pc, inst);
818
819 oldpc = pc;
820
821 pc += 2;
822
823 switch (inst >> 8)
824 {
825 case 0x00:
826 switch RS
827 {
828 case 0x0:
829 switch RD
830 {
831 case 0x0: /* bkpt */
832 cpu.asregs.exception = SIGTRAP;
833 pc -= 2;
834 break;
835
836 case 0x1: /* sync */
837 break;
838
839 case 0x2: /* rte */
840 pc = cpu.epc;
841 cpu.sr = cpu.esr;
842 needfetch = 1;
843
844 if (SR_AF ())
845 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
846 else
847 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
848 break;
849
850 case 0x3: /* rfi */
851 pc = cpu.fpc;
852 cpu.sr = cpu.fsr;
853 needfetch = 1;
854
855 if (SR_AF ())
856 cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0];
857 else
858 cpu.asregs.active_gregs = &cpu.asregs.gregs[0];
859 break;
860
861 case 0x4: /* stop */
862 if (issue_messages)
863 fprintf (stderr, "WARNING: stop unimplemented\n");
864 break;
865
866 case 0x5: /* wait */
867 if (issue_messages)
868 fprintf (stderr, "WARNING: wait unimplemented\n");
869 break;
870
871 case 0x6: /* doze */
872 if (issue_messages)
873 fprintf (stderr, "WARNING: doze unimplemented\n");
874 break;
875
876 case 0x7:
877 cpu.asregs.exception = SIGILL; /* illegal */
878 break;
879
880 case 0x8: /* trap 0 */
881 case 0xA: /* trap 2 */
882 case 0xB: /* trap 3 */
883 cpu.asregs.exception = SIGTRAP;
884 break;
885
886 case 0xC: /* trap 4 */
887 case 0xD: /* trap 5 */
888 case 0xE: /* trap 6 */
889 cpu.asregs.exception = SIGILL; /* illegal */
890 break;
891
892 case 0xF: /* trap 7 */
893 cpu.asregs.exception = SIGTRAP; /* integer div-by-0 */
894 break;
895
896 case 0x9: /* trap 1 */
897 handle_trap1 (sd);
898 break;
899 }
900 break;
901
902 case 0x1:
903 cpu.asregs.exception = SIGILL; /* illegal */
904 break;
905
906 case 0x2: /* mvc */
907 cpu.gr[RD] = C_VALUE();
908 break;
909 case 0x3: /* mvcv */
910 cpu.gr[RD] = C_OFF();
911 break;
912 case 0x4: /* ldq */
913 {
914 word addr = cpu.gr[RD];
915 int regno = 4; /* always r4-r7 */
916
917 bonus_cycles++;
918 memops += 4;
919 do
920 {
921 cpu.gr[regno] = rlat(addr);
922 addr += 4;
923 regno++;
924 }
925 while ((regno&0x3) != 0);
926 }
927 break;
928 case 0x5: /* stq */
929 {
930 word addr = cpu.gr[RD];
931 int regno = 4; /* always r4-r7 */
932
933 memops += 4;
934 bonus_cycles++;
935 do
936 {
937 wlat(addr, cpu.gr[regno]);
938 addr += 4;
939 regno++;
940 }
941 while ((regno & 0x3) != 0);
942 }
943 break;
944 case 0x6: /* ldm */
945 {
946 word addr = cpu.gr[0];
947 int regno = RD;
948
949 /* bonus cycle is really only needed if
950 the next insn shifts the last reg loaded.
951
952 bonus_cycles++;
953 */
954 memops += 16-regno;
955 while (regno <= 0xF)
956 {
957 cpu.gr[regno] = rlat(addr);
958 addr += 4;
959 regno++;
960 }
961 }
962 break;
963 case 0x7: /* stm */
964 {
965 word addr = cpu.gr[0];
966 int regno = RD;
967
968 /* this should be removed! */
969 /* bonus_cycles ++; */
970
971 memops += 16 - regno;
972 while (regno <= 0xF)
973 {
974 wlat(addr, cpu.gr[regno]);
975 addr += 4;
976 regno++;
977 }
978 }
979 break;
980
981 case 0x8: /* dect */
982 cpu.gr[RD] -= C_VALUE();
983 break;
984 case 0x9: /* decf */
985 cpu.gr[RD] -= C_OFF();
986 break;
987 case 0xA: /* inct */
988 cpu.gr[RD] += C_VALUE();
989 break;
990 case 0xB: /* incf */
991 cpu.gr[RD] += C_OFF();
992 break;
993 case 0xC: /* jmp */
994 pc = cpu.gr[RD];
995 if (tracing && RD == 15)
996 fprintf (stderr, "Func return, r2 = %x, r3 = %x\n",
997 cpu.gr[2], cpu.gr[3]);
998 bonus_cycles++;
999 needfetch = 1;
1000 break;
1001 case 0xD: /* jsr */
1002 cpu.gr[15] = pc;
1003 pc = cpu.gr[RD];
1004 bonus_cycles++;
1005 needfetch = 1;
1006 break;
1007 case 0xE: /* ff1 */
1008 {
1009 word tmp, i;
1010 tmp = cpu.gr[RD];
1011 for (i = 0; !(tmp & 0x80000000) && i < 32; i++)
1012 tmp <<= 1;
1013 cpu.gr[RD] = i;
1014 }
1015 break;
1016 case 0xF: /* brev */
1017 {
1018 word tmp;
1019 tmp = cpu.gr[RD];
1020 tmp = ((tmp & 0xaaaaaaaa) >> 1) | ((tmp & 0x55555555) << 1);
1021 tmp = ((tmp & 0xcccccccc) >> 2) | ((tmp & 0x33333333) << 2);
1022 tmp = ((tmp & 0xf0f0f0f0) >> 4) | ((tmp & 0x0f0f0f0f) << 4);
1023 tmp = ((tmp & 0xff00ff00) >> 8) | ((tmp & 0x00ff00ff) << 8);
1024 cpu.gr[RD] = ((tmp & 0xffff0000) >> 16) | ((tmp & 0x0000ffff) << 16);
1025 }
1026 break;
1027 }
1028 break;
1029 case 0x01:
1030 switch RS
1031 {
1032 case 0x0: /* xtrb3 */
1033 cpu.gr[1] = (cpu.gr[RD]) & 0xFF;
1034 NEW_C (cpu.gr[RD] != 0);
1035 break;
1036 case 0x1: /* xtrb2 */
1037 cpu.gr[1] = (cpu.gr[RD]>>8) & 0xFF;
1038 NEW_C (cpu.gr[RD] != 0);
1039 break;
1040 case 0x2: /* xtrb1 */
1041 cpu.gr[1] = (cpu.gr[RD]>>16) & 0xFF;
1042 NEW_C (cpu.gr[RD] != 0);
1043 break;
1044 case 0x3: /* xtrb0 */
1045 cpu.gr[1] = (cpu.gr[RD]>>24) & 0xFF;
1046 NEW_C (cpu.gr[RD] != 0);
1047 break;
1048 case 0x4: /* zextb */
1049 cpu.gr[RD] &= 0x000000FF;
1050 break;
1051 case 0x5: /* sextb */
1052 {
1053 long tmp;
1054 tmp = cpu.gr[RD];
1055 tmp <<= 24;
1056 tmp >>= 24;
1057 cpu.gr[RD] = tmp;
1058 }
1059 break;
1060 case 0x6: /* zexth */
1061 cpu.gr[RD] &= 0x0000FFFF;
1062 break;
1063 case 0x7: /* sexth */
1064 {
1065 long tmp;
1066 tmp = cpu.gr[RD];
1067 tmp <<= 16;
1068 tmp >>= 16;
1069 cpu.gr[RD] = tmp;
1070 }
1071 break;
1072 case 0x8: /* declt */
1073 --cpu.gr[RD];
1074 NEW_C ((long)cpu.gr[RD] < 0);
1075 break;
1076 case 0x9: /* tstnbz */
1077 {
1078 word tmp = cpu.gr[RD];
1079 NEW_C ((tmp & 0xFF000000) != 0 &&
1080 (tmp & 0x00FF0000) != 0 && (tmp & 0x0000FF00) != 0 &&
1081 (tmp & 0x000000FF) != 0);
1082 }
1083 break;
1084 case 0xA: /* decgt */
1085 --cpu.gr[RD];
1086 NEW_C ((long)cpu.gr[RD] > 0);
1087 break;
1088 case 0xB: /* decne */
1089 --cpu.gr[RD];
1090 NEW_C ((long)cpu.gr[RD] != 0);
1091 break;
1092 case 0xC: /* clrt */
1093 if (C_ON())
1094 cpu.gr[RD] = 0;
1095 break;
1096 case 0xD: /* clrf */
1097 if (C_OFF())
1098 cpu.gr[RD] = 0;
1099 break;
1100 case 0xE: /* abs */
1101 if (cpu.gr[RD] & 0x80000000)
1102 cpu.gr[RD] = ~cpu.gr[RD] + 1;
1103 break;
1104 case 0xF: /* not */
1105 cpu.gr[RD] = ~cpu.gr[RD];
1106 break;
1107 }
1108 break;
1109 case 0x02: /* movt */
1110 if (C_ON())
1111 cpu.gr[RD] = cpu.gr[RS];
1112 break;
1113 case 0x03: /* mult */
1114 /* consume 2 bits per cycle from rs, until rs is 0 */
1115 {
1116 unsigned int t = cpu.gr[RS];
1117 int ticks;
1118 for (ticks = 0; t != 0 ; t >>= 2)
1119 ticks++;
1120 bonus_cycles += ticks;
1121 }
1122 bonus_cycles += 2; /* min. is 3, so add 2, plus ticks above */
1123 if (tracing)
1124 fprintf (stderr, " mult %x by %x to give %x",
1125 cpu.gr[RD], cpu.gr[RS], cpu.gr[RD] * cpu.gr[RS]);
1126 cpu.gr[RD] = cpu.gr[RD] * cpu.gr[RS];
1127 break;
1128 case 0x04: /* loopt */
1129 if (C_ON())
1130 {
1131 pc += (IMM4 << 1) - 32;
1132 bonus_cycles ++;
1133 needfetch = 1;
1134 }
1135 --cpu.gr[RS]; /* not RD! */
1136 NEW_C (((long)cpu.gr[RS]) > 0);
1137 break;
1138 case 0x05: /* subu */
1139 cpu.gr[RD] -= cpu.gr[RS];
1140 break;
1141 case 0x06: /* addc */
1142 {
1143 unsigned long tmp, a, b;
1144 a = cpu.gr[RD];
1145 b = cpu.gr[RS];
1146 cpu.gr[RD] = a + b + C_VALUE ();
1147 tmp = iu_carry (a, b, C_VALUE ());
1148 NEW_C (tmp);
1149 }
1150 break;
1151 case 0x07: /* subc */
1152 {
1153 unsigned long tmp, a, b;
1154 a = cpu.gr[RD];
1155 b = cpu.gr[RS];
1156 cpu.gr[RD] = a - b + C_VALUE () - 1;
1157 tmp = iu_carry (a,~b, C_VALUE ());
1158 NEW_C (tmp);
1159 }
1160 break;
1161 case 0x08: /* illegal */
1162 case 0x09: /* illegal*/
1163 cpu.asregs.exception = SIGILL;
1164 break;
1165 case 0x0A: /* movf */
1166 if (C_OFF())
1167 cpu.gr[RD] = cpu.gr[RS];
1168 break;
1169 case 0x0B: /* lsr */
1170 {
1171 unsigned long dst, src;
1172 dst = cpu.gr[RD];
1173 src = cpu.gr[RS];
1174 /* We must not rely solely upon the native shift operations, since they
1175 may not match the M*Core's behaviour on boundary conditions. */
1176 dst = src > 31 ? 0 : dst >> src;
1177 cpu.gr[RD] = dst;
1178 }
1179 break;
1180 case 0x0C: /* cmphs */
1181 NEW_C ((unsigned long )cpu.gr[RD] >=
1182 (unsigned long)cpu.gr[RS]);
1183 break;
1184 case 0x0D: /* cmplt */
1185 NEW_C ((long)cpu.gr[RD] < (long)cpu.gr[RS]);
1186 break;
1187 case 0x0E: /* tst */
1188 NEW_C ((cpu.gr[RD] & cpu.gr[RS]) != 0);
1189 break;
1190 case 0x0F: /* cmpne */
1191 NEW_C (cpu.gr[RD] != cpu.gr[RS]);
1192 break;
1193 case 0x10: case 0x11: /* mfcr */
1194 {
1195 unsigned r;
1196 r = IMM5;
1197 if (r <= LAST_VALID_CREG)
1198 cpu.gr[RD] = cpu.cr[r];
1199 else
1200 cpu.asregs.exception = SIGILL;
1201 }
1202 break;
1203
1204 case 0x12: /* mov */
1205 cpu.gr[RD] = cpu.gr[RS];
1206 if (tracing)
1207 fprintf (stderr, "MOV %x into reg %d", cpu.gr[RD], RD);
1208 break;
1209
1210 case 0x13: /* bgenr */
1211 if (cpu.gr[RS] & 0x20)
1212 cpu.gr[RD] = 0;
1213 else
1214 cpu.gr[RD] = 1 << (cpu.gr[RS] & 0x1F);
1215 break;
1216
1217 case 0x14: /* rsub */
1218 cpu.gr[RD] = cpu.gr[RS] - cpu.gr[RD];
1219 break;
1220
1221 case 0x15: /* ixw */
1222 cpu.gr[RD] += cpu.gr[RS]<<2;
1223 break;
1224
1225 case 0x16: /* and */
1226 cpu.gr[RD] &= cpu.gr[RS];
1227 break;
1228
1229 case 0x17: /* xor */
1230 cpu.gr[RD] ^= cpu.gr[RS];
1231 break;
1232
1233 case 0x18: case 0x19: /* mtcr */
1234 {
1235 unsigned r;
1236 r = IMM5;
1237 if (r <= LAST_VALID_CREG)
1238 cpu.cr[r] = cpu.gr[RD];
1239 else
1240 cpu.asregs.exception = SIGILL;
1241
1242 /* we might have changed register sets... */
1243 if (SR_AF ())
1244 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
1245 else
1246 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
1247 }
1248 break;
1249
1250 case 0x1A: /* asr */
1251 /* We must not rely solely upon the native shift operations, since they
1252 may not match the M*Core's behaviour on boundary conditions. */
1253 if (cpu.gr[RS] > 30)
1254 cpu.gr[RD] = ((long) cpu.gr[RD]) < 0 ? -1 : 0;
1255 else
1256 cpu.gr[RD] = (long) cpu.gr[RD] >> cpu.gr[RS];
1257 break;
1258
1259 case 0x1B: /* lsl */
1260 /* We must not rely solely upon the native shift operations, since they
1261 may not match the M*Core's behaviour on boundary conditions. */
1262 cpu.gr[RD] = cpu.gr[RS] > 31 ? 0 : cpu.gr[RD] << cpu.gr[RS];
1263 break;
1264
1265 case 0x1C: /* addu */
1266 cpu.gr[RD] += cpu.gr[RS];
1267 break;
1268
1269 case 0x1D: /* ixh */
1270 cpu.gr[RD] += cpu.gr[RS] << 1;
1271 break;
1272
1273 case 0x1E: /* or */
1274 cpu.gr[RD] |= cpu.gr[RS];
1275 break;
1276
1277 case 0x1F: /* andn */
1278 cpu.gr[RD] &= ~cpu.gr[RS];
1279 break;
1280 case 0x20: case 0x21: /* addi */
1281 cpu.gr[RD] =
1282 cpu.gr[RD] + (IMM5 + 1);
1283 break;
1284 case 0x22: case 0x23: /* cmplti */
1285 {
1286 int tmp = (IMM5 + 1);
1287 if (cpu.gr[RD] < tmp)
1288 {
1289 SET_C();
1290 }
1291 else
1292 {
1293 CLR_C();
1294 }
1295 }
1296 break;
1297 case 0x24: case 0x25: /* subi */
1298 cpu.gr[RD] =
1299 cpu.gr[RD] - (IMM5 + 1);
1300 break;
1301 case 0x26: case 0x27: /* illegal */
1302 cpu.asregs.exception = SIGILL;
1303 break;
1304 case 0x28: case 0x29: /* rsubi */
1305 cpu.gr[RD] =
1306 IMM5 - cpu.gr[RD];
1307 break;
1308 case 0x2A: case 0x2B: /* cmpnei */
1309 if (cpu.gr[RD] != IMM5)
1310 {
1311 SET_C();
1312 }
1313 else
1314 {
1315 CLR_C();
1316 }
1317 break;
1318
1319 case 0x2C: case 0x2D: /* bmaski, divu */
1320 {
1321 unsigned imm = IMM5;
1322
1323 if (imm == 1)
1324 {
1325 int exe;
1326 int rxnlz, r1nlz;
1327 unsigned int rx, r1;
1328
1329 rx = cpu.gr[RD];
1330 r1 = cpu.gr[1];
1331 exe = 0;
1332
1333 /* unsigned divide */
1334 cpu.gr[RD] = (word) ((unsigned int) cpu.gr[RD] / (unsigned int)cpu.gr[1] );
1335
1336 /* compute bonus_cycles for divu */
1337 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32); r1nlz ++)
1338 r1 = r1 << 1;
1339
1340 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32); rxnlz ++)
1341 rx = rx << 1;
1342
1343 if (r1nlz < rxnlz)
1344 exe += 4;
1345 else
1346 exe += 5 + r1nlz - rxnlz;
1347
1348 if (exe >= (2 * memcycles - 1))
1349 {
1350 bonus_cycles += exe - (2 * memcycles) + 1;
1351 }
1352 }
1353 else if (imm == 0 || imm >= 8)
1354 {
1355 /* bmaski */
1356 if (imm == 0)
1357 cpu.gr[RD] = -1;
1358 else
1359 cpu.gr[RD] = (1 << imm) - 1;
1360 }
1361 else
1362 {
1363 /* illegal */
1364 cpu.asregs.exception = SIGILL;
1365 }
1366 }
1367 break;
1368 case 0x2E: case 0x2F: /* andi */
1369 cpu.gr[RD] = cpu.gr[RD] & IMM5;
1370 break;
1371 case 0x30: case 0x31: /* bclri */
1372 cpu.gr[RD] = cpu.gr[RD] & ~(1<<IMM5);
1373 break;
1374 case 0x32: case 0x33: /* bgeni, divs */
1375 {
1376 unsigned imm = IMM5;
1377 if (imm == 1)
1378 {
1379 int exe,sc;
1380 int rxnlz, r1nlz;
1381 signed int rx, r1;
1382
1383 /* compute bonus_cycles for divu */
1384 rx = cpu.gr[RD];
1385 r1 = cpu.gr[1];
1386 exe = 0;
1387
1388 if (((rx < 0) && (r1 > 0)) || ((rx >= 0) && (r1 < 0)))
1389 sc = 1;
1390 else
1391 sc = 0;
1392
1393 rx = abs (rx);
1394 r1 = abs (r1);
1395
1396 /* signed divide, general registers are of type int, so / op is OK */
1397 cpu.gr[RD] = cpu.gr[RD] / cpu.gr[1];
1398
1399 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32) ; r1nlz ++ )
1400 r1 = r1 << 1;
1401
1402 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32) ; rxnlz ++ )
1403 rx = rx << 1;
1404
1405 if (r1nlz < rxnlz)
1406 exe += 5;
1407 else
1408 exe += 6 + r1nlz - rxnlz + sc;
1409
1410 if (exe >= (2 * memcycles - 1))
1411 {
1412 bonus_cycles += exe - (2 * memcycles) + 1;
1413 }
1414 }
1415 else if (imm >= 7)
1416 {
1417 /* bgeni */
1418 cpu.gr[RD] = (1 << IMM5);
1419 }
1420 else
1421 {
1422 /* illegal */
1423 cpu.asregs.exception = SIGILL;
1424 }
1425 break;
1426 }
1427 case 0x34: case 0x35: /* bseti */
1428 cpu.gr[RD] = cpu.gr[RD] | (1 << IMM5);
1429 break;
1430 case 0x36: case 0x37: /* btsti */
1431 NEW_C (cpu.gr[RD] >> IMM5);
1432 break;
1433 case 0x38: case 0x39: /* xsr, rotli */
1434 {
1435 unsigned imm = IMM5;
1436 unsigned long tmp = cpu.gr[RD];
1437 if (imm == 0)
1438 {
1439 word cbit;
1440 cbit = C_VALUE();
1441 NEW_C (tmp);
1442 cpu.gr[RD] = (cbit << 31) | (tmp >> 1);
1443 }
1444 else
1445 cpu.gr[RD] = (tmp << imm) | (tmp >> (32 - imm));
1446 }
1447 break;
1448 case 0x3A: case 0x3B: /* asrc, asri */
1449 {
1450 unsigned imm = IMM5;
1451 long tmp = cpu.gr[RD];
1452 if (imm == 0)
1453 {
1454 NEW_C (tmp);
1455 cpu.gr[RD] = tmp >> 1;
1456 }
1457 else
1458 cpu.gr[RD] = tmp >> imm;
1459 }
1460 break;
1461 case 0x3C: case 0x3D: /* lslc, lsli */
1462 {
1463 unsigned imm = IMM5;
1464 unsigned long tmp = cpu.gr[RD];
1465 if (imm == 0)
1466 {
1467 NEW_C (tmp >> 31);
1468 cpu.gr[RD] = tmp << 1;
1469 }
1470 else
1471 cpu.gr[RD] = tmp << imm;
1472 }
1473 break;
1474 case 0x3E: case 0x3F: /* lsrc, lsri */
1475 {
1476 unsigned imm = IMM5;
1477 unsigned long tmp = cpu.gr[RD];
1478 if (imm == 0)
1479 {
1480 NEW_C (tmp);
1481 cpu.gr[RD] = tmp >> 1;
1482 }
1483 else
1484 cpu.gr[RD] = tmp >> imm;
1485 }
1486 break;
1487 case 0x40: case 0x41: case 0x42: case 0x43:
1488 case 0x44: case 0x45: case 0x46: case 0x47:
1489 case 0x48: case 0x49: case 0x4A: case 0x4B:
1490 case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1491 cpu.asregs.exception = SIGILL;
1492 break;
1493 case 0x50:
1494 util (sd, inst & 0xFF);
1495 break;
1496 case 0x51: case 0x52: case 0x53:
1497 case 0x54: case 0x55: case 0x56: case 0x57:
1498 case 0x58: case 0x59: case 0x5A: case 0x5B:
1499 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1500 cpu.asregs.exception = SIGILL;
1501 break;
1502 case 0x60: case 0x61: case 0x62: case 0x63: /* movi */
1503 case 0x64: case 0x65: case 0x66: case 0x67:
1504 cpu.gr[RD] = (inst >> 4) & 0x7F;
1505 break;
1506 case 0x68: case 0x69: case 0x6A: case 0x6B:
1507 case 0x6C: case 0x6D: case 0x6E: case 0x6F: /* illegal */
1508 cpu.asregs.exception = SIGILL;
1509 break;
1510 case 0x71: case 0x72: case 0x73:
1511 case 0x74: case 0x75: case 0x76: case 0x77:
1512 case 0x78: case 0x79: case 0x7A: case 0x7B:
1513 case 0x7C: case 0x7D: case 0x7E: /* lrw */
1514 cpu.gr[RX] = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1515 if (tracing)
1516 fprintf (stderr, "LRW of 0x%x from 0x%x to reg %d",
1517 rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC),
1518 (pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC, RX);
1519 memops++;
1520 break;
1521 case 0x7F: /* jsri */
1522 cpu.gr[15] = pc;
1523 if (tracing)
1524 fprintf (stderr, "func call: r2 = %x r3 = %x r4 = %x r5 = %x r6 = %x r7 = %x\n",
1525 cpu.gr[2], cpu.gr[3], cpu.gr[4], cpu.gr[5], cpu.gr[6], cpu.gr[7]);
1526 case 0x70: /* jmpi */
1527 pc = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1528 memops++;
1529 bonus_cycles++;
1530 needfetch = 1;
1531 break;
1532
1533 case 0x80: case 0x81: case 0x82: case 0x83:
1534 case 0x84: case 0x85: case 0x86: case 0x87:
1535 case 0x88: case 0x89: case 0x8A: case 0x8B:
1536 case 0x8C: case 0x8D: case 0x8E: case 0x8F: /* ld */
1537 cpu.gr[RX] = rlat (cpu.gr[RD] + ((inst >> 2) & 0x003C));
1538 if (tracing)
1539 fprintf (stderr, "load reg %d from 0x%x with 0x%x",
1540 RX,
1541 cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1542 memops++;
1543 break;
1544 case 0x90: case 0x91: case 0x92: case 0x93:
1545 case 0x94: case 0x95: case 0x96: case 0x97:
1546 case 0x98: case 0x99: case 0x9A: case 0x9B:
1547 case 0x9C: case 0x9D: case 0x9E: case 0x9F: /* st */
1548 wlat (cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1549 if (tracing)
1550 fprintf (stderr, "store reg %d (containing 0x%x) to 0x%x",
1551 RX, cpu.gr[RX],
1552 cpu.gr[RD] + ((inst >> 2) & 0x003C));
1553 memops++;
1554 break;
1555 case 0xA0: case 0xA1: case 0xA2: case 0xA3:
1556 case 0xA4: case 0xA5: case 0xA6: case 0xA7:
1557 case 0xA8: case 0xA9: case 0xAA: case 0xAB:
1558 case 0xAC: case 0xAD: case 0xAE: case 0xAF: /* ld.b */
1559 cpu.gr[RX] = rbat (cpu.gr[RD] + RS);
1560 memops++;
1561 break;
1562 case 0xB0: case 0xB1: case 0xB2: case 0xB3:
1563 case 0xB4: case 0xB5: case 0xB6: case 0xB7:
1564 case 0xB8: case 0xB9: case 0xBA: case 0xBB:
1565 case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* st.b */
1566 wbat (cpu.gr[RD] + RS, cpu.gr[RX]);
1567 memops++;
1568 break;
1569 case 0xC0: case 0xC1: case 0xC2: case 0xC3:
1570 case 0xC4: case 0xC5: case 0xC6: case 0xC7:
1571 case 0xC8: case 0xC9: case 0xCA: case 0xCB:
1572 case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* ld.h */
1573 cpu.gr[RX] = rhat (cpu.gr[RD] + ((inst >> 3) & 0x001E));
1574 memops++;
1575 break;
1576 case 0xD0: case 0xD1: case 0xD2: case 0xD3:
1577 case 0xD4: case 0xD5: case 0xD6: case 0xD7:
1578 case 0xD8: case 0xD9: case 0xDA: case 0xDB:
1579 case 0xDC: case 0xDD: case 0xDE: case 0xDF: /* st.h */
1580 what (cpu.gr[RD] + ((inst >> 3) & 0x001E), cpu.gr[RX]);
1581 memops++;
1582 break;
1583 case 0xE8: case 0xE9: case 0xEA: case 0xEB:
1584 case 0xEC: case 0xED: case 0xEE: case 0xEF: /* bf */
1585 if (C_OFF())
1586 {
1587 int disp;
1588 disp = inst & 0x03FF;
1589 if (inst & 0x0400)
1590 disp |= 0xFFFFFC00;
1591 pc += disp<<1;
1592 bonus_cycles++;
1593 needfetch = 1;
1594 }
1595 break;
1596 case 0xE0: case 0xE1: case 0xE2: case 0xE3:
1597 case 0xE4: case 0xE5: case 0xE6: case 0xE7: /* bt */
1598 if (C_ON())
1599 {
1600 int disp;
1601 disp = inst & 0x03FF;
1602 if (inst & 0x0400)
1603 disp |= 0xFFFFFC00;
1604 pc += disp<<1;
1605 bonus_cycles++;
1606 needfetch = 1;
1607 }
1608 break;
1609
1610 case 0xF8: case 0xF9: case 0xFA: case 0xFB:
1611 case 0xFC: case 0xFD: case 0xFE: case 0xFF: /* bsr */
1612 cpu.gr[15] = pc;
1613 case 0xF0: case 0xF1: case 0xF2: case 0xF3:
1614 case 0xF4: case 0xF5: case 0xF6: case 0xF7: /* br */
1615 {
1616 int disp;
1617 disp = inst & 0x03FF;
1618 if (inst & 0x0400)
1619 disp |= 0xFFFFFC00;
1620 pc += disp<<1;
1621 bonus_cycles++;
1622 needfetch = 1;
1623 }
1624 break;
1625
1626 }
1627
1628 if (tracing)
1629 fprintf (stderr, "\n");
1630
1631 if (needfetch)
1632 {
1633 /* Do not let him fetch from a bad address! */
1634 if (((uword)pc) >= cpu.asregs.msize)
1635 {
1636 if (issue_messages)
1637 fprintf (stderr, "PC loaded at 0x%x is outside of available memory! (0x%x)\n", oldpc, pc);
1638
1639 cpu.asregs.exception = SIGSEGV;
1640 }
1641 else
1642 {
1643 ibuf = rlat (pc & 0xFFFFFFFC);
1644 needfetch = 0;
1645 }
1646 }
1647 }
1648 while (!cpu.asregs.exception);
1649
1650 /* Hide away the things we've cached while executing. */
1651 CIA_SET (scpu, pc);
1652 cpu.asregs.insts += insts; /* instructions done ... */
1653 cpu.asregs.cycles += insts; /* and each takes a cycle */
1654 cpu.asregs.cycles += bonus_cycles; /* and extra cycles for branches */
1655 cpu.asregs.cycles += memops * memcycles; /* and memop cycle delays */
1656 }
1657
1658
1659 int
1660 sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
1661 {
1662 int i;
1663 init_pointers ();
1664
1665 memcpy (& cpu.mem[addr], buffer, size);
1666
1667 return size;
1668 }
1669
1670 int
1671 sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
1672 {
1673 int i;
1674 init_pointers ();
1675
1676 memcpy (buffer, & cpu.mem[addr], size);
1677
1678 return size;
1679 }
1680
1681
1682 int
1683 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
1684 {
1685 init_pointers ();
1686
1687 if (rn < NUM_MCORE_REGS && rn >= 0)
1688 {
1689 if (length == 4)
1690 {
1691 long ival;
1692
1693 /* misalignment safe */
1694 ival = mcore_extract_unsigned_integer (memory, 4);
1695 cpu.asints[rn] = ival;
1696 }
1697
1698 return 4;
1699 }
1700 else
1701 return 0;
1702 }
1703
1704 int
1705 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
1706 {
1707 init_pointers ();
1708
1709 if (rn < NUM_MCORE_REGS && rn >= 0)
1710 {
1711 if (length == 4)
1712 {
1713 long ival = cpu.asints[rn];
1714
1715 /* misalignment-safe */
1716 mcore_store_unsigned_integer (memory, 4, ival);
1717 }
1718
1719 return 4;
1720 }
1721 else
1722 return 0;
1723 }
1724
1725 void
1726 sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
1727 {
1728 if (cpu.asregs.exception == SIGQUIT)
1729 {
1730 * reason = sim_exited;
1731 * sigrc = cpu.gr[PARM1];
1732 }
1733 else
1734 {
1735 * reason = sim_stopped;
1736 * sigrc = cpu.asregs.exception;
1737 }
1738 }
1739
1740 void
1741 sim_info (SIM_DESC sd, int verbose)
1742 {
1743 #ifdef WATCHFUNCTIONS
1744 int w, wcyc;
1745 #endif
1746 double virttime = cpu.asregs.cycles / 36.0e6;
1747 host_callback *callback = STATE_CALLBACK (sd);
1748
1749 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
1750 cpu.asregs.insts);
1751 callback->printf_filtered (callback, "# cycles %10d\n",
1752 cpu.asregs.cycles);
1753 callback->printf_filtered (callback, "# pipeline stalls %10d\n",
1754 cpu.asregs.stalls);
1755 callback->printf_filtered (callback, "# virtual time taken %10.4f\n",
1756 virttime);
1757
1758 #ifdef WATCHFUNCTIONS
1759 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
1760 ENDWL);
1761
1762 wcyc = 0;
1763
1764 for (w = 1; w <= ENDWL; w++)
1765 {
1766 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
1767 callback->printf_filtered (callback, " calls = %d, cycles = %d\n",
1768 WLcnts[w],WLcyc[w]);
1769
1770 if (WLcnts[w] != 0)
1771 callback->printf_filtered (callback,
1772 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
1773 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
1774 wcyc += WLcyc[w];
1775 }
1776
1777 callback->printf_filtered (callback,
1778 "Total cycles for watched functions: %d\n",wcyc);
1779 #endif
1780 }
1781
1782 static sim_cia
1783 mcore_pc_get (sim_cpu *cpu)
1784 {
1785 return cpu->pc;
1786 }
1787
1788 static void
1789 mcore_pc_set (sim_cpu *cpu, sim_cia pc)
1790 {
1791 cpu->pc = pc;
1792 }
1793
1794 static void
1795 free_state (SIM_DESC sd)
1796 {
1797 if (STATE_MODULES (sd) != NULL)
1798 sim_module_uninstall (sd);
1799 sim_cpu_free_all (sd);
1800 sim_state_free (sd);
1801 }
1802
1803 SIM_DESC
1804 sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
1805 {
1806 SIM_DESC sd = sim_state_alloc (kind, cb);
1807 int i, osize;
1808 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1809
1810 /* The cpu data is kept in a separately allocated chunk of memory. */
1811 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
1812 {
1813 free_state (sd);
1814 return 0;
1815 }
1816
1817 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1818 {
1819 free_state (sd);
1820 return 0;
1821 }
1822
1823 /* getopt will print the error message so we just have to exit if this fails.
1824 FIXME: Hmmm... in the case of gdb we need getopt to call
1825 print_filtered. */
1826 if (sim_parse_args (sd, argv) != SIM_RC_OK)
1827 {
1828 free_state (sd);
1829 return 0;
1830 }
1831
1832 /* Check for/establish the a reference program image. */
1833 if (sim_analyze_program (sd,
1834 (STATE_PROG_ARGV (sd) != NULL
1835 ? *STATE_PROG_ARGV (sd)
1836 : NULL), abfd) != SIM_RC_OK)
1837 {
1838 free_state (sd);
1839 return 0;
1840 }
1841
1842 /* Configure/verify the target byte order and other runtime
1843 configuration options. */
1844 if (sim_config (sd) != SIM_RC_OK)
1845 {
1846 sim_module_uninstall (sd);
1847 return 0;
1848 }
1849
1850 if (sim_post_argv_init (sd) != SIM_RC_OK)
1851 {
1852 /* Uninstall the modules to avoid memory leaks,
1853 file descriptor leaks, etc. */
1854 sim_module_uninstall (sd);
1855 return 0;
1856 }
1857
1858 osize = sim_memory_size;
1859
1860 if (kind == SIM_OPEN_STANDALONE)
1861 issue_messages = 1;
1862
1863 /* Discard and reacquire memory -- start with a clean slate. */
1864 sim_size (1); /* small */
1865 sim_size (osize); /* and back again */
1866
1867 /* CPU specific initialization. */
1868 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1869 {
1870 SIM_CPU *cpu = STATE_CPU (sd, i);
1871
1872 CPU_PC_FETCH (cpu) = mcore_pc_get;
1873 CPU_PC_STORE (cpu) = mcore_pc_set;
1874
1875 set_initial_gprs (cpu); /* Reset the GPR registers. */
1876 }
1877
1878 return sd;
1879 }
1880
1881 void
1882 sim_close (SIM_DESC sd, int quitting)
1883 {
1884 /* nothing to do */
1885 }
1886
1887 SIM_RC
1888 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
1889 {
1890 SIM_CPU *scpu = STATE_CPU (sd, 0);
1891 char ** avp;
1892 int nargs = 0;
1893 int nenv = 0;
1894 int s_length;
1895 int l;
1896 unsigned long strings;
1897 unsigned long pointers;
1898 unsigned long hi_stack;
1899
1900
1901 /* Set the initial register set. */
1902 l = issue_messages;
1903 issue_messages = 0;
1904 set_initial_gprs (scpu);
1905 issue_messages = l;
1906
1907 hi_stack = cpu.asregs.msize - 4;
1908 CIA_SET (scpu, bfd_get_start_address (prog_bfd));
1909
1910 /* Calculate the argument and environment strings. */
1911 s_length = 0;
1912 nargs = 0;
1913 avp = argv;
1914 while (avp && *avp)
1915 {
1916 l = strlen (*avp) + 1; /* include the null */
1917 s_length += (l + 3) & ~3; /* make it a 4 byte boundary */
1918 nargs++; avp++;
1919 }
1920
1921 nenv = 0;
1922 avp = env;
1923 while (avp && *avp)
1924 {
1925 l = strlen (*avp) + 1; /* include the null */
1926 s_length += (l + 3) & ~ 3;/* make it a 4 byte boundary */
1927 nenv++; avp++;
1928 }
1929
1930 /* Claim some memory for the pointers and strings. */
1931 pointers = hi_stack - sizeof(word) * (nenv+1+nargs+1);
1932 pointers &= ~3; /* must be 4-byte aligned */
1933 cpu.gr[0] = pointers;
1934
1935 strings = cpu.gr[0] - s_length;
1936 strings &= ~3; /* want to make it 4-byte aligned */
1937 cpu.gr[0] = strings;
1938 /* dac fix, the stack address must be 8-byte aligned! */
1939 cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
1940
1941 /* Loop through the arguments and fill them in. */
1942 cpu.gr[PARM1] = nargs;
1943 if (nargs == 0)
1944 {
1945 /* No strings to fill in. */
1946 cpu.gr[PARM2] = 0;
1947 }
1948 else
1949 {
1950 cpu.gr[PARM2] = pointers;
1951 avp = argv;
1952 while (avp && *avp)
1953 {
1954 /* Save where we're putting it. */
1955 wlat (pointers, strings);
1956
1957 /* Copy the string. */
1958 l = strlen (* avp) + 1;
1959 strcpy ((char *)(cpu.mem + strings), *avp);
1960
1961 /* Bump the pointers. */
1962 avp++;
1963 pointers += 4;
1964 strings += l+1;
1965 }
1966
1967 /* A null to finish the list. */
1968 wlat (pointers, 0);
1969 pointers += 4;
1970 }
1971
1972 /* Now do the environment pointers. */
1973 if (nenv == 0)
1974 {
1975 /* No strings to fill in. */
1976 cpu.gr[PARM3] = 0;
1977 }
1978 else
1979 {
1980 cpu.gr[PARM3] = pointers;
1981 avp = env;
1982
1983 while (avp && *avp)
1984 {
1985 /* Save where we're putting it. */
1986 wlat (pointers, strings);
1987
1988 /* Copy the string. */
1989 l = strlen (* avp) + 1;
1990 strcpy ((char *)(cpu.mem + strings), *avp);
1991
1992 /* Bump the pointers. */
1993 avp++;
1994 pointers += 4;
1995 strings += l+1;
1996 }
1997
1998 /* A null to finish the list. */
1999 wlat (pointers, 0);
2000 pointers += 4;
2001 }
2002
2003 return SIM_RC_OK;
2004 }
2005
2006 void
2007 sim_do_command (SIM_DESC sd, const char *cmd)
2008 {
2009 /* Nothing there yet; it's all an error. */
2010
2011 if (cmd != NULL)
2012 {
2013 char ** simargv = buildargv (cmd);
2014
2015 if (strcmp (simargv[0], "watch") == 0)
2016 {
2017 if ((simargv[1] == NULL) || (simargv[2] == NULL))
2018 {
2019 fprintf (stderr, "Error: missing argument to watch cmd.\n");
2020 freeargv (simargv);
2021 return;
2022 }
2023
2024 ENDWL++;
2025
2026 WL[ENDWL] = strtol (simargv[2], NULL, 0);
2027 WLstr[ENDWL] = strdup (simargv[1]);
2028 fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
2029 WL[ENDWL], ENDWL);
2030
2031 }
2032 else if (strcmp (simargv[0], "dumpmem") == 0)
2033 {
2034 unsigned char * p;
2035 FILE * dumpfile;
2036
2037 if (simargv[1] == NULL)
2038 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
2039
2040 fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
2041
2042 dumpfile = fopen (simargv[1], "w");
2043 p = cpu.mem;
2044 fwrite (p, cpu.asregs.msize-1, 1, dumpfile);
2045 fclose (dumpfile);
2046
2047 fprintf (stderr, "done.\n");
2048 }
2049 else if (strcmp (simargv[0], "clearstats") == 0)
2050 {
2051 cpu.asregs.cycles = 0;
2052 cpu.asregs.insts = 0;
2053 cpu.asregs.stalls = 0;
2054 ENDWL = 0;
2055 }
2056 else if (strcmp (simargv[0], "verbose") == 0)
2057 {
2058 issue_messages = 2;
2059 }
2060 else
2061 {
2062 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
2063 cmd);
2064 }
2065
2066 freeargv (simargv);
2067 }
2068 else
2069 {
2070 fprintf (stderr, "M.CORE sim commands: \n");
2071 fprintf (stderr, " watch <funcname> <addr>\n");
2072 fprintf (stderr, " dumpmem <filename>\n");
2073 fprintf (stderr, " clearstats\n");
2074 fprintf (stderr, " verbose\n");
2075 }
2076 }