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