import gdb-1999-05-25 snapshot
[deliverable/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
2d514e6f
SS
43unsigned long
44mcore_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;
cd0fc7c3
SS
60
61 {
62 for (p = startaddr; p < endaddr;)
63 retval = (retval << 8) | * p ++;
64 }
2d514e6f
SS
65
66 return retval;
67}
68
69void
70mcore_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;
cd0fc7c3 78
2d514e6f 79 {
cd0fc7c3
SS
80 for (p = endaddr; p > startaddr;)
81 {
82 * -- p = val & 0xff;
83 val >>= 8;
84 }
2d514e6f
SS
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
cd0fc7c3 91 byte order and the target processor byte order.
2d514e6f
SS
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. */
99struct 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
115union
116{
117 struct mcore_regset asregs;
118 word asints [1]; /* but accessed larger... */
119} cpu;
120
9e086581
JM
121#define LAST_VALID_CREG 32 /* only 0..12 implemented */
122#define NUM_MCORE_REGS (16 + 16 + LAST_VALID_CREG + 1)
2d514e6f
SS
123
124int memcycles = 1;
125
126static SIM_OPEN_KIND sim_kind;
127static char * myname;
128
129static 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 */
cd0fc7c3 149#define C_ON() (cpu.sr & 1)
2d514e6f 150#define C_VALUE() (cpu.sr & 1)
cd0fc7c3
SS
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);}
2d514e6f
SS
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
165long
166int_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
181static void INLINE
182wbat (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
199static void INLINE
200wlat (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
230static void INLINE
231what (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)
cd0fc7c3
SS
246 fprintf (stderr, "short write to unaligned memory address: 0x%x\n",
247 x);
2d514e6f
SS
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 */
261static int INLINE
262rbat (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
280static int INLINE
281rlat (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
310static int INLINE
311rhat (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
344static int
345IOMEM (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 */
353static int sim_memory_size = 23;
354
355#define MEM_SIZE_FLOOR 64
356void
357sim_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,
cd0fc7c3
SS
377 "Not enough VM for simulation of %d bytes of RAM\n",
378 cpu.asregs.msize);
2d514e6f
SS
379
380 cpu.asregs.msize = 1;
381 cpu.mem = (unsigned char *) calloc (1, 1);
382 }
383}
384
385static void
386init_pointers ()
387{
388 if (cpu.asregs.msize != (1 << sim_memory_size))
389 sim_size (sim_memory_size);
390}
391
392static void
393set_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
b83266a0 407 if (issue_messages > 1)
2d514e6f
SS
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
435static void
436interrupt ()
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
446unsigned char opened[100];
447
448static void
449log_open (fd)
450 int fd;
451{
452 if (fd < 0 || fd > NUM_ELEM (opened))
453 return;
454
455 opened[fd] = 1;
456}
457
458static void
459log_close (fd)
460 int fd;
461{
462 if (fd < 0 || fd > NUM_ELEM (opened))
463 return;
464
465 opened[fd] = 0;
466}
467
468static int
469is_opened (fd)
470 int fd;
471{
472 if (fd < 0 || fd > NUM_ELEM (opened))
473 return 0;
474
475 return opened[fd];
476}
477
478static void
479handle_trap1 ()
480{
481 unsigned long a[3];
482
cd0fc7c3 483 switch ((unsigned long) (cpu.gr [TRAPCODE]))
2d514e6f
SS
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)
cd0fc7c3
SS
589 fprintf (stderr, "WARNING: sys call %d unimplemented\n",
590 cpu.gr[TRAPCODE]);
2d514e6f
SS
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 */
cd0fc7c3 603 case 4: /* _write */
2d514e6f
SS
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
620static void
621util (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:
cd0fc7c3 664 process_stub (cpu.gr[1]);
2d514e6f
SS
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. */
675static int
676iu_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
694word WL[MAXWL];
695char * WLstr[MAXWL];
696
697int ENDWL=0;
698int WLincyc;
699int WLcyc[MAXWL];
700int WLcnts[MAXWL];
701int WLmax[MAXWL];
702int WLmin[MAXWL];
703word WLendpc;
704int WLbcyc;
705int 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
714static int tracing = 0;
715
716void
717sim_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
cd0fc7c3 737 /* Fetch the initial instructions that we'll decode. */
2d514e6f
SS
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 {
cd0fc7c3
SS
759 word oldpc;
760
2d514e6f
SS
761 insts ++;
762
763 if (pc & 02)
764 {
cd0fc7c3 765 inst = ibuf & 0xFFFF;
2d514e6f
SS
766 needfetch = 1;
767 }
768 else
769 {
cd0fc7c3 770 inst = ibuf >> 16;
2d514e6f
SS
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
cd0fc7c3 804 /* Optimize with a hash to speed loop. */
2d514e6f
SS
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);
cd0fc7c3
SS
828
829 oldpc = pc;
830
2d514e6f
SS
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;
9e086581 843 pc -= 2;
2d514e6f
SS
844 break;
845
846 case 0x1: /* sync */
847 break;
848
849 case 0x2: /* rte */
850 pc = cpu.epc;
851 cpu.sr = cpu.esr;
852 needfetch = 1;
853
cd0fc7c3 854 if (SR_AF ())
2d514e6f
SS
855 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
856 else
857 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
858 break;
859
860 case 0x3: /* rfi */
861 pc = cpu.fpc;
862 cpu.sr = cpu.fsr;
863 needfetch = 1;
864
865 if (SR_AF ())
866 cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0];
867 else
868 cpu.asregs.active_gregs = &cpu.asregs.gregs[0];
869 break;
870
871 case 0x4: /* stop */
872 if (issue_messages)
873 fprintf (stderr, "WARNING: stop unimplemented\n");
874 break;
875
876 case 0x5: /* wait */
877 if (issue_messages)
878 fprintf (stderr, "WARNING: wait unimplemented\n");
879 break;
880
881 case 0x6: /* doze */
882 if (issue_messages)
cd0fc7c3 883 fprintf (stderr, "WARNING: doze unimplemented\n");
2d514e6f
SS
884 break;
885
886 case 0x7:
887 cpu.asregs.exception = SIGILL; /* illegal */
888 break;
889
890 case 0x8: /* trap 0 */
891 case 0xA: /* trap 2 */
892 case 0xB: /* trap 3 */
893 cpu.asregs.exception = SIGTRAP;
894 break;
895
896 case 0xC: /* trap 4 */
897 case 0xD: /* trap 5 */
898 case 0xE: /* trap 6 */
899 cpu.asregs.exception = SIGILL; /* illegal */
900 break;
901
902 case 0xF: /* trap 7 */
903 cpu.asregs.exception = SIGTRAP; /* integer div-by-0 */
904 break;
905
906 case 0x9: /* trap 1 */
907 handle_trap1 ();
908 break;
909 }
910 break;
911
912 case 0x1:
913 cpu.asregs.exception = SIGILL; /* illegal */
914 break;
915
916 case 0x2: /* mvc */
917 cpu.gr[RD] = C_VALUE();
918 break;
919 case 0x3: /* mvcv */
920 cpu.gr[RD] = C_OFF();
921 break;
922 case 0x4: /* ldq */
923 {
924 char *addr = (char *)cpu.gr[RD];
925 int regno = 4; /* always r4-r7 */
926
927 bonus_cycles++;
928 memops += 4;
929 do
930 {
931 cpu.gr[regno] = rlat(addr);
932 addr += 4;
933 regno++;
934 }
935 while ((regno&0x3) != 0);
936 }
937 break;
938 case 0x5: /* stq */
939 {
940 char *addr = (char *)cpu.gr[RD];
941 int regno = 4; /* always r4-r7 */
942
943 memops += 4;
944 bonus_cycles++;
945 do
946 {
947 wlat(addr, cpu.gr[regno]);
948 addr += 4;
949 regno++;
950 }
951 while ((regno & 0x3) != 0);
952 }
953 break;
954 case 0x6: /* ldm */
955 {
956 char *addr = (char *)cpu.gr[0];
957 int regno = RD;
958
959 /* bonus cycle is really only needed if
960 the next insn shifts the last reg loaded.
961
962 bonus_cycles++;
963 */
964 memops += 16-regno;
965 while (regno <= 0xF)
966 {
967 cpu.gr[regno] = rlat(addr);
968 addr += 4;
969 regno++;
970 }
971 }
972 break;
973 case 0x7: /* stm */
974 {
975 char *addr = (char *)cpu.gr[0];
976 int regno = RD;
977
978 /* this should be removed! */
979 /* bonus_cycles ++; */
980
981 memops += 16 - regno;
982 while (regno <= 0xF)
983 {
984 wlat(addr, cpu.gr[regno]);
985 addr += 4;
986 regno++;
987 }
988 }
989 break;
990
991 case 0x8: /* dect */
992 cpu.gr[RD] -= C_VALUE();
993 break;
994 case 0x9: /* decf */
995 cpu.gr[RD] -= C_OFF();
996 break;
997 case 0xA: /* inct */
998 cpu.gr[RD] += C_VALUE();
999 break;
1000 case 0xB: /* incf */
1001 cpu.gr[RD] += C_OFF();
1002 break;
1003 case 0xC: /* jmp */
1004 pc = cpu.gr[RD];
392a587b
JM
1005 if (tracing && RD == 15)
1006 fprintf (stderr, "Func return, r2 = %x, r3 = %x\n",
1007 cpu.gr[2], cpu.gr[3]);
2d514e6f
SS
1008 bonus_cycles++;
1009 needfetch = 1;
1010 break;
1011 case 0xD: /* jsr */
1012 cpu.gr[15] = pc;
1013 pc = cpu.gr[RD];
1014 bonus_cycles++;
1015 needfetch = 1;
1016 break;
1017 case 0xE: /* ff1 */
1018 {
1019 word tmp, i;
1020 tmp = cpu.gr[RD];
1021 for (i = 0; !(tmp & 0x80000000) && i < 32; i++)
1022 tmp <<= 1;
1023 cpu.gr[RD] = i;
1024 }
1025 break;
1026 case 0xF: /* brev */
1027 {
1028 word tmp;
1029 tmp = cpu.gr[RD];
1030 tmp = ((tmp & 0xaaaaaaaa) >> 1) | ((tmp & 0x55555555) << 1);
1031 tmp = ((tmp & 0xcccccccc) >> 2) | ((tmp & 0x33333333) << 2);
1032 tmp = ((tmp & 0xf0f0f0f0) >> 4) | ((tmp & 0x0f0f0f0f) << 4);
1033 tmp = ((tmp & 0xff00ff00) >> 8) | ((tmp & 0x00ff00ff) << 8);
1034 cpu.gr[RD] = ((tmp & 0xffff0000) >> 16) | ((tmp & 0x0000ffff) << 16);
1035 }
1036 break;
1037 }
1038 break;
1039 case 0x01:
1040 switch RS
1041 {
1042 case 0x0: /* xtrb3 */
1043 cpu.gr[1] = (cpu.gr[RD]) & 0xFF;
1044 NEW_C (cpu.gr[RD] != 0);
1045 break;
1046 case 0x1: /* xtrb2 */
1047 cpu.gr[1] = (cpu.gr[RD]>>8) & 0xFF;
1048 NEW_C (cpu.gr[RD] != 0);
1049 break;
1050 case 0x2: /* xtrb1 */
1051 cpu.gr[1] = (cpu.gr[RD]>>16) & 0xFF;
1052 NEW_C (cpu.gr[RD] != 0);
1053 break;
1054 case 0x3: /* xtrb0 */
1055 cpu.gr[1] = (cpu.gr[RD]>>24) & 0xFF;
1056 NEW_C (cpu.gr[RD] != 0);
1057 break;
1058 case 0x4: /* zextb */
1059 cpu.gr[RD] &= 0x000000FF;
1060 break;
1061 case 0x5: /* sextb */
1062 {
1063 long tmp;
1064 tmp = cpu.gr[RD];
1065 tmp <<= 24;
1066 tmp >>= 24;
1067 cpu.gr[RD] = tmp;
1068 }
1069 break;
1070 case 0x6: /* zexth */
1071 cpu.gr[RD] &= 0x0000FFFF;
1072 break;
1073 case 0x7: /* sexth */
1074 {
1075 long tmp;
1076 tmp = cpu.gr[RD];
1077 tmp <<= 16;
1078 tmp >>= 16;
1079 cpu.gr[RD] = tmp;
1080 }
1081 break;
1082 case 0x8: /* declt */
1083 --cpu.gr[RD];
1084 NEW_C ((long)cpu.gr[RD] < 0);
1085 break;
1086 case 0x9: /* tstnbz */
1087 {
1088 word tmp = cpu.gr[RD];
1089 NEW_C ((tmp & 0xFF000000) != 0 &&
1090 (tmp & 0x00FF0000) != 0 && (tmp & 0x0000FF00) != 0 &&
1091 (tmp & 0x000000FF) != 0);
1092 }
1093 break;
1094 case 0xA: /* decgt */
1095 --cpu.gr[RD];
1096 NEW_C ((long)cpu.gr[RD] > 0);
1097 break;
1098 case 0xB: /* decne */
1099 --cpu.gr[RD];
1100 NEW_C ((long)cpu.gr[RD] != 0);
1101 break;
1102 case 0xC: /* clrt */
1103 if (C_ON())
1104 cpu.gr[RD] = 0;
1105 break;
1106 case 0xD: /* clrf */
1107 if (C_OFF())
1108 cpu.gr[RD] = 0;
1109 break;
1110 case 0xE: /* abs */
1111 if (cpu.gr[RD] & 0x80000000)
1112 cpu.gr[RD] = ~cpu.gr[RD] + 1;
1113 break;
1114 case 0xF: /* not */
1115 cpu.gr[RD] = ~cpu.gr[RD];
1116 break;
1117 }
1118 break;
1119 case 0x02: /* movt */
1120 if (C_ON())
1121 cpu.gr[RD] = cpu.gr[RS];
1122 break;
1123 case 0x03: /* mult */
1124 /* consume 2 bits per cycle from rs, until rs is 0 */
1125 {
1126 unsigned int t = cpu.gr[RS];
1127 int ticks;
1128 for (ticks = 0; t != 0 ; t >>= 2)
1129 ticks++;
1130 bonus_cycles += ticks;
1131 }
1132 bonus_cycles += 2; /* min. is 3, so add 2, plus ticks above */
392a587b
JM
1133 if (tracing)
1134 fprintf (stderr, " mult %x by %x to give %x",
1135 cpu.gr[RD], cpu.gr[RS], cpu.gr[RD] * cpu.gr[RS]);
2d514e6f
SS
1136 cpu.gr[RD] = cpu.gr[RD] * cpu.gr[RS];
1137 break;
1138 case 0x04: /* loopt */
1139 if (C_ON())
1140 {
1141 pc += (IMM4 << 1) - 32;
1142 bonus_cycles ++;
1143 needfetch = 1;
1144 }
1145 --cpu.gr[RS]; /* not RD! */
1146 NEW_C (((long)cpu.gr[RS]) > 0);
1147 break;
1148 case 0x05: /* subu */
1149 cpu.gr[RD] -= cpu.gr[RS];
1150 break;
1151 case 0x06: /* addc */
1152 {
1153 unsigned long tmp, a, b;
1154 a = cpu.gr[RD];
1155 b = cpu.gr[RS];
1156 cpu.gr[RD] = a + b + C_VALUE ();
1157 tmp = iu_carry (a, b, C_VALUE ());
1158 NEW_C (tmp);
1159 }
1160 break;
1161 case 0x07: /* subc */
1162 {
1163 unsigned long tmp, a, b;
1164 a = cpu.gr[RD];
1165 b = cpu.gr[RS];
1166 cpu.gr[RD] = a - b + C_VALUE () - 1;
1167 tmp = iu_carry (a,~b, C_VALUE ());
1168 NEW_C (tmp);
1169 }
1170 break;
1171 case 0x08: /* illegal */
1172 case 0x09: /* illegal*/
1173 cpu.asregs.exception = SIGILL;
1174 break;
1175 case 0x0A: /* movf */
1176 if (C_OFF())
1177 cpu.gr[RD] = cpu.gr[RS];
1178 break;
1179 case 0x0B: /* lsr */
1180 {
1181 unsigned long dst, src;
1182 dst = cpu.gr[RD];
1183 src = cpu.gr[RS];
1184 dst = dst >> src;
1185 cpu.gr[RD] = dst;
1186 }
1187 break;
1188 case 0x0C: /* cmphs */
1189 NEW_C ((unsigned long )cpu.gr[RD] >=
1190 (unsigned long)cpu.gr[RS]);
1191 break;
1192 case 0x0D: /* cmplt */
1193 NEW_C ((long)cpu.gr[RD] < (long)cpu.gr[RS]);
1194 break;
1195 case 0x0E: /* tst */
1196 NEW_C ((cpu.gr[RD] & cpu.gr[RS]) != 0);
1197 break;
1198 case 0x0F: /* cmpne */
1199 NEW_C (cpu.gr[RD] != cpu.gr[RS]);
1200 break;
1201 case 0x10: case 0x11: /* mfcr */
1202 {
1203 unsigned r;
1204 r = IMM5;
1205 if (r <= LAST_VALID_CREG)
1206 cpu.gr[RD] = cpu.cr[r];
1207 else
1208 cpu.asregs.exception = SIGILL;
1209 }
1210 break;
1211
1212 case 0x12: /* mov */
1213 cpu.gr[RD] = cpu.gr[RS];
392a587b
JM
1214 if (tracing)
1215 fprintf (stderr, "MOV %x into reg %d", cpu.gr[RD], RD);
2d514e6f
SS
1216 break;
1217
1218 case 0x13: /* bgenr */
1219 if (cpu.gr[RS] & 0x20)
1220 cpu.gr[RD] = 0;
1221 else
1222 cpu.gr[RD] = 1 << (cpu.gr[RS] & 0x1F);
1223 break;
1224
1225 case 0x14: /* rsub */
1226 cpu.gr[RD] = cpu.gr[RS] - cpu.gr[RD];
1227 break;
1228
1229 case 0x15: /* ixw */
1230 cpu.gr[RD] += cpu.gr[RS]<<2;
1231 break;
1232
1233 case 0x16: /* and */
1234 cpu.gr[RD] &= cpu.gr[RS];
1235 break;
1236
1237 case 0x17: /* xor */
1238 cpu.gr[RD] ^= cpu.gr[RS];
1239 break;
1240
1241 case 0x18: case 0x19: /* mtcr */
1242 {
1243 unsigned r;
1244 r = IMM5;
1245 if (r <= LAST_VALID_CREG)
1246 cpu.cr[r] = cpu.gr[RD];
1247 else
1248 cpu.asregs.exception = SIGILL;
1249
1250 /* we might have changed register sets... */
1251 if (SR_AF ())
1252 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
1253 else
1254 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
1255 }
1256 break;
1257
1258 case 0x1A: /* asr */
1259 cpu.gr[RD] = (long)cpu.gr[RD] >> cpu.gr[RS];
1260 break;
1261
1262 case 0x1B: /* lsl */
1263 cpu.gr[RD] = cpu.gr[RD] << cpu.gr[RS];
1264 break;
1265
1266 case 0x1C: /* addu */
1267 cpu.gr[RD] += cpu.gr[RS];
1268 break;
1269
1270 case 0x1D: /* ixh */
1271 cpu.gr[RD] += cpu.gr[RS] << 1;
1272 break;
1273
1274 case 0x1E: /* or */
1275 cpu.gr[RD] |= cpu.gr[RS];
1276 break;
1277
1278 case 0x1F: /* andn */
1279 cpu.gr[RD] &= ~cpu.gr[RS];
1280 break;
1281 case 0x20: case 0x21: /* addi */
1282 cpu.gr[RD] =
1283 cpu.gr[RD] + (IMM5 + 1);
1284 break;
1285 case 0x22: case 0x23: /* cmplti */
1286 {
1287 int tmp = (IMM5 + 1);
1288 if (cpu.gr[RD] < tmp)
1289 {
1290 SET_C();
1291 }
1292 else
1293 {
1294 CLR_C();
1295 }
1296 }
1297 break;
1298 case 0x24: case 0x25: /* subi */
1299 cpu.gr[RD] =
1300 cpu.gr[RD] - (IMM5 + 1);
1301 break;
1302 case 0x26: case 0x27: /* illegal */
1303 cpu.asregs.exception = SIGILL;
1304 break;
1305 case 0x28: case 0x29: /* rsubi */
1306 cpu.gr[RD] =
1307 IMM5 - cpu.gr[RD];
1308 break;
1309 case 0x2A: case 0x2B: /* cmpnei */
1310 if (cpu.gr[RD] != IMM5)
1311 {
1312 SET_C();
1313 }
1314 else
1315 {
1316 CLR_C();
1317 }
1318 break;
1319
1320 case 0x2C: case 0x2D: /* bmaski, divu */
1321 {
1322 unsigned imm = IMM5;
1323
1324 if (imm == 1)
1325 {
1326 int exe;
1327 int rxnlz, r1nlz;
1328 unsigned int rx, r1;
1329
1330 rx = cpu.gr[RD];
1331 r1 = cpu.gr[1];
1332 exe = 0;
1333
1334 /* unsigned divide */
1335 cpu.gr[RD] = (word) ((unsigned int) cpu.gr[RD] / (unsigned int)cpu.gr[1] );
1336
1337 /* compute bonus_cycles for divu */
1338 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32); r1nlz ++)
1339 r1 = r1 << 1;
1340
1341 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32); rxnlz ++)
1342 rx = rx << 1;
1343
1344 if (r1nlz < rxnlz)
1345 exe += 4;
1346 else
1347 exe += 5 + r1nlz - rxnlz;
1348
1349 if (exe >= (2 * memcycles - 1))
1350 {
1351 bonus_cycles += exe - (2 * memcycles) + 1;
1352 }
1353 }
1354 else if (imm == 0 || imm >= 8)
1355 {
1356 /* bmaski */
1357 if (imm == 0)
1358 cpu.gr[RD] = -1;
1359 else
1360 cpu.gr[RD] = (1 << imm) - 1;
1361 }
1362 else
1363 {
1364 /* illegal */
1365 cpu.asregs.exception = SIGILL;
1366 }
1367 }
1368 break;
1369 case 0x2E: case 0x2F: /* andi */
1370 cpu.gr[RD] = cpu.gr[RD] & IMM5;
1371 break;
1372 case 0x30: case 0x31: /* bclri */
1373 cpu.gr[RD] = cpu.gr[RD] & ~(1<<IMM5);
1374 break;
1375 case 0x32: case 0x33: /* bgeni, divs */
1376 {
1377 unsigned imm = IMM5;
1378 if (imm == 1)
1379 {
1380 int exe,sc;
1381 int rxnlz, r1nlz;
1382 signed int rx, r1;
1383
1384 /* compute bonus_cycles for divu */
1385 rx = cpu.gr[RD];
1386 r1 = cpu.gr[1];
1387 exe = 0;
1388
1389 if (((rx < 0) && (r1 > 0)) || ((rx >= 0) && (r1 < 0)))
1390 sc = 1;
1391 else
1392 sc = 0;
1393
1394 rx = abs (rx);
1395 r1 = abs (r1);
1396
1397 /* signed divide, general registers are of type int, so / op is OK */
1398 cpu.gr[RD] = cpu.gr[RD] / cpu.gr[1];
1399
1400 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32) ; r1nlz ++ )
1401 r1 = r1 << 1;
1402
1403 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32) ; rxnlz ++ )
1404 rx = rx << 1;
1405
1406 if (r1nlz < rxnlz)
1407 exe += 5;
1408 else
1409 exe += 6 + r1nlz - rxnlz + sc;
1410
1411 if (exe >= (2 * memcycles - 1))
1412 {
1413 bonus_cycles += exe - (2 * memcycles) + 1;
1414 }
1415 }
1416 else if (imm >= 7)
1417 {
1418 /* bgeni */
1419 cpu.gr[RD] = (1 << IMM5);
1420 }
1421 else
1422 {
1423 /* illegal */
1424 cpu.asregs.exception = SIGILL;
1425 }
1426 break;
1427 }
1428 case 0x34: case 0x35: /* bseti */
1429 cpu.gr[RD] = cpu.gr[RD] | (1 << IMM5);
1430 break;
1431 case 0x36: case 0x37: /* btsti */
1432 NEW_C (cpu.gr[RD] >> IMM5);
1433 break;
1434 case 0x38: case 0x39: /* xsr, rotli */
1435 {
1436 unsigned imm = IMM5;
1437 unsigned long tmp = cpu.gr[RD];
1438 if (imm == 0)
1439 {
1440 word cbit;
1441 cbit = C_VALUE();
1442 NEW_C (tmp);
1443 cpu.gr[RD] = (cbit << 31) | (tmp >> 1);
1444 }
1445 else
1446 cpu.gr[RD] = (tmp << imm) | (tmp >> (32 - imm));
1447 }
1448 break;
1449 case 0x3A: case 0x3B: /* asrc, asri */
1450 {
1451 unsigned imm = IMM5;
1452 long tmp = cpu.gr[RD];
1453 if (imm == 0)
1454 {
1455 NEW_C (tmp);
1456 cpu.gr[RD] = tmp >> 1;
1457 }
1458 else
1459 cpu.gr[RD] = tmp >> imm;
1460 }
1461 break;
1462 case 0x3C: case 0x3D: /* lslc, lsli */
1463 {
1464 unsigned imm = IMM5;
1465 unsigned long tmp = cpu.gr[RD];
1466 if (imm == 0)
1467 {
1468 NEW_C (tmp >> 31);
1469 cpu.gr[RD] = tmp << 1;
1470 }
1471 else
1472 cpu.gr[RD] = tmp << imm;
1473 }
1474 break;
1475 case 0x3E: case 0x3F: /* lsrc, lsri */
1476 {
1477 unsigned imm = IMM5;
1478 unsigned long tmp = cpu.gr[RD];
1479 if (imm == 0)
1480 {
1481 NEW_C (tmp);
1482 cpu.gr[RD] = tmp >> 1;
1483 }
1484 else
1485 cpu.gr[RD] = tmp >> imm;
1486 }
1487 break;
1488 case 0x40: case 0x41: case 0x42: case 0x43:
1489 case 0x44: case 0x45: case 0x46: case 0x47:
1490 case 0x48: case 0x49: case 0x4A: case 0x4B:
1491 case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1492 cpu.asregs.exception = SIGILL;
1493 break;
1494 case 0x50:
1495 util (inst & 0xFF);
1496 break;
1497 case 0x51: case 0x52: case 0x53:
1498 case 0x54: case 0x55: case 0x56: case 0x57:
1499 case 0x58: case 0x59: case 0x5A: case 0x5B:
1500 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1501 cpu.asregs.exception = SIGILL;
1502 break;
1503 case 0x60: case 0x61: case 0x62: case 0x63: /* movi */
1504 case 0x64: case 0x65: case 0x66: case 0x67:
1505 cpu.gr[RD] = (inst >> 4) & 0x7F;
1506 break;
1507 case 0x68: case 0x69: case 0x6A: case 0x6B:
1508 case 0x6C: case 0x6D: case 0x6E: case 0x6F: /* illegal */
1509 cpu.asregs.exception = SIGILL;
1510 break;
1511 case 0x71: case 0x72: case 0x73:
1512 case 0x74: case 0x75: case 0x76: case 0x77:
1513 case 0x78: case 0x79: case 0x7A: case 0x7B:
1514 case 0x7C: case 0x7D: case 0x7E: /* lrw */
1515 cpu.gr[RX] = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1516 if (tracing)
1517 fprintf (stderr, "LRW of 0x%x from 0x%x to reg %d",
1518 rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC),
1519 (pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC, RX);
1520 memops++;
1521 break;
1522 case 0x7F: /* jsri */
1523 cpu.gr[15] = pc;
392a587b
JM
1524 if (tracing)
1525 fprintf (stderr, "func call: r2 = %x r3 = %x r4 = %x r5 = %x r6 = %x r7 = %x\n",
1526 cpu.gr[2], cpu.gr[3], cpu.gr[4], cpu.gr[5], cpu.gr[6], cpu.gr[7]);
2d514e6f
SS
1527 case 0x70: /* jmpi */
1528 pc = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1529 memops++;
1530 bonus_cycles++;
1531 needfetch = 1;
1532 break;
1533
1534 case 0x80: case 0x81: case 0x82: case 0x83:
1535 case 0x84: case 0x85: case 0x86: case 0x87:
1536 case 0x88: case 0x89: case 0x8A: case 0x8B:
1537 case 0x8C: case 0x8D: case 0x8E: case 0x8F: /* ld */
1538 cpu.gr[RX] = rlat (cpu.gr[RD] + ((inst >> 2) & 0x003C));
1539 if (tracing)
1540 fprintf (stderr, "load reg %d from 0x%x with 0x%x",
1541 RX,
1542 cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1543 memops++;
1544 break;
1545 case 0x90: case 0x91: case 0x92: case 0x93:
1546 case 0x94: case 0x95: case 0x96: case 0x97:
1547 case 0x98: case 0x99: case 0x9A: case 0x9B:
1548 case 0x9C: case 0x9D: case 0x9E: case 0x9F: /* st */
1549 wlat (cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1550 if (tracing)
1551 fprintf (stderr, "store reg %d (containing 0x%x) to 0x%x",
1552 RX, cpu.gr[RX],
1553 cpu.gr[RD] + ((inst >> 2) & 0x003C));
1554 memops++;
1555 break;
1556 case 0xA0: case 0xA1: case 0xA2: case 0xA3:
1557 case 0xA4: case 0xA5: case 0xA6: case 0xA7:
1558 case 0xA8: case 0xA9: case 0xAA: case 0xAB:
1559 case 0xAC: case 0xAD: case 0xAE: case 0xAF: /* ld.b */
1560 cpu.gr[RX] = rbat (cpu.gr[RD] + RS);
1561 memops++;
1562 break;
1563 case 0xB0: case 0xB1: case 0xB2: case 0xB3:
1564 case 0xB4: case 0xB5: case 0xB6: case 0xB7:
1565 case 0xB8: case 0xB9: case 0xBA: case 0xBB:
1566 case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* st.b */
1567 wbat (cpu.gr[RD] + RS, cpu.gr[RX]);
1568 memops++;
1569 break;
1570 case 0xC0: case 0xC1: case 0xC2: case 0xC3:
1571 case 0xC4: case 0xC5: case 0xC6: case 0xC7:
1572 case 0xC8: case 0xC9: case 0xCA: case 0xCB:
1573 case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* ld.h */
1574 cpu.gr[RX] = rhat (cpu.gr[RD] + ((inst >> 3) & 0x001E));
1575 memops++;
1576 break;
1577 case 0xD0: case 0xD1: case 0xD2: case 0xD3:
1578 case 0xD4: case 0xD5: case 0xD6: case 0xD7:
1579 case 0xD8: case 0xD9: case 0xDA: case 0xDB:
1580 case 0xDC: case 0xDD: case 0xDE: case 0xDF: /* st.h */
1581 what (cpu.gr[RD] + ((inst >> 3) & 0x001E), cpu.gr[RX]);
1582 memops++;
1583 break;
1584 case 0xE8: case 0xE9: case 0xEA: case 0xEB:
1585 case 0xEC: case 0xED: case 0xEE: case 0xEF: /* bf */
1586 if (C_OFF())
1587 {
1588 int disp;
1589 disp = inst & 0x03FF;
1590 if (inst & 0x0400)
1591 disp |= 0xFFFFFC00;
1592 pc += disp<<1;
1593 bonus_cycles++;
1594 needfetch = 1;
1595 }
1596 break;
1597 case 0xE0: case 0xE1: case 0xE2: case 0xE3:
1598 case 0xE4: case 0xE5: case 0xE6: case 0xE7: /* bt */
1599 if (C_ON())
1600 {
1601 int disp;
1602 disp = inst & 0x03FF;
1603 if (inst & 0x0400)
1604 disp |= 0xFFFFFC00;
1605 pc += disp<<1;
1606 bonus_cycles++;
1607 needfetch = 1;
1608 }
1609 break;
1610
1611 case 0xF8: case 0xF9: case 0xFA: case 0xFB:
1612 case 0xFC: case 0xFD: case 0xFE: case 0xFF: /* bsr */
1613 cpu.gr[15] = pc;
1614 case 0xF0: case 0xF1: case 0xF2: case 0xF3:
1615 case 0xF4: case 0xF5: case 0xF6: case 0xF7: /* br */
1616 {
1617 int disp;
1618 disp = inst & 0x03FF;
1619 if (inst & 0x0400)
1620 disp |= 0xFFFFFC00;
1621 pc += disp<<1;
1622 bonus_cycles++;
1623 needfetch = 1;
1624 }
1625 break;
1626
1627 }
1628
1629 if (tracing)
1630 fprintf (stderr, "\n");
cd0fc7c3 1631
2d514e6f
SS
1632 if (needfetch)
1633 {
1634 /* Do not let him fetch from a bad address! */
1635 if (((uword)pc) >= cpu.asregs.msize)
1636 {
1637 if (issue_messages)
cd0fc7c3 1638 fprintf (stderr, "PC loaded at 0x%x is outside of available memory! (0x%x)\n", oldpc, pc);
2d514e6f
SS
1639
1640 cpu.asregs.exception = SIGSEGV;
1641 }
1642 else
1643 {
1644 ibuf = rlat (pc & 0xFFFFFFFC);
1645 needfetch = 0;
1646 }
1647 }
1648 }
1649 while (!cpu.asregs.exception);
1650
1651 /* Hide away the things we've cached while executing. */
1652 cpu.asregs.pc = pc;
1653 cpu.asregs.insts += insts; /* instructions done ... */
1654 cpu.asregs.cycles += insts; /* and each takes a cycle */
1655 cpu.asregs.cycles += bonus_cycles; /* and extra cycles for branches */
1656 cpu.asregs.cycles += memops * memcycles; /* and memop cycle delays */
1657
1658 signal (SIGINT, sigsave);
1659}
1660
1661
1662int
1663sim_write (sd, addr, buffer, size)
1664 SIM_DESC sd;
1665 SIM_ADDR addr;
1666 unsigned char * buffer;
1667 int size;
1668{
1669 int i;
1670 init_pointers ();
1671
1672 memcpy (& cpu.mem[addr], buffer, size);
1673
1674 return size;
1675}
1676
1677int
1678sim_read (sd, addr, buffer, size)
1679 SIM_DESC sd;
1680 SIM_ADDR addr;
1681 unsigned char * buffer;
1682 int size;
1683{
1684 int i;
1685 init_pointers ();
1686
1687 memcpy (buffer, & cpu.mem[addr], size);
1688
1689 return size;
1690}
1691
1692
1693int
1694sim_store_register (sd, rn, memory, length)
1695 SIM_DESC sd;
1696 int rn;
1697 unsigned char * memory;
1698 int length;
1699{
1700 init_pointers ();
1701
1702 if (rn < NUM_MCORE_REGS && rn >= 0)
1703 {
1704 if (length == 4)
1705 {
2d514e6f 1706 long ival;
cd0fc7c3
SS
1707
1708 /* misalignment safe */
1709 ival = mcore_extract_unsigned_integer (memory, 4);
2d514e6f
SS
1710 cpu.asints[rn] = ival;
1711 }
1712
1713 return 4;
1714 }
1715 else
1716 return 0;
1717}
1718
1719int
1720sim_fetch_register (sd, rn, memory, length)
1721 SIM_DESC sd;
1722 int rn;
1723 unsigned char * memory;
1724 int length;
1725{
1726 init_pointers ();
1727
1728 if (rn < NUM_MCORE_REGS && rn >= 0)
1729 {
1730 if (length == 4)
1731 {
2d514e6f 1732 long ival = cpu.asints[rn];
cd0fc7c3
SS
1733
1734 /* misalignment-safe */
1735 mcore_store_unsigned_integer (memory, 4, ival);
2d514e6f
SS
1736 }
1737
1738 return 4;
1739 }
1740 else
1741 return 0;
1742}
1743
1744
1745int
1746sim_trace (sd)
1747 SIM_DESC sd;
1748{
1749 tracing = 1;
1750
1751 sim_resume (sd, 0, 0);
1752
1753 tracing = 0;
1754
1755 return 1;
1756}
1757
1758void
1759sim_stop_reason (sd, reason, sigrc)
1760 SIM_DESC sd;
1761 enum sim_stop * reason;
1762 int * sigrc;
1763{
1764 if (cpu.asregs.exception == SIGQUIT)
1765 {
1766 * reason = sim_exited;
1767 * sigrc = cpu.gr[PARM1];
1768 }
1769 else
1770 {
1771 * reason = sim_stopped;
1772 * sigrc = cpu.asregs.exception;
1773 }
1774}
1775
1776
1777int
1778sim_stop (sd)
1779 SIM_DESC sd;
1780{
1781 cpu.asregs.exception = SIGINT;
1782 return 1;
1783}
1784
1785
1786void
1787sim_info (sd, verbose)
1788 SIM_DESC sd;
1789 int verbose;
1790{
1791#ifdef WATCHFUNCTIONS
1792 int w, wcyc;
1793#endif
1794 double virttime = cpu.asregs.cycles / 36.0e6;
1795
cd0fc7c3
SS
1796 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
1797 cpu.asregs.insts);
1798 callback->printf_filtered (callback, "# cycles %10d\n",
1799 cpu.asregs.cycles);
1800 callback->printf_filtered (callback, "# pipeline stalls %10d\n",
1801 cpu.asregs.stalls);
1802 callback->printf_filtered (callback, "# virtual time taken %10.4f\n",
1803 virttime);
2d514e6f
SS
1804
1805#ifdef WATCHFUNCTIONS
cd0fc7c3
SS
1806 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
1807 ENDWL);
2d514e6f
SS
1808
1809 wcyc = 0;
1810
1811 for (w = 1; w <= ENDWL; w++)
1812 {
1813 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
cd0fc7c3
SS
1814 callback->printf_filtered (callback, " calls = %d, cycles = %d\n",
1815 WLcnts[w],WLcyc[w]);
2d514e6f
SS
1816
1817 if (WLcnts[w] != 0)
cd0fc7c3
SS
1818 callback->printf_filtered (callback,
1819 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
1820 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
2d514e6f
SS
1821 wcyc += WLcyc[w];
1822 }
1823
cd0fc7c3
SS
1824 callback->printf_filtered (callback,
1825 "Total cycles for watched functions: %d\n",wcyc);
2d514e6f
SS
1826#endif
1827}
1828
1829struct aout
1830{
1831 unsigned char sa_machtype[2];
1832 unsigned char sa_magic[2];
1833 unsigned char sa_tsize[4];
1834 unsigned char sa_dsize[4];
1835 unsigned char sa_bsize[4];
1836 unsigned char sa_syms[4];
1837 unsigned char sa_entry[4];
1838 unsigned char sa_trelo[4];
1839 unsigned char sa_drelo[4];
1840} aout;
1841
1842#define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
1843#define SHORT(x) (((x)[0]<<8)|(x)[1])
1844
1845SIM_DESC
1846sim_open (kind, cb, abfd, argv)
1847 SIM_OPEN_KIND kind;
1848 host_callback * cb;
1849 struct _bfd * abfd;
1850 char ** argv;
1851{
1852 int osize = sim_memory_size;
1853 myname = argv[0];
1854 callback = cb;
1855
1856 if (kind == SIM_OPEN_STANDALONE)
1857 issue_messages = 1;
1858
1859 /* Discard and reacquire memory -- start with a clean slate. */
1860 sim_size (1); /* small */
1861 sim_size (osize); /* and back again */
1862
1863 set_initial_gprs (); /* Reset the GPR registers. */
1864
1865 /* Fudge our descriptor for now. */
1866 return (SIM_DESC) 1;
1867}
1868
1869void
1870sim_close (sd, quitting)
1871 SIM_DESC sd;
1872 int quitting;
1873{
1874 /* nothing to do */
1875}
1876
1877SIM_RC
1878sim_load (sd, prog, abfd, from_tty)
1879 SIM_DESC sd;
1880 char * prog;
1881 bfd * abfd;
1882 int from_tty;
1883{
1884 /* Do the right thing for ELF executables; this turns out to be
1885 just about the right thing for any object format that:
1886 - we crack using BFD routines
1887 - follows the traditional UNIX text/data/bss layout
1888 - calls the bss section ".bss". */
1889
1890 extern bfd * sim_load_file (); /* ??? Don't know where this should live. */
1891 bfd * prog_bfd;
1892
1893 {
1894 bfd * handle;
1895 asection * s_bss;
1896 handle = bfd_openr (prog, 0); /* could be "mcore" */
1897
1898 if (!handle)
1899 {
1900 printf("``%s'' could not be opened.\n", prog);
1901 return SIM_RC_FAIL;
1902 }
1903
1904 /* Makes sure that we have an object file, also cleans gets the
1905 section headers in place. */
1906 if (!bfd_check_format (handle, bfd_object))
1907 {
1908 /* wasn't an object file */
1909 bfd_close (handle);
1910 printf ("``%s'' is not appropriate object file.\n", prog);
1911 return SIM_RC_FAIL;
1912 }
cd0fc7c3 1913
2d514e6f
SS
1914 /* Look for that bss section. */
1915 s_bss = bfd_get_section_by_name (handle, ".bss");
1916
1917 if (!s_bss)
1918 {
1919 printf("``%s'' has no bss section.\n", prog);
1920 return SIM_RC_FAIL;
1921 }
1922
1923 /* Appropriately paranoid would check that we have
1924 a traditional text/data/bss ordering within memory. */
1925
1926 /* figure the end of the bss section */
1927#if 0
1928 printf ("bss section at 0x%08x for 0x%08x bytes\n",
1929 (unsigned long) s_bss->vma , (unsigned long) s_bss->_cooked_size);
1930#endif
1931 heap_ptr = (unsigned long) s_bss->vma + (unsigned long) s_bss->_cooked_size;
1932
1933 /* Clean up after ourselves. */
1934 bfd_close (handle);
1935
1936 /* XXX: do we need to free the s_bss and handle structures? */
1937 }
1938
1939 /* from sh -- dac */
1940 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1941 sim_kind == SIM_OPEN_DEBUG,
1942 0, sim_write);
1943 if (prog_bfd == NULL)
1944 return SIM_RC_FAIL;
1945
cd0fc7c3 1946
2d514e6f
SS
1947 if (abfd == NULL)
1948 bfd_close (prog_bfd);
1949
1950 return SIM_RC_OK;
1951}
1952
1953SIM_RC
1954sim_create_inferior (sd, prog_bfd, argv, env)
1955 SIM_DESC sd;
1956 struct _bfd * prog_bfd;
1957 char ** argv;
1958 char ** env;
1959{
1960 char ** avp;
1961 int nargs = 0;
1962 int nenv = 0;
1963 int s_length;
1964 int l;
1965 unsigned long strings;
1966 unsigned long pointers;
1967 unsigned long hi_stack;
1968
1969
1970 /* Set the initial register set. */
1971 l = issue_messages;
1972 issue_messages = 0;
1973 set_initial_gprs ();
1974 issue_messages = l;
1975
1976 hi_stack = cpu.asregs.msize - 4;
1977 cpu.asregs.pc = bfd_get_start_address (prog_bfd);
1978
1979 /* Calculate the argument and environment strings. */
1980 s_length = 0;
1981 nargs = 0;
1982 avp = argv;
1983 while (avp && *avp)
1984 {
1985 l = strlen (*avp) + 1; /* include the null */
1986 s_length += (l + 3) & ~3; /* make it a 4 byte boundary */
1987 nargs++; avp++;
1988 }
1989
1990 nenv = 0;
1991 avp = env;
1992 while (avp && *avp)
1993 {
1994 l = strlen (*avp) + 1; /* include the null */
1995 s_length += (l + 3) & ~ 3;/* make it a 4 byte boundary */
1996 nenv++; avp++;
1997 }
1998
1999 /* Claim some memory for the pointers and strings. */
2000 pointers = hi_stack - sizeof(word) * (nenv+1+nargs+1);
2001 pointers &= ~3; /* must be 4-byte aligned */
2002 cpu.gr[0] = pointers;
2003
2004 strings = cpu.gr[0] - s_length;
2005 strings &= ~3; /* want to make it 4-byte aligned */
2006 cpu.gr[0] = strings;
2007 /* dac fix, the stack address must be 8-byte aligned! */
2008 cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
2009
2010 /* Loop through the arguments and fill them in. */
2011 cpu.gr[PARM1] = nargs;
2012 if (nargs == 0)
2013 {
2014 /* No strings to fill in. */
2015 cpu.gr[PARM2] = 0;
2016 }
2017 else
2018 {
2019 cpu.gr[PARM2] = pointers;
2020 avp = argv;
2021 while (avp && *avp)
2022 {
2023 /* Save where we're putting it. */
2024 wlat (pointers, strings);
2025
2026 /* Copy the string. */
2027 l = strlen (* avp) + 1;
2028 strcpy ((char *)(cpu.mem + strings), *avp);
2029
2030 /* Bump the pointers. */
2031 avp++;
2032 pointers += 4;
2033 strings += l+1;
2034 }
2035
2036 /* A null to finish the list. */
2037 wlat (pointers, 0);
2038 pointers += 4;
2039 }
2040
2041 /* Now do the environment pointers. */
2042 if (nenv == 0)
2043 {
2044 /* No strings to fill in. */
2045 cpu.gr[PARM3] = 0;
2046 }
2047 else
2048 {
2049 cpu.gr[PARM3] = pointers;
2050 avp = env;
2051
2052 while (avp && *avp)
2053 {
2054 /* Save where we're putting it. */
2055 wlat (pointers, strings);
2056
2057 /* Copy the string. */
2058 l = strlen (* avp) + 1;
2059 strcpy ((char *)(cpu.mem + strings), *avp);
2060
2061 /* Bump the pointers. */
2062 avp++;
2063 pointers += 4;
2064 strings += l+1;
2065 }
2066
2067 /* A null to finish the list. */
2068 wlat (pointers, 0);
2069 pointers += 4;
2070 }
2071
2072 return SIM_RC_OK;
2073}
2074
2075void
2076sim_kill (sd)
2077 SIM_DESC sd;
2078{
2079 /* nothing to do */
2080}
2081
2082void
2083sim_do_command (sd, cmd)
2084 SIM_DESC sd;
2085 char * cmd;
2086{
2087 /* Nothing there yet; it's all an error. */
2088
2089 if (cmd != NULL)
2090 {
2091 char ** simargv = buildargv (cmd);
2092
2093 if (strcmp (simargv[0], "watch") == 0)
2094 {
2095 if ((simargv[1] == NULL) || (simargv[2] == NULL))
2096 {
2097 fprintf (stderr, "Error: missing argument to watch cmd.\n");
2098 return;
2099 }
2100
2101 ENDWL++;
2102
2103 WL[ENDWL] = strtol (simargv[2], NULL, 0);
2104 WLstr[ENDWL] = strdup (simargv[1]);
2105 fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
2106 WL[ENDWL], ENDWL);
2107
2108 }
2109 else if (strcmp (simargv[0], "dumpmem") == 0)
2110 {
2111 unsigned char * p;
2112 FILE * dumpfile;
2113
2114 if (simargv[1] == NULL)
2115 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
2116
2117 fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
2118
2119 dumpfile = fopen (simargv[1], "w");
2120 p = cpu.mem;
2121 fwrite (p, cpu.asregs.msize-1, 1, dumpfile);
2122 fclose (dumpfile);
2123
2124 fprintf (stderr, "done.\n");
2125 }
2126 else if (strcmp (simargv[0], "clearstats") == 0)
2127 {
2128 cpu.asregs.cycles = 0;
2129 cpu.asregs.insts = 0;
2130 cpu.asregs.stalls = 0;
2131 ENDWL = 0;
2132 }
2133 else if (strcmp (simargv[0], "verbose") == 0)
2134 {
b83266a0 2135 issue_messages = 2;
2d514e6f
SS
2136 }
2137 else
2138 {
2139 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
2140 cmd);
2141 }
2142 }
2143 else
2144 {
2145 fprintf (stderr, "M.CORE sim commands: \n");
2146 fprintf (stderr, " watch <funcname> <addr>\n");
2147 fprintf (stderr, " dumpmem <filename>\n");
2148 fprintf (stderr, " clearstats\n");
2149 fprintf (stderr, " verbose\n");
2150 }
2151}
2152
2153void
2154sim_set_callbacks (ptr)
2155 host_callback * ptr;
2156{
2157 callback = ptr;
2158}
This page took 0.369181 seconds and 4 git commands to generate.