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