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