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