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