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