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