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