]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/mcore/interp.c
Add support for M340 part.
[thirdparty/binutils-gdb.git] / sim / mcore / interp.c
CommitLineData
0fda6bd2 1/* Simulator for Motorola's MCore processor
2d514e6f
SS
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];
c5394b80
JM
1184 /* We must not rely solely upon the native shift operations, since they
1185 may not match the M*Core's behaviour on boundary conditions. */
1186 dst = src > 31 ? 0 : dst >> src;
2d514e6f
SS
1187 cpu.gr[RD] = dst;
1188 }
1189 break;
1190 case 0x0C: /* cmphs */
1191 NEW_C ((unsigned long )cpu.gr[RD] >=
1192 (unsigned long)cpu.gr[RS]);
1193 break;
1194 case 0x0D: /* cmplt */
1195 NEW_C ((long)cpu.gr[RD] < (long)cpu.gr[RS]);
1196 break;
1197 case 0x0E: /* tst */
1198 NEW_C ((cpu.gr[RD] & cpu.gr[RS]) != 0);
1199 break;
1200 case 0x0F: /* cmpne */
1201 NEW_C (cpu.gr[RD] != cpu.gr[RS]);
1202 break;
1203 case 0x10: case 0x11: /* mfcr */
1204 {
1205 unsigned r;
1206 r = IMM5;
1207 if (r <= LAST_VALID_CREG)
1208 cpu.gr[RD] = cpu.cr[r];
1209 else
1210 cpu.asregs.exception = SIGILL;
1211 }
1212 break;
1213
1214 case 0x12: /* mov */
1215 cpu.gr[RD] = cpu.gr[RS];
392a587b
JM
1216 if (tracing)
1217 fprintf (stderr, "MOV %x into reg %d", cpu.gr[RD], RD);
2d514e6f
SS
1218 break;
1219
1220 case 0x13: /* bgenr */
1221 if (cpu.gr[RS] & 0x20)
1222 cpu.gr[RD] = 0;
1223 else
1224 cpu.gr[RD] = 1 << (cpu.gr[RS] & 0x1F);
1225 break;
1226
1227 case 0x14: /* rsub */
1228 cpu.gr[RD] = cpu.gr[RS] - cpu.gr[RD];
1229 break;
1230
1231 case 0x15: /* ixw */
1232 cpu.gr[RD] += cpu.gr[RS]<<2;
1233 break;
1234
1235 case 0x16: /* and */
1236 cpu.gr[RD] &= cpu.gr[RS];
1237 break;
1238
1239 case 0x17: /* xor */
1240 cpu.gr[RD] ^= cpu.gr[RS];
1241 break;
1242
1243 case 0x18: case 0x19: /* mtcr */
1244 {
1245 unsigned r;
1246 r = IMM5;
1247 if (r <= LAST_VALID_CREG)
1248 cpu.cr[r] = cpu.gr[RD];
1249 else
1250 cpu.asregs.exception = SIGILL;
1251
1252 /* we might have changed register sets... */
1253 if (SR_AF ())
1254 cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
1255 else
1256 cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
1257 }
1258 break;
1259
1260 case 0x1A: /* asr */
c5394b80
JM
1261 /* We must not rely solely upon the native shift operations, since they
1262 may not match the M*Core's behaviour on boundary conditions. */
1263 if (cpu.gr[RS] > 30)
1264 cpu.gr[RD] = ((long) cpu.gr[RD]) < 0 ? -1 : 0;
1265 else
1266 cpu.gr[RD] = (long) cpu.gr[RD] >> cpu.gr[RS];
2d514e6f
SS
1267 break;
1268
1269 case 0x1B: /* lsl */
c5394b80
JM
1270 /* We must not rely solely upon the native shift operations, since they
1271 may not match the M*Core's behaviour on boundary conditions. */
1272 cpu.gr[RD] = cpu.gr[RS] > 31 ? 0 : cpu.gr[RD] << cpu.gr[RS];
2d514e6f
SS
1273 break;
1274
1275 case 0x1C: /* addu */
1276 cpu.gr[RD] += cpu.gr[RS];
1277 break;
1278
1279 case 0x1D: /* ixh */
1280 cpu.gr[RD] += cpu.gr[RS] << 1;
1281 break;
1282
1283 case 0x1E: /* or */
1284 cpu.gr[RD] |= cpu.gr[RS];
1285 break;
1286
1287 case 0x1F: /* andn */
1288 cpu.gr[RD] &= ~cpu.gr[RS];
1289 break;
1290 case 0x20: case 0x21: /* addi */
1291 cpu.gr[RD] =
1292 cpu.gr[RD] + (IMM5 + 1);
1293 break;
1294 case 0x22: case 0x23: /* cmplti */
1295 {
1296 int tmp = (IMM5 + 1);
1297 if (cpu.gr[RD] < tmp)
1298 {
1299 SET_C();
1300 }
1301 else
1302 {
1303 CLR_C();
1304 }
1305 }
1306 break;
1307 case 0x24: case 0x25: /* subi */
1308 cpu.gr[RD] =
1309 cpu.gr[RD] - (IMM5 + 1);
1310 break;
1311 case 0x26: case 0x27: /* illegal */
1312 cpu.asregs.exception = SIGILL;
1313 break;
1314 case 0x28: case 0x29: /* rsubi */
1315 cpu.gr[RD] =
1316 IMM5 - cpu.gr[RD];
1317 break;
1318 case 0x2A: case 0x2B: /* cmpnei */
1319 if (cpu.gr[RD] != IMM5)
1320 {
1321 SET_C();
1322 }
1323 else
1324 {
1325 CLR_C();
1326 }
1327 break;
1328
1329 case 0x2C: case 0x2D: /* bmaski, divu */
1330 {
1331 unsigned imm = IMM5;
1332
1333 if (imm == 1)
1334 {
1335 int exe;
1336 int rxnlz, r1nlz;
1337 unsigned int rx, r1;
1338
1339 rx = cpu.gr[RD];
1340 r1 = cpu.gr[1];
1341 exe = 0;
1342
1343 /* unsigned divide */
1344 cpu.gr[RD] = (word) ((unsigned int) cpu.gr[RD] / (unsigned int)cpu.gr[1] );
1345
1346 /* compute bonus_cycles for divu */
1347 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32); r1nlz ++)
1348 r1 = r1 << 1;
1349
1350 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32); rxnlz ++)
1351 rx = rx << 1;
1352
1353 if (r1nlz < rxnlz)
1354 exe += 4;
1355 else
1356 exe += 5 + r1nlz - rxnlz;
1357
1358 if (exe >= (2 * memcycles - 1))
1359 {
1360 bonus_cycles += exe - (2 * memcycles) + 1;
1361 }
1362 }
1363 else if (imm == 0 || imm >= 8)
1364 {
1365 /* bmaski */
1366 if (imm == 0)
1367 cpu.gr[RD] = -1;
1368 else
1369 cpu.gr[RD] = (1 << imm) - 1;
1370 }
1371 else
1372 {
1373 /* illegal */
1374 cpu.asregs.exception = SIGILL;
1375 }
1376 }
1377 break;
1378 case 0x2E: case 0x2F: /* andi */
1379 cpu.gr[RD] = cpu.gr[RD] & IMM5;
1380 break;
1381 case 0x30: case 0x31: /* bclri */
1382 cpu.gr[RD] = cpu.gr[RD] & ~(1<<IMM5);
1383 break;
1384 case 0x32: case 0x33: /* bgeni, divs */
1385 {
1386 unsigned imm = IMM5;
1387 if (imm == 1)
1388 {
1389 int exe,sc;
1390 int rxnlz, r1nlz;
1391 signed int rx, r1;
1392
1393 /* compute bonus_cycles for divu */
1394 rx = cpu.gr[RD];
1395 r1 = cpu.gr[1];
1396 exe = 0;
1397
1398 if (((rx < 0) && (r1 > 0)) || ((rx >= 0) && (r1 < 0)))
1399 sc = 1;
1400 else
1401 sc = 0;
1402
1403 rx = abs (rx);
1404 r1 = abs (r1);
1405
1406 /* signed divide, general registers are of type int, so / op is OK */
1407 cpu.gr[RD] = cpu.gr[RD] / cpu.gr[1];
1408
1409 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32) ; r1nlz ++ )
1410 r1 = r1 << 1;
1411
1412 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32) ; rxnlz ++ )
1413 rx = rx << 1;
1414
1415 if (r1nlz < rxnlz)
1416 exe += 5;
1417 else
1418 exe += 6 + r1nlz - rxnlz + sc;
1419
1420 if (exe >= (2 * memcycles - 1))
1421 {
1422 bonus_cycles += exe - (2 * memcycles) + 1;
1423 }
1424 }
1425 else if (imm >= 7)
1426 {
1427 /* bgeni */
1428 cpu.gr[RD] = (1 << IMM5);
1429 }
1430 else
1431 {
1432 /* illegal */
1433 cpu.asregs.exception = SIGILL;
1434 }
1435 break;
1436 }
1437 case 0x34: case 0x35: /* bseti */
1438 cpu.gr[RD] = cpu.gr[RD] | (1 << IMM5);
1439 break;
1440 case 0x36: case 0x37: /* btsti */
1441 NEW_C (cpu.gr[RD] >> IMM5);
1442 break;
1443 case 0x38: case 0x39: /* xsr, rotli */
1444 {
1445 unsigned imm = IMM5;
1446 unsigned long tmp = cpu.gr[RD];
1447 if (imm == 0)
1448 {
1449 word cbit;
1450 cbit = C_VALUE();
1451 NEW_C (tmp);
1452 cpu.gr[RD] = (cbit << 31) | (tmp >> 1);
1453 }
1454 else
1455 cpu.gr[RD] = (tmp << imm) | (tmp >> (32 - imm));
1456 }
1457 break;
1458 case 0x3A: case 0x3B: /* asrc, asri */
1459 {
1460 unsigned imm = IMM5;
1461 long tmp = cpu.gr[RD];
1462 if (imm == 0)
1463 {
1464 NEW_C (tmp);
1465 cpu.gr[RD] = tmp >> 1;
1466 }
1467 else
1468 cpu.gr[RD] = tmp >> imm;
1469 }
1470 break;
1471 case 0x3C: case 0x3D: /* lslc, lsli */
1472 {
1473 unsigned imm = IMM5;
1474 unsigned long tmp = cpu.gr[RD];
1475 if (imm == 0)
1476 {
1477 NEW_C (tmp >> 31);
1478 cpu.gr[RD] = tmp << 1;
1479 }
1480 else
1481 cpu.gr[RD] = tmp << imm;
1482 }
1483 break;
1484 case 0x3E: case 0x3F: /* lsrc, lsri */
1485 {
1486 unsigned imm = IMM5;
1487 unsigned long tmp = cpu.gr[RD];
1488 if (imm == 0)
1489 {
1490 NEW_C (tmp);
1491 cpu.gr[RD] = tmp >> 1;
1492 }
1493 else
1494 cpu.gr[RD] = tmp >> imm;
1495 }
1496 break;
1497 case 0x40: case 0x41: case 0x42: case 0x43:
1498 case 0x44: case 0x45: case 0x46: case 0x47:
1499 case 0x48: case 0x49: case 0x4A: case 0x4B:
1500 case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1501 cpu.asregs.exception = SIGILL;
1502 break;
1503 case 0x50:
1504 util (inst & 0xFF);
1505 break;
1506 case 0x51: case 0x52: case 0x53:
1507 case 0x54: case 0x55: case 0x56: case 0x57:
1508 case 0x58: case 0x59: case 0x5A: case 0x5B:
1509 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1510 cpu.asregs.exception = SIGILL;
1511 break;
1512 case 0x60: case 0x61: case 0x62: case 0x63: /* movi */
1513 case 0x64: case 0x65: case 0x66: case 0x67:
1514 cpu.gr[RD] = (inst >> 4) & 0x7F;
1515 break;
1516 case 0x68: case 0x69: case 0x6A: case 0x6B:
1517 case 0x6C: case 0x6D: case 0x6E: case 0x6F: /* illegal */
1518 cpu.asregs.exception = SIGILL;
1519 break;
1520 case 0x71: case 0x72: case 0x73:
1521 case 0x74: case 0x75: case 0x76: case 0x77:
1522 case 0x78: case 0x79: case 0x7A: case 0x7B:
1523 case 0x7C: case 0x7D: case 0x7E: /* lrw */
1524 cpu.gr[RX] = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1525 if (tracing)
1526 fprintf (stderr, "LRW of 0x%x from 0x%x to reg %d",
1527 rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC),
1528 (pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC, RX);
1529 memops++;
1530 break;
1531 case 0x7F: /* jsri */
1532 cpu.gr[15] = pc;
392a587b
JM
1533 if (tracing)
1534 fprintf (stderr, "func call: r2 = %x r3 = %x r4 = %x r5 = %x r6 = %x r7 = %x\n",
1535 cpu.gr[2], cpu.gr[3], cpu.gr[4], cpu.gr[5], cpu.gr[6], cpu.gr[7]);
2d514e6f
SS
1536 case 0x70: /* jmpi */
1537 pc = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1538 memops++;
1539 bonus_cycles++;
1540 needfetch = 1;
1541 break;
1542
1543 case 0x80: case 0x81: case 0x82: case 0x83:
1544 case 0x84: case 0x85: case 0x86: case 0x87:
1545 case 0x88: case 0x89: case 0x8A: case 0x8B:
1546 case 0x8C: case 0x8D: case 0x8E: case 0x8F: /* ld */
1547 cpu.gr[RX] = rlat (cpu.gr[RD] + ((inst >> 2) & 0x003C));
1548 if (tracing)
1549 fprintf (stderr, "load reg %d from 0x%x with 0x%x",
1550 RX,
1551 cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1552 memops++;
1553 break;
1554 case 0x90: case 0x91: case 0x92: case 0x93:
1555 case 0x94: case 0x95: case 0x96: case 0x97:
1556 case 0x98: case 0x99: case 0x9A: case 0x9B:
1557 case 0x9C: case 0x9D: case 0x9E: case 0x9F: /* st */
1558 wlat (cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1559 if (tracing)
1560 fprintf (stderr, "store reg %d (containing 0x%x) to 0x%x",
1561 RX, cpu.gr[RX],
1562 cpu.gr[RD] + ((inst >> 2) & 0x003C));
1563 memops++;
1564 break;
1565 case 0xA0: case 0xA1: case 0xA2: case 0xA3:
1566 case 0xA4: case 0xA5: case 0xA6: case 0xA7:
1567 case 0xA8: case 0xA9: case 0xAA: case 0xAB:
1568 case 0xAC: case 0xAD: case 0xAE: case 0xAF: /* ld.b */
1569 cpu.gr[RX] = rbat (cpu.gr[RD] + RS);
1570 memops++;
1571 break;
1572 case 0xB0: case 0xB1: case 0xB2: case 0xB3:
1573 case 0xB4: case 0xB5: case 0xB6: case 0xB7:
1574 case 0xB8: case 0xB9: case 0xBA: case 0xBB:
1575 case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* st.b */
1576 wbat (cpu.gr[RD] + RS, cpu.gr[RX]);
1577 memops++;
1578 break;
1579 case 0xC0: case 0xC1: case 0xC2: case 0xC3:
1580 case 0xC4: case 0xC5: case 0xC6: case 0xC7:
1581 case 0xC8: case 0xC9: case 0xCA: case 0xCB:
1582 case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* ld.h */
1583 cpu.gr[RX] = rhat (cpu.gr[RD] + ((inst >> 3) & 0x001E));
1584 memops++;
1585 break;
1586 case 0xD0: case 0xD1: case 0xD2: case 0xD3:
1587 case 0xD4: case 0xD5: case 0xD6: case 0xD7:
1588 case 0xD8: case 0xD9: case 0xDA: case 0xDB:
1589 case 0xDC: case 0xDD: case 0xDE: case 0xDF: /* st.h */
1590 what (cpu.gr[RD] + ((inst >> 3) & 0x001E), cpu.gr[RX]);
1591 memops++;
1592 break;
1593 case 0xE8: case 0xE9: case 0xEA: case 0xEB:
1594 case 0xEC: case 0xED: case 0xEE: case 0xEF: /* bf */
1595 if (C_OFF())
1596 {
1597 int disp;
1598 disp = inst & 0x03FF;
1599 if (inst & 0x0400)
1600 disp |= 0xFFFFFC00;
1601 pc += disp<<1;
1602 bonus_cycles++;
1603 needfetch = 1;
1604 }
1605 break;
1606 case 0xE0: case 0xE1: case 0xE2: case 0xE3:
1607 case 0xE4: case 0xE5: case 0xE6: case 0xE7: /* bt */
1608 if (C_ON())
1609 {
1610 int disp;
1611 disp = inst & 0x03FF;
1612 if (inst & 0x0400)
1613 disp |= 0xFFFFFC00;
1614 pc += disp<<1;
1615 bonus_cycles++;
1616 needfetch = 1;
1617 }
1618 break;
1619
1620 case 0xF8: case 0xF9: case 0xFA: case 0xFB:
1621 case 0xFC: case 0xFD: case 0xFE: case 0xFF: /* bsr */
1622 cpu.gr[15] = pc;
1623 case 0xF0: case 0xF1: case 0xF2: case 0xF3:
1624 case 0xF4: case 0xF5: case 0xF6: case 0xF7: /* br */
1625 {
1626 int disp;
1627 disp = inst & 0x03FF;
1628 if (inst & 0x0400)
1629 disp |= 0xFFFFFC00;
1630 pc += disp<<1;
1631 bonus_cycles++;
1632 needfetch = 1;
1633 }
1634 break;
1635
1636 }
1637
1638 if (tracing)
1639 fprintf (stderr, "\n");
cd0fc7c3 1640
2d514e6f
SS
1641 if (needfetch)
1642 {
1643 /* Do not let him fetch from a bad address! */
1644 if (((uword)pc) >= cpu.asregs.msize)
1645 {
1646 if (issue_messages)
cd0fc7c3 1647 fprintf (stderr, "PC loaded at 0x%x is outside of available memory! (0x%x)\n", oldpc, pc);
2d514e6f
SS
1648
1649 cpu.asregs.exception = SIGSEGV;
1650 }
1651 else
1652 {
1653 ibuf = rlat (pc & 0xFFFFFFFC);
1654 needfetch = 0;
1655 }
1656 }
1657 }
1658 while (!cpu.asregs.exception);
1659
1660 /* Hide away the things we've cached while executing. */
1661 cpu.asregs.pc = pc;
1662 cpu.asregs.insts += insts; /* instructions done ... */
1663 cpu.asregs.cycles += insts; /* and each takes a cycle */
1664 cpu.asregs.cycles += bonus_cycles; /* and extra cycles for branches */
1665 cpu.asregs.cycles += memops * memcycles; /* and memop cycle delays */
1666
1667 signal (SIGINT, sigsave);
1668}
1669
1670
1671int
1672sim_write (sd, addr, buffer, size)
1673 SIM_DESC sd;
1674 SIM_ADDR addr;
1675 unsigned char * buffer;
1676 int size;
1677{
1678 int i;
1679 init_pointers ();
1680
1681 memcpy (& cpu.mem[addr], buffer, size);
1682
1683 return size;
1684}
1685
1686int
1687sim_read (sd, addr, buffer, size)
1688 SIM_DESC sd;
1689 SIM_ADDR addr;
1690 unsigned char * buffer;
1691 int size;
1692{
1693 int i;
1694 init_pointers ();
1695
1696 memcpy (buffer, & cpu.mem[addr], size);
1697
1698 return size;
1699}
1700
1701
1702int
1703sim_store_register (sd, rn, memory, length)
1704 SIM_DESC sd;
1705 int rn;
1706 unsigned char * memory;
1707 int length;
1708{
1709 init_pointers ();
1710
1711 if (rn < NUM_MCORE_REGS && rn >= 0)
1712 {
1713 if (length == 4)
1714 {
2d514e6f 1715 long ival;
cd0fc7c3
SS
1716
1717 /* misalignment safe */
1718 ival = mcore_extract_unsigned_integer (memory, 4);
2d514e6f
SS
1719 cpu.asints[rn] = ival;
1720 }
1721
1722 return 4;
1723 }
1724 else
1725 return 0;
1726}
1727
1728int
1729sim_fetch_register (sd, rn, memory, length)
1730 SIM_DESC sd;
1731 int rn;
1732 unsigned char * memory;
1733 int length;
1734{
1735 init_pointers ();
1736
1737 if (rn < NUM_MCORE_REGS && rn >= 0)
1738 {
1739 if (length == 4)
1740 {
2d514e6f 1741 long ival = cpu.asints[rn];
cd0fc7c3
SS
1742
1743 /* misalignment-safe */
1744 mcore_store_unsigned_integer (memory, 4, ival);
2d514e6f
SS
1745 }
1746
1747 return 4;
1748 }
1749 else
1750 return 0;
1751}
1752
1753
1754int
1755sim_trace (sd)
1756 SIM_DESC sd;
1757{
1758 tracing = 1;
1759
1760 sim_resume (sd, 0, 0);
1761
1762 tracing = 0;
1763
1764 return 1;
1765}
1766
1767void
1768sim_stop_reason (sd, reason, sigrc)
1769 SIM_DESC sd;
1770 enum sim_stop * reason;
1771 int * sigrc;
1772{
1773 if (cpu.asregs.exception == SIGQUIT)
1774 {
1775 * reason = sim_exited;
1776 * sigrc = cpu.gr[PARM1];
1777 }
1778 else
1779 {
1780 * reason = sim_stopped;
1781 * sigrc = cpu.asregs.exception;
1782 }
1783}
1784
1785
1786int
1787sim_stop (sd)
1788 SIM_DESC sd;
1789{
1790 cpu.asregs.exception = SIGINT;
1791 return 1;
1792}
1793
1794
1795void
1796sim_info (sd, verbose)
1797 SIM_DESC sd;
1798 int verbose;
1799{
1800#ifdef WATCHFUNCTIONS
1801 int w, wcyc;
1802#endif
1803 double virttime = cpu.asregs.cycles / 36.0e6;
1804
cd0fc7c3
SS
1805 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
1806 cpu.asregs.insts);
1807 callback->printf_filtered (callback, "# cycles %10d\n",
1808 cpu.asregs.cycles);
1809 callback->printf_filtered (callback, "# pipeline stalls %10d\n",
1810 cpu.asregs.stalls);
1811 callback->printf_filtered (callback, "# virtual time taken %10.4f\n",
1812 virttime);
2d514e6f
SS
1813
1814#ifdef WATCHFUNCTIONS
cd0fc7c3
SS
1815 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
1816 ENDWL);
2d514e6f
SS
1817
1818 wcyc = 0;
1819
1820 for (w = 1; w <= ENDWL; w++)
1821 {
1822 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
cd0fc7c3
SS
1823 callback->printf_filtered (callback, " calls = %d, cycles = %d\n",
1824 WLcnts[w],WLcyc[w]);
2d514e6f
SS
1825
1826 if (WLcnts[w] != 0)
cd0fc7c3
SS
1827 callback->printf_filtered (callback,
1828 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
1829 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
2d514e6f
SS
1830 wcyc += WLcyc[w];
1831 }
1832
cd0fc7c3
SS
1833 callback->printf_filtered (callback,
1834 "Total cycles for watched functions: %d\n",wcyc);
2d514e6f
SS
1835#endif
1836}
1837
1838struct aout
1839{
1840 unsigned char sa_machtype[2];
1841 unsigned char sa_magic[2];
1842 unsigned char sa_tsize[4];
1843 unsigned char sa_dsize[4];
1844 unsigned char sa_bsize[4];
1845 unsigned char sa_syms[4];
1846 unsigned char sa_entry[4];
1847 unsigned char sa_trelo[4];
1848 unsigned char sa_drelo[4];
1849} aout;
1850
1851#define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
1852#define SHORT(x) (((x)[0]<<8)|(x)[1])
1853
1854SIM_DESC
1855sim_open (kind, cb, abfd, argv)
1856 SIM_OPEN_KIND kind;
1857 host_callback * cb;
1858 struct _bfd * abfd;
1859 char ** argv;
1860{
1861 int osize = sim_memory_size;
1862 myname = argv[0];
1863 callback = cb;
1864
1865 if (kind == SIM_OPEN_STANDALONE)
1866 issue_messages = 1;
1867
1868 /* Discard and reacquire memory -- start with a clean slate. */
1869 sim_size (1); /* small */
1870 sim_size (osize); /* and back again */
1871
1872 set_initial_gprs (); /* Reset the GPR registers. */
1873
1874 /* Fudge our descriptor for now. */
1875 return (SIM_DESC) 1;
1876}
1877
1878void
1879sim_close (sd, quitting)
1880 SIM_DESC sd;
1881 int quitting;
1882{
1883 /* nothing to do */
1884}
1885
1886SIM_RC
1887sim_load (sd, prog, abfd, from_tty)
1888 SIM_DESC sd;
1889 char * prog;
1890 bfd * abfd;
1891 int from_tty;
1892{
1893 /* Do the right thing for ELF executables; this turns out to be
1894 just about the right thing for any object format that:
1895 - we crack using BFD routines
1896 - follows the traditional UNIX text/data/bss layout
1897 - calls the bss section ".bss". */
1898
1899 extern bfd * sim_load_file (); /* ??? Don't know where this should live. */
1900 bfd * prog_bfd;
1901
1902 {
1903 bfd * handle;
1904 asection * s_bss;
1905 handle = bfd_openr (prog, 0); /* could be "mcore" */
1906
1907 if (!handle)
1908 {
1909 printf("``%s'' could not be opened.\n", prog);
1910 return SIM_RC_FAIL;
1911 }
1912
1913 /* Makes sure that we have an object file, also cleans gets the
1914 section headers in place. */
1915 if (!bfd_check_format (handle, bfd_object))
1916 {
1917 /* wasn't an object file */
1918 bfd_close (handle);
1919 printf ("``%s'' is not appropriate object file.\n", prog);
1920 return SIM_RC_FAIL;
1921 }
cd0fc7c3 1922
2d514e6f
SS
1923 /* Look for that bss section. */
1924 s_bss = bfd_get_section_by_name (handle, ".bss");
1925
1926 if (!s_bss)
1927 {
1928 printf("``%s'' has no bss section.\n", prog);
1929 return SIM_RC_FAIL;
1930 }
1931
1932 /* Appropriately paranoid would check that we have
1933 a traditional text/data/bss ordering within memory. */
1934
1935 /* figure the end of the bss section */
1936#if 0
1937 printf ("bss section at 0x%08x for 0x%08x bytes\n",
1938 (unsigned long) s_bss->vma , (unsigned long) s_bss->_cooked_size);
1939#endif
1940 heap_ptr = (unsigned long) s_bss->vma + (unsigned long) s_bss->_cooked_size;
1941
1942 /* Clean up after ourselves. */
1943 bfd_close (handle);
1944
1945 /* XXX: do we need to free the s_bss and handle structures? */
1946 }
1947
1948 /* from sh -- dac */
1949 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1950 sim_kind == SIM_OPEN_DEBUG,
1951 0, sim_write);
1952 if (prog_bfd == NULL)
1953 return SIM_RC_FAIL;
1954
cd0fc7c3 1955
2d514e6f
SS
1956 if (abfd == NULL)
1957 bfd_close (prog_bfd);
1958
1959 return SIM_RC_OK;
1960}
1961
1962SIM_RC
1963sim_create_inferior (sd, prog_bfd, argv, env)
1964 SIM_DESC sd;
1965 struct _bfd * prog_bfd;
1966 char ** argv;
1967 char ** env;
1968{
1969 char ** avp;
1970 int nargs = 0;
1971 int nenv = 0;
1972 int s_length;
1973 int l;
1974 unsigned long strings;
1975 unsigned long pointers;
1976 unsigned long hi_stack;
1977
1978
1979 /* Set the initial register set. */
1980 l = issue_messages;
1981 issue_messages = 0;
1982 set_initial_gprs ();
1983 issue_messages = l;
1984
1985 hi_stack = cpu.asregs.msize - 4;
1986 cpu.asregs.pc = bfd_get_start_address (prog_bfd);
1987
1988 /* Calculate the argument and environment strings. */
1989 s_length = 0;
1990 nargs = 0;
1991 avp = argv;
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 nargs++; avp++;
1997 }
1998
1999 nenv = 0;
2000 avp = env;
2001 while (avp && *avp)
2002 {
2003 l = strlen (*avp) + 1; /* include the null */
2004 s_length += (l + 3) & ~ 3;/* make it a 4 byte boundary */
2005 nenv++; avp++;
2006 }
2007
2008 /* Claim some memory for the pointers and strings. */
2009 pointers = hi_stack - sizeof(word) * (nenv+1+nargs+1);
2010 pointers &= ~3; /* must be 4-byte aligned */
2011 cpu.gr[0] = pointers;
2012
2013 strings = cpu.gr[0] - s_length;
2014 strings &= ~3; /* want to make it 4-byte aligned */
2015 cpu.gr[0] = strings;
2016 /* dac fix, the stack address must be 8-byte aligned! */
2017 cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
2018
2019 /* Loop through the arguments and fill them in. */
2020 cpu.gr[PARM1] = nargs;
2021 if (nargs == 0)
2022 {
2023 /* No strings to fill in. */
2024 cpu.gr[PARM2] = 0;
2025 }
2026 else
2027 {
2028 cpu.gr[PARM2] = pointers;
2029 avp = argv;
2030 while (avp && *avp)
2031 {
2032 /* Save where we're putting it. */
2033 wlat (pointers, strings);
2034
2035 /* Copy the string. */
2036 l = strlen (* avp) + 1;
2037 strcpy ((char *)(cpu.mem + strings), *avp);
2038
2039 /* Bump the pointers. */
2040 avp++;
2041 pointers += 4;
2042 strings += l+1;
2043 }
2044
2045 /* A null to finish the list. */
2046 wlat (pointers, 0);
2047 pointers += 4;
2048 }
2049
2050 /* Now do the environment pointers. */
2051 if (nenv == 0)
2052 {
2053 /* No strings to fill in. */
2054 cpu.gr[PARM3] = 0;
2055 }
2056 else
2057 {
2058 cpu.gr[PARM3] = pointers;
2059 avp = env;
2060
2061 while (avp && *avp)
2062 {
2063 /* Save where we're putting it. */
2064 wlat (pointers, strings);
2065
2066 /* Copy the string. */
2067 l = strlen (* avp) + 1;
2068 strcpy ((char *)(cpu.mem + strings), *avp);
2069
2070 /* Bump the pointers. */
2071 avp++;
2072 pointers += 4;
2073 strings += l+1;
2074 }
2075
2076 /* A null to finish the list. */
2077 wlat (pointers, 0);
2078 pointers += 4;
2079 }
2080
2081 return SIM_RC_OK;
2082}
2083
2084void
2085sim_kill (sd)
2086 SIM_DESC sd;
2087{
2088 /* nothing to do */
2089}
2090
2091void
2092sim_do_command (sd, cmd)
2093 SIM_DESC sd;
2094 char * cmd;
2095{
2096 /* Nothing there yet; it's all an error. */
2097
2098 if (cmd != NULL)
2099 {
2100 char ** simargv = buildargv (cmd);
2101
2102 if (strcmp (simargv[0], "watch") == 0)
2103 {
2104 if ((simargv[1] == NULL) || (simargv[2] == NULL))
2105 {
2106 fprintf (stderr, "Error: missing argument to watch cmd.\n");
2107 return;
2108 }
2109
2110 ENDWL++;
2111
2112 WL[ENDWL] = strtol (simargv[2], NULL, 0);
2113 WLstr[ENDWL] = strdup (simargv[1]);
2114 fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
2115 WL[ENDWL], ENDWL);
2116
2117 }
2118 else if (strcmp (simargv[0], "dumpmem") == 0)
2119 {
2120 unsigned char * p;
2121 FILE * dumpfile;
2122
2123 if (simargv[1] == NULL)
2124 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
2125
2126 fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
2127
2128 dumpfile = fopen (simargv[1], "w");
2129 p = cpu.mem;
2130 fwrite (p, cpu.asregs.msize-1, 1, dumpfile);
2131 fclose (dumpfile);
2132
2133 fprintf (stderr, "done.\n");
2134 }
2135 else if (strcmp (simargv[0], "clearstats") == 0)
2136 {
2137 cpu.asregs.cycles = 0;
2138 cpu.asregs.insts = 0;
2139 cpu.asregs.stalls = 0;
2140 ENDWL = 0;
2141 }
2142 else if (strcmp (simargv[0], "verbose") == 0)
2143 {
b83266a0 2144 issue_messages = 2;
2d514e6f
SS
2145 }
2146 else
2147 {
2148 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
2149 cmd);
2150 }
2151 }
2152 else
2153 {
2154 fprintf (stderr, "M.CORE sim commands: \n");
2155 fprintf (stderr, " watch <funcname> <addr>\n");
2156 fprintf (stderr, " dumpmem <filename>\n");
2157 fprintf (stderr, " clearstats\n");
2158 fprintf (stderr, " verbose\n");
2159 }
2160}
2161
2162void
2163sim_set_callbacks (ptr)
2164 host_callback * ptr;
2165{
2166 callback = ptr;
2167}