sim: mcore: switch to common syscall handling
[deliverable/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 #define WATCHFUNCTIONS 1
565 #ifdef WATCHFUNCTIONS
566
567 #define MAXWL 80
568 word WL[MAXWL];
569 char * WLstr[MAXWL];
570
571 int ENDWL=0;
572 int WLincyc;
573 int WLcyc[MAXWL];
574 int WLcnts[MAXWL];
575 int WLmax[MAXWL];
576 int WLmin[MAXWL];
577 word WLendpc;
578 int WLbcyc;
579 int WLW;
580 #endif
581
582 #define RD (inst & 0xF)
583 #define RS ((inst >> 4) & 0xF)
584 #define RX ((inst >> 8) & 0xF)
585 #define IMM5 ((inst >> 4) & 0x1F)
586 #define IMM4 ((inst) & 0xF)
587
588 static int tracing = 0;
589
590 void
591 sim_resume (SIM_DESC sd, int step, int siggnal)
592 {
593 SIM_CPU *scpu = STATE_CPU (sd, 0);
594 int needfetch;
595 word ibuf;
596 word pc;
597 unsigned short inst;
598 int memops;
599 int bonus_cycles;
600 int insts;
601 int w;
602 int cycs;
603 word WLhash;
604
605 cpu.asregs.exception = step ? SIGTRAP: 0;
606 pc = CPU_PC_GET (scpu);
607
608 /* Fetch the initial instructions that we'll decode. */
609 ibuf = rlat (pc & 0xFFFFFFFC);
610 needfetch = 0;
611
612 memops = 0;
613 bonus_cycles = 0;
614 insts = 0;
615
616 /* make our register set point to the right place */
617 if (SR_AF ())
618 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
619 else
620 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
621
622 /* make a hash to speed exec loop, hope it's nonzero */
623 WLhash = 0xFFFFFFFF;
624
625 for (w = 1; w <= ENDWL; w++)
626 WLhash = WLhash & WL[w];
627
628 do
629 {
630 word oldpc;
631
632 insts ++;
633
634 if (pc & 02)
635 {
636 if (! target_big_endian)
637 inst = ibuf >> 16;
638 else
639 inst = ibuf & 0xFFFF;
640 needfetch = 1;
641 }
642 else
643 {
644 if (! target_big_endian)
645 inst = ibuf & 0xFFFF;
646 else
647 inst = ibuf >> 16;
648 }
649
650 #ifdef WATCHFUNCTIONS
651 /* now scan list of watch addresses, if match, count it and
652 note return address and count cycles until pc=return address */
653
654 if ((WLincyc == 1) && (pc == WLendpc))
655 {
656 cycs = (cpu.asregs.cycles + (insts + bonus_cycles +
657 (memops * memcycles)) - WLbcyc);
658
659 if (WLcnts[WLW] == 1)
660 {
661 WLmax[WLW] = cycs;
662 WLmin[WLW] = cycs;
663 WLcyc[WLW] = 0;
664 }
665
666 if (cycs > WLmax[WLW])
667 {
668 WLmax[WLW] = cycs;
669 }
670
671 if (cycs < WLmin[WLW])
672 {
673 WLmin[WLW] = cycs;
674 }
675
676 WLcyc[WLW] += cycs;
677 WLincyc = 0;
678 WLendpc = 0;
679 }
680
681 /* Optimize with a hash to speed loop. */
682 if (WLincyc == 0)
683 {
684 if ((WLhash == 0) || ((WLhash & pc) != 0))
685 {
686 for (w=1; w <= ENDWL; w++)
687 {
688 if (pc == WL[w])
689 {
690 WLcnts[w]++;
691 WLbcyc = cpu.asregs.cycles + insts
692 + bonus_cycles + (memops * memcycles);
693 WLendpc = cpu.gr[15];
694 WLincyc = 1;
695 WLW = w;
696 break;
697 }
698 }
699 }
700 }
701 #endif
702
703 if (tracing)
704 fprintf (stderr, "%.4x: inst = %.4x ", pc, inst);
705
706 oldpc = pc;
707
708 pc += 2;
709
710 switch (inst >> 8)
711 {
712 case 0x00:
713 switch RS
714 {
715 case 0x0:
716 switch RD
717 {
718 case 0x0: /* bkpt */
719 cpu.asregs.exception = SIGTRAP;
720 pc -= 2;
721 break;
722
723 case 0x1: /* sync */
724 break;
725
726 case 0x2: /* rte */
727 pc = cpu.epc;
728 cpu.sr = cpu.esr;
729 needfetch = 1;
730
731 if (SR_AF ())
732 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
733 else
734 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
735 break;
736
737 case 0x3: /* rfi */
738 pc = cpu.fpc;
739 cpu.sr = cpu.fsr;
740 needfetch = 1;
741
742 if (SR_AF ())
743 cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0];
744 else
745 cpu.asregs.active_gregs = &cpu.asregs.gregs[0];
746 break;
747
748 case 0x4: /* stop */
749 if (issue_messages)
750 fprintf (stderr, "WARNING: stop unimplemented\n");
751 break;
752
753 case 0x5: /* wait */
754 if (issue_messages)
755 fprintf (stderr, "WARNING: wait unimplemented\n");
756 break;
757
758 case 0x6: /* doze */
759 if (issue_messages)
760 fprintf (stderr, "WARNING: doze unimplemented\n");
761 break;
762
763 case 0x7:
764 cpu.asregs.exception = SIGILL; /* illegal */
765 break;
766
767 case 0x8: /* trap 0 */
768 case 0xA: /* trap 2 */
769 case 0xB: /* trap 3 */
770 cpu.asregs.exception = SIGTRAP;
771 break;
772
773 case 0xC: /* trap 4 */
774 case 0xD: /* trap 5 */
775 case 0xE: /* trap 6 */
776 cpu.asregs.exception = SIGILL; /* illegal */
777 break;
778
779 case 0xF: /* trap 7 */
780 cpu.asregs.exception = SIGTRAP; /* integer div-by-0 */
781 break;
782
783 case 0x9: /* trap 1 */
784 handle_trap1 (sd);
785 break;
786 }
787 break;
788
789 case 0x1:
790 cpu.asregs.exception = SIGILL; /* illegal */
791 break;
792
793 case 0x2: /* mvc */
794 cpu.gr[RD] = C_VALUE();
795 break;
796 case 0x3: /* mvcv */
797 cpu.gr[RD] = C_OFF();
798 break;
799 case 0x4: /* ldq */
800 {
801 word addr = cpu.gr[RD];
802 int regno = 4; /* always r4-r7 */
803
804 bonus_cycles++;
805 memops += 4;
806 do
807 {
808 cpu.gr[regno] = rlat(addr);
809 addr += 4;
810 regno++;
811 }
812 while ((regno&0x3) != 0);
813 }
814 break;
815 case 0x5: /* stq */
816 {
817 word addr = cpu.gr[RD];
818 int regno = 4; /* always r4-r7 */
819
820 memops += 4;
821 bonus_cycles++;
822 do
823 {
824 wlat(addr, cpu.gr[regno]);
825 addr += 4;
826 regno++;
827 }
828 while ((regno & 0x3) != 0);
829 }
830 break;
831 case 0x6: /* ldm */
832 {
833 word addr = cpu.gr[0];
834 int regno = RD;
835
836 /* bonus cycle is really only needed if
837 the next insn shifts the last reg loaded.
838
839 bonus_cycles++;
840 */
841 memops += 16-regno;
842 while (regno <= 0xF)
843 {
844 cpu.gr[regno] = rlat(addr);
845 addr += 4;
846 regno++;
847 }
848 }
849 break;
850 case 0x7: /* stm */
851 {
852 word addr = cpu.gr[0];
853 int regno = RD;
854
855 /* this should be removed! */
856 /* bonus_cycles ++; */
857
858 memops += 16 - regno;
859 while (regno <= 0xF)
860 {
861 wlat(addr, cpu.gr[regno]);
862 addr += 4;
863 regno++;
864 }
865 }
866 break;
867
868 case 0x8: /* dect */
869 cpu.gr[RD] -= C_VALUE();
870 break;
871 case 0x9: /* decf */
872 cpu.gr[RD] -= C_OFF();
873 break;
874 case 0xA: /* inct */
875 cpu.gr[RD] += C_VALUE();
876 break;
877 case 0xB: /* incf */
878 cpu.gr[RD] += C_OFF();
879 break;
880 case 0xC: /* jmp */
881 pc = cpu.gr[RD];
882 if (tracing && RD == 15)
883 fprintf (stderr, "Func return, r2 = %x, r3 = %x\n",
884 cpu.gr[2], cpu.gr[3]);
885 bonus_cycles++;
886 needfetch = 1;
887 break;
888 case 0xD: /* jsr */
889 cpu.gr[15] = pc;
890 pc = cpu.gr[RD];
891 bonus_cycles++;
892 needfetch = 1;
893 break;
894 case 0xE: /* ff1 */
895 {
896 word tmp, i;
897 tmp = cpu.gr[RD];
898 for (i = 0; !(tmp & 0x80000000) && i < 32; i++)
899 tmp <<= 1;
900 cpu.gr[RD] = i;
901 }
902 break;
903 case 0xF: /* brev */
904 {
905 word tmp;
906 tmp = cpu.gr[RD];
907 tmp = ((tmp & 0xaaaaaaaa) >> 1) | ((tmp & 0x55555555) << 1);
908 tmp = ((tmp & 0xcccccccc) >> 2) | ((tmp & 0x33333333) << 2);
909 tmp = ((tmp & 0xf0f0f0f0) >> 4) | ((tmp & 0x0f0f0f0f) << 4);
910 tmp = ((tmp & 0xff00ff00) >> 8) | ((tmp & 0x00ff00ff) << 8);
911 cpu.gr[RD] = ((tmp & 0xffff0000) >> 16) | ((tmp & 0x0000ffff) << 16);
912 }
913 break;
914 }
915 break;
916 case 0x01:
917 switch RS
918 {
919 case 0x0: /* xtrb3 */
920 cpu.gr[1] = (cpu.gr[RD]) & 0xFF;
921 NEW_C (cpu.gr[RD] != 0);
922 break;
923 case 0x1: /* xtrb2 */
924 cpu.gr[1] = (cpu.gr[RD]>>8) & 0xFF;
925 NEW_C (cpu.gr[RD] != 0);
926 break;
927 case 0x2: /* xtrb1 */
928 cpu.gr[1] = (cpu.gr[RD]>>16) & 0xFF;
929 NEW_C (cpu.gr[RD] != 0);
930 break;
931 case 0x3: /* xtrb0 */
932 cpu.gr[1] = (cpu.gr[RD]>>24) & 0xFF;
933 NEW_C (cpu.gr[RD] != 0);
934 break;
935 case 0x4: /* zextb */
936 cpu.gr[RD] &= 0x000000FF;
937 break;
938 case 0x5: /* sextb */
939 {
940 long tmp;
941 tmp = cpu.gr[RD];
942 tmp <<= 24;
943 tmp >>= 24;
944 cpu.gr[RD] = tmp;
945 }
946 break;
947 case 0x6: /* zexth */
948 cpu.gr[RD] &= 0x0000FFFF;
949 break;
950 case 0x7: /* sexth */
951 {
952 long tmp;
953 tmp = cpu.gr[RD];
954 tmp <<= 16;
955 tmp >>= 16;
956 cpu.gr[RD] = tmp;
957 }
958 break;
959 case 0x8: /* declt */
960 --cpu.gr[RD];
961 NEW_C ((long)cpu.gr[RD] < 0);
962 break;
963 case 0x9: /* tstnbz */
964 {
965 word tmp = cpu.gr[RD];
966 NEW_C ((tmp & 0xFF000000) != 0 &&
967 (tmp & 0x00FF0000) != 0 && (tmp & 0x0000FF00) != 0 &&
968 (tmp & 0x000000FF) != 0);
969 }
970 break;
971 case 0xA: /* decgt */
972 --cpu.gr[RD];
973 NEW_C ((long)cpu.gr[RD] > 0);
974 break;
975 case 0xB: /* decne */
976 --cpu.gr[RD];
977 NEW_C ((long)cpu.gr[RD] != 0);
978 break;
979 case 0xC: /* clrt */
980 if (C_ON())
981 cpu.gr[RD] = 0;
982 break;
983 case 0xD: /* clrf */
984 if (C_OFF())
985 cpu.gr[RD] = 0;
986 break;
987 case 0xE: /* abs */
988 if (cpu.gr[RD] & 0x80000000)
989 cpu.gr[RD] = ~cpu.gr[RD] + 1;
990 break;
991 case 0xF: /* not */
992 cpu.gr[RD] = ~cpu.gr[RD];
993 break;
994 }
995 break;
996 case 0x02: /* movt */
997 if (C_ON())
998 cpu.gr[RD] = cpu.gr[RS];
999 break;
1000 case 0x03: /* mult */
1001 /* consume 2 bits per cycle from rs, until rs is 0 */
1002 {
1003 unsigned int t = cpu.gr[RS];
1004 int ticks;
1005 for (ticks = 0; t != 0 ; t >>= 2)
1006 ticks++;
1007 bonus_cycles += ticks;
1008 }
1009 bonus_cycles += 2; /* min. is 3, so add 2, plus ticks above */
1010 if (tracing)
1011 fprintf (stderr, " mult %x by %x to give %x",
1012 cpu.gr[RD], cpu.gr[RS], cpu.gr[RD] * cpu.gr[RS]);
1013 cpu.gr[RD] = cpu.gr[RD] * cpu.gr[RS];
1014 break;
1015 case 0x04: /* loopt */
1016 if (C_ON())
1017 {
1018 pc += (IMM4 << 1) - 32;
1019 bonus_cycles ++;
1020 needfetch = 1;
1021 }
1022 --cpu.gr[RS]; /* not RD! */
1023 NEW_C (((long)cpu.gr[RS]) > 0);
1024 break;
1025 case 0x05: /* subu */
1026 cpu.gr[RD] -= cpu.gr[RS];
1027 break;
1028 case 0x06: /* addc */
1029 {
1030 unsigned long tmp, a, b;
1031 a = cpu.gr[RD];
1032 b = cpu.gr[RS];
1033 cpu.gr[RD] = a + b + C_VALUE ();
1034 tmp = iu_carry (a, b, C_VALUE ());
1035 NEW_C (tmp);
1036 }
1037 break;
1038 case 0x07: /* subc */
1039 {
1040 unsigned long tmp, a, b;
1041 a = cpu.gr[RD];
1042 b = cpu.gr[RS];
1043 cpu.gr[RD] = a - b + C_VALUE () - 1;
1044 tmp = iu_carry (a,~b, C_VALUE ());
1045 NEW_C (tmp);
1046 }
1047 break;
1048 case 0x08: /* illegal */
1049 case 0x09: /* illegal*/
1050 cpu.asregs.exception = SIGILL;
1051 break;
1052 case 0x0A: /* movf */
1053 if (C_OFF())
1054 cpu.gr[RD] = cpu.gr[RS];
1055 break;
1056 case 0x0B: /* lsr */
1057 {
1058 unsigned long dst, src;
1059 dst = cpu.gr[RD];
1060 src = cpu.gr[RS];
1061 /* We must not rely solely upon the native shift operations, since they
1062 may not match the M*Core's behaviour on boundary conditions. */
1063 dst = src > 31 ? 0 : dst >> src;
1064 cpu.gr[RD] = dst;
1065 }
1066 break;
1067 case 0x0C: /* cmphs */
1068 NEW_C ((unsigned long )cpu.gr[RD] >=
1069 (unsigned long)cpu.gr[RS]);
1070 break;
1071 case 0x0D: /* cmplt */
1072 NEW_C ((long)cpu.gr[RD] < (long)cpu.gr[RS]);
1073 break;
1074 case 0x0E: /* tst */
1075 NEW_C ((cpu.gr[RD] & cpu.gr[RS]) != 0);
1076 break;
1077 case 0x0F: /* cmpne */
1078 NEW_C (cpu.gr[RD] != cpu.gr[RS]);
1079 break;
1080 case 0x10: case 0x11: /* mfcr */
1081 {
1082 unsigned r;
1083 r = IMM5;
1084 if (r <= LAST_VALID_CREG)
1085 cpu.gr[RD] = cpu.cr[r];
1086 else
1087 cpu.asregs.exception = SIGILL;
1088 }
1089 break;
1090
1091 case 0x12: /* mov */
1092 cpu.gr[RD] = cpu.gr[RS];
1093 if (tracing)
1094 fprintf (stderr, "MOV %x into reg %d", cpu.gr[RD], RD);
1095 break;
1096
1097 case 0x13: /* bgenr */
1098 if (cpu.gr[RS] & 0x20)
1099 cpu.gr[RD] = 0;
1100 else
1101 cpu.gr[RD] = 1 << (cpu.gr[RS] & 0x1F);
1102 break;
1103
1104 case 0x14: /* rsub */
1105 cpu.gr[RD] = cpu.gr[RS] - cpu.gr[RD];
1106 break;
1107
1108 case 0x15: /* ixw */
1109 cpu.gr[RD] += cpu.gr[RS]<<2;
1110 break;
1111
1112 case 0x16: /* and */
1113 cpu.gr[RD] &= cpu.gr[RS];
1114 break;
1115
1116 case 0x17: /* xor */
1117 cpu.gr[RD] ^= cpu.gr[RS];
1118 break;
1119
1120 case 0x18: case 0x19: /* mtcr */
1121 {
1122 unsigned r;
1123 r = IMM5;
1124 if (r <= LAST_VALID_CREG)
1125 cpu.cr[r] = cpu.gr[RD];
1126 else
1127 cpu.asregs.exception = SIGILL;
1128
1129 /* we might have changed register sets... */
1130 if (SR_AF ())
1131 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
1132 else
1133 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
1134 }
1135 break;
1136
1137 case 0x1A: /* asr */
1138 /* We must not rely solely upon the native shift operations, since they
1139 may not match the M*Core's behaviour on boundary conditions. */
1140 if (cpu.gr[RS] > 30)
1141 cpu.gr[RD] = ((long) cpu.gr[RD]) < 0 ? -1 : 0;
1142 else
1143 cpu.gr[RD] = (long) cpu.gr[RD] >> cpu.gr[RS];
1144 break;
1145
1146 case 0x1B: /* lsl */
1147 /* We must not rely solely upon the native shift operations, since they
1148 may not match the M*Core's behaviour on boundary conditions. */
1149 cpu.gr[RD] = cpu.gr[RS] > 31 ? 0 : cpu.gr[RD] << cpu.gr[RS];
1150 break;
1151
1152 case 0x1C: /* addu */
1153 cpu.gr[RD] += cpu.gr[RS];
1154 break;
1155
1156 case 0x1D: /* ixh */
1157 cpu.gr[RD] += cpu.gr[RS] << 1;
1158 break;
1159
1160 case 0x1E: /* or */
1161 cpu.gr[RD] |= cpu.gr[RS];
1162 break;
1163
1164 case 0x1F: /* andn */
1165 cpu.gr[RD] &= ~cpu.gr[RS];
1166 break;
1167 case 0x20: case 0x21: /* addi */
1168 cpu.gr[RD] =
1169 cpu.gr[RD] + (IMM5 + 1);
1170 break;
1171 case 0x22: case 0x23: /* cmplti */
1172 {
1173 int tmp = (IMM5 + 1);
1174 if (cpu.gr[RD] < tmp)
1175 {
1176 SET_C();
1177 }
1178 else
1179 {
1180 CLR_C();
1181 }
1182 }
1183 break;
1184 case 0x24: case 0x25: /* subi */
1185 cpu.gr[RD] =
1186 cpu.gr[RD] - (IMM5 + 1);
1187 break;
1188 case 0x26: case 0x27: /* illegal */
1189 cpu.asregs.exception = SIGILL;
1190 break;
1191 case 0x28: case 0x29: /* rsubi */
1192 cpu.gr[RD] =
1193 IMM5 - cpu.gr[RD];
1194 break;
1195 case 0x2A: case 0x2B: /* cmpnei */
1196 if (cpu.gr[RD] != IMM5)
1197 {
1198 SET_C();
1199 }
1200 else
1201 {
1202 CLR_C();
1203 }
1204 break;
1205
1206 case 0x2C: case 0x2D: /* bmaski, divu */
1207 {
1208 unsigned imm = IMM5;
1209
1210 if (imm == 1)
1211 {
1212 int exe;
1213 int rxnlz, r1nlz;
1214 unsigned int rx, r1;
1215
1216 rx = cpu.gr[RD];
1217 r1 = cpu.gr[1];
1218 exe = 0;
1219
1220 /* unsigned divide */
1221 cpu.gr[RD] = (word) ((unsigned int) cpu.gr[RD] / (unsigned int)cpu.gr[1] );
1222
1223 /* compute bonus_cycles for divu */
1224 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32); r1nlz ++)
1225 r1 = r1 << 1;
1226
1227 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32); rxnlz ++)
1228 rx = rx << 1;
1229
1230 if (r1nlz < rxnlz)
1231 exe += 4;
1232 else
1233 exe += 5 + r1nlz - rxnlz;
1234
1235 if (exe >= (2 * memcycles - 1))
1236 {
1237 bonus_cycles += exe - (2 * memcycles) + 1;
1238 }
1239 }
1240 else if (imm == 0 || imm >= 8)
1241 {
1242 /* bmaski */
1243 if (imm == 0)
1244 cpu.gr[RD] = -1;
1245 else
1246 cpu.gr[RD] = (1 << imm) - 1;
1247 }
1248 else
1249 {
1250 /* illegal */
1251 cpu.asregs.exception = SIGILL;
1252 }
1253 }
1254 break;
1255 case 0x2E: case 0x2F: /* andi */
1256 cpu.gr[RD] = cpu.gr[RD] & IMM5;
1257 break;
1258 case 0x30: case 0x31: /* bclri */
1259 cpu.gr[RD] = cpu.gr[RD] & ~(1<<IMM5);
1260 break;
1261 case 0x32: case 0x33: /* bgeni, divs */
1262 {
1263 unsigned imm = IMM5;
1264 if (imm == 1)
1265 {
1266 int exe,sc;
1267 int rxnlz, r1nlz;
1268 signed int rx, r1;
1269
1270 /* compute bonus_cycles for divu */
1271 rx = cpu.gr[RD];
1272 r1 = cpu.gr[1];
1273 exe = 0;
1274
1275 if (((rx < 0) && (r1 > 0)) || ((rx >= 0) && (r1 < 0)))
1276 sc = 1;
1277 else
1278 sc = 0;
1279
1280 rx = abs (rx);
1281 r1 = abs (r1);
1282
1283 /* signed divide, general registers are of type int, so / op is OK */
1284 cpu.gr[RD] = cpu.gr[RD] / cpu.gr[1];
1285
1286 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32) ; r1nlz ++ )
1287 r1 = r1 << 1;
1288
1289 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32) ; rxnlz ++ )
1290 rx = rx << 1;
1291
1292 if (r1nlz < rxnlz)
1293 exe += 5;
1294 else
1295 exe += 6 + r1nlz - rxnlz + sc;
1296
1297 if (exe >= (2 * memcycles - 1))
1298 {
1299 bonus_cycles += exe - (2 * memcycles) + 1;
1300 }
1301 }
1302 else if (imm >= 7)
1303 {
1304 /* bgeni */
1305 cpu.gr[RD] = (1 << IMM5);
1306 }
1307 else
1308 {
1309 /* illegal */
1310 cpu.asregs.exception = SIGILL;
1311 }
1312 break;
1313 }
1314 case 0x34: case 0x35: /* bseti */
1315 cpu.gr[RD] = cpu.gr[RD] | (1 << IMM5);
1316 break;
1317 case 0x36: case 0x37: /* btsti */
1318 NEW_C (cpu.gr[RD] >> IMM5);
1319 break;
1320 case 0x38: case 0x39: /* xsr, rotli */
1321 {
1322 unsigned imm = IMM5;
1323 unsigned long tmp = cpu.gr[RD];
1324 if (imm == 0)
1325 {
1326 word cbit;
1327 cbit = C_VALUE();
1328 NEW_C (tmp);
1329 cpu.gr[RD] = (cbit << 31) | (tmp >> 1);
1330 }
1331 else
1332 cpu.gr[RD] = (tmp << imm) | (tmp >> (32 - imm));
1333 }
1334 break;
1335 case 0x3A: case 0x3B: /* asrc, asri */
1336 {
1337 unsigned imm = IMM5;
1338 long tmp = cpu.gr[RD];
1339 if (imm == 0)
1340 {
1341 NEW_C (tmp);
1342 cpu.gr[RD] = tmp >> 1;
1343 }
1344 else
1345 cpu.gr[RD] = tmp >> imm;
1346 }
1347 break;
1348 case 0x3C: case 0x3D: /* lslc, lsli */
1349 {
1350 unsigned imm = IMM5;
1351 unsigned long tmp = cpu.gr[RD];
1352 if (imm == 0)
1353 {
1354 NEW_C (tmp >> 31);
1355 cpu.gr[RD] = tmp << 1;
1356 }
1357 else
1358 cpu.gr[RD] = tmp << imm;
1359 }
1360 break;
1361 case 0x3E: case 0x3F: /* lsrc, lsri */
1362 {
1363 unsigned imm = IMM5;
1364 unsigned long tmp = cpu.gr[RD];
1365 if (imm == 0)
1366 {
1367 NEW_C (tmp);
1368 cpu.gr[RD] = tmp >> 1;
1369 }
1370 else
1371 cpu.gr[RD] = tmp >> imm;
1372 }
1373 break;
1374 case 0x40: case 0x41: case 0x42: case 0x43:
1375 case 0x44: case 0x45: case 0x46: case 0x47:
1376 case 0x48: case 0x49: case 0x4A: case 0x4B:
1377 case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1378 cpu.asregs.exception = SIGILL;
1379 break;
1380 case 0x50:
1381 util (sd, inst & 0xFF);
1382 break;
1383 case 0x51: case 0x52: case 0x53:
1384 case 0x54: case 0x55: case 0x56: case 0x57:
1385 case 0x58: case 0x59: case 0x5A: case 0x5B:
1386 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1387 cpu.asregs.exception = SIGILL;
1388 break;
1389 case 0x60: case 0x61: case 0x62: case 0x63: /* movi */
1390 case 0x64: case 0x65: case 0x66: case 0x67:
1391 cpu.gr[RD] = (inst >> 4) & 0x7F;
1392 break;
1393 case 0x68: case 0x69: case 0x6A: case 0x6B:
1394 case 0x6C: case 0x6D: case 0x6E: case 0x6F: /* illegal */
1395 cpu.asregs.exception = SIGILL;
1396 break;
1397 case 0x71: case 0x72: case 0x73:
1398 case 0x74: case 0x75: case 0x76: case 0x77:
1399 case 0x78: case 0x79: case 0x7A: case 0x7B:
1400 case 0x7C: case 0x7D: case 0x7E: /* lrw */
1401 cpu.gr[RX] = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1402 if (tracing)
1403 fprintf (stderr, "LRW of 0x%x from 0x%x to reg %d",
1404 rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC),
1405 (pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC, RX);
1406 memops++;
1407 break;
1408 case 0x7F: /* jsri */
1409 cpu.gr[15] = pc;
1410 if (tracing)
1411 fprintf (stderr, "func call: r2 = %x r3 = %x r4 = %x r5 = %x r6 = %x r7 = %x\n",
1412 cpu.gr[2], cpu.gr[3], cpu.gr[4], cpu.gr[5], cpu.gr[6], cpu.gr[7]);
1413 case 0x70: /* jmpi */
1414 pc = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1415 memops++;
1416 bonus_cycles++;
1417 needfetch = 1;
1418 break;
1419
1420 case 0x80: case 0x81: case 0x82: case 0x83:
1421 case 0x84: case 0x85: case 0x86: case 0x87:
1422 case 0x88: case 0x89: case 0x8A: case 0x8B:
1423 case 0x8C: case 0x8D: case 0x8E: case 0x8F: /* ld */
1424 cpu.gr[RX] = rlat (cpu.gr[RD] + ((inst >> 2) & 0x003C));
1425 if (tracing)
1426 fprintf (stderr, "load reg %d from 0x%x with 0x%x",
1427 RX,
1428 cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1429 memops++;
1430 break;
1431 case 0x90: case 0x91: case 0x92: case 0x93:
1432 case 0x94: case 0x95: case 0x96: case 0x97:
1433 case 0x98: case 0x99: case 0x9A: case 0x9B:
1434 case 0x9C: case 0x9D: case 0x9E: case 0x9F: /* st */
1435 wlat (cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1436 if (tracing)
1437 fprintf (stderr, "store reg %d (containing 0x%x) to 0x%x",
1438 RX, cpu.gr[RX],
1439 cpu.gr[RD] + ((inst >> 2) & 0x003C));
1440 memops++;
1441 break;
1442 case 0xA0: case 0xA1: case 0xA2: case 0xA3:
1443 case 0xA4: case 0xA5: case 0xA6: case 0xA7:
1444 case 0xA8: case 0xA9: case 0xAA: case 0xAB:
1445 case 0xAC: case 0xAD: case 0xAE: case 0xAF: /* ld.b */
1446 cpu.gr[RX] = rbat (cpu.gr[RD] + RS);
1447 memops++;
1448 break;
1449 case 0xB0: case 0xB1: case 0xB2: case 0xB3:
1450 case 0xB4: case 0xB5: case 0xB6: case 0xB7:
1451 case 0xB8: case 0xB9: case 0xBA: case 0xBB:
1452 case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* st.b */
1453 wbat (cpu.gr[RD] + RS, cpu.gr[RX]);
1454 memops++;
1455 break;
1456 case 0xC0: case 0xC1: case 0xC2: case 0xC3:
1457 case 0xC4: case 0xC5: case 0xC6: case 0xC7:
1458 case 0xC8: case 0xC9: case 0xCA: case 0xCB:
1459 case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* ld.h */
1460 cpu.gr[RX] = rhat (cpu.gr[RD] + ((inst >> 3) & 0x001E));
1461 memops++;
1462 break;
1463 case 0xD0: case 0xD1: case 0xD2: case 0xD3:
1464 case 0xD4: case 0xD5: case 0xD6: case 0xD7:
1465 case 0xD8: case 0xD9: case 0xDA: case 0xDB:
1466 case 0xDC: case 0xDD: case 0xDE: case 0xDF: /* st.h */
1467 what (cpu.gr[RD] + ((inst >> 3) & 0x001E), cpu.gr[RX]);
1468 memops++;
1469 break;
1470 case 0xE8: case 0xE9: case 0xEA: case 0xEB:
1471 case 0xEC: case 0xED: case 0xEE: case 0xEF: /* bf */
1472 if (C_OFF())
1473 {
1474 int disp;
1475 disp = inst & 0x03FF;
1476 if (inst & 0x0400)
1477 disp |= 0xFFFFFC00;
1478 pc += disp<<1;
1479 bonus_cycles++;
1480 needfetch = 1;
1481 }
1482 break;
1483 case 0xE0: case 0xE1: case 0xE2: case 0xE3:
1484 case 0xE4: case 0xE5: case 0xE6: case 0xE7: /* bt */
1485 if (C_ON())
1486 {
1487 int disp;
1488 disp = inst & 0x03FF;
1489 if (inst & 0x0400)
1490 disp |= 0xFFFFFC00;
1491 pc += disp<<1;
1492 bonus_cycles++;
1493 needfetch = 1;
1494 }
1495 break;
1496
1497 case 0xF8: case 0xF9: case 0xFA: case 0xFB:
1498 case 0xFC: case 0xFD: case 0xFE: case 0xFF: /* bsr */
1499 cpu.gr[15] = pc;
1500 case 0xF0: case 0xF1: case 0xF2: case 0xF3:
1501 case 0xF4: case 0xF5: case 0xF6: case 0xF7: /* br */
1502 {
1503 int disp;
1504 disp = inst & 0x03FF;
1505 if (inst & 0x0400)
1506 disp |= 0xFFFFFC00;
1507 pc += disp<<1;
1508 bonus_cycles++;
1509 needfetch = 1;
1510 }
1511 break;
1512
1513 }
1514
1515 if (tracing)
1516 fprintf (stderr, "\n");
1517
1518 if (needfetch)
1519 {
1520 /* Do not let him fetch from a bad address! */
1521 if (((uword)pc) >= cpu.asregs.msize)
1522 {
1523 if (issue_messages)
1524 fprintf (stderr, "PC loaded at 0x%x is outside of available memory! (0x%x)\n", oldpc, pc);
1525
1526 cpu.asregs.exception = SIGSEGV;
1527 }
1528 else
1529 {
1530 ibuf = rlat (pc & 0xFFFFFFFC);
1531 needfetch = 0;
1532 }
1533 }
1534 }
1535 while (!cpu.asregs.exception);
1536
1537 /* Hide away the things we've cached while executing. */
1538 CPU_PC_SET (scpu, pc);
1539 cpu.asregs.insts += insts; /* instructions done ... */
1540 cpu.asregs.cycles += insts; /* and each takes a cycle */
1541 cpu.asregs.cycles += bonus_cycles; /* and extra cycles for branches */
1542 cpu.asregs.cycles += memops * memcycles; /* and memop cycle delays */
1543 }
1544
1545
1546 int
1547 sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
1548 {
1549 int i;
1550 init_pointers ();
1551
1552 memcpy (& cpu.mem[addr], buffer, size);
1553
1554 return size;
1555 }
1556
1557 int
1558 sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
1559 {
1560 int i;
1561 init_pointers ();
1562
1563 memcpy (buffer, & cpu.mem[addr], size);
1564
1565 return size;
1566 }
1567
1568
1569 int
1570 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
1571 {
1572 init_pointers ();
1573
1574 if (rn < NUM_MCORE_REGS && rn >= 0)
1575 {
1576 if (length == 4)
1577 {
1578 long ival;
1579
1580 /* misalignment safe */
1581 ival = mcore_extract_unsigned_integer (memory, 4);
1582 cpu.asints[rn] = ival;
1583 }
1584
1585 return 4;
1586 }
1587 else
1588 return 0;
1589 }
1590
1591 int
1592 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
1593 {
1594 init_pointers ();
1595
1596 if (rn < NUM_MCORE_REGS && rn >= 0)
1597 {
1598 if (length == 4)
1599 {
1600 long ival = cpu.asints[rn];
1601
1602 /* misalignment-safe */
1603 mcore_store_unsigned_integer (memory, 4, ival);
1604 }
1605
1606 return 4;
1607 }
1608 else
1609 return 0;
1610 }
1611
1612 void
1613 sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
1614 {
1615 if (cpu.asregs.exception == SIGQUIT)
1616 {
1617 * reason = sim_exited;
1618 * sigrc = cpu.gr[PARM1];
1619 }
1620 else
1621 {
1622 * reason = sim_stopped;
1623 * sigrc = cpu.asregs.exception;
1624 }
1625 }
1626
1627 void
1628 sim_info (SIM_DESC sd, int verbose)
1629 {
1630 #ifdef WATCHFUNCTIONS
1631 int w, wcyc;
1632 #endif
1633 double virttime = cpu.asregs.cycles / 36.0e6;
1634 host_callback *callback = STATE_CALLBACK (sd);
1635
1636 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
1637 cpu.asregs.insts);
1638 callback->printf_filtered (callback, "# cycles %10d\n",
1639 cpu.asregs.cycles);
1640 callback->printf_filtered (callback, "# pipeline stalls %10d\n",
1641 cpu.asregs.stalls);
1642 callback->printf_filtered (callback, "# virtual time taken %10.4f\n",
1643 virttime);
1644
1645 #ifdef WATCHFUNCTIONS
1646 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
1647 ENDWL);
1648
1649 wcyc = 0;
1650
1651 for (w = 1; w <= ENDWL; w++)
1652 {
1653 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
1654 callback->printf_filtered (callback, " calls = %d, cycles = %d\n",
1655 WLcnts[w],WLcyc[w]);
1656
1657 if (WLcnts[w] != 0)
1658 callback->printf_filtered (callback,
1659 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
1660 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
1661 wcyc += WLcyc[w];
1662 }
1663
1664 callback->printf_filtered (callback,
1665 "Total cycles for watched functions: %d\n",wcyc);
1666 #endif
1667 }
1668
1669 static sim_cia
1670 mcore_pc_get (sim_cpu *cpu)
1671 {
1672 return cpu->pc;
1673 }
1674
1675 static void
1676 mcore_pc_set (sim_cpu *cpu, sim_cia pc)
1677 {
1678 cpu->pc = pc;
1679 }
1680
1681 static void
1682 free_state (SIM_DESC sd)
1683 {
1684 if (STATE_MODULES (sd) != NULL)
1685 sim_module_uninstall (sd);
1686 sim_cpu_free_all (sd);
1687 sim_state_free (sd);
1688 }
1689
1690 SIM_DESC
1691 sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
1692 {
1693 SIM_DESC sd = sim_state_alloc (kind, cb);
1694 int i, osize;
1695 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
1696
1697 /* The cpu data is kept in a separately allocated chunk of memory. */
1698 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
1699 {
1700 free_state (sd);
1701 return 0;
1702 }
1703
1704 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
1705 {
1706 free_state (sd);
1707 return 0;
1708 }
1709
1710 /* getopt will print the error message so we just have to exit if this fails.
1711 FIXME: Hmmm... in the case of gdb we need getopt to call
1712 print_filtered. */
1713 if (sim_parse_args (sd, argv) != SIM_RC_OK)
1714 {
1715 free_state (sd);
1716 return 0;
1717 }
1718
1719 /* Check for/establish the a reference program image. */
1720 if (sim_analyze_program (sd,
1721 (STATE_PROG_ARGV (sd) != NULL
1722 ? *STATE_PROG_ARGV (sd)
1723 : NULL), abfd) != SIM_RC_OK)
1724 {
1725 free_state (sd);
1726 return 0;
1727 }
1728
1729 /* Configure/verify the target byte order and other runtime
1730 configuration options. */
1731 if (sim_config (sd) != SIM_RC_OK)
1732 {
1733 sim_module_uninstall (sd);
1734 return 0;
1735 }
1736
1737 if (sim_post_argv_init (sd) != SIM_RC_OK)
1738 {
1739 /* Uninstall the modules to avoid memory leaks,
1740 file descriptor leaks, etc. */
1741 sim_module_uninstall (sd);
1742 return 0;
1743 }
1744
1745 osize = sim_memory_size;
1746
1747 if (kind == SIM_OPEN_STANDALONE)
1748 issue_messages = 1;
1749
1750 /* Discard and reacquire memory -- start with a clean slate. */
1751 sim_size (1); /* small */
1752 sim_size (osize); /* and back again */
1753
1754 /* CPU specific initialization. */
1755 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1756 {
1757 SIM_CPU *cpu = STATE_CPU (sd, i);
1758
1759 CPU_PC_FETCH (cpu) = mcore_pc_get;
1760 CPU_PC_STORE (cpu) = mcore_pc_set;
1761
1762 set_initial_gprs (cpu); /* Reset the GPR registers. */
1763 }
1764
1765 return sd;
1766 }
1767
1768 void
1769 sim_close (SIM_DESC sd, int quitting)
1770 {
1771 /* nothing to do */
1772 }
1773
1774 SIM_RC
1775 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
1776 {
1777 SIM_CPU *scpu = STATE_CPU (sd, 0);
1778 char ** avp;
1779 int nargs = 0;
1780 int nenv = 0;
1781 int s_length;
1782 int l;
1783 unsigned long strings;
1784 unsigned long pointers;
1785 unsigned long hi_stack;
1786
1787
1788 /* Set the initial register set. */
1789 l = issue_messages;
1790 issue_messages = 0;
1791 set_initial_gprs (scpu);
1792 issue_messages = l;
1793
1794 hi_stack = cpu.asregs.msize - 4;
1795 CPU_PC_SET (scpu, bfd_get_start_address (prog_bfd));
1796
1797 /* Calculate the argument and environment strings. */
1798 s_length = 0;
1799 nargs = 0;
1800 avp = argv;
1801 while (avp && *avp)
1802 {
1803 l = strlen (*avp) + 1; /* include the null */
1804 s_length += (l + 3) & ~3; /* make it a 4 byte boundary */
1805 nargs++; avp++;
1806 }
1807
1808 nenv = 0;
1809 avp = env;
1810 while (avp && *avp)
1811 {
1812 l = strlen (*avp) + 1; /* include the null */
1813 s_length += (l + 3) & ~ 3;/* make it a 4 byte boundary */
1814 nenv++; avp++;
1815 }
1816
1817 /* Claim some memory for the pointers and strings. */
1818 pointers = hi_stack - sizeof(word) * (nenv+1+nargs+1);
1819 pointers &= ~3; /* must be 4-byte aligned */
1820 cpu.gr[0] = pointers;
1821
1822 strings = cpu.gr[0] - s_length;
1823 strings &= ~3; /* want to make it 4-byte aligned */
1824 cpu.gr[0] = strings;
1825 /* dac fix, the stack address must be 8-byte aligned! */
1826 cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
1827
1828 /* Loop through the arguments and fill them in. */
1829 cpu.gr[PARM1] = nargs;
1830 if (nargs == 0)
1831 {
1832 /* No strings to fill in. */
1833 cpu.gr[PARM2] = 0;
1834 }
1835 else
1836 {
1837 cpu.gr[PARM2] = pointers;
1838 avp = argv;
1839 while (avp && *avp)
1840 {
1841 /* Save where we're putting it. */
1842 wlat (pointers, strings);
1843
1844 /* Copy the string. */
1845 l = strlen (* avp) + 1;
1846 strcpy ((char *)(cpu.mem + strings), *avp);
1847
1848 /* Bump the pointers. */
1849 avp++;
1850 pointers += 4;
1851 strings += l+1;
1852 }
1853
1854 /* A null to finish the list. */
1855 wlat (pointers, 0);
1856 pointers += 4;
1857 }
1858
1859 /* Now do the environment pointers. */
1860 if (nenv == 0)
1861 {
1862 /* No strings to fill in. */
1863 cpu.gr[PARM3] = 0;
1864 }
1865 else
1866 {
1867 cpu.gr[PARM3] = pointers;
1868 avp = env;
1869
1870 while (avp && *avp)
1871 {
1872 /* Save where we're putting it. */
1873 wlat (pointers, strings);
1874
1875 /* Copy the string. */
1876 l = strlen (* avp) + 1;
1877 strcpy ((char *)(cpu.mem + strings), *avp);
1878
1879 /* Bump the pointers. */
1880 avp++;
1881 pointers += 4;
1882 strings += l+1;
1883 }
1884
1885 /* A null to finish the list. */
1886 wlat (pointers, 0);
1887 pointers += 4;
1888 }
1889
1890 return SIM_RC_OK;
1891 }
1892
1893 void
1894 sim_do_command (SIM_DESC sd, const char *cmd)
1895 {
1896 /* Nothing there yet; it's all an error. */
1897
1898 if (cmd != NULL)
1899 {
1900 char ** simargv = buildargv (cmd);
1901
1902 if (strcmp (simargv[0], "watch") == 0)
1903 {
1904 if ((simargv[1] == NULL) || (simargv[2] == NULL))
1905 {
1906 fprintf (stderr, "Error: missing argument to watch cmd.\n");
1907 freeargv (simargv);
1908 return;
1909 }
1910
1911 ENDWL++;
1912
1913 WL[ENDWL] = strtol (simargv[2], NULL, 0);
1914 WLstr[ENDWL] = strdup (simargv[1]);
1915 fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
1916 WL[ENDWL], ENDWL);
1917
1918 }
1919 else if (strcmp (simargv[0], "dumpmem") == 0)
1920 {
1921 unsigned char * p;
1922 FILE * dumpfile;
1923
1924 if (simargv[1] == NULL)
1925 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
1926
1927 fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
1928
1929 dumpfile = fopen (simargv[1], "w");
1930 p = cpu.mem;
1931 fwrite (p, cpu.asregs.msize-1, 1, dumpfile);
1932 fclose (dumpfile);
1933
1934 fprintf (stderr, "done.\n");
1935 }
1936 else if (strcmp (simargv[0], "clearstats") == 0)
1937 {
1938 cpu.asregs.cycles = 0;
1939 cpu.asregs.insts = 0;
1940 cpu.asregs.stalls = 0;
1941 ENDWL = 0;
1942 }
1943 else if (strcmp (simargv[0], "verbose") == 0)
1944 {
1945 issue_messages = 2;
1946 }
1947 else
1948 {
1949 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1950 cmd);
1951 }
1952
1953 freeargv (simargv);
1954 }
1955 else
1956 {
1957 fprintf (stderr, "M.CORE sim commands: \n");
1958 fprintf (stderr, " watch <funcname> <addr>\n");
1959 fprintf (stderr, " dumpmem <filename>\n");
1960 fprintf (stderr, " clearstats\n");
1961 fprintf (stderr, " verbose\n");
1962 }
1963 }
This page took 0.070702 seconds and 4 git commands to generate.