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