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