1 /* Simulator for Xilinx MicroBlaze processor 2 Copyright 2009-2014 Free Software Foundation, Inc. 3 4 This file is part of GDB, the GNU debugger. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, see <http://www.gnu.org/licenses/>. */ 18 19 #include "config.h" 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 #include "sim-main.h" 30 #include "sim-utils.h" 31 #include "microblaze-dis.h" 32 33 34 #ifndef NUM_ELEM 35 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0]) 36 #endif 37 38 static int target_big_endian = 1; 39 static unsigned long heap_ptr = 0; 40 static unsigned long stack_ptr = 0; 41 host_callback *callback; 42 43 unsigned long 44 microblaze_extract_unsigned_integer (unsigned char *addr, int len) 45 { 46 unsigned long retval; 47 unsigned char *p; 48 unsigned char *startaddr = (unsigned char *)addr; 49 unsigned char *endaddr = startaddr + len; 50 51 if (len > (int) sizeof (unsigned long)) 52 printf ("That operation is not available on integers of more than " 53 "%d bytes.", sizeof (unsigned long)); 54 55 /* Start at the most significant end of the integer, and work towards 56 the least significant. */ 57 retval = 0; 58 59 if (!target_big_endian) 60 { 61 for (p = endaddr; p > startaddr;) 62 retval = (retval << 8) | * -- p; 63 } 64 else 65 { 66 for (p = startaddr; p < endaddr;) 67 retval = (retval << 8) | * p ++; 68 } 69 70 return retval; 71 } 72 73 void 74 microblaze_store_unsigned_integer (unsigned char *addr, int len, 75 unsigned long val) 76 { 77 unsigned char *p; 78 unsigned char *startaddr = (unsigned char *)addr; 79 unsigned char *endaddr = startaddr + len; 80 81 if (!target_big_endian) 82 { 83 for (p = startaddr; p < endaddr;) 84 { 85 *p++ = val & 0xff; 86 val >>= 8; 87 } 88 } 89 else 90 { 91 for (p = endaddr; p > startaddr;) 92 { 93 *--p = val & 0xff; 94 val >>= 8; 95 } 96 } 97 } 98 99 struct sim_state microblaze_state; 100 101 int memcycles = 1; 102 103 static SIM_OPEN_KIND sim_kind; 104 static char *myname; 105 106 static int issue_messages = 0; 107 108 long 109 int_sbrk (int inc_bytes) 110 { 111 long addr; 112 113 addr = heap_ptr; 114 115 heap_ptr += inc_bytes; 116 117 if (issue_messages && heap_ptr > SP) 118 fprintf (stderr, "Warning: heap_ptr overlaps stack!\n"); 119 120 return addr; 121 } 122 123 static void /* INLINE */ 124 wbat (word x, word v) 125 { 126 if (((uword)x) >= CPU.msize) 127 { 128 if (issue_messages) 129 fprintf (stderr, "byte write to 0x%x outside memory range\n", x); 130 131 CPU.exception = SIGSEGV; 132 } 133 else 134 { 135 unsigned char *p = CPU.memory + x; 136 p[0] = v; 137 } 138 } 139 140 static void /* INLINE */ 141 wlat (word x, word v) 142 { 143 if (((uword)x) >= CPU.msize) 144 { 145 if (issue_messages) 146 fprintf (stderr, "word write to 0x%x outside memory range\n", x); 147 148 CPU.exception = SIGSEGV; 149 } 150 else 151 { 152 if ((x & 3) != 0) 153 { 154 if (issue_messages) 155 fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x); 156 157 CPU.exception = SIGBUS; 158 } 159 else if (!target_big_endian) 160 { 161 unsigned char *p = CPU.memory + x; 162 p[3] = v >> 24; 163 p[2] = v >> 16; 164 p[1] = v >> 8; 165 p[0] = v; 166 } 167 else 168 { 169 unsigned char *p = CPU.memory + x; 170 p[0] = v >> 24; 171 p[1] = v >> 16; 172 p[2] = v >> 8; 173 p[3] = v; 174 } 175 } 176 } 177 178 static void /* INLINE */ 179 what (word x, word v) 180 { 181 if (((uword)x) >= CPU.msize) 182 { 183 if (issue_messages) 184 fprintf (stderr, "short write to 0x%x outside memory range\n", x); 185 186 CPU.exception = SIGSEGV; 187 } 188 else 189 { 190 if ((x & 1) != 0) 191 { 192 if (issue_messages) 193 fprintf (stderr, "short write to unaligned memory address: 0x%x\n", 194 x); 195 196 CPU.exception = SIGBUS; 197 } 198 else if (!target_big_endian) 199 { 200 unsigned char *p = CPU.memory + x; 201 p[1] = v >> 8; 202 p[0] = v; 203 } 204 else 205 { 206 unsigned char *p = CPU.memory + x; 207 p[0] = v >> 8; 208 p[1] = v; 209 } 210 } 211 } 212 213 /* Read functions. */ 214 static int /* INLINE */ 215 rbat (word x) 216 { 217 if (((uword)x) >= CPU.msize) 218 { 219 if (issue_messages) 220 fprintf (stderr, "byte read from 0x%x outside memory range\n", x); 221 222 CPU.exception = SIGSEGV; 223 return 0; 224 } 225 else 226 { 227 unsigned char *p = CPU.memory + x; 228 return p[0]; 229 } 230 } 231 232 static int /* INLINE */ 233 rlat (word x) 234 { 235 if (((uword) x) >= CPU.msize) 236 { 237 if (issue_messages) 238 fprintf (stderr, "word read from 0x%x outside memory range\n", x); 239 240 CPU.exception = SIGSEGV; 241 return 0; 242 } 243 else 244 { 245 if ((x & 3) != 0) 246 { 247 if (issue_messages) 248 fprintf (stderr, "word read from unaligned address: 0x%x\n", x); 249 250 CPU.exception = SIGBUS; 251 return 0; 252 } 253 else if (! target_big_endian) 254 { 255 unsigned char *p = CPU.memory + x; 256 return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; 257 } 258 else 259 { 260 unsigned char *p = CPU.memory + x; 261 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 262 } 263 } 264 } 265 266 static int /* INLINE */ 267 rhat (word x) 268 { 269 if (((uword)x) >= CPU.msize) 270 { 271 if (issue_messages) 272 fprintf (stderr, "short read from 0x%x outside memory range\n", x); 273 274 CPU.exception = SIGSEGV; 275 return 0; 276 } 277 else 278 { 279 if ((x & 1) != 0) 280 { 281 if (issue_messages) 282 fprintf (stderr, "short read from unaligned address: 0x%x\n", x); 283 284 CPU.exception = SIGBUS; 285 return 0; 286 } 287 else if (!target_big_endian) 288 { 289 unsigned char *p = CPU.memory + x; 290 return (p[1] << 8) | p[0]; 291 } 292 else 293 { 294 unsigned char *p = CPU.memory + x; 295 return (p[0] << 8) | p[1]; 296 } 297 } 298 } 299 300 301 #define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80) 302 #define SEXTW(y) ((int)((short)y)) 303 304 static int 305 IOMEM (int addr, int write, int value) 306 { 307 } 308 309 /* Default to a 8 Mbyte (== 2^23) memory space. */ 310 static int sim_memory_size = 1 << 23; 311 312 #define MEM_SIZE_FLOOR 64 313 void 314 sim_size (int size) 315 { 316 sim_memory_size = size; 317 CPU.msize = sim_memory_size; 318 319 if (CPU.memory) 320 free (CPU.memory); 321 322 CPU.memory = (unsigned char *) calloc (1, CPU.msize); 323 324 if (!CPU.memory) 325 { 326 if (issue_messages) 327 fprintf (stderr, 328 "Not enough VM for simulation of %d bytes of RAM\n", 329 CPU.msize); 330 331 CPU.msize = 1; 332 CPU.memory = (unsigned char *) calloc (1, 1); 333 } 334 } 335 336 static void 337 init_pointers () 338 { 339 if (CPU.msize != (sim_memory_size)) 340 sim_size (sim_memory_size); 341 } 342 343 static void 344 set_initial_gprs () 345 { 346 int i; 347 long space; 348 unsigned long memsize; 349 350 init_pointers (); 351 352 /* Set up machine just out of reset. */ 353 PC = 0; 354 MSR = 0; 355 356 memsize = CPU.msize / (1024 * 1024); 357 358 if (issue_messages > 1) 359 fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n", 360 memsize, CPU.msize - 1); 361 362 /* Clean out the GPRs */ 363 for (i = 0; i < 32; i++) 364 CPU.regs[i] = 0; 365 CPU.insts = 0; 366 CPU.cycles = 0; 367 CPU.imm_enable = 0; 368 369 } 370 371 static void 372 interrupt () 373 { 374 CPU.exception = SIGINT; 375 } 376 377 /* Functions so that trapped open/close don't interfere with the 378 parent's functions. We say that we can't close the descriptors 379 that we didn't open. exit() and cleanup() get in trouble here, 380 to some extent. That's the price of emulation. */ 381 382 unsigned char opened[100]; 383 384 static void 385 log_open (int fd) 386 { 387 if (fd < 0 || fd > NUM_ELEM (opened)) 388 return; 389 390 opened[fd] = 1; 391 } 392 393 static void 394 log_close (int fd) 395 { 396 if (fd < 0 || fd > NUM_ELEM (opened)) 397 return; 398 399 opened[fd] = 0; 400 } 401 402 static int 403 is_opened (int fd) 404 { 405 if (fd < 0 || fd > NUM_ELEM (opened)) 406 return 0; 407 408 return opened[fd]; 409 } 410 411 static void 412 handle_trap1 () 413 { 414 } 415 416 static void 417 process_stub (int what) 418 { 419 /* These values should match those in libgloss/microblaze/syscalls.s. */ 420 switch (what) 421 { 422 case 3: /* _read */ 423 case 4: /* _write */ 424 case 5: /* _open */ 425 case 6: /* _close */ 426 case 10: /* _unlink */ 427 case 19: /* _lseek */ 428 case 43: /* _times */ 429 handle_trap1 (); 430 break; 431 432 default: 433 if (issue_messages) 434 fprintf (stderr, "Unhandled stub opcode: %d\n", what); 435 break; 436 } 437 } 438 439 static void 440 util (unsigned what) 441 { 442 switch (what) 443 { 444 case 0: /* exit */ 445 CPU.exception = SIGQUIT; 446 break; 447 448 case 1: /* printf */ 449 { 450 unsigned long a[6]; 451 unsigned char *s; 452 int i; 453 454 for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++) 455 if (*s == '%') 456 i++; 457 } 458 break; 459 460 case 2: /* scanf */ 461 if (issue_messages) 462 fprintf (stderr, "WARNING: scanf unimplemented\n"); 463 break; 464 465 case 3: /* utime */ 466 break; 467 468 case 0xFF: 469 process_stub (CPU.regs[1]); 470 break; 471 472 default: 473 if (issue_messages) 474 fprintf (stderr, "Unhandled util code: %x\n", what); 475 break; 476 } 477 } 478 479 /* For figuring out whether we carried; addc/subc use this. */ 480 static int 481 iu_carry (unsigned long a, unsigned long b, int cin) 482 { 483 unsigned long x; 484 485 x = (a & 0xffff) + (b & 0xffff) + cin; 486 x = (x >> 16) + (a >> 16) + (b >> 16); 487 x >>= 16; 488 489 return (x != 0); 490 } 491 492 #define WATCHFUNCTIONS 1 493 #ifdef WATCHFUNCTIONS 494 495 #define MAXWL 80 496 word WL[MAXWL]; 497 char *WLstr[MAXWL]; 498 499 int ENDWL=0; 500 int WLincyc; 501 int WLcyc[MAXWL]; 502 int WLcnts[MAXWL]; 503 int WLmax[MAXWL]; 504 int WLmin[MAXWL]; 505 word WLendpc; 506 int WLbcyc; 507 int WLW; 508 #endif 509 510 static int tracing = 0; 511 512 void 513 sim_resume (SIM_DESC sd, int step, int siggnal) 514 { 515 int needfetch; 516 word inst; 517 enum microblaze_instr op; 518 void (*sigsave)(); 519 int memops; 520 int bonus_cycles; 521 int insts; 522 int w; 523 int cycs; 524 word WLhash; 525 ubyte carry; 526 int imm_unsigned; 527 short ra, rb, rd; 528 long immword; 529 uword oldpc, newpc; 530 short delay_slot_enable; 531 short branch_taken; 532 short num_delay_slot; /* UNUSED except as reqd parameter */ 533 enum microblaze_instr_type insn_type; 534 535 sigsave = signal (SIGINT, interrupt); 536 CPU.exception = step ? SIGTRAP : 0; 537 538 memops = 0; 539 bonus_cycles = 0; 540 insts = 0; 541 542 do 543 { 544 /* Fetch the initial instructions that we'll decode. */ 545 inst = rlat (PC & 0xFFFFFFFC); 546 547 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type, 548 &num_delay_slot); 549 550 if (op == invalid_inst) 551 fprintf (stderr, "Unknown instruction 0x%04x", inst); 552 553 if (tracing) 554 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst); 555 556 rd = GET_RD; 557 rb = GET_RB; 558 ra = GET_RA; 559 /* immword = IMM_W; */ 560 561 oldpc = PC; 562 delay_slot_enable = 0; 563 branch_taken = 0; 564 if (op == microblaze_brk) 565 CPU.exception = SIGTRAP; 566 else if (inst == MICROBLAZE_HALT_INST) 567 { 568 CPU.exception = SIGQUIT; 569 insts += 1; 570 bonus_cycles++; 571 } 572 else 573 { 574 switch(op) 575 { 576 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \ 577 case NAME: \ 578 ACTION; \ 579 break; 580 #include "microblaze.isa" 581 #undef INSTRUCTION 582 583 default: 584 CPU.exception = SIGILL; 585 fprintf (stderr, "ERROR: Unknown opcode\n"); 586 } 587 /* Make R0 consistent */ 588 CPU.regs[0] = 0; 589 590 /* Check for imm instr */ 591 if (op == imm) 592 IMM_ENABLE = 1; 593 else 594 IMM_ENABLE = 0; 595 596 /* Update cycle counts */ 597 insts ++; 598 if (insn_type == memory_store_inst || insn_type == memory_load_inst) 599 memops++; 600 if (insn_type == mult_inst) 601 bonus_cycles++; 602 if (insn_type == barrel_shift_inst) 603 bonus_cycles++; 604 if (insn_type == anyware_inst) 605 bonus_cycles++; 606 if (insn_type == div_inst) 607 bonus_cycles += 33; 608 609 if ((insn_type == branch_inst || insn_type == return_inst) 610 && branch_taken) 611 { 612 /* Add an extra cycle for taken branches */ 613 bonus_cycles++; 614 /* For branch instructions handle the instruction in the delay slot */ 615 if (delay_slot_enable) 616 { 617 newpc = PC; 618 PC = oldpc + INST_SIZE; 619 inst = rlat (PC & 0xFFFFFFFC); 620 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type, 621 &num_delay_slot); 622 if (op == invalid_inst) 623 fprintf (stderr, "Unknown instruction 0x%04x", inst); 624 if (tracing) 625 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst); 626 rd = GET_RD; 627 rb = GET_RB; 628 ra = GET_RA; 629 /* immword = IMM_W; */ 630 if (op == microblaze_brk) 631 { 632 if (issue_messages) 633 fprintf (stderr, "Breakpoint set in delay slot " 634 "(at address 0x%x) will not be honored\n", PC); 635 /* ignore the breakpoint */ 636 } 637 else if (insn_type == branch_inst || insn_type == return_inst) 638 { 639 if (issue_messages) 640 fprintf (stderr, "Cannot have branch or return instructions " 641 "in delay slot (at address 0x%x)\n", PC); 642 CPU.exception = SIGILL; 643 } 644 else 645 { 646 switch(op) 647 { 648 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \ 649 case NAME: \ 650 ACTION; \ 651 break; 652 #include "microblaze.isa" 653 #undef INSTRUCTION 654 655 default: 656 CPU.exception = SIGILL; 657 fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC); 658 } 659 /* Update cycle counts */ 660 insts++; 661 if (insn_type == memory_store_inst 662 || insn_type == memory_load_inst) 663 memops++; 664 if (insn_type == mult_inst) 665 bonus_cycles++; 666 if (insn_type == barrel_shift_inst) 667 bonus_cycles++; 668 if (insn_type == anyware_inst) 669 bonus_cycles++; 670 if (insn_type == div_inst) 671 bonus_cycles += 33; 672 } 673 /* Restore the PC */ 674 PC = newpc; 675 /* Make R0 consistent */ 676 CPU.regs[0] = 0; 677 /* Check for imm instr */ 678 if (op == imm) 679 IMM_ENABLE = 1; 680 else 681 IMM_ENABLE = 0; 682 } 683 else 684 /* no delay slot: increment cycle count */ 685 bonus_cycles++; 686 } 687 } 688 689 if (tracing) 690 fprintf (stderr, "\n"); 691 } 692 while (!CPU.exception); 693 694 /* Hide away the things we've cached while executing. */ 695 /* CPU.pc = pc; */ 696 CPU.insts += insts; /* instructions done ... */ 697 CPU.cycles += insts; /* and each takes a cycle */ 698 CPU.cycles += bonus_cycles; /* and extra cycles for branches */ 699 CPU.cycles += memops; /* and memop cycle delays */ 700 701 signal (SIGINT, sigsave); 702 } 703 704 705 int 706 sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size) 707 { 708 int i; 709 init_pointers (); 710 711 memcpy (&CPU.memory[addr], buffer, size); 712 713 return size; 714 } 715 716 int 717 sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size) 718 { 719 int i; 720 init_pointers (); 721 722 memcpy (buffer, &CPU.memory[addr], size); 723 724 return size; 725 } 726 727 728 int 729 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length) 730 { 731 init_pointers (); 732 733 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0) 734 { 735 if (length == 4) 736 { 737 /* misalignment safe */ 738 long ival = microblaze_extract_unsigned_integer (memory, 4); 739 if (rn < NUM_REGS) 740 CPU.regs[rn] = ival; 741 else 742 CPU.spregs[rn-NUM_REGS] = ival; 743 return 4; 744 } 745 else 746 return 0; 747 } 748 else 749 return 0; 750 } 751 752 int 753 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length) 754 { 755 long ival; 756 init_pointers (); 757 758 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0) 759 { 760 if (length == 4) 761 { 762 if (rn < NUM_REGS) 763 ival = CPU.regs[rn]; 764 else 765 ival = CPU.spregs[rn-NUM_REGS]; 766 767 /* misalignment-safe */ 768 microblaze_store_unsigned_integer (memory, 4, ival); 769 return 4; 770 } 771 else 772 return 0; 773 } 774 else 775 return 0; 776 } 777 778 779 int 780 sim_trace (SIM_DESC sd) 781 { 782 tracing = 1; 783 784 sim_resume (sd, 0, 0); 785 786 tracing = 0; 787 788 return 1; 789 } 790 791 void 792 sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc) 793 { 794 if (CPU.exception == SIGQUIT) 795 { 796 *reason = sim_exited; 797 *sigrc = RETREG; 798 } 799 else 800 { 801 *reason = sim_stopped; 802 *sigrc = CPU.exception; 803 } 804 } 805 806 807 int 808 sim_stop (SIM_DESC sd) 809 { 810 CPU.exception = SIGINT; 811 return 1; 812 } 813 814 815 void 816 sim_info (SIM_DESC sd, int verbose) 817 { 818 #ifdef WATCHFUNCTIONS 819 int w, wcyc; 820 #endif 821 822 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n", 823 CPU.insts); 824 callback->printf_filtered (callback, "# cycles %10d\n", 825 (CPU.cycles) ? CPU.cycles+2 : 0); 826 827 #ifdef WATCHFUNCTIONS 828 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n", 829 ENDWL); 830 831 wcyc = 0; 832 833 for (w = 1; w <= ENDWL; w++) 834 { 835 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]); 836 callback->printf_filtered (callback, " calls = %d, cycles = %d\n", 837 WLcnts[w],WLcyc[w]); 838 839 if (WLcnts[w] != 0) 840 callback->printf_filtered (callback, 841 " maxcpc = %d, mincpc = %d, avecpc = %d\n", 842 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]); 843 wcyc += WLcyc[w]; 844 } 845 846 callback->printf_filtered (callback, 847 "Total cycles for watched functions: %d\n",wcyc); 848 #endif 849 } 850 851 struct aout 852 { 853 unsigned char sa_machtype[2]; 854 unsigned char sa_magic[2]; 855 unsigned char sa_tsize[4]; 856 unsigned char sa_dsize[4]; 857 unsigned char sa_bsize[4]; 858 unsigned char sa_syms[4]; 859 unsigned char sa_entry[4]; 860 unsigned char sa_trelo[4]; 861 unsigned char sa_drelo[4]; 862 } aout; 863 864 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) 865 #define SHORT(x) (((x)[0]<<8)|(x)[1]) 866 867 SIM_DESC 868 sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv) 869 { 870 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/ 871 872 int osize = sim_memory_size; 873 myname = argv[0]; 874 callback = cb; 875 876 if (kind == SIM_OPEN_STANDALONE) 877 issue_messages = 1; 878 879 /* Discard and reacquire memory -- start with a clean slate. */ 880 sim_size (1); /* small */ 881 sim_size (osize); /* and back again */ 882 883 set_initial_gprs (); /* Reset the GPR registers. */ 884 885 return ((SIM_DESC) 1); 886 } 887 888 void 889 sim_close (SIM_DESC sd, int quitting) 890 { 891 if (CPU.memory) 892 { 893 free(CPU.memory); 894 CPU.memory = NULL; 895 CPU.msize = 0; 896 } 897 } 898 899 SIM_RC 900 sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty) 901 { 902 /* Do the right thing for ELF executables; this turns out to be 903 just about the right thing for any object format that: 904 - we crack using BFD routines 905 - follows the traditional UNIX text/data/bss layout 906 - calls the bss section ".bss". */ 907 908 extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ 909 bfd *prog_bfd; 910 911 { 912 bfd *handle; 913 asection *s; 914 int found_loadable_section = 0; 915 bfd_vma max_addr = 0; 916 handle = bfd_openr (prog, 0); 917 918 if (!handle) 919 { 920 printf("``%s'' could not be opened.\n", prog); 921 return SIM_RC_FAIL; 922 } 923 924 /* Makes sure that we have an object file, also cleans gets the 925 section headers in place. */ 926 if (!bfd_check_format (handle, bfd_object)) 927 { 928 /* wasn't an object file */ 929 bfd_close (handle); 930 printf ("``%s'' is not appropriate object file.\n", prog); 931 return SIM_RC_FAIL; 932 } 933 934 for (s = handle->sections; s; s = s->next) 935 { 936 if (s->flags & SEC_ALLOC) 937 { 938 bfd_vma vma = 0; 939 int size = bfd_get_section_size (s); 940 if (size > 0) 941 { 942 vma = bfd_section_vma (handle, s); 943 if (vma >= max_addr) 944 { 945 max_addr = vma + size; 946 } 947 } 948 if (s->flags & SEC_LOAD) 949 found_loadable_section = 1; 950 } 951 } 952 953 if (!found_loadable_section) 954 { 955 /* No loadable sections */ 956 bfd_close(handle); 957 printf("No loadable sections in file %s\n", prog); 958 return SIM_RC_FAIL; 959 } 960 961 sim_memory_size = (unsigned long) max_addr; 962 963 /* Clean up after ourselves. */ 964 bfd_close (handle); 965 966 } 967 968 /* from sh -- dac */ 969 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd, 970 /* sim_kind == SIM_OPEN_DEBUG, */ 971 1, 972 0, sim_write); 973 if (prog_bfd == NULL) 974 return SIM_RC_FAIL; 975 976 target_big_endian = bfd_big_endian (prog_bfd); 977 PC = bfd_get_start_address (prog_bfd); 978 979 if (abfd == NULL) 980 bfd_close (prog_bfd); 981 982 return SIM_RC_OK; 983 } 984 985 SIM_RC 986 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env) 987 { 988 char **avp; 989 int nargs = 0; 990 int nenv = 0; 991 int s_length; 992 int l; 993 unsigned long strings; 994 unsigned long pointers; 995 unsigned long hi_stack; 996 997 998 /* Set the initial register set. */ 999 l = issue_messages; 1000 issue_messages = 0; 1001 set_initial_gprs (); 1002 issue_messages = l; 1003 1004 hi_stack = CPU.msize - 4; 1005 PC = bfd_get_start_address (prog_bfd); 1006 1007 /* For now ignore all parameters to the program */ 1008 1009 return SIM_RC_OK; 1010 } 1011 1012 void 1013 sim_kill (SIM_DESC sd) 1014 { 1015 /* nothing to do */ 1016 } 1017 1018 void 1019 sim_do_command (SIM_DESC sd, char * cmd) 1020 { 1021 /* Nothing there yet; it's all an error. */ 1022 1023 if (cmd != NULL) 1024 { 1025 char ** simargv = buildargv (cmd); 1026 1027 if (strcmp (simargv[0], "watch") == 0) 1028 { 1029 if ((simargv[1] == NULL) || (simargv[2] == NULL)) 1030 { 1031 fprintf (stderr, "Error: missing argument to watch cmd.\n"); 1032 return; 1033 } 1034 1035 ENDWL++; 1036 1037 WL[ENDWL] = strtol (simargv[2], NULL, 0); 1038 WLstr[ENDWL] = strdup (simargv[1]); 1039 fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL], 1040 WL[ENDWL], ENDWL); 1041 1042 } 1043 else if (strcmp (simargv[0], "dumpmem") == 0) 1044 { 1045 unsigned char * p; 1046 FILE * dumpfile; 1047 1048 if (simargv[1] == NULL) 1049 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n"); 1050 1051 fprintf (stderr, "Writing dumpfile %s...",simargv[1]); 1052 1053 dumpfile = fopen (simargv[1], "w"); 1054 p = CPU.memory; 1055 fwrite (p, CPU.msize-1, 1, dumpfile); 1056 fclose (dumpfile); 1057 1058 fprintf (stderr, "done.\n"); 1059 } 1060 else if (strcmp (simargv[0], "clearstats") == 0) 1061 { 1062 CPU.cycles = 0; 1063 CPU.insts = 0; 1064 ENDWL = 0; 1065 } 1066 else if (strcmp (simargv[0], "verbose") == 0) 1067 { 1068 issue_messages = 2; 1069 } 1070 else 1071 { 1072 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n", 1073 cmd); 1074 } 1075 } 1076 else 1077 { 1078 fprintf (stderr, "M.CORE sim commands: \n"); 1079 fprintf (stderr, " watch <funcname> <addr>\n"); 1080 fprintf (stderr, " dumpmem <filename>\n"); 1081 fprintf (stderr, " clearstats\n"); 1082 fprintf (stderr, " verbose\n"); 1083 } 1084 } 1085 1086 void 1087 sim_set_callbacks (host_callback *ptr) 1088 { 1089 callback = ptr; 1090 } 1091 1092 char ** 1093 sim_complete_command (SIM_DESC sd, const char *text, const char *word) 1094 { 1095 return NULL; 1096 } 1097