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