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