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