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