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