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