1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)iris.c 5.1 (Berkeley) 01/12/88"; 9 #endif not lint 10 11 static char rcsid[] = "$Header: machine.c,v 1.2 87/03/26 14:54:55 donn Exp $"; 12 13 /* 14 * Target machine dependent stuff. 15 */ 16 17 #include "defs.h" 18 #include "machine.h" 19 #include "process.h" 20 #include "runtime.h" 21 #include "events.h" 22 #include "main.h" 23 #include "symbols.h" 24 #include "source.h" 25 #include "mappings.h" 26 #include "object.h" 27 #include "tree.h" 28 #include "eval.h" 29 #include "keywords.h" 30 #include "ops.h" 31 32 #ifndef public 33 typedef unsigned int Address; 34 typedef unsigned char Byte; 35 typedef unsigned int Word; 36 37 /* 38 * On the 68000, the pc isn't in a register, but we make believe 39 * so there's one more register. 40 * 41 * Note that there's also no argument pointer, this means code 42 * involving "ARGP" should always be #ifdef'd. 43 * 44 * The address corresponding to the beginning of a function is recorded 45 * as the address + FUNCOFFSET (skip the link instruction so that 46 * local information is available). 47 */ 48 49 #define NREG 17 50 51 #define FRP 14 52 #define STKP 15 53 #define PROGCTR 16 54 55 #define CALL_RETADDR 0x800c /* Return address for 'call' command */ 56 #define FUNCOFFSET 4 57 58 #ifdef sun 59 # define CODESTART 0x8000 60 #else /* IRIS */ 61 # define CODESTART 0x1000 62 #endif 63 64 #define optab_init() 65 66 #define BITSPERBYTE 8 67 #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 68 69 /* 70 * This magic macro enables us to look at the process' registers 71 * in its user structure. 72 */ 73 74 #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * ((reg) - PC)) - 10) 75 76 #include "source.h" 77 #include "symbols.h" 78 #include <signal.h> 79 #include <sys/param.h> 80 #include <sys/dir.h> 81 #include <machine/psl.h> 82 #include <machine/pte.h> 83 #include <sys/user.h> 84 #undef DELETE /* XXX */ 85 #include <sys/vm.h> 86 #include <machine/reg.h> 87 88 Address pc; 89 Address prtaddr; 90 91 #endif 92 93 /* 94 * Indices into u. for use in collecting registers values. 95 */ 96 public int rloc[] ={ 97 #ifdef sun 98 R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, PC 99 #else /* IRIS */ 100 R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, AR7, 16 101 #endif 102 }; 103 104 private Address printop(); 105 106 /* 107 * Decode and print the instructions within the given address range. 108 */ 109 110 public printinst(lowaddr, highaddr) 111 Address lowaddr; 112 Address highaddr; 113 { 114 register Address addr; 115 116 for (addr = lowaddr; addr <= highaddr; ) { 117 addr = printop(addr); 118 } 119 prtaddr = addr; 120 } 121 122 /* 123 * Another approach: print n instructions starting at the given address. 124 */ 125 126 public printninst(count, addr) 127 int count; 128 Address addr; 129 { 130 register Integer i; 131 register Address newaddr; 132 133 if (count <= 0) { 134 error("non-positive repetition count"); 135 } else { 136 newaddr = addr; 137 for (i = 0; i < count; i++) { 138 newaddr = printop(newaddr); 139 } 140 prtaddr = newaddr; 141 } 142 } 143 144 /* 145 * Print the contents of the addresses within the given range 146 * according to the given format. 147 */ 148 149 typedef struct { 150 String name; 151 String printfstring; 152 int length; 153 } Format; 154 155 private Format fmt[] = { 156 { "d", " %d", sizeof(short) }, 157 { "D", " %ld", sizeof(long) }, 158 { "o", " %o", sizeof(short) }, 159 { "O", " %lo", sizeof(long) }, 160 { "x", " %04x", sizeof(short) }, 161 { "X", " %08x", sizeof(long) }, 162 { "b", " \\%o", sizeof(char) }, 163 { "c", " '%c'", sizeof(char) }, 164 { "s", "%c", sizeof(char) }, 165 { "f", " %f", sizeof(float) }, 166 { "g", " %g", sizeof(double) }, 167 { nil, nil, 0 } 168 }; 169 170 private Format *findformat(s) 171 String s; 172 { 173 register Format *f; 174 175 f = &fmt[0]; 176 while (f->name != nil and not streq(f->name, s)) { 177 ++f; 178 } 179 if (f->name == nil) { 180 error("bad print format \"%s\"", s); 181 } 182 return f; 183 } 184 185 /* 186 * Retrieve and print out the appropriate data in the given format. 187 * Floats have to be handled specially to allow the compiler to 188 * convert them to doubles when passing to printf. 189 */ 190 191 private printformat (f, addr) 192 Format *f; 193 Address addr; 194 { 195 union { 196 char charv; 197 short shortv; 198 int intv; 199 float floatv; 200 double doublev; 201 } value; 202 203 value.intv = 0; 204 dread(&value, addr, f->length); 205 if (streq(f->name, "f")) { 206 printf(f->printfstring, value.floatv); 207 } else { 208 printf(f->printfstring, value); 209 } 210 } 211 212 public Address printdata(lowaddr, highaddr, format) 213 Address lowaddr; 214 Address highaddr; 215 String format; 216 { 217 int n; 218 register Address addr; 219 Format *f; 220 221 if (lowaddr > highaddr) { 222 error("first address larger than second"); 223 } 224 f = findformat(format); 225 n = 0; 226 for (addr = lowaddr; addr <= highaddr; addr += f->length) { 227 if (n == 0) { 228 printf("%08x: ", addr); 229 } 230 printformat(f, addr); 231 ++n; 232 if (n >= (16 div f->length)) { 233 printf("\n"); 234 n = 0; 235 } 236 } 237 if (n != 0) { 238 printf("\n"); 239 } 240 prtaddr = addr; 241 return addr; 242 } 243 244 /* 245 * The other approach is to print n items starting with a given address. 246 */ 247 248 public printndata(count, startaddr, format) 249 int count; 250 Address startaddr; 251 String format; 252 { 253 int i, n; 254 Address addr; 255 Format *f; 256 Boolean isstring; 257 char c; 258 259 if (count <= 0) { 260 error("non-positive repetition count"); 261 } 262 f = findformat(format); 263 isstring = (Boolean) streq(f->name, "s"); 264 n = 0; 265 addr = startaddr; 266 for (i = 0; i < count; i++) { 267 if (n == 0) { 268 printf("%08x: ", addr); 269 } 270 if (isstring) { 271 printf("\""); 272 dread(&c, addr, sizeof(char)); 273 while (c != '\0') { 274 printchar(c); 275 ++addr; 276 dread(&c, addr, sizeof(char)); 277 } 278 printf("\"\n"); 279 n = 0; 280 addr += sizeof(String); 281 } else { 282 printformat(f, addr); 283 ++n; 284 if (n >= (16 div f->length)) { 285 printf("\n"); 286 n = 0; 287 } 288 addr += f->length; 289 } 290 } 291 if (n != 0) { 292 printf("\n"); 293 } 294 prtaddr = addr; 295 } 296 297 /* 298 * Print out a value according to the given format. 299 */ 300 301 public printvalue(v, format) 302 long v; 303 String format; 304 { 305 Format *f; 306 char *p, *q; 307 308 f = findformat(format); 309 if (streq(f->name, "s")) { 310 putchar('"'); 311 p = (char *) &v; 312 q = p + sizeof(v); 313 while (p < q) { 314 printchar(*p); 315 ++p; 316 } 317 putchar('"'); 318 } else { 319 printf(f->printfstring, v); 320 } 321 putchar('\n'); 322 } 323 324 /* 325 * Print out an execution time error. 326 * Assumes the source position of the error has been calculated. 327 * 328 * Have to check if the -r option was specified; if so then 329 * the object file information hasn't been read in yet. 330 */ 331 332 public printerror() 333 { 334 extern Integer sys_nsig; 335 extern String sys_siglist[]; 336 integer err; 337 338 if (isfinished(process)) { 339 err = exitcode(process); 340 if (err == 0) { 341 printf("\"%s\" terminated normally\n", objname); 342 } else { 343 printf("\"%s\" terminated abnormally (exit code %d)\n", 344 objname, err 345 ); 346 } 347 erecover(); 348 } 349 err = errnum(process); 350 putchar('\n'); 351 printsig(err); 352 putchar(' '); 353 printloc(); 354 putchar('\n'); 355 if (curline > 0) { 356 printlines(curline, curline); 357 } else { 358 printinst(pc, pc); 359 } 360 erecover(); 361 } 362 363 /* 364 * Print out a signal. 365 */ 366 367 private String illinames[] = { 368 "reserved addressing fault", 369 "privileged instruction fault", 370 "reserved operand fault" 371 }; 372 373 private String fpenames[] = { 374 nil, 375 "integer overflow trap", 376 "integer divide by zero trap", 377 "floating overflow trap", 378 "floating/decimal divide by zero trap", 379 "floating underflow trap", 380 "decimal overflow trap", 381 "subscript out of range trap", 382 "floating overflow fault", 383 "floating divide by zero fault", 384 "floating underflow fault" 385 }; 386 387 public printsig (signo) 388 integer signo; 389 { 390 integer code; 391 392 if (signo < 0 or signo > sys_nsig) { 393 printf("[signal %d]", signo); 394 } else { 395 printf("%s", sys_siglist[signo]); 396 } 397 code = errcode(process); 398 if (signo == SIGILL) { 399 if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 400 printf(" (%s)", illinames[code]); 401 } 402 } else if (signo == SIGFPE) { 403 if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 404 printf(" (%s)", fpenames[code]); 405 } 406 } 407 } 408 409 /* 410 * Note the termination of the program. We do this so as to avoid 411 * having the process exit, which would make the values of variables 412 * inaccessible. We do want to flush all output buffers here, 413 * otherwise it'll never get done. 414 */ 415 416 public endprogram() 417 { 418 Integer exitcode; 419 420 stepto(nextaddr(pc, true)); 421 printnews(); 422 exitcode = argn(1, nil); 423 if (exitcode != 0) { 424 printf("\nexecution completed (exit code %d)\n", exitcode); 425 } else { 426 printf("\nexecution completed\n"); 427 } 428 getsrcpos(); 429 erecover(); 430 } 431 432 /* 433 * Single step the machine a source line (or instruction if "inst_tracing" 434 * is true). If "isnext" is true, skip over procedure calls. 435 */ 436 437 private Address getcall(); 438 439 public dostep(isnext) 440 Boolean isnext; 441 { 442 register Address addr; 443 register Lineno line; 444 String filename; 445 Address startaddr; 446 447 startaddr = pc; 448 addr = nextaddr(pc, isnext); 449 if (not inst_tracing and nlhdr.nlines != 0) { 450 line = linelookup(addr); 451 while (line == 0) { 452 addr = nextaddr(addr, isnext); 453 line = linelookup(addr); 454 } 455 curline = line; 456 } else { 457 curline = 0; 458 } 459 stepto(addr); 460 filename = srcfilename(addr); 461 setsource(filename); 462 } 463 464 typedef short Bpinst; 465 466 extern Bpinst BP_OP; 467 #ifdef sun 468 asm("_BP_OP: trap #15"); 469 #else /* IRIS */ 470 asm("_BP_OP: trap #1"); 471 #endif 472 473 #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 474 475 /* 476 * Setting a breakpoint at a location consists of saving 477 * the word at the location and poking a BP_OP there. 478 * 479 * We save the locations and words on a list for use in unsetting. 480 */ 481 482 typedef struct Savelist *Savelist; 483 484 struct Savelist { 485 Address location; 486 Bpinst save; 487 short refcount; 488 Savelist link; 489 }; 490 491 private Savelist savelist; 492 493 /* 494 * Set a breakpoint at the given address. Only save the word there 495 * if it's not already a breakpoint. 496 */ 497 498 public setbp(addr) 499 Address addr; 500 { 501 Bpinst w, save; 502 register Savelist newsave, s; 503 504 for (s = savelist; s != nil; s = s->link) { 505 if (s->location == addr) { 506 s->refcount++; 507 return; 508 } 509 } 510 iread(&save, addr, sizeof(save)); 511 newsave = new(Savelist); 512 newsave->location = addr; 513 newsave->save = save; 514 newsave->refcount = 1; 515 newsave->link = savelist; 516 savelist = newsave; 517 w = BP_OP; 518 iwrite(&w, addr, sizeof(w)); 519 } 520 521 /* 522 * Unset a breakpoint; unfortunately we have to search the SAVELIST 523 * to find the saved value. The assumption is that the SAVELIST will 524 * usually be quite small. 525 */ 526 527 public unsetbp(addr) 528 Address addr; 529 { 530 register Savelist s, prev; 531 532 prev = nil; 533 for (s = savelist; s != nil; s = s->link) { 534 if (s->location == addr) { 535 iwrite(&s->save, addr, sizeof(s->save)); 536 s->refcount--; 537 if (s->refcount == 0) { 538 if (prev == nil) { 539 savelist = s->link; 540 } else { 541 prev->link = s->link; 542 } 543 dispose(s); 544 } 545 return; 546 } 547 prev = s; 548 } 549 panic("unsetbp: couldn't find address %d", addr); 550 } 551 552 /* 553 * Instruction decoding routines for 68000, derived from adb. 554 * 555 * The shared boolean variable "printing" is true if the decoded 556 * instruction is to be printed, false if not. In either case, 557 * the address of the next instruction after the given one is returned. 558 */ 559 560 private Boolean printing; 561 private Boolean following; 562 private Boolean followcalls; 563 private Address instaddr; 564 565 #define instread(var) \ 566 { \ 567 iread(&var, instaddr, sizeof(var)); \ 568 instaddr += sizeof(var); \ 569 } 570 571 private Optab *decode(inst, addr) 572 Word inst; 573 Address addr; 574 { 575 register Optab *o; 576 577 o = &optab[0]; 578 while (o->mask != 0 and (inst&o->mask) != o->match) { 579 ++o; 580 } 581 return o; 582 } 583 584 private Address printop(addr) 585 Address addr; 586 { 587 Optab *o; 588 short inst; 589 590 printf("%08x ", addr); 591 iread(&inst, addr, sizeof(inst)); 592 o = decode(inst, addr); 593 if (o->mask == 0) { 594 printf("\tbadop"); 595 instaddr = addr + sizeof(inst); 596 } else { 597 printing = true; 598 following = false; 599 instaddr = addr + sizeof(inst); 600 (*o->opfun)(inst, o->farg); 601 printing = false; 602 } 603 printf("\n"); 604 return instaddr; 605 } 606 607 /* 608 * Quickly find the return address of the current procedure or function 609 * while single stepping. Just get the word pointed at by sp. 610 */ 611 612 private Address currtnaddr () 613 { 614 Address retaddr; 615 616 dread(&retaddr, reg(STKP), sizeof(retaddr)); 617 return retaddr; 618 } 619 620 /* 621 * Print out the effective address for the given parameters. 622 */ 623 624 private printea(mode, reg, size) 625 long mode, reg; 626 int size; 627 { 628 long index, disp; 629 static char *aregs[] = { "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp" }; 630 Byte b; 631 short w; 632 long l; 633 634 switch ((int)(mode)) { 635 case 0: 636 if (printing) { 637 printf("d%D", reg); 638 } 639 break; 640 641 case 1: 642 if (printing) { 643 printf("%s", aregs[reg]); 644 } 645 break; 646 647 case 2: 648 if (printing) { 649 printf("%s@", aregs[reg]); 650 } 651 break; 652 653 case 3: 654 if (printing) { 655 printf("%s@+", aregs[reg]); 656 } 657 break; 658 659 case 4: 660 if (printing) { 661 printf("%s@-", aregs[reg]); 662 } 663 break; 664 665 case 5: 666 instread(w); 667 if (printing) { 668 printf("%s@(%D)", aregs[reg], w); 669 } 670 break; 671 672 case 6: 673 instread(w); 674 if (printing) { 675 index = w; 676 disp = (char)(index&0377); 677 printf("%s@(%d,%c%D:%c)", aregs[reg], disp, 678 (index&0100000)?'a':'d',(index>>12)&07, 679 (index&04000)?'l':'w'); 680 } 681 break; 682 683 case 7: 684 switch ((int)(reg)) { 685 case 0: 686 instread(w); 687 if (printing) { 688 index = w; 689 psymoff(index); 690 } 691 break; 692 693 case 1: 694 instread(l); 695 if (printing) { 696 index = l; 697 psymoff(index); 698 } 699 break; 700 701 case 2: 702 instread(w); 703 if (printing) { 704 disp = w; 705 psymoff(disp + instaddr); 706 } 707 break; 708 709 case 3: 710 instread(w); 711 if (printing) { 712 index = w; 713 disp = (char)(index&0377); 714 printf("pc@(%D,%c%D:%c)", disp, 715 (index&0100000)?'a':'d',(index>>12)&07, 716 (index&04000)?'l':'w'); 717 } 718 break; 719 720 case 4: 721 switch (size) { 722 case sizeof(b): 723 instread(w); 724 index = (w&0xff); 725 break; 726 727 case sizeof(w): 728 instread(w); 729 index = w; 730 break; 731 732 case sizeof(l): 733 instread(l); 734 index = l; 735 break; 736 737 default: 738 if (printing) { 739 printf("unexpected size %d in printea\n", size); 740 } 741 instread(l); 742 index = l; 743 break; 744 } 745 if (printing) { 746 printf(IMDF, index); 747 } 748 break; 749 750 default: 751 if (printing) { 752 printf("???"); 753 } 754 break; 755 } 756 break; 757 758 default: 759 if (printing) { 760 printf("???"); 761 } 762 break; 763 } 764 } 765 766 private printEA(ea, size) 767 long ea; 768 int size; 769 { 770 printea((ea>>3)&07, ea&07, size); 771 } 772 773 private mapsize(inst) 774 register long inst; 775 { 776 int m; 777 778 inst >>= 6; 779 inst &= 03; 780 switch (inst) { 781 case 0: 782 m = 1; 783 break; 784 785 case 1: 786 m = 2; 787 break; 788 789 case 2: 790 m = 4; 791 break; 792 793 default: 794 m = -1; 795 break; 796 } 797 return m; 798 } 799 800 private char suffix(size) 801 int size; 802 { 803 char c; 804 805 switch (size) { 806 case 1: 807 c = 'b'; 808 break; 809 810 case 2: 811 c = 'w'; 812 break; 813 814 case 4: 815 c = 'l'; 816 break; 817 818 default: 819 panic("bad size %d in suffix", size); 820 } 821 return c; 822 } 823 824 /* 825 * Print an address offset. Eventually this should attempt to be symbolic, 826 * but for now its just printed in hex. 827 */ 828 829 private psymoff (off) 830 Word off; 831 { 832 Symbol f; 833 834 f = whatblock((Address) (off + FUNCOFFSET)); 835 if (codeloc(f) == off + FUNCOFFSET) { 836 printf("%s", symname(f)); 837 } else { 838 printf("0x%x", off); 839 } 840 } 841 842 /* 843 * Instruction class specific routines. 844 */ 845 846 public omove(inst, s) 847 long inst; 848 String s; 849 { 850 register int c; 851 int size; 852 853 c = s[0]; 854 if (printing) { 855 printf("\tmov%c\t", c); 856 } 857 size = ((c == 'b') ? 1 : (c == 'w') ? 2 : 4); 858 printea((inst>>3)&07, inst&07, size); 859 if (printing) { 860 printf(","); 861 } 862 printea((inst>>6)&07, (inst>>9)&07, size); 863 } 864 865 /* 866 * Two types: bsr (4 bytes) and bsrs (2 bytes) 867 */ 868 869 public obranch(inst, dummy) 870 long inst; 871 { 872 long disp; 873 String s; 874 short w; 875 Address startingaddr; /* address of branch instruction */ 876 int branchtype; /* type of branch (0 = unconditional) */ 877 Address dest; 878 Address retaddr; /* for bsr instruction */ 879 880 startingaddr = instaddr - 2; 881 disp = inst&0377; 882 s = "s "; 883 if (disp == 0) { 884 retaddr = startingaddr + 4; 885 } else { 886 retaddr = startingaddr + 2; 887 } 888 if (disp > 127) { 889 disp |= ~0377; 890 } else if (disp == 0){ 891 s = " "; 892 instread(w); 893 disp = w; 894 } 895 branchtype = (int)((inst>>8)&017); 896 dest = startingaddr + 2 + disp; 897 if (printing) { 898 printf("\tb%s%s\t", bname[branchtype], s); 899 psymoff(dest); 900 } 901 if (following) { 902 /* 903 * If we're to follow the dynamic flow of instructions, 904 * we must see where the branch leads. A branchtype of 0 905 * indicates an unconditional branch which we simply take 906 * as the new instruction address. For a conditional branch, 907 * we continue execution up to the current address, single step, 908 * and keep going. 909 */ 910 if (branchtype == 0) { 911 instaddr = dest; 912 } else if (branchtype == 01) { /* bsr */ 913 if (followcalls) { 914 steppast(startingaddr); 915 curfunc = whatblock(pc, true); 916 if (not isbperr()) { 917 printstatus(); 918 /* NOTREACHED */ 919 } 920 bpact(); 921 if (nosource(curfunc) and canskip(curfunc) and 922 nlhdr.nlines != 0) { 923 stepto(retaddr); 924 instaddr = pc; 925 bpact(); 926 } else { 927 callnews(/* iscall = */ true); 928 } 929 } 930 } else { 931 steppast(startingaddr); 932 } 933 } 934 } 935 936 public odbcc(inst, form) 937 long inst; 938 String form; 939 { 940 long disp; 941 short w; 942 943 instread(w); 944 if (printing) { 945 printf(form, dbname[(int)((inst>>8)&017)], inst&07); 946 psymoff(w + sizeof(w)); 947 } 948 } 949 950 public oscc(inst, dummy) 951 long inst; 952 long dummy; 953 { 954 if (printing) { 955 printf("\ts%s\t", cname[(int)((inst>>8)&017)]); 956 } 957 printea((inst>>3)&07, inst&07, 1); 958 } 959 960 public biti(inst, dummy) 961 long inst; 962 long dummy; 963 { 964 short w; 965 966 if (printing) { 967 printf("\t%s\t", bit[(int)((inst>>6)&03)]); 968 } 969 if (inst&0x0100) { 970 if (printing) { 971 printf("d%D,", inst>>9); 972 } 973 } else { 974 instread(w); 975 if (printing) { 976 printf(IMDF, w); 977 printf(","); 978 } 979 } 980 printEA(inst); 981 } 982 983 public opmode(inst, opcode) 984 long inst; 985 long opcode; 986 { 987 register int opmode; 988 register int reg; 989 int size; 990 991 opmode = (int)((inst>>6) & 07); 992 reg = (int)((inst>>9) & 07); 993 if (opmode == 0 or opmode == 4) { 994 size = 1; 995 } else if (opmode == 1 or opmode == 3 or opmode == 5) { 996 size = 2; 997 } else { 998 size = 4; 999 } 1000 if (printing) { 1001 printf("\t%s%c\t", opcode, suffix(size)); 1002 } 1003 if (opmode >= 4 and opmode <= 6) { 1004 if (printing) { 1005 printf("d%d,", reg); 1006 } 1007 printea((inst>>3)&07, inst&07, size); 1008 } else { 1009 printea((inst>>3)&07, inst&07, size); 1010 if (printing) { 1011 printf(",%c%d",(opmode<=2) ? 'd' : 'a', reg); 1012 } 1013 } 1014 } 1015 1016 public shroi(inst, ds) 1017 long inst; 1018 String ds; 1019 { 1020 int rx, ry; 1021 String opcode; 1022 1023 if ((inst & 0xC0) == 0xC0) { 1024 opcode = shro[(int)((inst>>9)&03)]; 1025 if (printing) { 1026 printf("\t%s%s\t", opcode, ds); 1027 } 1028 printEA(inst); 1029 } else { 1030 if (printing) { 1031 opcode = shro[(int)((inst>>3)&03)]; 1032 printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst))); 1033 rx = (int)((inst>>9)&07); ry = (int)(inst&07); 1034 if ((inst>>5)&01) { 1035 printf("d%d,d%d", rx, ry); 1036 } else { 1037 printf(IMDF, (rx ? rx : 8)); 1038 printf(",d%d", ry); 1039 } 1040 } 1041 } 1042 } 1043 1044 public oimmed(inst, opcode) 1045 long inst; 1046 register String opcode; 1047 { 1048 register int size; 1049 long const; 1050 short w; 1051 1052 size = mapsize(inst); 1053 if (size > 0) { 1054 if (size == 4) { 1055 instread(const); 1056 } else { 1057 instread(w); 1058 const = w; 1059 } 1060 if (printing) { 1061 printf("\t%s%c\t", opcode, suffix(size)); 1062 printf(IMDF, const); 1063 printf(","); 1064 } 1065 printEA(inst, size); 1066 } else { 1067 if (printing) { 1068 printf("\tbadop"); 1069 } 1070 } 1071 } 1072 1073 public oreg(inst, opcode) 1074 long inst; 1075 register String opcode; 1076 { 1077 if (printing) { 1078 printf(opcode, (inst & 07)); 1079 } 1080 } 1081 1082 public extend(inst, opcode) 1083 long inst; 1084 String opcode; 1085 { 1086 register int size; 1087 int ry, rx; 1088 char c; 1089 1090 if (printing) { 1091 size = mapsize(inst); 1092 ry = (inst&07); 1093 rx = ((inst>>9)&07); 1094 c = ((inst & 0x1000) ? suffix(size) : ' '); 1095 printf("\t%s%c\t", opcode, c); 1096 if (opcode[0] == 'e') { 1097 if (inst & 0x0080) { 1098 printf("d%D,a%D", rx, ry); 1099 } else if (inst & 0x0008) { 1100 printf("a%D,a%D", rx, ry); 1101 } else { 1102 printf("d%D,d%D", rx, ry); 1103 } 1104 } else if ((inst & 0xF000) == 0xB000) { 1105 printf("a%D@+,a%D@+", ry, rx); 1106 } else if (inst & 0x8) { 1107 printf("a%D@-,a%D@-", ry, rx); 1108 } else { 1109 printf("d%D,d%D", ry, rx); 1110 } 1111 } 1112 } 1113 1114 public olink(inst, dummy) 1115 long inst; 1116 long dummy; 1117 { 1118 short w; 1119 1120 instread(w); 1121 if (printing) { 1122 printf("\tlink\ta%D,", inst&07); 1123 printf(IMDF, w); 1124 } 1125 } 1126 1127 public otrap(inst, dummy) 1128 long inst; 1129 { 1130 if (printing) { 1131 printf("\ttrap\t"); 1132 printf(IMDF, inst&017); 1133 } 1134 } 1135 1136 public oneop(inst, opcode) 1137 long inst; 1138 register String opcode; 1139 { 1140 if (printing) { 1141 printf("\t%s",opcode); 1142 } 1143 printEA(inst); 1144 } 1145 1146 public jsrop(inst, opcode) 1147 long inst; 1148 register String opcode; 1149 { 1150 Address startingaddr; /* beginning of jsr instruction */ 1151 Address retaddr; /* can't call return_addr (frame not set up yet) */ 1152 1153 startingaddr = instaddr - 2; 1154 switch ((inst >> 3) & 07) { 1155 case 2: 1156 retaddr = instaddr; /* two byte instruction */ 1157 break; 1158 case 5: 1159 case 6: 1160 retaddr = instaddr + 2; /* four byte instruction */ 1161 break; 1162 case 7: 1163 default: 1164 switch (inst & 07) { 1165 case 0: 1166 case 2: 1167 case 3: 1168 retaddr = instaddr + 2; 1169 break; 1170 case 1: 1171 default: 1172 retaddr = instaddr + 4; /* six byte instruction */ 1173 break; 1174 } 1175 break; 1176 } 1177 if (printing) { 1178 printf("\t%s",opcode); 1179 } 1180 printEA(inst); 1181 if (following and followcalls) { 1182 steppast(startingaddr); 1183 curfunc = whatblock(pc, true); 1184 if (not isbperr()) { 1185 printstatus(); 1186 /* NOTREACHED */ 1187 } 1188 bpact(); 1189 if (nosource(curfunc) and canskip(curfunc) and nlhdr.nlines != 0) { 1190 stepto(retaddr); 1191 instaddr = pc; 1192 bpact(); 1193 } else { 1194 callnews(/* iscall = */ true); 1195 } 1196 } 1197 } 1198 1199 public jmpop(inst, opcode) 1200 long inst; 1201 register String opcode; 1202 { 1203 Address startingaddr; /* beginning of jump instruction */ 1204 1205 startingaddr = instaddr - 2; 1206 if (printing) { 1207 printf("\t%s",opcode); 1208 } 1209 printEA(inst); 1210 if (following) { 1211 steppast(startingaddr); 1212 } 1213 } 1214 1215 public pregmask(mask) 1216 register int mask; 1217 { 1218 register int i; 1219 register int flag = 0; 1220 1221 if (printing) { 1222 printf("#<"); 1223 for (i=0; i<16; i++) { 1224 if (mask&1) { 1225 if (flag) { 1226 printf(","); 1227 } else { 1228 ++flag; 1229 } 1230 printf("%c%d",(i<8) ? 'd' : 'a', i&07); 1231 } 1232 mask >>= 1; 1233 } 1234 printf(">"); 1235 } 1236 } 1237 1238 public omovem(inst, dummy) 1239 long inst; 1240 long dummy; 1241 { 1242 register int i, list, mask; 1243 register int reglist; 1244 short w; 1245 1246 i = 0; 1247 list = 0; 1248 mask = 0100000; 1249 instread(w); 1250 reglist = w; 1251 if ((inst & 070) == 040) { /* predecrement */ 1252 for (i = 15; i > 0; i -= 2) { 1253 list |= ((mask & reglist) >> i); 1254 mask >>= 1; 1255 } 1256 for (i = 1; i < 16; i += 2) { 1257 list |= ((mask & reglist) << i); 1258 mask >>= 1; 1259 } 1260 reglist = list; 1261 } 1262 if (printing) { 1263 printf("\tmovem%c\t",(inst&100)?'l':'w'); 1264 } 1265 if (inst&02000) { 1266 printEA(inst); 1267 if (printing) { 1268 printf(","); 1269 } 1270 pregmask(reglist); 1271 } else { 1272 pregmask(reglist); 1273 if (printing) { 1274 printf(","); 1275 } 1276 printEA(inst); 1277 } 1278 } 1279 1280 public ochk(inst, opcode) 1281 long inst; 1282 register String opcode; 1283 { 1284 if (printing) { 1285 printf("\t%s\t", opcode); 1286 } 1287 printEA(inst, sizeof(Byte)); 1288 if (printing) { 1289 printf(",%c%D", (opcode[0] == 'l') ? 'a' : 'd', (inst>>9)&07); 1290 } 1291 } 1292 1293 public soneop(inst, opcode) 1294 long inst; 1295 register String opcode; 1296 { 1297 register int size; 1298 1299 size = mapsize(inst); 1300 if (size > 0) { 1301 if (printing) { 1302 printf("\t%s%c\t", opcode, suffix(size)); 1303 } 1304 printEA(inst); 1305 } else { 1306 if (printing) { 1307 printf("\tbadop"); 1308 } 1309 } 1310 } 1311 1312 public oquick(inst, opcode) 1313 long inst; 1314 register String opcode; 1315 { 1316 register int size; 1317 register int data; 1318 1319 size = mapsize(inst); 1320 data = (int)((inst>>9) & 07); 1321 if (data == 0) { 1322 data = 8; 1323 } 1324 if (size > 0) { 1325 if (printing) { 1326 printf("\t%s%c\t", opcode, suffix(size)); 1327 printf(IMDF, data); 1328 printf(","); 1329 } 1330 printEA(inst); 1331 } else { 1332 if (printing) { 1333 printf("\tbadop"); 1334 } 1335 } 1336 } 1337 1338 public omoveq(inst, dummy) 1339 long inst; 1340 long dummy; 1341 { 1342 register int data; 1343 1344 if (printing) { 1345 data = (int)(inst & 0377); 1346 if (data > 127) { 1347 data |= ~0377; 1348 } 1349 printf("\tmoveq\t"); 1350 printf(IMDF, data); 1351 printf(",d%D", (inst>>9)&07); 1352 } 1353 } 1354 1355 public oprint(inst, opcode) 1356 long inst; 1357 register String opcode; 1358 { 1359 if (printing) { 1360 printf("\t%s",opcode); 1361 } 1362 } 1363 1364 public ostop(inst, opcode) 1365 long inst; 1366 register String opcode; 1367 { 1368 short w; 1369 1370 instread(w); 1371 if (printing) { 1372 printf(opcode, w); 1373 } 1374 } 1375 1376 public orts(inst, opcode) 1377 long inst; 1378 register String opcode; 1379 { 1380 Address addr; 1381 1382 if (following) { 1383 callnews(/* iscall = */ false); 1384 if (inst_tracing) { 1385 addr = currtnaddr(); 1386 } else { 1387 addr = return_addr(); 1388 if (addr == 0) { 1389 stepto(instaddr - 2); 1390 addr = currtnaddr(); 1391 } 1392 } 1393 stepto(addr); 1394 instaddr = pc; 1395 } 1396 if (printing) { 1397 printf("\t%s",opcode); 1398 } 1399 } 1400 1401 /* 1402 * Not used by C compiler; does an rts but before doing so, pops 1403 * arg bytes from the stack. 1404 */ 1405 1406 public ortspop(inst, opcode) 1407 long inst; 1408 register String opcode; 1409 { 1410 Address addr; 1411 short w; 1412 1413 instread(w); 1414 if (following) { 1415 callnews(/* iscall = */ false); 1416 if (inst_tracing) { 1417 addr = currtnaddr(); 1418 } else { 1419 addr = return_addr(); 1420 } 1421 stepto(addr); 1422 instaddr = pc; 1423 } 1424 if (printing) { 1425 printf(opcode, w); 1426 } 1427 } 1428 1429 public omovs(inst, opcode) 1430 long inst; 1431 String opcode; 1432 { 1433 register int size; 1434 register unsigned int controlword; 1435 short w; 1436 1437 size = mapsize(inst); 1438 instread(w); 1439 controlword = w >> 11; 1440 if (printing) { 1441 printf("\t%s%c\t", opcode, suffix(size)); 1442 } 1443 if (controlword & 1){ 1444 controlword >>= 1; 1445 if (printing) { 1446 printf((controlword&0x8) ? "a%D," : "d%D,", controlword&7 ); 1447 } 1448 printEA(inst&0xff, size); 1449 } else { 1450 controlword >>= 1; 1451 printEA(inst&0xff, size); 1452 if (printing) { 1453 printf((controlword&0x8) ? ",a%D" : ",d%D", controlword&7); 1454 } 1455 } 1456 } 1457 1458 public omovc(inst, opcode) 1459 long inst; 1460 String opcode; 1461 { 1462 register unsigned int controlword; 1463 String creg; 1464 short w; 1465 1466 instread(w); 1467 if (printing) { 1468 controlword = w; 1469 switch (controlword & 0xfff) { 1470 case 0: 1471 creg = "sfc"; 1472 break; 1473 1474 case 1: 1475 creg = "dfc"; 1476 break; 1477 1478 case 0x800: 1479 creg = "usp"; 1480 break; 1481 1482 case 0x801: 1483 creg = "vbr"; 1484 break; 1485 1486 default: 1487 creg = "???"; 1488 break; 1489 } 1490 controlword >>= 12; 1491 if (inst & 1){ 1492 printf((controlword&0x8) ? "%sa%D,%s" : "%sd%D,%s", 1493 opcode, controlword&7, creg ); 1494 } else { 1495 printf((controlword&0x8) ? "%s%s,a%D" : "%s%s,d%D", 1496 opcode, creg, controlword&7 ); 1497 } 1498 } 1499 } 1500 1501 /* 1502 * Compute the next address that will be executed from the given one. 1503 * If "isnext" is true then consider a procedure call as straight line code. 1504 * 1505 * Unconditional branches we just follow, for conditional branches 1506 * we continue execution to the current location and then single step 1507 * the machine. 1508 */ 1509 1510 public Address nextaddr(startaddr, isnext) 1511 Address startaddr; 1512 Boolean isnext; 1513 { 1514 Optab *o; 1515 short inst; 1516 1517 instaddr = usignal(process); 1518 if (instaddr == 0 or instaddr == 1) { 1519 following = true; 1520 followcalls = (Boolean) (not isnext); 1521 printing = false; 1522 iread(&inst, startaddr, sizeof(inst)); 1523 instaddr = startaddr + sizeof(inst); 1524 o = decode(inst, startaddr); 1525 if (o->mask == 0) { 1526 fprintf(stderr, 1527 "[internal error: undecodable op at 0x%x]\n", startaddr); 1528 fflush(stderr); 1529 } else { 1530 (*o->opfun)(inst, o->farg); 1531 } 1532 following = false; 1533 } 1534 return instaddr; 1535 } 1536 1537 /* 1538 * Step to the given address and then execute one instruction past it. 1539 * Set instaddr to the new instruction address. 1540 */ 1541 1542 private steppast(addr) 1543 Address addr; 1544 { 1545 stepto(addr); 1546 pstep(process, DEFSIG); 1547 pc = reg(PROGCTR); 1548 instaddr = pc; 1549 } 1550 1551 /* 1552 * Enter a procedure by creating and executing a call instruction. 1553 */ 1554 1555 #define CALLSIZE 6 /* size of call instruction */ 1556 1557 public beginproc(p) 1558 Symbol p; 1559 { 1560 char save[CALLSIZE]; 1561 struct { 1562 short op; 1563 char addr[sizeof(long)]; /* unaligned long */ 1564 } call; 1565 long dest; 1566 1567 pc = CODESTART + 6; 1568 iread(save, pc, sizeof(save)); 1569 call.op = 0x4eb9; /* jsr */ 1570 dest = codeloc(p) - FUNCOFFSET; 1571 mov(&dest, call.addr, sizeof(call.addr)); 1572 iwrite(&call, pc, sizeof(call)); 1573 setreg(PROGCTR, pc); 1574 pstep(process, DEFSIG); 1575 iwrite(save, pc, sizeof(save)); 1576 pc = reg(PROGCTR); 1577 if (not isbperr()) { 1578 printstatus(); 1579 } 1580 /* 1581 * Execute link instruction so the return addr is visible. 1582 */ 1583 pstep(process, DEFSIG); 1584 pc = reg(PROGCTR); 1585 if (not isbperr()) { 1586 printstatus(); 1587 } 1588 } 1589 1590 /* 1591 * Special variables for debugging the kernel. 1592 */ 1593 1594 public integer masterpcbb; 1595 public integer slr; 1596 public struct pte *sbr; 1597 private struct pcb pcb; 1598 1599 public getpcb () 1600 { 1601 integer i; 1602 1603 fseek(corefile, masterpcbb & ~0x80000000, 0); 1604 get(corefile, pcb); 1605 pcb.pcb_p0lr &= ~AST_CLR; 1606 printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", 1607 pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr 1608 ); 1609 # ifdef sun 1610 for (i = 0; i < 14; i++) { 1611 setreg(i, pcb.pcb_regs.val[i]); 1612 } 1613 # else /* IRIS */ 1614 for (i = 0; i < 14; i++) { 1615 setreg(i, pcb.pcb_regs[i]); 1616 } 1617 # endif 1618 } 1619 1620 public copyregs (savreg, reg) 1621 Word savreg[], reg[]; 1622 { 1623 reg[0] = savreg[R0]; 1624 reg[1] = savreg[R1]; 1625 reg[2] = savreg[R2]; 1626 reg[3] = savreg[R3]; 1627 reg[4] = savreg[R4]; 1628 reg[5] = savreg[R5]; 1629 reg[6] = savreg[R6]; 1630 reg[7] = savreg[R7]; 1631 reg[8] = savreg[AR0]; 1632 reg[9] = savreg[AR1]; 1633 reg[10] = savreg[AR2]; 1634 reg[11] = savreg[AR3]; 1635 reg[12] = savreg[AR4]; 1636 reg[13] = savreg[AR5]; 1637 reg[14] = savreg[AR6]; 1638 reg[15] = savreg[AR7]; 1639 reg[PROGCTR] = savreg[PC]; 1640 } 1641 1642 /* 1643 * Map a virtual address to a physical address. 1644 * XXX THIS CAN'T BE RIGHT... XXX 1645 */ 1646 1647 public Address vmap (addr) 1648 Address addr; 1649 { 1650 Address r; 1651 integer v, n; 1652 struct pte pte; 1653 1654 r = addr & ~0xc0000000; 1655 v = btop(r); 1656 switch (addr&0xc0000000) { 1657 case 0xc0000000: 1658 case 0x80000000: 1659 /* 1660 * In system space, so get system pte. 1661 * If it is valid or reclaimable then the physical address 1662 * is the combination of its page number and the page offset 1663 * of the original address. 1664 */ 1665 if (v >= slr) { 1666 error("address %x out of segment", addr); 1667 } 1668 r = ((long) (sbr + v)) & ~0x80000000; 1669 goto simple; 1670 1671 case 0x40000000: 1672 /* 1673 * In p1 space, must not be in shadow region. 1674 */ 1675 if (v < pcb.pcb_p1lr) { 1676 error("address %x out of segment", addr); 1677 } 1678 r = (Address) (pcb.pcb_p1br + v); 1679 break; 1680 1681 case 0x00000000: 1682 /* 1683 * In p0 space, must not be off end of region. 1684 */ 1685 if (v >= pcb.pcb_p0lr) { 1686 error("address %x out of segment", addr); 1687 } 1688 r = (Address) (pcb.pcb_p0br + v); 1689 break; 1690 1691 default: 1692 /* do nothing */ 1693 break; 1694 } 1695 /* 1696 * For p0/p1 address, user-level page table should be in 1697 * kernel virtual memory. Do second-level indirect by recursing. 1698 */ 1699 if ((r & 0x80000000) == 0) { 1700 error("bad p0br or p1br in pcb"); 1701 } 1702 r = vmap(r); 1703 simple: 1704 /* 1705 * "r" is now the address of the pte of the page 1706 * we are interested in; get the pte and paste up the physical address. 1707 */ 1708 fseek(corefile, r, 0); 1709 n = fread(&pte, sizeof(pte), 1, corefile); 1710 if (n != 1) { 1711 error("page table botch (fread at %x returns %d)", r, n); 1712 } 1713 if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { 1714 error("page no valid or reclamable"); 1715 } 1716 return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); 1717 } 1718 1719 /* 1720 * Extract a bit field from an integer. 1721 */ 1722 1723 public integer extractField (s) 1724 Symbol s; 1725 { 1726 integer nbytes, nbits, n, r, off, len; 1727 1728 off = s->symvalue.field.offset; 1729 len = s->symvalue.field.length; 1730 nbytes = size(s); 1731 n = 0; 1732 if (nbytes > sizeof(n)) { 1733 printf("[bad size in extractField -- word assumed]\n"); 1734 nbytes = sizeof(n); 1735 } 1736 popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes)); 1737 nbits = nbytes * BITSPERBYTE; 1738 r = n >> (nbits - ((off mod nbits) + len)); 1739 r &= ((1 << len) - 1); 1740 return r; 1741 } 1742 1743 /* 1744 * Change the length of a value in memory according to a given difference 1745 * in the lengths of its new and old types. 1746 */ 1747 1748 public loophole (oldlen, newlen) 1749 integer oldlen, newlen; 1750 { 1751 integer i, n; 1752 Stack *oldsp; 1753 1754 n = newlen - oldlen; 1755 oldsp = sp - oldlen; 1756 if (n > 0) { 1757 for (i = oldlen - 1; i >= 0; i--) { 1758 oldsp[n + i] = oldsp[i]; 1759 } 1760 for (i = 0; i < n; i++) { 1761 oldsp[i] = '\0'; 1762 } 1763 } else { 1764 for (i = 0; i < newlen; i++) { 1765 oldsp[i] = oldsp[i - n]; 1766 } 1767 } 1768 sp += n; 1769 } 1770