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