import gdb-2000-01-24 snapshot
[external/binutils.git] / sim / mcore / interp.c
1 /* Simulator for Motorola's MCore processor
2    Copyright (C) 1999 Free Software Foundation, Inc.
3    Contributed by Cygnus Solutions.
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include <signal.h>
22 #include "sysdep.h"
23 #include <sys/times.h>
24 #include <sys/param.h>
25 #include <netinet/in.h> /* for byte ordering macros */
26 #include "bfd.h"
27 #include "callback.h"
28 #include "libiberty.h"
29 #include "remote-sim.h"
30
31 #ifndef NUM_ELEM
32 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
33 #endif
34
35
36 typedef long int           word;
37 typedef unsigned long int  uword;
38
39 static unsigned long  heap_ptr = 0;
40 host_callback *       callback;
41
42
43 unsigned long
44 mcore_extract_unsigned_integer (addr, len)
45      unsigned char * addr;
46      int len;
47 {
48   unsigned long retval;
49   unsigned char * p;
50   unsigned char * startaddr = (unsigned char *)addr;
51   unsigned char * endaddr = startaddr + len;
52  
53   if (len > (int) sizeof (unsigned long))
54     printf ("That operation is not available on integers of more than %d bytes.",
55             sizeof (unsigned long));
56  
57   /* Start at the most significant end of the integer, and work towards
58      the least significant.  */
59   retval = 0;
60
61     {
62       for (p = startaddr; p < endaddr;)
63         retval = (retval << 8) | * p ++;
64     }
65   
66   return retval;
67 }
68
69 void
70 mcore_store_unsigned_integer (addr, len, val)
71      unsigned char * addr;
72      int len;
73      unsigned long val;
74 {
75   unsigned char * p;
76   unsigned char * startaddr = (unsigned char *)addr;
77   unsigned char * endaddr = startaddr + len;
78
79     {
80       for (p = endaddr; p > startaddr;)
81         {
82           * -- p = val & 0xff;
83           val >>= 8;
84         }
85     }
86 }
87
88 /* The machine state.
89    This state is maintained in host byte order.  The 
90    fetch/store register functions must translate between host
91    byte order and the target processor byte order.  
92    Keeping this data in target byte order simplifies the register
93    read/write functions.  Keeping this data in native order improves
94    the performance of the simulator.  Simulation speed is deemed more
95    important. */
96
97 /* The ordering of the mcore_regset structure is matched in the
98    gdb/config/mcore/tm-mcore.h file in the REGISTER_NAMES macro.  */
99 struct mcore_regset
100 {
101   word            gregs [16];           /* primary registers */
102   word            alt_gregs [16];       /* alt register file */
103   word            cregs [32];           /* control registers */
104   word            pc;                   /* the pc */
105   int             ticks;
106   int             stalls;
107   int             cycles;
108   int             insts;
109   int             exception;
110   unsigned long   msize;
111   unsigned char * memory;
112   word *          active_gregs;
113 };
114
115 union
116 {
117   struct mcore_regset asregs;
118   word asints [1];              /* but accessed larger... */
119 } cpu;
120
121 #define LAST_VALID_CREG 32              /* only 0..12 implemented */
122 #define NUM_MCORE_REGS  (16 + 16 + LAST_VALID_CREG + 1)
123
124 int memcycles = 1;
125
126 static SIM_OPEN_KIND sim_kind;
127 static char * myname;
128
129 static int issue_messages = 0;
130
131 #define gr      asregs.active_gregs
132 #define cr      asregs.cregs
133 #define sr      asregs.cregs[0]
134 #define vbr     asregs.cregs[1]
135 #define esr     asregs.cregs[2]
136 #define fsr     asregs.cregs[3]
137 #define epc     asregs.cregs[4]
138 #define fpc     asregs.cregs[5]
139 #define ss0     asregs.cregs[6]
140 #define ss1     asregs.cregs[7]
141 #define ss2     asregs.cregs[8]
142 #define ss3     asregs.cregs[9]
143 #define ss4     asregs.cregs[10]
144 #define gcr     asregs.cregs[11]
145 #define gsr     asregs.cregs[12]
146 #define mem     asregs.memory
147
148 /* maniuplate the carry bit */
149 #define C_ON()   (cpu.sr & 1)
150 #define C_VALUE() (cpu.sr & 1)
151 #define C_OFF()  ((cpu.sr & 1) == 0)
152 #define SET_C()  {cpu.sr |= 1;}
153 #define CLR_C()  {cpu.sr &= 0xfffffffe;}
154 #define NEW_C(v) {CLR_C(); cpu.sr |= ((v) & 1);}
155
156 #define SR_AF() ((cpu.sr >> 1) & 1)
157
158 #define TRAPCODE        1       /* r1 holds which function we want */
159 #define PARM1   2               /* first parameter  */
160 #define PARM2   3
161 #define PARM3   4
162 #define PARM4   5
163 #define RET1    2               /* register for return values. */
164
165 long
166 int_sbrk (inc_bytes)
167      int inc_bytes;
168 {
169   long addr;
170   
171   addr = heap_ptr;
172   
173   heap_ptr += inc_bytes;
174   
175   if (issue_messages && heap_ptr>cpu.gr[0])
176     fprintf (stderr, "Warning: heap_ptr overlaps stack!\n");
177   
178   return addr;
179 }
180
181 static void INLINE 
182 wbat (x, v)
183      word x, v;
184 {
185   if (((uword)x) >= cpu.asregs.msize)
186     {
187       if (issue_messages)
188         fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
189       
190       cpu.asregs.exception = SIGSEGV;
191     }
192   else
193     {
194       unsigned char *p = cpu.mem + x;
195       p[0] = v;
196     }
197 }
198
199 static void INLINE 
200 wlat (x, v)
201      word x, v;
202 {
203   if (((uword)x) >= cpu.asregs.msize)
204     {
205       if (issue_messages)
206         fprintf (stderr, "word write to 0x%x outside memory range\n", x);
207       
208       cpu.asregs.exception = SIGSEGV;
209     }
210   else
211     {
212       if ((x & 3) != 0)
213         {
214           if (issue_messages)
215             fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
216       
217           cpu.asregs.exception = SIGBUS;
218         }
219       else
220         {
221           unsigned char * p = cpu.mem + x;
222           p[0] = v >> 24;
223           p[1] = v >> 16;
224           p[2] = v >> 8;
225           p[3] = v;
226         }
227     }
228 }
229
230 static void INLINE 
231 what (x, v)
232      word x, v;
233 {
234   if (((uword)x) >= cpu.asregs.msize)
235     {
236       if (issue_messages)
237         fprintf (stderr, "short write to 0x%x outside memory range\n", x);
238       
239       cpu.asregs.exception = SIGSEGV;
240     }
241   else
242     {
243       if ((x & 1) != 0)
244         {
245           if (issue_messages)
246             fprintf (stderr, "short write to unaligned memory address: 0x%x\n",
247                      x);
248       
249           cpu.asregs.exception = SIGBUS;
250         }
251       else
252         {
253           unsigned char * p = cpu.mem + x;
254           p[0] = v >> 8;
255           p[1] = v;
256         }
257     }
258 }
259
260 /* Read functions */
261 static int INLINE 
262 rbat (x)
263      word x;
264 {
265   if (((uword)x) >= cpu.asregs.msize)
266     {
267       if (issue_messages)
268         fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
269       
270       cpu.asregs.exception = SIGSEGV;
271       return 0;
272     }
273   else
274     {
275       unsigned char * p = cpu.mem + x;
276       return p[0];
277     }
278 }
279
280 static int INLINE 
281 rlat (x)
282      word x;
283 {
284   if (((uword) x) >= cpu.asregs.msize)
285     {
286       if (issue_messages)
287         fprintf (stderr, "word read from 0x%x outside memory range\n", x);
288       
289       cpu.asregs.exception = SIGSEGV;
290       return 0;
291     }
292   else
293     {
294       if ((x & 3) != 0)
295         {
296           if (issue_messages)
297             fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
298       
299           cpu.asregs.exception = SIGBUS;
300           return 0;
301         }
302       else
303         {
304           unsigned char * p = cpu.mem + x;
305           return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
306         }
307     }
308 }
309
310 static int INLINE 
311 rhat (x)
312      word x;
313 {
314   if (((uword)x) >= cpu.asregs.msize)
315     {
316       if (issue_messages)
317         fprintf (stderr, "short read from 0x%x outside memory range\n", x);
318       
319       cpu.asregs.exception = SIGSEGV;
320       return 0;
321     }
322   else
323     {
324       if ((x & 1) != 0)
325         {
326           if (issue_messages)
327             fprintf (stderr, "short read from unaligned address: 0x%x\n", x);
328       
329           cpu.asregs.exception = SIGBUS;
330           return 0;
331         }
332       else
333         {
334           unsigned char * p = cpu.mem + x;
335           return (p[0] << 8) | p[1];
336         }
337     }
338 }
339
340
341 #define SEXTB(x)        (((x & 0xff) ^ (~ 0x7f)) + 0x80)
342 #define SEXTW(y)        ((int)((short)y))
343
344 static int
345 IOMEM (addr, write, value)
346      int addr;
347      int write;
348      int value;
349 {
350 }
351
352 /* default to a 8 Mbyte (== 2^23) memory space */
353 static int sim_memory_size = 23;
354
355 #define MEM_SIZE_FLOOR  64
356 void
357 sim_size (power)
358      int power;
359 {
360   sim_memory_size = power;
361   cpu.asregs.msize = 1 << sim_memory_size;
362
363   if (cpu.mem)
364     free (cpu.mem);
365
366   /* watch out for the '0 count' problem. There's probably a better
367      way.. e.g., why do we use 64 here? */
368   if (cpu.asregs.msize < 64)    /* ensure a boundary */
369     cpu.mem = (unsigned char *) calloc (64, (64 + cpu.asregs.msize) / 64);
370   else
371     cpu.mem = (unsigned char *) calloc (64, cpu.asregs.msize / 64);
372
373   if (!cpu.mem)
374     {
375       if (issue_messages)
376         fprintf (stderr,
377                  "Not enough VM for simulation of %d bytes of RAM\n",
378                  cpu.asregs.msize);
379
380       cpu.asregs.msize = 1;
381       cpu.mem = (unsigned char *) calloc (1, 1);
382     }
383 }
384
385 static void
386 init_pointers ()
387 {
388   if (cpu.asregs.msize != (1 << sim_memory_size))
389     sim_size (sim_memory_size);
390 }
391
392 static void
393 set_initial_gprs ()
394 {
395   int i;
396   long space;
397   unsigned long memsize;
398   
399   init_pointers ();
400
401   /* Set up machine just out of reset.  */
402   cpu.asregs.pc = 0;
403   cpu.sr = 0;
404   
405   memsize = cpu.asregs.msize / (1024 * 1024);
406
407   if (issue_messages > 1)
408     fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
409              memsize, cpu.asregs.msize - 1);
410
411   /* Clean out the GPRs and alternate GPRs.  */
412   for (i = 0; i < 16; i++)
413     {
414       cpu.asregs.gregs[i] = 0;
415       cpu.asregs.alt_gregs[i] = 0;
416     }
417   
418   /* Make our register set point to the right place.  */
419   if (SR_AF())
420     cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0];
421   else
422     cpu.asregs.active_gregs = &cpu.asregs.gregs[0];
423   
424   /* ABI specifies initial values for these registers.  */
425   cpu.gr[0] = cpu.asregs.msize - 4;
426  
427   /* dac fix, the stack address must be 8-byte aligned! */
428   cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
429   cpu.gr[PARM1] = 0;
430   cpu.gr[PARM2] = 0;
431   cpu.gr[PARM3] = 0;
432   cpu.gr[PARM4] = cpu.gr[0];
433 }
434
435 static void
436 interrupt ()
437 {
438   cpu.asregs.exception = SIGINT;
439 }
440
441 /* Functions so that trapped open/close don't interfere with the
442    parent's functions.  We say that we can't close the descriptors
443    that we didn't open.  exit() and cleanup() get in trouble here,
444    to some extent.  That's the price of emulation.  */
445
446 unsigned char opened[100];
447
448 static void
449 log_open (fd)
450     int fd;
451 {
452   if (fd < 0 || fd > NUM_ELEM (opened))
453     return;
454   
455   opened[fd] = 1;
456 }
457
458 static void
459 log_close (fd)
460      int fd;
461 {
462   if (fd < 0 || fd > NUM_ELEM (opened))
463     return;
464   
465   opened[fd] = 0;
466 }
467
468 static int
469 is_opened (fd)
470     int fd;
471 {
472   if (fd < 0 || fd > NUM_ELEM (opened))
473     return 0;
474
475   return opened[fd];
476 }
477
478 static void
479 handle_trap1 ()
480 {
481   unsigned long a[3];
482
483   switch ((unsigned long) (cpu.gr [TRAPCODE]))
484     {
485     case 3:
486       a[0] = (unsigned long) (cpu.gr[PARM1]);
487       a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
488       a[2] = (unsigned long) (cpu.gr[PARM3]);
489       cpu.gr[RET1] = callback->read (callback, a[0], (char *) a[1], a[2]);
490       break;
491       
492     case 4:
493       a[0] = (unsigned long) (cpu.gr[PARM1]);
494       a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
495       a[2] = (unsigned long) (cpu.gr[PARM3]);
496       cpu.gr[RET1] = (int)callback->write (callback, a[0], (char *) a[1], a[2]);
497       break;
498       
499     case 5:
500       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
501       a[1] = (unsigned long) (cpu.gr[PARM2]);
502       /* a[2] = (unsigned long) (cpu.gr[PARM3]); */
503       cpu.gr[RET1] = callback->open (callback, (char *) a[0], a[1]);
504       log_open (cpu.gr[RET1]);
505       break;
506       
507     case 6:
508       a[0] = (unsigned long) (cpu.gr[4]);
509       /* Watch out for debugger's files. */
510       if (is_opened (a[0]))
511         {
512           log_close (a[0]);
513           cpu.gr[RET1] = callback->close (callback, a[0]);
514         }
515       else
516         {
517           /* Don't let him close it.  */
518           cpu.gr[RET1] = (-1);
519         }
520       break;
521       
522     case 9:
523       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
524       a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
525       cpu.gr[RET1] = link ((char *) a[0], (char *) a[1]);
526       break;
527       
528     case 10:
529       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
530       cpu.gr[RET1] = callback->unlink (callback, (char *) a[0]);
531       break;
532       
533     case 13:
534       /* handle time(0) vs time(&var) */
535       a[0] = (unsigned long) (cpu.gr[PARM1]);
536       if (a[0])
537         a[0] += (unsigned long) cpu.mem;
538       cpu.gr[RET1] = callback->time (callback, (time_t *) a[0]);
539       break;
540       
541     case 19:
542       a[0] = (unsigned long) (cpu.gr[PARM1]);
543       a[1] = (unsigned long) (cpu.gr[PARM2]);
544       a[2] = (unsigned long) (cpu.gr[PARM3]);
545       cpu.gr[RET1] = callback->lseek (callback, a[0], a[1], a[2]);
546       break;
547       
548     case 33:
549       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
550       a[1] = (unsigned long) (cpu.gr[PARM2]);
551       cpu.gr[RET1] = access ((char *) a[0], a[1]);
552       break;
553       
554     case 43:
555       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
556 #if 0
557       cpu.gr[RET1] = times ((char *)a[0]);
558 #else
559       {
560         /* Give him simulated cycles for utime
561            and an instruction count for stime. */
562         struct tms
563         {
564           time_t tms_utime;
565           time_t tms_stime;
566           time_t tms_cutime;
567           time_t tms_cstime;
568         } t;
569
570         t.tms_utime = cpu.asregs.cycles;
571         t.tms_stime = cpu.asregs.insts;
572         t.tms_cutime = t.tms_utime;
573         t.tms_cstime = t.tms_stime;
574                             
575         memcpy ((struct tms *)(a[0]), &t, sizeof (t));
576                             
577         cpu.gr[RET1] = cpu.asregs.cycles;
578       }
579 #endif
580       break;
581       
582     case 69:
583       a[0] = (unsigned long) (cpu.gr[PARM1]);
584       cpu.gr[RET1] = int_sbrk (a[0]);
585       break;
586       
587     default:
588       if (issue_messages)
589         fprintf (stderr, "WARNING: sys call %d unimplemented\n",
590                  cpu.gr[TRAPCODE]);
591       break;
592     }
593 }
594
595 static void
596 process_stub (what)
597      int what;
598 {
599   /* These values should match those in libgloss/mcore/syscalls.s.  */
600   switch (what)
601     {
602     case 3:  /* _read */
603     case 4:  /* _write */
604     case 5:  /* _open */
605     case 6:  /* _close */
606     case 10: /* _unlink */
607     case 19: /* _lseek */
608     case 43: /* _times */
609       cpu.gr [TRAPCODE] = what;
610       handle_trap1 ();
611       break;
612       
613     default:
614       if (issue_messages)
615         fprintf (stderr, "Unhandled stub opcode: %d\n", what);
616       break;
617     }
618 }
619
620 static void
621 util (what)
622      unsigned what;
623 {
624   switch (what)
625     {
626     case 0:     /* exit */
627       cpu.asregs.exception = SIGQUIT;
628       break;
629
630     case 1:     /* printf */
631       {
632         unsigned long a[6];
633         unsigned char *s;
634         int i;
635
636         a[0] = (unsigned long)(cpu.mem + cpu.gr[PARM1]);
637
638         for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++)
639           {
640             if (*s == '%')
641               {
642                 if (*++s == 's')
643                   a[i] = (unsigned long)(cpu.mem + cpu.gr[PARM1+i]);
644                 else
645                   a[i] = cpu.gr[i+PARM1];
646                 i++;
647               }
648           }
649         
650         cpu.gr[RET1] = printf ((char *)a[0], a[1], a[2], a[3], a[4], a[5]);
651       }
652       break;
653       
654     case 2:     /* scanf */
655       if (issue_messages)
656         fprintf (stderr, "WARNING: scanf unimplemented\n");
657       break;
658       
659     case 3:     /* utime */
660       cpu.gr[RET1] = cpu.asregs.insts;
661       break;
662
663     case 0xFF:
664       process_stub (cpu.gr[1]);
665       break;
666       
667     default:
668       if (issue_messages)
669         fprintf (stderr, "Unhandled util code: %x\n", what);
670       break;
671     }
672 }       
673
674 /* For figuring out whether we carried; addc/subc use this. */
675 static int
676 iu_carry (a, b, cin)
677      unsigned long a;
678      unsigned long b;
679      int cin;
680 {
681   unsigned long x;
682   
683   x = (a & 0xffff) + (b & 0xffff) + cin;
684   x = (x >> 16) + (a >> 16) + (b >> 16);
685   x >>= 16;
686
687   return (x != 0);
688 }
689
690 #define WATCHFUNCTIONS 1
691 #ifdef WATCHFUNCTIONS
692
693 #define MAXWL 80
694 word WL[MAXWL];
695 char * WLstr[MAXWL];
696
697 int ENDWL=0;
698 int WLincyc;
699 int WLcyc[MAXWL];
700 int WLcnts[MAXWL];
701 int WLmax[MAXWL];
702 int WLmin[MAXWL];
703 word WLendpc;
704 int WLbcyc;
705 int WLW;
706 #endif
707
708 #define RD      (inst        & 0xF)
709 #define RS      ((inst >> 4) & 0xF)
710 #define RX      ((inst >> 8) & 0xF)
711 #define IMM5    ((inst >> 4) & 0x1F)
712 #define IMM4    ((inst) & 0xF)
713
714 static int tracing = 0;
715
716 void
717 sim_resume (sd, step, siggnal)
718      SIM_DESC sd;
719      int step, siggnal;
720 {
721   int needfetch;
722   word ibuf;
723   word pc;
724   unsigned short inst;
725   void (* sigsave)();
726   int memops;
727   int bonus_cycles;
728   int insts;
729   int w;
730   int cycs;
731   word WLhash;
732
733   sigsave = signal (SIGINT, interrupt);
734   cpu.asregs.exception = step ? SIGTRAP: 0;
735   pc = cpu.asregs.pc;
736
737   /* Fetch the initial instructions that we'll decode. */
738   ibuf = rlat (pc & 0xFFFFFFFC);
739   needfetch = 0;
740
741   memops = 0;
742   bonus_cycles = 0;
743   insts = 0;
744   
745   /* make our register set point to the right place */
746   if (SR_AF ())
747     cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
748   else
749     cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
750   
751   /* make a hash to speed exec loop, hope it's nonzero */
752   WLhash = 0xFFFFFFFF;
753
754   for (w = 1; w <= ENDWL; w++)
755     WLhash = WLhash & WL[w];
756
757   do
758     {
759       word oldpc;
760       
761       insts ++;
762       
763       if (pc & 02)
764         {
765             inst = ibuf & 0xFFFF;
766           needfetch = 1;
767         }
768       else
769         {
770             inst = ibuf >> 16;
771         }
772
773 #ifdef WATCHFUNCTIONS
774       /* now scan list of watch addresses, if match, count it and
775          note return address and count cycles until pc=return address */
776       
777       if ((WLincyc == 1) && (pc == WLendpc))
778         {
779           cycs = (cpu.asregs.cycles + (insts + bonus_cycles +
780                                        (memops * memcycles)) - WLbcyc);
781           
782           if (WLcnts[WLW] == 1)
783             {
784               WLmax[WLW] = cycs;
785               WLmin[WLW] = cycs;
786               WLcyc[WLW] = 0;
787             }
788           
789           if (cycs > WLmax[WLW])
790             {
791               WLmax[WLW] = cycs;
792             }
793           
794           if (cycs < WLmin[WLW])
795             {
796               WLmin[WLW] = cycs;
797             }
798           
799           WLcyc[WLW] += cycs;
800           WLincyc = 0;
801           WLendpc = 0;
802         } 
803
804       /* Optimize with a hash to speed loop.  */
805       if (WLincyc == 0)
806         {
807           if ((WLhash == 0) || ((WLhash & pc) != 0))
808             {
809               for (w=1; w <= ENDWL; w++)
810                 {
811                   if (pc == WL[w])
812                     {
813                       WLcnts[w]++;
814                       WLbcyc = cpu.asregs.cycles + insts 
815                         + bonus_cycles + (memops * memcycles);
816                       WLendpc = cpu.gr[15];
817                       WLincyc = 1;
818                       WLW = w;
819                       break;
820                     }
821                 }
822             }
823         }
824 #endif
825
826       if (tracing)
827         fprintf (stderr, "%.4x: inst = %.4x ", pc, inst);
828
829       oldpc = pc;
830       
831       pc += 2;
832       
833       switch (inst >> 8)
834         {
835         case 0x00:
836           switch RS
837             {
838             case 0x0:
839               switch RD
840                 {
841                 case 0x0:                               /* bkpt */
842                   cpu.asregs.exception = SIGTRAP;
843                   pc -= 2;
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                   
854                   if (SR_AF ())
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)
883                     fprintf (stderr, "WARNING: doze unimplemented\n");
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               if (tracing && RD == 15)
1006                 fprintf (stderr, "Func return, r2 = %x, r3 = %x\n",
1007                          cpu.gr[2], cpu.gr[3]);
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 */
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]);
1136           cpu.gr[RD] = cpu.gr[RD] * cpu.gr[RS];
1137           break;
1138         case 0x04:                                      /* loopt */
1139           if (C_ON())
1140             {
1141               pc += (IMM4 << 1) - 32;
1142               bonus_cycles ++;
1143               needfetch = 1;
1144             }
1145           --cpu.gr[RS];                         /* not RD! */
1146           NEW_C (((long)cpu.gr[RS]) > 0);
1147           break; 
1148         case 0x05:                                      /* subu */
1149           cpu.gr[RD] -= cpu.gr[RS];
1150           break;
1151         case 0x06:                                      /* addc */
1152           {
1153             unsigned long tmp, a, b;
1154             a = cpu.gr[RD];
1155             b = cpu.gr[RS];
1156             cpu.gr[RD] = a + b + C_VALUE ();
1157             tmp = iu_carry (a, b, C_VALUE ());
1158             NEW_C (tmp);
1159           }
1160           break;
1161         case 0x07:                                      /* subc */
1162           {
1163             unsigned long tmp, a, b;
1164             a = cpu.gr[RD];
1165             b = cpu.gr[RS];
1166             cpu.gr[RD] = a - b + C_VALUE () - 1;
1167             tmp = iu_carry (a,~b, C_VALUE ());
1168             NEW_C (tmp);
1169           }
1170           break;
1171         case 0x08:                                      /* illegal */
1172         case 0x09:                                      /* illegal*/
1173           cpu.asregs.exception = SIGILL;
1174           break;
1175         case 0x0A:                                      /* movf */
1176           if (C_OFF())
1177             cpu.gr[RD] = cpu.gr[RS];
1178           break;
1179         case 0x0B:                                      /* lsr */
1180           { 
1181             unsigned long dst, src;
1182             dst = cpu.gr[RD];
1183             src = cpu.gr[RS];
1184             /* 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;
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];
1216           if (tracing)
1217             fprintf (stderr, "MOV %x into reg %d", cpu.gr[RD], RD);
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 */
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];
1267           break;
1268
1269         case 0x1B:                                      /* lsl */
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];
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;
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]);
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");
1640
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)
1647                 fprintf (stderr, "PC loaded at 0x%x is outside of available memory! (0x%x)\n", oldpc, pc);
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
1671 int
1672 sim_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
1686 int
1687 sim_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
1702 int
1703 sim_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         {
1715           long ival;
1716           
1717           /* misalignment safe */
1718           ival = mcore_extract_unsigned_integer (memory, 4);
1719           cpu.asints[rn] = ival;
1720         }
1721
1722       return 4;
1723     }
1724   else
1725     return 0;
1726 }
1727
1728 int
1729 sim_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         {
1741           long ival = cpu.asints[rn];
1742
1743           /* misalignment-safe */
1744           mcore_store_unsigned_integer (memory, 4, ival);
1745         }
1746       
1747       return 4;
1748     }
1749   else
1750     return 0;
1751 }
1752
1753
1754 int
1755 sim_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
1767 void
1768 sim_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
1786 int
1787 sim_stop (sd)
1788      SIM_DESC sd;
1789 {
1790   cpu.asregs.exception = SIGINT;
1791   return 1;
1792 }
1793
1794
1795 void
1796 sim_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
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);
1813
1814 #ifdef WATCHFUNCTIONS
1815   callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
1816                              ENDWL);
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]);
1823       callback->printf_filtered (callback, "  calls = %d, cycles = %d\n",
1824                                  WLcnts[w],WLcyc[w]);
1825       
1826       if (WLcnts[w] != 0)
1827         callback->printf_filtered (callback,
1828                                    "  maxcpc = %d, mincpc = %d, avecpc = %d\n",
1829                                    WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
1830       wcyc += WLcyc[w];
1831     }
1832   
1833   callback->printf_filtered (callback,
1834                              "Total cycles for watched functions: %d\n",wcyc);
1835 #endif
1836 }
1837
1838 struct  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
1854 SIM_DESC
1855 sim_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
1878 void
1879 sim_close (sd, quitting)
1880      SIM_DESC sd;
1881      int quitting;
1882 {
1883   /* nothing to do */
1884 }
1885
1886 SIM_RC
1887 sim_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       }
1922
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   
1955     
1956   if (abfd == NULL)
1957     bfd_close (prog_bfd);
1958
1959   return SIM_RC_OK;
1960 }
1961
1962 SIM_RC
1963 sim_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
2084 void
2085 sim_kill (sd)
2086      SIM_DESC sd;
2087 {
2088   /* nothing to do */
2089 }
2090
2091 void
2092 sim_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         {
2144           issue_messages = 2;
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
2162 void
2163 sim_set_callbacks (ptr)
2164      host_callback * ptr;
2165 {
2166   callback = ptr; 
2167 }