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