import gdb-19990504 snapshot
[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 #define TARGET_BYTE_ORDER BIG_ENDIAN /* XXX */
44
45 unsigned long
46 mcore_extract_unsigned_integer (addr, len)
47      unsigned char * addr;
48      int len;
49 {
50   unsigned long retval;
51   unsigned char * p;
52   unsigned char * startaddr = (unsigned char *)addr;
53   unsigned char * endaddr = startaddr + len;
54  
55   if (len > (int) sizeof (unsigned long))
56     printf ("That operation is not available on integers of more than %d bytes.",
57             sizeof (unsigned long));
58  
59   /* Start at the most significant end of the integer, and work towards
60      the least significant.  */
61   retval = 0;
62   for (p = startaddr; p < endaddr; ++p)
63      retval = (retval << 8) | * p;
64   
65   return retval;
66 }
67
68 void
69 mcore_store_unsigned_integer (addr, len, val)
70      unsigned char * addr;
71      int len;
72      unsigned long val;
73 {
74   unsigned char * p;
75   unsigned char * startaddr = (unsigned char *)addr;
76   unsigned char * endaddr = startaddr + len;
77  
78   /* Start at the least significant end of the integer, and work towards
79      the most significant.  */
80   for (p = endaddr - 1; p >= startaddr; --p)
81     {
82       * p = val & 0xff;
83       val >>= 8;
84     }
85 }
86
87 /* The machine state.
88    This state is maintained in host byte order.  The 
89    fetch/store register functions must translate between host
90    byte order and the target processor byte order (for MCore this
91    is big-endian).  Since we know that the MCore is always big-endian,
92    we cheat a bit and use the ntohl() and htonl() macros to
93    achieve this end.
94   
95    Keeping this data in target byte order simplifies the register
96    read/write functions.  Keeping this data in native order improves
97    the performance of the simulator.  Simulation speed is deemed more
98    important. */
99
100 /* The ordering of the mcore_regset structure is matched in the
101    gdb/config/mcore/tm-mcore.h file in the REGISTER_NAMES macro.  */
102 struct mcore_regset
103 {
104   word            gregs [16];           /* primary registers */
105   word            alt_gregs [16];       /* alt register file */
106   word            cregs [32];           /* control registers */
107   word            pc;                   /* the pc */
108   int             ticks;
109   int             stalls;
110   int             cycles;
111   int             insts;
112   int             exception;
113   unsigned long   msize;
114   unsigned char * memory;
115   word *          active_gregs;
116 };
117
118 union
119 {
120   struct mcore_regset asregs;
121   word asints [1];              /* but accessed larger... */
122 } cpu;
123
124 #define LAST_VALID_CREG 12              /* only 0..12 implemented */
125 #define NUM_MCORE_REGS  (16 + 16 + LAST_VALID_CREG)
126
127 int memcycles = 1;
128
129 static SIM_OPEN_KIND sim_kind;
130 static char * myname;
131
132 static int issue_messages = 0;
133
134 #define gr      asregs.active_gregs
135 #define cr      asregs.cregs
136 #define sr      asregs.cregs[0]
137 #define vbr     asregs.cregs[1]
138 #define esr     asregs.cregs[2]
139 #define fsr     asregs.cregs[3]
140 #define epc     asregs.cregs[4]
141 #define fpc     asregs.cregs[5]
142 #define ss0     asregs.cregs[6]
143 #define ss1     asregs.cregs[7]
144 #define ss2     asregs.cregs[8]
145 #define ss3     asregs.cregs[9]
146 #define ss4     asregs.cregs[10]
147 #define gcr     asregs.cregs[11]
148 #define gsr     asregs.cregs[12]
149 #define mem     asregs.memory
150
151 /* maniuplate the carry bit */
152 #define C_ON()  (cpu.sr & 1)
153 #define C_VALUE() (cpu.sr & 1)
154 #define C_OFF() ((cpu.sr & 1) == 0)
155 #define SET_C() {cpu.sr |= 1;}
156 #define CLR_C() {cpu.sr &= 0xfffffffe;}
157 #define NEW_C(v){CLR_C(); cpu.sr |= ((v) & 1);}
158
159 #define SR_AF() ((cpu.sr >> 1) & 1)
160
161 #define TRAPCODE        1       /* r1 holds which function we want */
162 #define PARM1   2               /* first parameter  */
163 #define PARM2   3
164 #define PARM3   4
165 #define PARM4   5
166 #define RET1    2               /* register for return values. */
167
168 long
169 int_sbrk (inc_bytes)
170      int inc_bytes;
171 {
172   long addr;
173   
174   addr = heap_ptr;
175   
176   heap_ptr += inc_bytes;
177   
178   if (issue_messages && heap_ptr>cpu.gr[0])
179     fprintf (stderr, "Warning: heap_ptr overlaps stack!\n");
180   
181   return addr;
182 }
183
184 static void INLINE 
185 wbat (x, v)
186      word x, v;
187 {
188   if (((uword)x) >= cpu.asregs.msize)
189     {
190       if (issue_messages)
191         fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
192       
193       cpu.asregs.exception = SIGSEGV;
194     }
195   else
196     {
197       unsigned char *p = cpu.mem + x;
198       p[0] = v;
199     }
200 }
201
202 static void INLINE 
203 wlat (x, v)
204      word x, v;
205 {
206   if (((uword)x) >= cpu.asregs.msize)
207     {
208       if (issue_messages)
209         fprintf (stderr, "word write to 0x%x outside memory range\n", x);
210       
211       cpu.asregs.exception = SIGSEGV;
212     }
213   else
214     {
215       if ((x & 3) != 0)
216         {
217           if (issue_messages)
218             fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
219       
220           cpu.asregs.exception = SIGBUS;
221         }
222       else
223         {
224           unsigned char * p = cpu.mem + x;
225           p[0] = v >> 24;
226           p[1] = v >> 16;
227           p[2] = v >> 8;
228           p[3] = v;
229         }
230     }
231 }
232
233 static void INLINE 
234 what (x, v)
235      word x, v;
236 {
237   if (((uword)x) >= cpu.asregs.msize)
238     {
239       if (issue_messages)
240         fprintf (stderr, "short write to 0x%x outside memory range\n", x);
241       
242       cpu.asregs.exception = SIGSEGV;
243     }
244   else
245     {
246       if ((x & 1) != 0)
247         {
248           if (issue_messages)
249             fprintf (stderr, "short write to unaligned memory address: 0x%x\n", x);
250       
251           cpu.asregs.exception = SIGBUS;
252         }
253       else
254         {
255           unsigned char * p = cpu.mem + x;
256           p[0] = v >> 8;
257           p[1] = v;
258         }
259     }
260 }
261
262 /* Read functions */
263 static int INLINE 
264 rbat (x)
265      word x;
266 {
267   if (((uword)x) >= cpu.asregs.msize)
268     {
269       if (issue_messages)
270         fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
271       
272       cpu.asregs.exception = SIGSEGV;
273       return 0;
274     }
275   else
276     {
277       unsigned char * p = cpu.mem + x;
278       return p[0];
279     }
280 }
281
282 static int INLINE 
283 rlat (x)
284      word x;
285 {
286   if (((uword) x) >= cpu.asregs.msize)
287     {
288       if (issue_messages)
289         fprintf (stderr, "word read from 0x%x outside memory range\n", x);
290       
291       cpu.asregs.exception = SIGSEGV;
292       return 0;
293     }
294   else
295     {
296       if ((x & 3) != 0)
297         {
298           if (issue_messages)
299             fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
300       
301           cpu.asregs.exception = SIGBUS;
302           return 0;
303         }
304       else
305         {
306           unsigned char * p = cpu.mem + x;
307           return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
308         }
309     }
310 }
311
312 static int INLINE 
313 rhat (x)
314      word x;
315 {
316   if (((uword)x) >= cpu.asregs.msize)
317     {
318       if (issue_messages)
319         fprintf (stderr, "short read from 0x%x outside memory range\n", x);
320       
321       cpu.asregs.exception = SIGSEGV;
322       return 0;
323     }
324   else
325     {
326       if ((x & 1) != 0)
327         {
328           if (issue_messages)
329             fprintf (stderr, "short read from unaligned address: 0x%x\n", x);
330       
331           cpu.asregs.exception = SIGBUS;
332           return 0;
333         }
334       else
335         {
336           unsigned char * p = cpu.mem + x;
337           return (p[0] << 8) | p[1];
338         }
339     }
340 }
341
342
343 #define SEXTB(x)        (((x & 0xff) ^ (~ 0x7f)) + 0x80)
344 #define SEXTW(y)        ((int)((short)y))
345
346 static int
347 IOMEM (addr, write, value)
348      int addr;
349      int write;
350      int value;
351 {
352 }
353
354 /* default to a 8 Mbyte (== 2^23) memory space */
355 static int sim_memory_size = 23;
356
357 #define MEM_SIZE_FLOOR  64
358 void
359 sim_size (power)
360      int power;
361 {
362   sim_memory_size = power;
363   cpu.asregs.msize = 1 << sim_memory_size;
364
365   if (cpu.mem)
366     free (cpu.mem);
367
368   /* watch out for the '0 count' problem. There's probably a better
369      way.. e.g., why do we use 64 here? */
370   if (cpu.asregs.msize < 64)    /* ensure a boundary */
371     cpu.mem = (unsigned char *) calloc (64, (64 + cpu.asregs.msize) / 64);
372   else
373     cpu.mem = (unsigned char *) calloc (64, cpu.asregs.msize / 64);
374
375   if (!cpu.mem)
376     {
377       if (issue_messages)
378         fprintf (stderr,
379                  "Not enough VM for simulation of %d bytes of RAM\n", cpu.asregs.msize);
380
381       cpu.asregs.msize = 1;
382       cpu.mem = (unsigned char *) calloc (1, 1);
383     }
384 }
385
386 static void
387 init_pointers ()
388 {
389   if (cpu.asregs.msize != (1 << sim_memory_size))
390     sim_size (sim_memory_size);
391 }
392
393 static void
394 set_initial_gprs ()
395 {
396   int i;
397   long space;
398   unsigned long memsize;
399   
400   init_pointers ();
401
402   /* Set up machine just out of reset.  */
403   cpu.asregs.pc = 0;
404   cpu.sr = 0;
405   
406   memsize = cpu.asregs.msize / (1024 * 1024);
407
408   if (issue_messages > 1)
409     fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
410              memsize, cpu.asregs.msize - 1);
411
412   /* Clean out the GPRs and alternate GPRs.  */
413   for (i = 0; i < 16; i++)
414     {
415       cpu.asregs.gregs[i] = 0;
416       cpu.asregs.alt_gregs[i] = 0;
417     }
418   
419   /* Make our register set point to the right place.  */
420   if (SR_AF())
421     cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0];
422   else
423     cpu.asregs.active_gregs = &cpu.asregs.gregs[0];
424   
425   /* ABI specifies initial values for these registers.  */
426   cpu.gr[0] = cpu.asregs.msize - 4;
427  
428   /* dac fix, the stack address must be 8-byte aligned! */
429   cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
430   cpu.gr[PARM1] = 0;
431   cpu.gr[PARM2] = 0;
432   cpu.gr[PARM3] = 0;
433   cpu.gr[PARM4] = cpu.gr[0];
434 }
435
436 static void
437 interrupt ()
438 {
439   cpu.asregs.exception = SIGINT;
440 }
441
442 /* Functions so that trapped open/close don't interfere with the
443    parent's functions.  We say that we can't close the descriptors
444    that we didn't open.  exit() and cleanup() get in trouble here,
445    to some extent.  That's the price of emulation.  */
446
447 unsigned char opened[100];
448
449 static void
450 log_open (fd)
451     int fd;
452 {
453   if (fd < 0 || fd > NUM_ELEM (opened))
454     return;
455   
456   opened[fd] = 1;
457 }
458
459 static void
460 log_close (fd)
461      int fd;
462 {
463   if (fd < 0 || fd > NUM_ELEM (opened))
464     return;
465   
466   opened[fd] = 0;
467 }
468
469 static int
470 is_opened (fd)
471     int fd;
472 {
473   if (fd < 0 || fd > NUM_ELEM (opened))
474     return 0;
475
476   return opened[fd];
477 }
478
479 static void
480 handle_trap1 ()
481 {
482   unsigned long a[3];
483
484   switch ((unsigned long) (cpu.gr[TRAPCODE]))
485     {
486     case 3:
487       a[0] = (unsigned long) (cpu.gr[PARM1]);
488       a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
489       a[2] = (unsigned long) (cpu.gr[PARM3]);
490       cpu.gr[RET1] = callback->read (callback, a[0], (char *) a[1], a[2]);
491       break;
492       
493     case 4:
494       a[0] = (unsigned long) (cpu.gr[PARM1]);
495       a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
496       a[2] = (unsigned long) (cpu.gr[PARM3]);
497       cpu.gr[RET1] = (int)callback->write (callback, a[0], (char *) a[1], a[2]);
498       break;
499       
500     case 5:
501       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
502       a[1] = (unsigned long) (cpu.gr[PARM2]);
503       /* a[2] = (unsigned long) (cpu.gr[PARM3]); */
504       cpu.gr[RET1] = callback->open (callback, (char *) a[0], a[1]);
505       log_open (cpu.gr[RET1]);
506       break;
507       
508     case 6:
509       a[0] = (unsigned long) (cpu.gr[4]);
510       /* Watch out for debugger's files. */
511       if (is_opened (a[0]))
512         {
513           log_close (a[0]);
514           cpu.gr[RET1] = callback->close (callback, a[0]);
515         }
516       else
517         {
518           /* Don't let him close it.  */
519           cpu.gr[RET1] = (-1);
520         }
521       break;
522       
523     case 9:
524       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
525       a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]);
526       cpu.gr[RET1] = link ((char *) a[0], (char *) a[1]);
527       break;
528       
529     case 10:
530       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
531       cpu.gr[RET1] = callback->unlink (callback, (char *) a[0]);
532       break;
533       
534     case 13:
535       /* handle time(0) vs time(&var) */
536       a[0] = (unsigned long) (cpu.gr[PARM1]);
537       if (a[0])
538         a[0] += (unsigned long) cpu.mem;
539       cpu.gr[RET1] = callback->time (callback, (time_t *) a[0]);
540       break;
541       
542     case 19:
543       a[0] = (unsigned long) (cpu.gr[PARM1]);
544       a[1] = (unsigned long) (cpu.gr[PARM2]);
545       a[2] = (unsigned long) (cpu.gr[PARM3]);
546       cpu.gr[RET1] = callback->lseek (callback, a[0], a[1], a[2]);
547       break;
548       
549     case 33:
550       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
551       a[1] = (unsigned long) (cpu.gr[PARM2]);
552       cpu.gr[RET1] = access ((char *) a[0], a[1]);
553       break;
554       
555     case 43:
556       a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]);
557 #if 0
558       cpu.gr[RET1] = times ((char *)a[0]);
559 #else
560       {
561         /* Give him simulated cycles for utime
562            and an instruction count for stime. */
563         struct tms
564         {
565           time_t tms_utime;
566           time_t tms_stime;
567           time_t tms_cutime;
568           time_t tms_cstime;
569         } t;
570
571         t.tms_utime = cpu.asregs.cycles;
572         t.tms_stime = cpu.asregs.insts;
573         t.tms_cutime = t.tms_utime;
574         t.tms_cstime = t.tms_stime;
575                             
576         memcpy ((struct tms *)(a[0]), &t, sizeof (t));
577                             
578         cpu.gr[RET1] = cpu.asregs.cycles;
579       }
580 #endif
581       break;
582       
583     case 69:
584       a[0] = (unsigned long) (cpu.gr[PARM1]);
585       cpu.gr[RET1] = int_sbrk (a[0]);
586       break;
587       
588     default:
589       if (issue_messages)
590         fprintf (stderr, "WARNING: sys call %d unimplemented\n", 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 5:  /* _open */
604     case 6:  /* _close */
605     case 10: /* _unlink */
606     case 19: /* _lseek */
607     case 43: /* _times */
608       cpu.gr [TRAPCODE] = what;
609       handle_trap1 ();
610       break;
611       
612     default:
613       if (issue_messages)
614         fprintf (stderr, "Unhandled stub opcode: %d\n", what);
615       break;
616     }
617 }
618
619 static void
620 util (what)
621      unsigned what;
622 {
623   switch (what)
624     {
625     case 0:     /* exit */
626       cpu.asregs.exception = SIGQUIT;
627       break;
628
629     case 1:     /* printf */
630       {
631         unsigned long a[6];
632         unsigned char *s;
633         int i;
634
635         a[0] = (unsigned long)(cpu.mem + cpu.gr[PARM1]);
636
637         for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++)
638           {
639             if (*s == '%')
640               {
641                 if (*++s == 's')
642                   a[i] = (unsigned long)(cpu.mem + cpu.gr[PARM1+i]);
643                 else
644                   a[i] = cpu.gr[i+PARM1];
645                 i++;
646               }
647           }
648         
649         cpu.gr[RET1] = printf ((char *)a[0], a[1], a[2], a[3], a[4], a[5]);
650       }
651       break;
652       
653     case 2:     /* scanf */
654       if (issue_messages)
655         fprintf (stderr, "WARNING: scanf unimplemented\n");
656       break;
657       
658     case 3:     /* utime */
659       cpu.gr[RET1] = cpu.asregs.insts;
660       break;
661
662     case 0xFF:
663       process_stub (what);
664       break;
665       
666     default:
667       if (issue_messages)
668         fprintf (stderr, "Unhandled util code: %x\n", what);
669       break;
670     }
671 }       
672
673 /* For figuring out whether we carried; addc/subc use this. */
674 static int
675 iu_carry (a, b, cin)
676      unsigned long a;
677      unsigned long b;
678      int cin;
679 {
680   unsigned long x;
681   
682   x = (a & 0xffff) + (b & 0xffff) + cin;
683   x = (x >> 16) + (a >> 16) + (b >> 16);
684   x >>= 16;
685
686   return (x != 0);
687 }
688
689 #define WATCHFUNCTIONS 1
690 #ifdef WATCHFUNCTIONS
691
692 #define MAXWL 80
693 word WL[MAXWL];
694 char * WLstr[MAXWL];
695
696 int ENDWL=0;
697 int WLincyc;
698 int WLcyc[MAXWL];
699 int WLcnts[MAXWL];
700 int WLmax[MAXWL];
701 int WLmin[MAXWL];
702 word WLendpc;
703 int WLbcyc;
704 int WLW;
705 #endif
706
707 #define RD      (inst        & 0xF)
708 #define RS      ((inst >> 4) & 0xF)
709 #define RX      ((inst >> 8) & 0xF)
710 #define IMM5    ((inst >> 4) & 0x1F)
711 #define IMM4    ((inst) & 0xF)
712
713 static int tracing = 0;
714
715 void
716 sim_resume (sd, step, siggnal)
717      SIM_DESC sd;
718      int step, siggnal;
719 {
720   int needfetch;
721   word ibuf;
722   word pc;
723   unsigned short inst;
724   void (* sigsave)();
725   int memops;
726   int bonus_cycles;
727   int insts;
728   int w;
729   int cycs;
730   word WLhash;
731
732   sigsave = signal (SIGINT, interrupt);
733   cpu.asregs.exception = step ? SIGTRAP: 0;
734   pc = cpu.asregs.pc;
735
736   /* fetch the initial instructions that we'll decode */
737   ibuf = rlat (pc & 0xFFFFFFFC);
738   needfetch = 0;
739
740   memops = 0;
741   bonus_cycles = 0;
742   insts = 0;
743   
744   /* make our register set point to the right place */
745   if (SR_AF ())
746     cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
747   else
748     cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
749   
750   /* make a hash to speed exec loop, hope it's nonzero */
751   WLhash = 0xFFFFFFFF;
752
753   for (w = 1; w <= ENDWL; w++)
754     WLhash = WLhash & WL[w];
755
756   do
757     {
758       insts ++;
759       
760       if (pc & 02)
761         {
762           inst = ibuf & 0xFFFF;
763           needfetch = 1;
764         }
765       else
766         {
767           inst = ibuf >> 16;
768         }
769
770 #ifdef WATCHFUNCTIONS
771       /* now scan list of watch addresses, if match, count it and
772          note return address and count cycles until pc=return address */
773       
774       if ((WLincyc == 1) && (pc == WLendpc))
775         {
776           cycs = (cpu.asregs.cycles + (insts + bonus_cycles +
777                                        (memops * memcycles)) - WLbcyc);
778           
779           if (WLcnts[WLW] == 1)
780             {
781               WLmax[WLW] = cycs;
782               WLmin[WLW] = cycs;
783               WLcyc[WLW] = 0;
784             }
785           
786           if (cycs > WLmax[WLW])
787             {
788               WLmax[WLW] = cycs;
789             }
790           
791           if (cycs < WLmin[WLW])
792             {
793               WLmin[WLW] = cycs;
794             }
795           
796           WLcyc[WLW] += cycs;
797           WLincyc = 0;
798           WLendpc = 0;
799         } 
800
801       /* optimize with a hash to speed loop */
802       if (WLincyc == 0)
803         {
804           if ((WLhash == 0) || ((WLhash & pc) != 0))
805             {
806               for (w=1; w <= ENDWL; w++)
807                 {
808                   if (pc == WL[w])
809                     {
810                       WLcnts[w]++;
811                       WLbcyc = cpu.asregs.cycles + insts 
812                         + bonus_cycles + (memops * memcycles);
813                       WLendpc = cpu.gr[15];
814                       WLincyc = 1;
815                       WLW = w;
816                       break;
817                     }
818                 }
819             }
820         }
821 #endif
822
823       if (tracing)
824         fprintf (stderr, "%.4x: inst = %.4x ", pc, inst);
825  
826       pc += 2;
827       
828       switch (inst >> 8)
829         {
830         case 0x00:
831           switch RS
832             {
833             case 0x0:
834               switch RD
835                 {
836                 case 0x0:                               /* bkpt */
837                   cpu.asregs.exception = SIGTRAP;
838                   break;
839                   
840                 case 0x1:                               /* sync */
841                   break;
842                   
843                 case 0x2:                               /* rte */
844                   pc = cpu.epc;
845                   cpu.sr = cpu.esr;
846                   needfetch = 1;
847                   
848                   if (SR_AF())
849                     cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
850                   else
851                     cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
852                   break;
853
854                 case 0x3:                               /* rfi */
855                   pc = cpu.fpc;
856                   cpu.sr = cpu.fsr;
857                   needfetch = 1;
858
859                   if (SR_AF ())
860                     cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0];
861                   else
862                     cpu.asregs.active_gregs = &cpu.asregs.gregs[0];
863                   break;
864                   
865                 case 0x4:                               /* stop */
866                   if (issue_messages)
867                     fprintf (stderr, "WARNING: stop unimplemented\n");
868                   break;
869                     
870                 case 0x5:                               /* wait */
871                   if (issue_messages)
872                     fprintf (stderr, "WARNING: wait unimplemented\n");
873                   break;
874                     
875                 case 0x6:                               /* doze */
876                   if (issue_messages)
877                     fprintf (stderr, "WARNING: oze unimplemented\n");
878                   break;
879                     
880                 case 0x7:
881                   cpu.asregs.exception = SIGILL;        /* illegal */
882                   break;
883                     
884                 case 0x8:                               /* trap 0 */
885                 case 0xA:                               /* trap 2 */
886                 case 0xB:                               /* trap 3 */
887                   cpu.asregs.exception = SIGTRAP;
888                   break;
889                     
890                 case 0xC:                               /* trap 4 */
891                 case 0xD:                               /* trap 5 */
892                 case 0xE:                               /* trap 6 */
893                   cpu.asregs.exception = SIGILL;        /* illegal */
894                   break;
895                   
896                 case 0xF:                               /* trap 7 */
897                   cpu.asregs.exception = SIGTRAP;       /* integer div-by-0 */
898                   break;
899                     
900                 case 0x9:                               /* trap 1 */
901                   handle_trap1 ();
902                   break;
903                 }
904               break;
905               
906             case 0x1:
907               cpu.asregs.exception = SIGILL;            /* illegal */
908               break;
909               
910             case 0x2:                                   /* mvc */
911               cpu.gr[RD] = C_VALUE();
912               break;
913             case 0x3:                                   /* mvcv */
914               cpu.gr[RD] = C_OFF();
915               break;
916             case 0x4:                                   /* ldq */
917               {
918                 char *addr = (char *)cpu.gr[RD];
919                 int regno = 4;                  /* always r4-r7 */
920                 
921                 bonus_cycles++;
922                 memops += 4;
923                 do
924                   {
925                     cpu.gr[regno] = rlat(addr);
926                     addr += 4;
927                     regno++;
928                   }
929                 while ((regno&0x3) != 0);
930               }
931               break;
932             case 0x5:                                   /* stq */
933               {
934                 char *addr = (char *)cpu.gr[RD];
935                 int regno = 4;                  /* always r4-r7 */
936                 
937                 memops += 4;
938                 bonus_cycles++;
939                 do
940                   {
941                     wlat(addr, cpu.gr[regno]);
942                     addr += 4;
943                     regno++;
944                   }
945                 while ((regno & 0x3) != 0);
946               }
947               break;
948             case 0x6:                                   /* ldm */
949               {
950                 char *addr = (char *)cpu.gr[0];
951                 int regno = RD;
952                 
953                 /* bonus cycle is really only needed if
954                    the next insn shifts the last reg loaded.
955                    
956                    bonus_cycles++;
957                 */
958                 memops += 16-regno;
959                 while (regno <= 0xF)
960                   {
961                     cpu.gr[regno] = rlat(addr);
962                     addr += 4;
963                     regno++;
964                   }
965               }
966               break;
967             case 0x7:                                   /* stm */
968               {
969                 char *addr = (char *)cpu.gr[0];
970                 int regno = RD;
971                 
972                 /* this should be removed! */
973                 /*  bonus_cycles ++; */
974
975                 memops += 16 - regno;
976                 while (regno <= 0xF)
977                   {
978                     wlat(addr, cpu.gr[regno]);
979                     addr += 4;
980                     regno++;
981                   }
982               }
983               break;
984
985             case 0x8:                                   /* dect */
986               cpu.gr[RD] -= C_VALUE();
987               break;
988             case 0x9:                                   /* decf */
989               cpu.gr[RD] -= C_OFF();
990               break;
991             case 0xA:                                   /* inct */
992               cpu.gr[RD] += C_VALUE();
993               break;
994             case 0xB:                                   /* incf */
995               cpu.gr[RD] += C_OFF();
996               break;
997             case 0xC:                                   /* jmp */
998               pc = cpu.gr[RD];
999               bonus_cycles++;
1000               needfetch = 1;
1001               break;
1002             case 0xD:                                   /* jsr */
1003               cpu.gr[15] = pc;
1004               pc = cpu.gr[RD];
1005               bonus_cycles++;
1006               needfetch = 1;
1007               break;
1008             case 0xE:                                   /* ff1 */
1009               {
1010                 word tmp, i;
1011                 tmp = cpu.gr[RD];
1012                 for (i = 0; !(tmp & 0x80000000) && i < 32; i++)
1013                   tmp <<= 1;
1014                 cpu.gr[RD] = i;
1015               }
1016               break;
1017             case 0xF:                                   /* brev */
1018               {
1019                 word tmp;
1020                 tmp = cpu.gr[RD];
1021                 tmp = ((tmp & 0xaaaaaaaa) >>  1) | ((tmp & 0x55555555) <<  1);
1022                 tmp = ((tmp & 0xcccccccc) >>  2) | ((tmp & 0x33333333) <<  2);
1023                 tmp = ((tmp & 0xf0f0f0f0) >>  4) | ((tmp & 0x0f0f0f0f) <<  4);
1024                 tmp = ((tmp & 0xff00ff00) >>  8) | ((tmp & 0x00ff00ff) <<  8);
1025                 cpu.gr[RD] = ((tmp & 0xffff0000) >> 16) | ((tmp & 0x0000ffff) << 16);
1026               }
1027               break;
1028             }
1029           break;
1030         case 0x01:
1031           switch RS
1032             {
1033             case 0x0:                                   /* xtrb3 */     
1034               cpu.gr[1] = (cpu.gr[RD]) & 0xFF;
1035               NEW_C (cpu.gr[RD] != 0);
1036               break;
1037             case 0x1:                                   /* xtrb2 */
1038               cpu.gr[1] = (cpu.gr[RD]>>8) & 0xFF;
1039               NEW_C (cpu.gr[RD] != 0);
1040               break;
1041             case 0x2:                                   /* xtrb1 */
1042               cpu.gr[1] = (cpu.gr[RD]>>16) & 0xFF;
1043               NEW_C (cpu.gr[RD] != 0);
1044               break;
1045             case 0x3:                                   /* xtrb0 */
1046               cpu.gr[1] = (cpu.gr[RD]>>24) & 0xFF;
1047               NEW_C (cpu.gr[RD] != 0);
1048               break;
1049             case 0x4:                                   /* zextb */
1050               cpu.gr[RD] &= 0x000000FF;
1051               break;
1052             case 0x5:                                   /* sextb */
1053               {
1054                 long tmp;
1055                 tmp = cpu.gr[RD];
1056                 tmp <<= 24;
1057                 tmp >>= 24;
1058                 cpu.gr[RD] = tmp;
1059               }
1060               break;
1061             case 0x6:                                   /* zexth */
1062               cpu.gr[RD] &= 0x0000FFFF;
1063               break;
1064             case 0x7:                                   /* sexth */
1065               {
1066                 long tmp;
1067                 tmp = cpu.gr[RD];
1068                 tmp <<= 16;
1069                 tmp >>= 16;
1070                 cpu.gr[RD] = tmp;
1071               }
1072               break;
1073             case 0x8:                                   /* declt */ 
1074               --cpu.gr[RD];
1075               NEW_C ((long)cpu.gr[RD] < 0);
1076               break;
1077             case 0x9:                                   /* tstnbz */
1078               {
1079                 word tmp = cpu.gr[RD];
1080                 NEW_C ((tmp & 0xFF000000) != 0 &&
1081                        (tmp & 0x00FF0000) != 0 && (tmp & 0x0000FF00) != 0 &&
1082                        (tmp & 0x000000FF) != 0);
1083               }
1084               break; 
1085             case 0xA:                                   /* decgt */
1086               --cpu.gr[RD];
1087               NEW_C ((long)cpu.gr[RD] > 0);
1088               break;
1089             case 0xB:                                   /* decne */
1090               --cpu.gr[RD];
1091               NEW_C ((long)cpu.gr[RD] != 0);
1092               break;
1093             case 0xC:                                   /* clrt */
1094               if (C_ON())
1095                 cpu.gr[RD] = 0;
1096               break;
1097             case 0xD:                                   /* clrf */
1098               if (C_OFF())
1099                 cpu.gr[RD] = 0;
1100               break;
1101             case 0xE:                                   /* abs */
1102               if (cpu.gr[RD] & 0x80000000)
1103                 cpu.gr[RD] = ~cpu.gr[RD] + 1;
1104               break;
1105             case 0xF:                                   /* not */
1106               cpu.gr[RD] = ~cpu.gr[RD];
1107               break;
1108             }
1109           break;
1110         case 0x02:                                      /* movt */
1111           if (C_ON())
1112             cpu.gr[RD] = cpu.gr[RS];
1113           break;
1114         case 0x03:                                      /* mult */
1115           /* consume 2 bits per cycle from rs, until rs is 0 */
1116           {
1117             unsigned int t = cpu.gr[RS];
1118             int ticks;
1119             for (ticks = 0; t != 0 ; t >>= 2) 
1120               ticks++;
1121             bonus_cycles += ticks;
1122           }
1123           bonus_cycles += 2;  /* min. is 3, so add 2, plus ticks above */
1124           cpu.gr[RD] = cpu.gr[RD] * cpu.gr[RS];
1125           break;
1126         case 0x04:                                      /* loopt */
1127           if (C_ON())
1128             {
1129               pc += (IMM4 << 1) - 32;
1130               bonus_cycles ++;
1131               needfetch = 1;
1132             }
1133           --cpu.gr[RS];                         /* not RD! */
1134           NEW_C (((long)cpu.gr[RS]) > 0);
1135           break; 
1136         case 0x05:                                      /* subu */
1137           cpu.gr[RD] -= cpu.gr[RS];
1138           break;
1139         case 0x06:                                      /* addc */
1140           {
1141             unsigned long tmp, a, b;
1142             a = cpu.gr[RD];
1143             b = cpu.gr[RS];
1144             cpu.gr[RD] = a + b + C_VALUE ();
1145             tmp = iu_carry (a, b, C_VALUE ());
1146             NEW_C (tmp);
1147           }
1148           break;
1149         case 0x07:                                      /* subc */
1150           {
1151             unsigned long tmp, a, b;
1152             a = cpu.gr[RD];
1153             b = cpu.gr[RS];
1154             cpu.gr[RD] = a - b + C_VALUE () - 1;
1155             tmp = iu_carry (a,~b, C_VALUE ());
1156             NEW_C (tmp);
1157           }
1158           break;
1159         case 0x08:                                      /* illegal */
1160         case 0x09:                                      /* illegal*/
1161           cpu.asregs.exception = SIGILL;
1162           break;
1163         case 0x0A:                                      /* movf */
1164           if (C_OFF())
1165             cpu.gr[RD] = cpu.gr[RS];
1166           break;
1167         case 0x0B:                                      /* lsr */
1168           { 
1169             unsigned long dst, src;
1170             dst = cpu.gr[RD];
1171             src = cpu.gr[RS];
1172             dst = dst >> src;   
1173             cpu.gr[RD] = dst;
1174           }
1175           break;
1176         case 0x0C:                                      /* cmphs */
1177           NEW_C ((unsigned long )cpu.gr[RD] >= 
1178                  (unsigned long)cpu.gr[RS]);
1179           break;
1180         case 0x0D:                                      /* cmplt */
1181           NEW_C ((long)cpu.gr[RD] < (long)cpu.gr[RS]);
1182           break;
1183         case 0x0E:                                      /* tst */
1184           NEW_C ((cpu.gr[RD] & cpu.gr[RS]) != 0);
1185           break;
1186         case 0x0F:                                      /* cmpne */
1187           NEW_C (cpu.gr[RD] != cpu.gr[RS]);
1188           break;
1189         case 0x10: case 0x11:                           /* mfcr */
1190           {
1191             unsigned r;
1192             r = IMM5;
1193             if (r <= LAST_VALID_CREG)
1194               cpu.gr[RD] = cpu.cr[r];
1195             else
1196               cpu.asregs.exception = SIGILL;
1197           }
1198           break;
1199
1200         case 0x12:                                      /* mov */
1201           cpu.gr[RD] = cpu.gr[RS];
1202           break;
1203
1204         case 0x13:                                      /* bgenr */
1205           if (cpu.gr[RS] & 0x20)
1206             cpu.gr[RD] = 0;
1207           else
1208             cpu.gr[RD] = 1 << (cpu.gr[RS] & 0x1F);
1209           break;
1210
1211         case 0x14:                                      /* rsub */
1212           cpu.gr[RD] = cpu.gr[RS] - cpu.gr[RD];
1213           break;
1214
1215         case 0x15:                                      /* ixw */
1216           cpu.gr[RD] += cpu.gr[RS]<<2;
1217           break;
1218
1219         case 0x16:                                      /* and */
1220           cpu.gr[RD] &= cpu.gr[RS];
1221           break;
1222
1223         case 0x17:                                      /* xor */
1224           cpu.gr[RD] ^= cpu.gr[RS];
1225           break;
1226
1227         case 0x18: case 0x19:                           /* mtcr */
1228           {
1229             unsigned r;
1230             r = IMM5;
1231             if (r <= LAST_VALID_CREG)
1232               cpu.cr[r] = cpu.gr[RD];
1233             else
1234               cpu.asregs.exception = SIGILL;
1235             
1236             /* we might have changed register sets... */
1237             if (SR_AF ())
1238               cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0];
1239             else
1240               cpu.asregs.active_gregs = & cpu.asregs.gregs[0];
1241           }
1242           break;
1243
1244         case 0x1A:                                      /* asr */
1245           cpu.gr[RD] = (long)cpu.gr[RD] >> cpu.gr[RS];
1246           break;
1247
1248         case 0x1B:                                      /* lsl */
1249           cpu.gr[RD] = cpu.gr[RD] << cpu.gr[RS];
1250           break;
1251
1252         case 0x1C:                                      /* addu */
1253           cpu.gr[RD] += cpu.gr[RS];
1254           break;
1255
1256         case 0x1D:                                      /* ixh */
1257           cpu.gr[RD] += cpu.gr[RS] << 1;
1258           break;
1259
1260         case 0x1E:                                      /* or */
1261           cpu.gr[RD] |= cpu.gr[RS];
1262           break;
1263
1264         case 0x1F:                                      /* andn */
1265           cpu.gr[RD] &= ~cpu.gr[RS];
1266           break;
1267         case 0x20: case 0x21:                           /* addi */
1268           cpu.gr[RD] =
1269             cpu.gr[RD] + (IMM5 + 1);
1270           break;
1271         case 0x22: case 0x23:                           /* cmplti */
1272           {
1273             int tmp = (IMM5 + 1);
1274             if (cpu.gr[RD] < tmp)
1275               {
1276                 SET_C();
1277               }
1278             else
1279               {
1280                 CLR_C();
1281               }
1282           }
1283           break;
1284         case 0x24: case 0x25:                           /* subi */
1285           cpu.gr[RD] =
1286             cpu.gr[RD] - (IMM5 + 1);
1287           break;
1288         case 0x26: case 0x27:                           /* illegal */
1289           cpu.asregs.exception = SIGILL;
1290           break;
1291         case 0x28: case 0x29:                           /* rsubi */
1292           cpu.gr[RD] =
1293             IMM5 - cpu.gr[RD];
1294           break;
1295         case 0x2A: case 0x2B:                           /* cmpnei */
1296           if (cpu.gr[RD] != IMM5)
1297             {
1298               SET_C();
1299             }
1300           else
1301             {
1302               CLR_C();
1303             }
1304           break;
1305           
1306         case 0x2C: case 0x2D:                           /* bmaski, divu */
1307           {
1308             unsigned imm = IMM5;
1309             
1310             if (imm == 1)
1311               {
1312                 int exe;
1313                 int rxnlz, r1nlz;
1314                 unsigned int rx, r1;
1315
1316                 rx = cpu.gr[RD];
1317                 r1 = cpu.gr[1];
1318                 exe = 0;
1319
1320                 /* unsigned divide */
1321                 cpu.gr[RD] = (word) ((unsigned int) cpu.gr[RD] / (unsigned int)cpu.gr[1] );
1322                 
1323                 /* compute bonus_cycles for divu */
1324                 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32); r1nlz ++)
1325                   r1 = r1 << 1;
1326
1327                 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32); rxnlz ++)
1328                   rx = rx << 1;
1329
1330                 if (r1nlz < rxnlz)
1331                   exe += 4;
1332                 else
1333                   exe += 5 + r1nlz - rxnlz;
1334
1335                 if (exe >= (2 * memcycles - 1))
1336                   {
1337                     bonus_cycles += exe - (2 * memcycles) + 1;
1338                   }
1339               }
1340             else if (imm == 0 || imm >= 8)
1341               {
1342                 /* bmaski */
1343                 if (imm == 0)
1344                   cpu.gr[RD] = -1;
1345                 else
1346                   cpu.gr[RD] = (1 << imm) - 1;
1347               }
1348             else
1349               {
1350                 /* illegal */
1351                 cpu.asregs.exception = SIGILL;
1352               }
1353           }
1354           break;
1355         case 0x2E: case 0x2F:                           /* andi */
1356           cpu.gr[RD] = cpu.gr[RD] & IMM5;
1357           break;
1358         case 0x30: case 0x31:                           /* bclri */
1359           cpu.gr[RD] = cpu.gr[RD] & ~(1<<IMM5);
1360           break;
1361         case 0x32: case 0x33:                           /* bgeni, divs */
1362           {
1363             unsigned imm = IMM5;
1364             if (imm == 1)
1365               {
1366                 int exe,sc;
1367                 int rxnlz, r1nlz;
1368                 signed int rx, r1;
1369                 
1370                 /* compute bonus_cycles for divu */
1371                 rx = cpu.gr[RD];
1372                 r1 = cpu.gr[1];
1373                 exe = 0;
1374                 
1375                 if (((rx < 0) && (r1 > 0)) || ((rx >= 0) && (r1 < 0)))
1376                   sc = 1;
1377                 else
1378                   sc = 0;
1379                 
1380                 rx = abs (rx);
1381                 r1 = abs (r1);
1382                 
1383                 /* signed divide, general registers are of type int, so / op is OK */
1384                 cpu.gr[RD] = cpu.gr[RD] / cpu.gr[1];
1385               
1386                 for (r1nlz = 0; ((r1 & 0x80000000) == 0) && (r1nlz < 32) ; r1nlz ++ )
1387                   r1 = r1 << 1;
1388                 
1389                 for (rxnlz = 0; ((rx & 0x80000000) == 0) && (rxnlz < 32) ; rxnlz ++ )
1390                   rx = rx << 1;
1391                 
1392                 if (r1nlz < rxnlz)
1393                   exe += 5;
1394                 else
1395                   exe += 6 + r1nlz - rxnlz + sc;
1396                 
1397                 if (exe >= (2 * memcycles - 1))
1398                   {
1399                     bonus_cycles += exe - (2 * memcycles) + 1;
1400                   }
1401               }
1402             else if (imm >= 7)
1403               {
1404                 /* bgeni */
1405                 cpu.gr[RD] = (1 << IMM5);
1406               }
1407             else
1408               {
1409                 /* illegal */
1410                 cpu.asregs.exception = SIGILL;
1411               }
1412             break;
1413           }
1414         case 0x34: case 0x35:                           /* bseti */
1415           cpu.gr[RD] = cpu.gr[RD] | (1 << IMM5);
1416           break;
1417         case 0x36: case 0x37:                           /* btsti */
1418           NEW_C (cpu.gr[RD] >> IMM5);
1419           break;
1420         case 0x38: case 0x39:                           /* xsr, rotli */
1421           {
1422             unsigned imm = IMM5;
1423             unsigned long tmp = cpu.gr[RD];
1424             if (imm == 0)
1425               {
1426                 word cbit;
1427                 cbit = C_VALUE();
1428                 NEW_C (tmp);
1429                 cpu.gr[RD] = (cbit << 31) | (tmp >> 1);
1430               }
1431             else
1432               cpu.gr[RD] = (tmp << imm) | (tmp >> (32 - imm));
1433           }
1434           break;
1435         case 0x3A: case 0x3B:                           /* asrc, asri */
1436           {
1437             unsigned imm = IMM5;
1438             long tmp = cpu.gr[RD];
1439             if (imm == 0)
1440               {
1441                 NEW_C (tmp);
1442                 cpu.gr[RD] = tmp >> 1;
1443               }
1444             else
1445               cpu.gr[RD] = tmp >> imm;
1446           }
1447           break;
1448         case 0x3C: case 0x3D:                           /* lslc, lsli */
1449           {
1450             unsigned imm = IMM5;
1451             unsigned long tmp = cpu.gr[RD];
1452             if (imm == 0)
1453               {
1454                 NEW_C (tmp >> 31);
1455                 cpu.gr[RD] = tmp << 1;
1456               }
1457             else
1458               cpu.gr[RD] = tmp << imm;
1459           }
1460           break;
1461         case 0x3E: case 0x3F:                           /* lsrc, lsri */
1462           {
1463             unsigned imm = IMM5;
1464             unsigned long tmp = cpu.gr[RD];
1465             if (imm == 0)
1466               {
1467                 NEW_C (tmp);
1468                 cpu.gr[RD] = tmp >> 1;
1469               }
1470             else
1471               cpu.gr[RD] = tmp >> imm;
1472           }
1473           break;
1474         case 0x40: case 0x41: case 0x42: case 0x43:
1475         case 0x44: case 0x45: case 0x46: case 0x47:
1476         case 0x48: case 0x49: case 0x4A: case 0x4B:
1477         case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1478           cpu.asregs.exception = SIGILL;
1479           break;
1480         case 0x50:
1481           util (inst & 0xFF); 
1482           break;
1483         case 0x51: case 0x52: case 0x53:
1484         case 0x54: case 0x55: case 0x56: case 0x57:
1485         case 0x58: case 0x59: case 0x5A: case 0x5B:
1486         case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1487           cpu.asregs.exception = SIGILL;
1488           break;
1489         case 0x60: case 0x61: case 0x62: case 0x63:     /* movi  */
1490         case 0x64: case 0x65: case 0x66: case 0x67:
1491           cpu.gr[RD] = (inst >> 4) & 0x7F;
1492           break;
1493         case 0x68: case 0x69: case 0x6A: case 0x6B:
1494         case 0x6C: case 0x6D: case 0x6E: case 0x6F:     /* illegal */
1495           cpu.asregs.exception = SIGILL;
1496           break;
1497         case 0x71: case 0x72: case 0x73:
1498         case 0x74: case 0x75: case 0x76: case 0x77:
1499         case 0x78: case 0x79: case 0x7A: case 0x7B:
1500         case 0x7C: case 0x7D: case 0x7E:                /* lrw */
1501           cpu.gr[RX] =  rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1502           if (tracing)
1503             fprintf (stderr, "LRW of 0x%x from 0x%x to reg %d",
1504                      rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC),
1505                      (pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC, RX);
1506           memops++;
1507           break;
1508         case 0x7F:                                      /* jsri */
1509           cpu.gr[15] = pc;
1510         case 0x70:                                      /* jmpi */
1511           pc = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
1512           memops++;
1513           bonus_cycles++;
1514           needfetch = 1;
1515           break;
1516
1517         case 0x80: case 0x81: case 0x82: case 0x83:
1518         case 0x84: case 0x85: case 0x86: case 0x87:
1519         case 0x88: case 0x89: case 0x8A: case 0x8B:
1520         case 0x8C: case 0x8D: case 0x8E: case 0x8F:     /* ld */
1521           cpu.gr[RX] = rlat (cpu.gr[RD] + ((inst >> 2) & 0x003C));
1522           if (tracing)
1523             fprintf (stderr, "load reg %d from 0x%x with 0x%x",
1524                      RX,
1525                      cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1526           memops++;
1527           break;
1528         case 0x90: case 0x91: case 0x92: case 0x93:
1529         case 0x94: case 0x95: case 0x96: case 0x97:
1530         case 0x98: case 0x99: case 0x9A: case 0x9B:
1531         case 0x9C: case 0x9D: case 0x9E: case 0x9F:     /* st */
1532           wlat (cpu.gr[RD] + ((inst >> 2) & 0x003C), cpu.gr[RX]);
1533           if (tracing)
1534             fprintf (stderr, "store reg %d (containing 0x%x) to 0x%x",
1535                      RX, cpu.gr[RX],
1536                      cpu.gr[RD] + ((inst >> 2) & 0x003C));
1537           memops++;
1538           break;
1539         case 0xA0: case 0xA1: case 0xA2: case 0xA3:
1540         case 0xA4: case 0xA5: case 0xA6: case 0xA7:
1541         case 0xA8: case 0xA9: case 0xAA: case 0xAB:
1542         case 0xAC: case 0xAD: case 0xAE: case 0xAF:     /* ld.b */
1543           cpu.gr[RX] = rbat (cpu.gr[RD] + RS);
1544           memops++;
1545           break;
1546         case 0xB0: case 0xB1: case 0xB2: case 0xB3:
1547         case 0xB4: case 0xB5: case 0xB6: case 0xB7:
1548         case 0xB8: case 0xB9: case 0xBA: case 0xBB:
1549         case 0xBC: case 0xBD: case 0xBE: case 0xBF:     /* st.b */
1550           wbat (cpu.gr[RD] + RS, cpu.gr[RX]);
1551           memops++;
1552           break;
1553         case 0xC0: case 0xC1: case 0xC2: case 0xC3:
1554         case 0xC4: case 0xC5: case 0xC6: case 0xC7:
1555         case 0xC8: case 0xC9: case 0xCA: case 0xCB:
1556         case 0xCC: case 0xCD: case 0xCE: case 0xCF:     /* ld.h */
1557           cpu.gr[RX] = rhat (cpu.gr[RD] + ((inst >> 3) & 0x001E));
1558           memops++;
1559           break;
1560         case 0xD0: case 0xD1: case 0xD2: case 0xD3:
1561         case 0xD4: case 0xD5: case 0xD6: case 0xD7:
1562         case 0xD8: case 0xD9: case 0xDA: case 0xDB:
1563         case 0xDC: case 0xDD: case 0xDE: case 0xDF:     /* st.h */
1564           what (cpu.gr[RD] + ((inst >> 3) & 0x001E), cpu.gr[RX]);
1565           memops++;
1566           break;
1567         case 0xE8: case 0xE9: case 0xEA: case 0xEB:
1568         case 0xEC: case 0xED: case 0xEE: case 0xEF:     /* bf */        
1569           if (C_OFF())
1570             {
1571               int disp;
1572               disp = inst & 0x03FF;
1573               if (inst & 0x0400)
1574                 disp |= 0xFFFFFC00;
1575               pc += disp<<1;
1576               bonus_cycles++;
1577               needfetch = 1;
1578             }
1579           break;
1580         case 0xE0: case 0xE1: case 0xE2: case 0xE3:
1581         case 0xE4: case 0xE5: case 0xE6: case 0xE7:     /* bt */
1582           if (C_ON())
1583             {
1584               int disp;
1585               disp = inst & 0x03FF;
1586               if (inst & 0x0400)
1587                 disp |= 0xFFFFFC00;
1588               pc += disp<<1;
1589               bonus_cycles++;
1590               needfetch = 1;
1591             }
1592           break;
1593
1594         case 0xF8: case 0xF9: case 0xFA: case 0xFB:
1595         case 0xFC: case 0xFD: case 0xFE: case 0xFF:     /* bsr */       
1596           cpu.gr[15] = pc;
1597         case 0xF0: case 0xF1: case 0xF2: case 0xF3:
1598         case 0xF4: case 0xF5: case 0xF6: case 0xF7:     /* br */
1599           {
1600             int disp;
1601             disp = inst & 0x03FF;
1602             if (inst & 0x0400)
1603               disp |= 0xFFFFFC00;
1604             pc += disp<<1;
1605             bonus_cycles++;
1606             needfetch = 1;
1607           }
1608           break;
1609
1610         }
1611
1612       if (tracing)
1613         fprintf (stderr, "\n");
1614       
1615       if (needfetch)   
1616         {
1617           /* Do not let him fetch from a bad address! */
1618           if (((uword)pc) >= cpu.asregs.msize)
1619             {
1620               if (issue_messages)
1621                 fprintf (stderr, "PC outside of available memory! (%x)\n", pc);
1622               
1623               cpu.asregs.exception = SIGSEGV;
1624             }
1625           else
1626             {
1627               ibuf = rlat (pc & 0xFFFFFFFC);
1628               needfetch = 0;
1629             }
1630         }
1631     }
1632   while (!cpu.asregs.exception);
1633
1634   /* Hide away the things we've cached while executing.  */
1635   cpu.asregs.pc = pc;
1636   cpu.asregs.insts += insts;            /* instructions done ... */
1637   cpu.asregs.cycles += insts;           /* and each takes a cycle */
1638   cpu.asregs.cycles += bonus_cycles;    /* and extra cycles for branches */
1639   cpu.asregs.cycles += memops * memcycles;      /* and memop cycle delays */
1640   
1641   signal (SIGINT, sigsave);
1642 }
1643
1644
1645 int
1646 sim_write (sd, addr, buffer, size)
1647      SIM_DESC sd;
1648      SIM_ADDR addr;
1649      unsigned char * buffer;
1650      int size;
1651 {
1652   int i;
1653   init_pointers ();
1654   
1655   memcpy (& cpu.mem[addr], buffer, size);
1656   
1657   return size;
1658 }
1659
1660 int
1661 sim_read (sd, addr, buffer, size)
1662      SIM_DESC sd;
1663      SIM_ADDR addr;
1664      unsigned char * buffer;
1665      int size;
1666 {
1667   int i;
1668   init_pointers ();
1669   
1670   memcpy (buffer, & cpu.mem[addr], size);
1671   
1672   return size;
1673 }
1674
1675
1676 int
1677 sim_store_register (sd, rn, memory, length)
1678      SIM_DESC sd;
1679      int rn;
1680      unsigned char * memory;
1681      int length;
1682 {
1683   init_pointers ();
1684
1685   if (rn < NUM_MCORE_REGS && rn >= 0)
1686     {
1687       if (length == 4)
1688         {
1689           /* ival is in 'target' order, which we know to be big-endian.
1690              Let's convert it to natural order.  */
1691           long ival;
1692
1693           ival = mcore_extract_unsigned_integer (memory, 4);/* misalignment safe */
1694           cpu.asints[rn] = ival;
1695         }
1696
1697       return 4;
1698     }
1699   else
1700     return 0;
1701 }
1702
1703 int
1704 sim_fetch_register (sd, rn, memory, length)
1705      SIM_DESC sd;
1706      int rn;
1707      unsigned char * memory;
1708      int length;
1709 {
1710   init_pointers ();
1711   
1712   if (rn < NUM_MCORE_REGS && rn >= 0)
1713     {
1714       if (length == 4)
1715         {
1716           /* caller expects 'target order', which is big-endian. Convert
1717            * the native order we used [to speed up simulation] to the
1718            * byte order expected by the caller.  */
1719           long ival = cpu.asints[rn];
1720           mcore_store_unsigned_integer (memory, 4, ival);/* misalignment-safe */
1721         }
1722       
1723       return 4;
1724     }
1725   else
1726     return 0;
1727 }
1728
1729
1730 int
1731 sim_trace (sd)
1732      SIM_DESC sd;
1733 {
1734   tracing = 1;
1735   
1736   sim_resume (sd, 0, 0);
1737
1738   tracing = 0;
1739   
1740   return 1;
1741 }
1742
1743 void
1744 sim_stop_reason (sd, reason, sigrc)
1745      SIM_DESC sd;
1746      enum sim_stop * reason;
1747      int * sigrc;
1748 {
1749   if (cpu.asregs.exception == SIGQUIT)
1750     {
1751       * reason = sim_exited;
1752       * sigrc = cpu.gr[PARM1];
1753     }
1754   else
1755     {
1756       * reason = sim_stopped;
1757       * sigrc = cpu.asregs.exception;
1758     }
1759 }
1760
1761
1762 int
1763 sim_stop (sd)
1764      SIM_DESC sd;
1765 {
1766   cpu.asregs.exception = SIGINT;
1767   return 1;
1768 }
1769
1770
1771 void
1772 sim_info (sd, verbose)
1773      SIM_DESC sd;
1774      int verbose;
1775 {
1776 #ifdef WATCHFUNCTIONS
1777   int w, wcyc;
1778 #endif
1779   double virttime = cpu.asregs.cycles / 36.0e6;
1780
1781   callback->printf_filtered (callback, "\n\n# instructions executed  %10d\n", cpu.asregs.insts);
1782   callback->printf_filtered (callback, "# cycles                 %10d\n", cpu.asregs.cycles);
1783   callback->printf_filtered (callback, "# pipeline stalls        %10d\n", cpu.asregs.stalls);
1784   callback->printf_filtered (callback, "# virtual time taken     %10.4f\n", virttime);
1785
1786 #ifdef WATCHFUNCTIONS
1787   callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",ENDWL);
1788
1789   wcyc = 0;
1790   
1791   for (w = 1; w <= ENDWL; w++)
1792     {
1793       callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
1794       callback->printf_filtered (callback, "  calls = %d, cycles = %d\n", WLcnts[w],WLcyc[w]);
1795       
1796       if (WLcnts[w] != 0)
1797         callback->printf_filtered (callback, "  maxcpc = %d, mincpc = %d, avecpc = %d\n",WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
1798       wcyc += WLcyc[w];
1799     }
1800   
1801   callback->printf_filtered (callback, "Total cycles for watched functions: %d\n",wcyc);
1802 #endif
1803 }
1804
1805 struct  aout
1806 {
1807   unsigned char  sa_machtype[2];
1808   unsigned char  sa_magic[2];
1809   unsigned char  sa_tsize[4];
1810   unsigned char  sa_dsize[4];
1811   unsigned char  sa_bsize[4];
1812   unsigned char  sa_syms[4];
1813   unsigned char  sa_entry[4];
1814   unsigned char  sa_trelo[4];
1815   unsigned char  sa_drelo[4];
1816 } aout;
1817
1818 #define LONG(x)         (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
1819 #define SHORT(x)        (((x)[0]<<8)|(x)[1])
1820
1821 SIM_DESC
1822 sim_open (kind, cb, abfd, argv)
1823      SIM_OPEN_KIND kind;
1824      host_callback * cb;
1825      struct _bfd * abfd;
1826      char ** argv;
1827 {
1828   int osize = sim_memory_size;
1829   myname = argv[0];
1830   callback = cb;
1831   
1832   if (kind == SIM_OPEN_STANDALONE)
1833     issue_messages = 1;
1834   
1835   /* Discard and reacquire memory -- start with a clean slate.  */
1836   sim_size (1);         /* small */
1837   sim_size (osize);     /* and back again */
1838
1839   set_initial_gprs ();  /* Reset the GPR registers.  */
1840   
1841   /* Fudge our descriptor for now.  */
1842   return (SIM_DESC) 1;
1843 }
1844
1845 void
1846 sim_close (sd, quitting)
1847      SIM_DESC sd;
1848      int quitting;
1849 {
1850   /* nothing to do */
1851 }
1852
1853 SIM_RC
1854 sim_load (sd, prog, abfd, from_tty)
1855      SIM_DESC sd;
1856      char * prog;
1857      bfd * abfd;
1858      int from_tty;
1859 {
1860   /* Do the right thing for ELF executables; this turns out to be
1861      just about the right thing for any object format that:
1862        - we crack using BFD routines
1863        - follows the traditional UNIX text/data/bss layout
1864        - calls the bss section ".bss".   */
1865
1866   extern bfd * sim_load_file (); /* ??? Don't know where this should live.  */
1867   bfd * prog_bfd;
1868
1869   {
1870     bfd * handle;
1871     asection * s_bss;
1872     handle = bfd_openr (prog, 0);       /* could be "mcore" */
1873     
1874     if (!handle)
1875       {
1876         printf("``%s'' could not be opened.\n", prog);
1877         return SIM_RC_FAIL;
1878       }
1879     
1880     /* Makes sure that we have an object file, also cleans gets the 
1881        section headers in place.  */
1882     if (!bfd_check_format (handle, bfd_object))
1883       {
1884         /* wasn't an object file */
1885         bfd_close (handle);
1886         printf ("``%s'' is not appropriate object file.\n", prog);
1887         return SIM_RC_FAIL;
1888       }
1889     
1890     /* Look for that bss section.  */
1891     s_bss = bfd_get_section_by_name (handle, ".bss");
1892     
1893     if (!s_bss)
1894       {
1895         printf("``%s'' has no bss section.\n", prog);
1896         return SIM_RC_FAIL;
1897       }
1898
1899     /* Appropriately paranoid would check that we have
1900        a traditional text/data/bss ordering within memory.  */
1901
1902     /* figure the end of the bss section */
1903 #if 0
1904     printf ("bss section at 0x%08x for 0x%08x bytes\n",
1905         (unsigned long) s_bss->vma , (unsigned long) s_bss->_cooked_size);
1906 #endif
1907     heap_ptr = (unsigned long) s_bss->vma + (unsigned long) s_bss->_cooked_size;
1908
1909     /* Clean up after ourselves.  */
1910     bfd_close (handle);
1911     
1912     /* XXX: do we need to free the s_bss and handle structures? */
1913   }
1914
1915   /* from sh -- dac */
1916   prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
1917                             sim_kind == SIM_OPEN_DEBUG,
1918                             0, sim_write);
1919   if (prog_bfd == NULL)
1920     return SIM_RC_FAIL;
1921   
1922   if (abfd == NULL)
1923     bfd_close (prog_bfd);
1924
1925   return SIM_RC_OK;
1926 }
1927
1928 SIM_RC
1929 sim_create_inferior (sd, prog_bfd, argv, env)
1930      SIM_DESC sd;
1931      struct _bfd * prog_bfd;
1932      char ** argv;
1933      char ** env;
1934 {
1935   char ** avp;
1936   int nargs = 0;
1937   int nenv = 0;
1938   int s_length;
1939   int l;
1940   unsigned long strings;
1941   unsigned long pointers;
1942   unsigned long hi_stack;
1943
1944
1945   /* Set the initial register set.  */
1946   l = issue_messages;
1947   issue_messages = 0;
1948   set_initial_gprs ();
1949   issue_messages = l;
1950   
1951   hi_stack = cpu.asregs.msize - 4;
1952   cpu.asregs.pc = bfd_get_start_address (prog_bfd);
1953
1954   /* Calculate the argument and environment strings.  */
1955   s_length = 0;
1956   nargs = 0;
1957   avp = argv;
1958   while (avp && *avp)
1959     {
1960       l = strlen (*avp) + 1;    /* include the null */
1961       s_length += (l + 3) & ~3; /* make it a 4 byte boundary */
1962       nargs++; avp++;
1963     }
1964
1965   nenv = 0;
1966   avp = env;
1967   while (avp && *avp)
1968     {
1969       l = strlen (*avp) + 1;    /* include the null */
1970       s_length += (l + 3) & ~ 3;/* make it a 4 byte boundary */
1971       nenv++; avp++;
1972     }
1973
1974   /* Claim some memory for the pointers and strings. */
1975   pointers = hi_stack - sizeof(word) * (nenv+1+nargs+1);
1976   pointers &= ~3;               /* must be 4-byte aligned */
1977   cpu.gr[0] = pointers;
1978
1979   strings = cpu.gr[0] - s_length;
1980   strings &= ~3;                /* want to make it 4-byte aligned */
1981   cpu.gr[0] = strings;
1982   /* dac fix, the stack address must be 8-byte aligned! */
1983   cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8;
1984
1985   /* Loop through the arguments and fill them in.  */
1986   cpu.gr[PARM1] = nargs;
1987   if (nargs == 0)
1988     {
1989       /* No strings to fill in.  */
1990       cpu.gr[PARM2] = 0;
1991     }
1992   else
1993     {
1994       cpu.gr[PARM2] = pointers;
1995       avp = argv;
1996       while (avp && *avp)
1997         {
1998           /* Save where we're putting it.  */
1999           wlat (pointers, strings);
2000
2001           /* Copy the string.  */
2002           l = strlen (* avp) + 1;
2003           strcpy ((char *)(cpu.mem + strings), *avp);
2004
2005           /* Bump the pointers.  */
2006           avp++;
2007           pointers += 4;
2008           strings += l+1;
2009         }
2010       
2011       /* A null to finish the list.  */
2012       wlat (pointers, 0);
2013       pointers += 4;
2014     }
2015
2016   /* Now do the environment pointers.  */
2017   if (nenv == 0)
2018     {
2019       /* No strings to fill in.  */
2020       cpu.gr[PARM3] = 0;
2021     }
2022   else
2023     {
2024       cpu.gr[PARM3] = pointers;
2025       avp = env;
2026       
2027       while (avp && *avp)
2028         {
2029           /* Save where we're putting it.  */
2030           wlat (pointers, strings);
2031
2032           /* Copy the string.  */
2033           l = strlen (* avp) + 1;
2034           strcpy ((char *)(cpu.mem + strings), *avp);
2035
2036           /* Bump the pointers.  */
2037           avp++;
2038           pointers += 4;
2039           strings += l+1;
2040         }
2041       
2042       /* A null to finish the list.  */
2043       wlat (pointers, 0);
2044       pointers += 4;
2045     }
2046   
2047   return SIM_RC_OK;
2048 }
2049
2050 void
2051 sim_kill (sd)
2052      SIM_DESC sd;
2053 {
2054   /* nothing to do */
2055 }
2056
2057 void
2058 sim_do_command (sd, cmd)
2059      SIM_DESC sd;
2060      char * cmd;
2061 {
2062   /* Nothing there yet; it's all an error.  */
2063   
2064   if (cmd != NULL)
2065     {
2066       char ** simargv = buildargv (cmd);
2067       
2068       if (strcmp (simargv[0], "watch") == 0)
2069         {
2070           if ((simargv[1] == NULL) || (simargv[2] == NULL))
2071             {
2072               fprintf (stderr, "Error: missing argument to watch cmd.\n");
2073               return;
2074             }
2075           
2076           ENDWL++;
2077           
2078           WL[ENDWL] = strtol (simargv[2], NULL, 0);
2079           WLstr[ENDWL] = strdup (simargv[1]);
2080           fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
2081                    WL[ENDWL], ENDWL);
2082
2083         }
2084       else if (strcmp (simargv[0], "dumpmem") == 0)
2085         {
2086           unsigned char * p;
2087           FILE * dumpfile;
2088
2089           if (simargv[1] == NULL)
2090             fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
2091
2092           fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
2093           
2094           dumpfile = fopen (simargv[1], "w");
2095           p = cpu.mem;
2096           fwrite (p, cpu.asregs.msize-1, 1, dumpfile);
2097           fclose (dumpfile);
2098           
2099           fprintf (stderr, "done.\n");
2100         }
2101       else if (strcmp (simargv[0], "clearstats") == 0)
2102         {
2103           cpu.asregs.cycles = 0;
2104           cpu.asregs.insts = 0;
2105           cpu.asregs.stalls = 0;
2106           ENDWL = 0;
2107         }
2108       else if (strcmp (simargv[0], "verbose") == 0)
2109         {
2110           issue_messages = 2;
2111         }
2112       else
2113         {
2114           fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
2115                    cmd);
2116         }
2117     }
2118   else
2119     {
2120       fprintf (stderr, "M.CORE sim commands: \n");
2121       fprintf (stderr, "  watch <funcname> <addr>\n");
2122       fprintf (stderr, "  dumpmem <filename>\n");
2123       fprintf (stderr, "  clearstats\n");
2124       fprintf (stderr, "  verbose\n");
2125     }
2126 }
2127
2128 void
2129 sim_set_callbacks (ptr)
2130      host_callback * ptr;
2131 {
2132   callback = ptr; 
2133 }