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