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[] = "@(#)vax.c 5.8 (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 #define NREG 16 37 38 #define ARGP 12 39 #define FRP 13 40 #define STKP 14 41 #define PROGCTR 15 42 43 #define CODESTART 0 44 #define FUNCOFFSET 2 45 46 #define nargspassed(frame) argn(0, frame) 47 48 #define BITSPERBYTE 8 49 #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 50 51 /* 52 * This magic macro enables us to look at the process' registers 53 * in its user structure. 54 */ 55 56 #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg))) 57 58 #include "source.h" 59 #include "symbols.h" 60 #include <signal.h> 61 #include <sys/param.h> 62 #include <machine/psl.h> 63 #include <machine/pte.h> 64 #include <sys/user.h> 65 #undef DELETE /* XXX */ 66 #include <sys/vm.h> 67 #include <machine/reg.h> 68 69 Address pc; 70 Address prtaddr; 71 72 #endif 73 74 /* 75 * Indices into u. for use in collecting registers values. 76 */ 77 public int rloc[] ={ 78 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC 79 }; 80 81 private Address printop(); 82 83 private Optab *ioptab[256]; /* index by opcode to optab */ 84 private Optab *esctab[256]; /* for extended opcodes */ 85 86 /* 87 * Initialize the opcode lookup table. 88 */ 89 public optab_init() 90 { 91 register Optab *p; 92 93 for (p = optab; p->iname; p++) { 94 if (p->format == O_ESCD) { 95 esctab[p->val] = p; 96 } else if (p->format != O_ESCD && p->format != O_ESCE) { 97 ioptab[p->val] = p; 98 } 99 } 100 } 101 102 /* 103 * Decode and print the instructions within the given address range. 104 */ 105 106 public printinst(lowaddr, highaddr) 107 Address lowaddr; 108 Address highaddr; 109 { 110 register Address addr; 111 112 for (addr = lowaddr; addr <= highaddr; ) { 113 addr = printop(addr); 114 } 115 prtaddr = addr; 116 } 117 118 /* 119 * Another approach: print n instructions starting at the given address. 120 */ 121 122 public printninst(count, addr) 123 int count; 124 Address addr; 125 { 126 register Integer i; 127 register Address newaddr; 128 129 if (count <= 0) { 130 error("non-positive repetition count"); 131 } else { 132 newaddr = addr; 133 for (i = 0; i < count; i++) { 134 newaddr = printop(newaddr); 135 } 136 prtaddr = newaddr; 137 } 138 } 139 140 /* 141 * Print the contents of the addresses within the given range 142 * according to the given format. 143 */ 144 145 typedef struct { 146 String name; 147 String printfstring; 148 int length; 149 } Format; 150 151 private Format fmt[] = { 152 { "d", " %d", sizeof(short) }, 153 { "D", " %ld", sizeof(long) }, 154 { "o", " %o", sizeof(short) }, 155 { "O", " %lo", sizeof(long) }, 156 { "x", " %04x", sizeof(short) }, 157 { "X", " %08x", sizeof(long) }, 158 { "b", " \\%o", sizeof(char) }, 159 { "c", " '%c'", sizeof(char) }, 160 { "s", "%c", sizeof(char) }, 161 { "f", " %f", sizeof(float) }, 162 { "g", " %g", sizeof(double) }, 163 { nil, nil, 0 } 164 }; 165 166 private Format *findformat(s) 167 String s; 168 { 169 register Format *f; 170 171 f = &fmt[0]; 172 while (f->name != nil and not streq(f->name, s)) { 173 ++f; 174 } 175 if (f->name == nil) { 176 error("bad print format \"%s\"", s); 177 } 178 return f; 179 } 180 181 /* 182 * Retrieve and print out the appropriate data in the given format. 183 * Floats have to be handled specially to allow the compiler to 184 * convert them to doubles when passing to printf. 185 */ 186 187 private printformat (f, addr) 188 Format *f; 189 Address addr; 190 { 191 union { 192 char charv; 193 short shortv; 194 int intv; 195 float floatv; 196 double doublev; 197 } value; 198 199 value.intv = 0; 200 dread(&value, addr, f->length); 201 if (streq(f->name, "f")) { 202 printf(f->printfstring, value.floatv); 203 } else { 204 printf(f->printfstring, value); 205 } 206 } 207 208 public Address printdata(lowaddr, highaddr, format) 209 Address lowaddr; 210 Address highaddr; 211 String format; 212 { 213 int n; 214 register Address addr; 215 Format *f; 216 217 if (lowaddr > highaddr) { 218 error("first address larger than second"); 219 } 220 f = findformat(format); 221 n = 0; 222 for (addr = lowaddr; addr <= highaddr; addr += f->length) { 223 if (n == 0) { 224 printf("%08x: ", addr); 225 } 226 printformat(f, addr); 227 ++n; 228 if (n >= (16 div f->length)) { 229 printf("\n"); 230 n = 0; 231 } 232 } 233 if (n != 0) { 234 printf("\n"); 235 } 236 prtaddr = addr; 237 return addr; 238 } 239 240 /* 241 * The other approach is to print n items starting with a given address. 242 */ 243 244 public printndata(count, startaddr, format) 245 int count; 246 Address startaddr; 247 String format; 248 { 249 int i, n; 250 Address addr; 251 Format *f; 252 Boolean isstring; 253 char c; 254 255 if (count <= 0) { 256 error("non-positive repetition count"); 257 } 258 f = findformat(format); 259 isstring = (Boolean) streq(f->name, "s"); 260 n = 0; 261 addr = startaddr; 262 for (i = 0; i < count; i++) { 263 if (n == 0) { 264 printf("%08x: ", addr); 265 } 266 if (isstring) { 267 printf("\""); 268 dread(&c, addr, sizeof(char)); 269 while (c != '\0') { 270 printchar(c); 271 ++addr; 272 dread(&c, addr, sizeof(char)); 273 } 274 printf("\"\n"); 275 n = 0; 276 addr += sizeof(String); 277 } else { 278 printformat(f, addr); 279 ++n; 280 if (n >= (16 div f->length)) { 281 printf("\n"); 282 n = 0; 283 } 284 addr += f->length; 285 } 286 } 287 if (n != 0) { 288 printf("\n"); 289 } 290 prtaddr = addr; 291 } 292 293 /* 294 * Print out a value according to the given format. 295 */ 296 297 public printvalue(v, format) 298 long v; 299 String format; 300 { 301 Format *f; 302 char *p, *q; 303 304 f = findformat(format); 305 if (streq(f->name, "s")) { 306 putchar('"'); 307 p = (char *) &v; 308 q = p + sizeof(v); 309 while (p < q) { 310 printchar(*p); 311 ++p; 312 } 313 putchar('"'); 314 } else { 315 printf(f->printfstring, v); 316 } 317 putchar('\n'); 318 } 319 320 /* 321 * Print out an execution time error. 322 * Assumes the source position of the error has been calculated. 323 * 324 * Have to check if the -r option was specified; if so then 325 * the object file information hasn't been read in yet. 326 */ 327 328 public printerror() 329 { 330 extern Integer sys_nsig; 331 extern String sys_siglist[]; 332 integer err; 333 334 if (isfinished(process)) { 335 err = exitcode(process); 336 if (err == 0) { 337 printf("\"%s\" terminated normally\n", objname); 338 } else { 339 printf("\"%s\" terminated abnormally (exit code %d)\n", 340 objname, err 341 ); 342 } 343 erecover(); 344 } 345 err = errnum(process); 346 putchar('\n'); 347 printsig(err); 348 putchar(' '); 349 printloc(); 350 putchar('\n'); 351 if (curline > 0) { 352 printlines(curline, curline); 353 } else { 354 printinst(pc, pc); 355 } 356 erecover(); 357 } 358 359 /* 360 * Print out a signal. 361 */ 362 363 private String illinames[] = { 364 "reserved addressing fault", 365 "privileged instruction fault", 366 "reserved operand fault" 367 }; 368 369 private String fpenames[] = { 370 nil, 371 "integer overflow trap", 372 "integer divide by zero trap", 373 "floating overflow trap", 374 "floating/decimal divide by zero trap", 375 "floating underflow trap", 376 "decimal overflow trap", 377 "subscript out of range trap", 378 "floating overflow fault", 379 "floating divide by zero fault", 380 "floating underflow fault" 381 }; 382 383 public printsig (signo) 384 integer signo; 385 { 386 integer code; 387 388 if (signo < 0 or signo > sys_nsig) { 389 printf("[signal %d]", signo); 390 } else { 391 printf("%s", sys_siglist[signo]); 392 } 393 code = errcode(process); 394 if (signo == SIGILL) { 395 if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 396 printf(" (%s)", illinames[code]); 397 } 398 } else if (signo == SIGFPE) { 399 if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 400 printf(" (%s)", fpenames[code]); 401 } 402 } 403 } 404 405 /* 406 * Note the termination of the program. We do this so as to avoid 407 * having the process exit, which would make the values of variables 408 * inaccessible. We do want to flush all output buffers here, 409 * otherwise it'll never get done. 410 */ 411 412 public endprogram() 413 { 414 Integer exitcode; 415 416 stepto(nextaddr(pc, true)); 417 printnews(); 418 exitcode = argn(1, nil); 419 if (exitcode != 0) { 420 printf("\nexecution completed (exit code %d)\n", exitcode); 421 } else { 422 printf("\nexecution completed\n"); 423 } 424 getsrcpos(); 425 erecover(); 426 } 427 428 /* 429 * Single step the machine a source line (or instruction if "inst_tracing" 430 * is true). If "isnext" is true, skip over procedure calls. 431 */ 432 433 private Address getcall(); 434 435 public dostep(isnext) 436 Boolean isnext; 437 { 438 register Address addr; 439 register Lineno line; 440 String filename; 441 Address startaddr; 442 443 startaddr = pc; 444 addr = nextaddr(pc, isnext); 445 if (not inst_tracing and nlhdr.nlines != 0) { 446 line = linelookup(addr); 447 while (line == 0) { 448 addr = nextaddr(addr, isnext); 449 line = linelookup(addr); 450 } 451 curline = line; 452 } else { 453 curline = 0; 454 } 455 stepto(addr); 456 filename = srcfilename(addr); 457 setsource(filename); 458 } 459 460 typedef char Bpinst; 461 462 #define BP_OP O_BPT /* breakpoint trap */ 463 464 #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 465 466 /* 467 * Setting a breakpoint at a location consists of saving 468 * the word at the location and poking a BP_OP there. 469 * 470 * We save the locations and words on a list for use in unsetting. 471 */ 472 473 typedef struct Savelist *Savelist; 474 475 struct Savelist { 476 Address location; 477 Bpinst save; 478 short refcount; 479 Savelist link; 480 }; 481 482 private Savelist savelist; 483 484 /* 485 * Set a breakpoint at the given address. Only save the word there 486 * if it's not already a breakpoint. 487 */ 488 489 public setbp(addr) 490 Address addr; 491 { 492 Bpinst w, save; 493 register Savelist newsave, s; 494 495 for (s = savelist; s != nil; s = s->link) { 496 if (s->location == addr) { 497 s->refcount++; 498 return; 499 } 500 } 501 iread(&save, addr, sizeof(save)); 502 newsave = new(Savelist); 503 newsave->location = addr; 504 newsave->save = save; 505 newsave->refcount = 1; 506 newsave->link = savelist; 507 savelist = newsave; 508 w = BP_OP; 509 iwrite(&w, addr, sizeof(w)); 510 } 511 512 /* 513 * Unset a breakpoint; unfortunately we have to search the SAVELIST 514 * to find the saved value. The assumption is that the SAVELIST will 515 * usually be quite small. 516 */ 517 518 public unsetbp(addr) 519 Address addr; 520 { 521 register Savelist s, prev; 522 523 prev = nil; 524 for (s = savelist; s != nil; s = s->link) { 525 if (s->location == addr) { 526 iwrite(&s->save, addr, sizeof(s->save)); 527 s->refcount--; 528 if (s->refcount == 0) { 529 if (prev == nil) { 530 savelist = s->link; 531 } else { 532 prev->link = s->link; 533 } 534 dispose(s); 535 } 536 return; 537 } 538 prev = s; 539 } 540 panic("unsetbp: couldn't find address %d", addr); 541 } 542 543 /* 544 * VAX instruction decoder, derived from adb. 545 */ 546 547 private Address printop(addr) 548 Address addr; 549 { 550 register Optab *op; 551 VaxOpcode ins; 552 unsigned char mode; 553 int argtype, amode, argno, argval; 554 String reg; 555 Boolean indexf; 556 short offset; 557 558 argval = 0; 559 indexf = false; 560 printf("%08x ", addr); 561 iread(&ins, addr, sizeof(ins)); 562 addr += 1; 563 if (ins == O_ESCF) { 564 iread(&ins, addr, sizeof(ins)); 565 addr += 1; 566 op = ioptab[ins]; 567 } else if (ins == O_ESCD) { 568 iread(&ins, addr, sizeof(ins)); 569 addr += 1; 570 op = esctab[ins]; 571 } else { 572 op = ioptab[ins]; 573 } 574 if (op == nil) { 575 printf("[unrecognized opcode %#0x]\n", ins); 576 return addr; 577 } 578 printf("%s", op->iname); 579 for (argno = 0; argno < op->numargs; argno++) { 580 if (indexf == true) { 581 indexf = false; 582 } else if (argno == 0) { 583 printf("\t"); 584 } else { 585 printf(","); 586 } 587 argtype = op->argtype[argno]; 588 if (is_branch_disp(argtype)) { 589 mode = 0xAF + (typelen(argtype) << 5); 590 } else { 591 iread(&mode, addr, sizeof(mode)); 592 addr += 1; 593 } 594 reg = regname[regnm(mode)]; 595 amode = addrmode(mode); 596 switch (amode) { 597 case LITSHORT: 598 case LITUPTO31: 599 case LITUPTO47: 600 case LITUPTO63: 601 if (typelen(argtype) == TYPF || typelen(argtype) == TYPD || 602 typelen(argtype) == TYPG || typelen(argtype) == TYPH) 603 printf("$%s", fltimm[mode]); 604 else 605 printf("$%x", mode); 606 argval = mode; 607 break; 608 609 case INDEX: 610 printf("[%s]", reg); 611 indexf = true; 612 argno--; 613 break; 614 615 case REG: 616 printf("%s", reg); 617 break; 618 619 case REGDEF: 620 printf("(%s)", reg); 621 break; 622 623 case AUTODEC: 624 printf("-(%s)", reg); 625 break; 626 627 case AUTOINC: 628 if (reg != regname[PROGCTR]) { 629 printf("(%s)+", reg); 630 } else { 631 printf("$"); 632 switch (typelen(argtype)) { 633 case TYPB: 634 argval = printdisp(addr, 1, reg, amode); 635 addr += 1; 636 break; 637 638 case TYPW: 639 argval = printdisp(addr, 2, reg, amode); 640 addr += 2; 641 break; 642 643 case TYPL: 644 argval = printdisp(addr, 4, reg, amode); 645 addr += 4; 646 break; 647 648 case TYPF: 649 iread(&argval, addr, sizeof(argval)); 650 if ((argval & 0xffff007f) == 0x8000) { 651 printf("[reserved operand]"); 652 } else { 653 printf("%g", *(float *)&argval); 654 } 655 addr += 4; 656 break; 657 658 case TYPD: 659 /* XXX this bags the low order bits */ 660 iread(&argval, addr, sizeof(argval)); 661 if ((argval & 0xffff007f) == 0x8000) { 662 printf("[reserved operand]"); 663 } else { 664 printf("%g", *(float *)&argval); 665 } 666 addr += 8; 667 break; 668 669 case TYPG: 670 case TYPQ: 671 iread(&argval, addr+4, sizeof(argval)); 672 printf("%08x", argval); 673 iread(&argval, addr, sizeof(argval)); 674 printf("%08x", argval); 675 addr += 8; 676 break; 677 678 case TYPH: 679 case TYPO: 680 iread(&argval, addr+12, sizeof(argval)); 681 printf("%08x", argval); 682 iread(&argval, addr+8, sizeof(argval)); 683 printf("%08x", argval); 684 iread(&argval, addr+4, sizeof(argval)); 685 printf("%08x", argval); 686 iread(&argval, addr, sizeof(argval)); 687 printf("%08x", argval); 688 addr += 16; 689 break; 690 } 691 } 692 break; 693 694 case AUTOINCDEF: 695 if (reg == regname[PROGCTR]) { 696 printf("*$"); 697 argval = printdisp(addr, 4, reg, amode); 698 addr += 4; 699 } else { 700 printf("*(%s)+", reg); 701 } 702 break; 703 704 case BYTEDISP: 705 argval = printdisp(addr, 1, reg, amode); 706 addr += 1; 707 break; 708 709 case BYTEDISPDEF: 710 printf("*"); 711 argval = printdisp(addr, 1, reg, amode); 712 addr += 1; 713 break; 714 715 case WORDDISP: 716 argval = printdisp(addr, 2, reg, amode); 717 addr += 2; 718 break; 719 720 case WORDDISPDEF: 721 printf("*"); 722 argval = printdisp(addr, 2, reg, amode); 723 addr += 2; 724 break; 725 726 case LONGDISP: 727 argval = printdisp(addr, 4, reg, amode); 728 addr += 4; 729 break; 730 731 case LONGDISPDEF: 732 printf("*"); 733 argval = printdisp(addr, 4, reg, amode); 734 addr += 4; 735 break; 736 } 737 } 738 if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 739 for (argno = 0; argno <= argval; argno++) { 740 iread(&offset, addr, sizeof(offset)); 741 printf("\n\t\t%d", offset); 742 addr += 2; 743 } 744 } 745 printf("\n"); 746 return addr; 747 } 748 749 /* 750 * Print the displacement of an instruction that uses displacement 751 * addressing. 752 */ 753 754 private int printdisp(addr, nbytes, reg, mode) 755 Address addr; 756 int nbytes; 757 char *reg; 758 int mode; 759 { 760 char byte; 761 short hword; 762 int argval; 763 Symbol f; 764 765 switch (nbytes) { 766 case 1: 767 iread(&byte, addr, sizeof(byte)); 768 argval = byte; 769 break; 770 771 case 2: 772 iread(&hword, addr, sizeof(hword)); 773 argval = hword; 774 break; 775 776 case 4: 777 iread(&argval, addr, sizeof(argval)); 778 break; 779 } 780 if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 781 argval += addr + nbytes; 782 } 783 if (reg == regname[PROGCTR]) { 784 f = whatblock((Address) argval + 2); 785 if (codeloc(f) == argval + 2) { 786 printf("%s", symname(f)); 787 } else { 788 printf("%x", argval); 789 } 790 } else { 791 if (varIsSet("$hexoffsets")) { 792 if (argval < 0) { 793 printf("-%x(%s)", -(argval), reg); 794 } else { 795 printf("%x(%s)", argval, reg); 796 } 797 } else { 798 printf("%d(%s)", argval, reg); 799 } 800 } 801 return argval; 802 } 803 804 /* 805 * Compute the next address that will be executed from the given one. 806 * If "isnext" is true then consider a procedure call as straight line code. 807 * 808 * We must unfortunately do much of the same work that is necessary 809 * to print instructions. In addition we have to deal with branches. 810 * Unconditional branches we just follow, for conditional branches 811 * we continue execution to the current location and then single step 812 * the machine. We assume that the last argument in an instruction 813 * that branches is the branch address (or relative offset). 814 */ 815 816 private Address findnextaddr(); 817 818 public Address nextaddr(startaddr, isnext) 819 Address startaddr; 820 boolean isnext; 821 { 822 Address addr; 823 824 addr = usignal(process); 825 if (addr == 0 or addr == 1) { 826 addr = findnextaddr(startaddr, isnext); 827 } 828 return addr; 829 } 830 831 /* 832 * Determine if it's ok to skip function f entered by instruction ins. 833 * If so, we're going to compute the return address and step to it. 834 * Therefore we cannot skip over a function entered by a jsb or bsb, 835 * since the return address is not easily computed for them. 836 */ 837 838 private boolean skipfunc (ins, f) 839 VaxOpcode ins; 840 Symbol f; 841 { 842 boolean b; 843 844 b = (boolean) ( 845 ins != O_JSB and ins != O_BSBB and ins != O_BSBW and 846 not inst_tracing and nlhdr.nlines != 0 and 847 nosource(curfunc) and canskip(curfunc) 848 ); 849 return b; 850 } 851 852 private Address findnextaddr(startaddr, isnext) 853 Address startaddr; 854 Boolean isnext; 855 { 856 register Address addr; 857 register Optab *op; 858 VaxOpcode ins, ins2; 859 unsigned char mode; 860 int argtype, amode, argno, argval; 861 String r; 862 Boolean indexf; 863 enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 864 865 argval = 0; 866 indexf = false; 867 addr = startaddr; 868 iread(&ins, addr, sizeof(ins)); 869 switch (ins) { 870 /* 871 * It used to be that unconditional jumps and branches were handled 872 * by taking their destination address as the next address. While 873 * saving the cost of starting up the process, this approach 874 * doesn't work when jumping indirect (since the value in the 875 * register might not yet have been set). 876 * 877 * So unconditional jumps and branches are now handled the same way 878 * as conditional jumps and branches. 879 * 880 case O_BRB: 881 case O_BRW: 882 addrstatus = BRANCH; 883 break; 884 * 885 */ 886 887 case O_BSBB: 888 case O_BSBW: 889 case O_JSB: 890 case O_CALLG: 891 case O_CALLS: 892 addrstatus = KNOWN; 893 stepto(addr); 894 pstep(process, DEFSIG); 895 addr = reg(PROGCTR); 896 pc = addr; 897 setcurfunc(whatblock(pc)); 898 if (not isbperr()) { 899 printstatus(); 900 /* NOTREACHED */ 901 } 902 bpact(); 903 if (isnext or skipfunc(ins, curfunc)) { 904 addrstatus = KNOWN; 905 addr = return_addr(); 906 stepto(addr); 907 bpact(); 908 } else { 909 callnews(/* iscall = */ true); 910 } 911 break; 912 913 case O_RSB: 914 case O_RET: 915 addrstatus = KNOWN; 916 stepto(addr); 917 callnews(/* iscall = */ false); 918 pstep(process, DEFSIG); 919 addr = reg(PROGCTR); 920 pc = addr; 921 if (not isbperr()) { 922 printstatus(); 923 } 924 bpact(); 925 break; 926 927 case O_BRB: case O_BRW: 928 case O_JMP: /* because it may be jmp (r1) */ 929 case O_BNEQ: case O_BEQL: case O_BGTR: 930 case O_BLEQ: case O_BGEQ: case O_BLSS: 931 case O_BGTRU: case O_BLEQU: case O_BVC: 932 case O_BVS: case O_BCC: case O_BCS: 933 case O_CASEB: case O_CASEW: case O_CASEL: 934 case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 935 case O_BBSC: case O_BBCC: case O_BBSSI: 936 case O_BBCCI: case O_BLBS: case O_BLBC: 937 case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 938 case O_SOBGEQ: case O_SOBGTR: 939 case O_ESCF: /* bugchecks */ 940 branches: 941 addrstatus = KNOWN; 942 stepto(addr); 943 pstep(process, DEFSIG); 944 addr = reg(PROGCTR); 945 pc = addr; 946 if (not isbperr()) { 947 printstatus(); 948 } 949 break; 950 951 case O_ESCD: 952 iread(&ins2, addr+1, sizeof(ins2)); 953 if (ins2 == O_ACBF || ins2 == O_ACBD) 954 /* actually ACBG and ACBH */ 955 goto branches; 956 /* fall through */ 957 958 default: 959 addrstatus = SEQUENTIAL; 960 break; 961 } 962 if (addrstatus != KNOWN) { 963 addr += 1; 964 if (ins == O_ESCD) { 965 ins = ins2; 966 addr += 1; 967 op = esctab[ins]; 968 if (op == nil) { 969 printf("[bad extended opcode %#x in findnextaddr]\n", ins); 970 return addr; 971 } 972 } else { 973 op = ioptab[ins]; 974 if (op == nil) { 975 printf("[bad opcode %#x in findnextaddr]\n", ins); 976 return addr; 977 } 978 } 979 for (argno = 0; argno < op->numargs; argno++) { 980 if (indexf == true) { 981 indexf = false; 982 } 983 argtype = op->argtype[argno]; 984 if (is_branch_disp(argtype)) { 985 mode = 0xAF + (typelen(argtype) << 5); 986 } else { 987 iread(&mode, addr, sizeof(mode)); 988 addr += 1; 989 } 990 r = regname[regnm(mode)]; 991 amode = addrmode(mode); 992 switch (amode) { 993 case LITSHORT: 994 case LITUPTO31: 995 case LITUPTO47: 996 case LITUPTO63: 997 argval = mode; 998 break; 999 1000 case INDEX: 1001 indexf = true; 1002 --argno; 1003 break; 1004 1005 case REG: 1006 case REGDEF: 1007 case AUTODEC: 1008 break; 1009 1010 case AUTOINC: 1011 if (r == regname[PROGCTR]) { 1012 switch (typelen(argtype)) { 1013 case TYPB: 1014 argval = getdisp(addr, 1, r, amode); 1015 addr += 1; 1016 break; 1017 1018 case TYPW: 1019 argval = getdisp(addr, 2, r, amode); 1020 addr += 2; 1021 break; 1022 1023 case TYPL: 1024 argval = getdisp(addr, 4, r, amode); 1025 addr += 4; 1026 break; 1027 1028 case TYPF: 1029 iread(&argval, addr, sizeof(argval)); 1030 addr += 4; 1031 break; 1032 1033 case TYPQ: 1034 case TYPD: 1035 case TYPG: 1036 iread(&argval, addr+4, sizeof(argval)); 1037 addr += 8; 1038 break; 1039 1040 case TYPO: 1041 case TYPH: 1042 iread(&argval, addr+12, sizeof(argval)); 1043 addr += 16; 1044 break; 1045 } 1046 } 1047 break; 1048 1049 case AUTOINCDEF: 1050 if (r == regname[PROGCTR]) { 1051 argval = getdisp(addr, 4, r, amode); 1052 addr += 4; 1053 } 1054 break; 1055 1056 case BYTEDISP: 1057 case BYTEDISPDEF: 1058 argval = getdisp(addr, 1, r, amode); 1059 addr += 1; 1060 break; 1061 1062 case WORDDISP: 1063 case WORDDISPDEF: 1064 argval = getdisp(addr, 2, r, amode); 1065 addr += 2; 1066 break; 1067 1068 case LONGDISP: 1069 case LONGDISPDEF: 1070 argval = getdisp(addr, 4, r, amode); 1071 addr += 4; 1072 break; 1073 } 1074 } 1075 if (ins == O_CALLS or ins == O_CALLG) { 1076 argval += 2; 1077 } 1078 if (addrstatus == BRANCH) { 1079 addr = argval; 1080 } 1081 } 1082 return addr; 1083 } 1084 1085 /* 1086 * Get the displacement of an instruction that uses displacement addressing. 1087 */ 1088 1089 private int getdisp(addr, nbytes, reg, mode) 1090 Address addr; 1091 int nbytes; 1092 String reg; 1093 int mode; 1094 { 1095 char byte; 1096 short hword; 1097 int argval; 1098 1099 switch (nbytes) { 1100 case 1: 1101 iread(&byte, addr, sizeof(byte)); 1102 argval = byte; 1103 break; 1104 1105 case 2: 1106 iread(&hword, addr, sizeof(hword)); 1107 argval = hword; 1108 break; 1109 1110 case 4: 1111 iread(&argval, addr, sizeof(argval)); 1112 break; 1113 } 1114 if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 1115 argval += addr + nbytes; 1116 } 1117 return argval; 1118 } 1119 1120 /* 1121 * Enter a procedure by creating and executing a call instruction. 1122 */ 1123 1124 #define CALLSIZE 7 /* size of call instruction */ 1125 1126 public beginproc(p, argc) 1127 Symbol p; 1128 Integer argc; 1129 { 1130 char save[CALLSIZE]; 1131 struct { 1132 VaxOpcode op; 1133 unsigned char numargs; 1134 unsigned char mode; 1135 char addr[sizeof(long)]; /* unaligned long */ 1136 } call; 1137 long dest; 1138 1139 pc = 2; 1140 iread(save, pc, sizeof(save)); 1141 call.op = O_CALLS; 1142 call.numargs = argc; 1143 call.mode = 0xef; 1144 dest = codeloc(p) - 2 - (pc + 7); 1145 mov(&dest, call.addr, sizeof(call.addr)); 1146 iwrite(&call, pc, sizeof(call)); 1147 setreg(PROGCTR, pc); 1148 pstep(process, DEFSIG); 1149 iwrite(save, pc, sizeof(save)); 1150 pc = reg(PROGCTR); 1151 if (not isbperr()) { 1152 printstatus(); 1153 } 1154 } 1155 1156 /* 1157 * Special variables for debugging the kernel. 1158 */ 1159 1160 public integer masterpcbb; 1161 public integer slr; 1162 public struct pte *sbr; 1163 private struct pcb pcb; 1164 1165 public getpcb () 1166 { 1167 integer i; 1168 1169 fseek(corefile, masterpcbb & ~0x80000000, 0); 1170 get(corefile, pcb); 1171 pcb.pcb_p0lr &= ~AST_CLR; 1172 printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", 1173 pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr 1174 ); 1175 setreg(0, pcb.pcb_r0); 1176 setreg(1, pcb.pcb_r1); 1177 setreg(2, pcb.pcb_r2); 1178 setreg(3, pcb.pcb_r3); 1179 setreg(4, pcb.pcb_r4); 1180 setreg(5, pcb.pcb_r5); 1181 setreg(6, pcb.pcb_r6); 1182 setreg(7, pcb.pcb_r7); 1183 setreg(8, pcb.pcb_r8); 1184 setreg(9, pcb.pcb_r9); 1185 setreg(10, pcb.pcb_r10); 1186 setreg(11, pcb.pcb_r11); 1187 setreg(ARGP, pcb.pcb_ap); 1188 setreg(FRP, pcb.pcb_fp); 1189 setreg(STKP, pcb.pcb_ksp); 1190 setreg(PROGCTR, pcb.pcb_pc); 1191 } 1192 1193 public copyregs (savreg, reg) 1194 Word savreg[], reg[]; 1195 { 1196 reg[0] = savreg[R0]; 1197 reg[1] = savreg[R1]; 1198 reg[2] = savreg[R2]; 1199 reg[3] = savreg[R3]; 1200 reg[4] = savreg[R4]; 1201 reg[5] = savreg[R5]; 1202 reg[6] = savreg[R6]; 1203 reg[7] = savreg[R7]; 1204 reg[8] = savreg[R8]; 1205 reg[9] = savreg[R9]; 1206 reg[10] = savreg[R10]; 1207 reg[11] = savreg[R11]; 1208 reg[ARGP] = savreg[AP]; 1209 reg[FRP] = savreg[FP]; 1210 reg[STKP] = savreg[SP]; 1211 reg[PROGCTR] = savreg[PC]; 1212 } 1213 1214 /* 1215 * Map a virtual address to a physical address. 1216 */ 1217 1218 public Address vmap (addr) 1219 Address addr; 1220 { 1221 Address r; 1222 integer v, n; 1223 struct pte pte; 1224 1225 r = addr & ~0xc0000000; 1226 v = btop(r); 1227 switch (addr&0xc0000000) { 1228 case 0xc0000000: 1229 case 0x80000000: 1230 /* 1231 * In system space, so get system pte. 1232 * If it is valid or reclaimable then the physical address 1233 * is the combination of its page number and the page offset 1234 * of the original address. 1235 */ 1236 if (v >= slr) { 1237 error("address %x out of segment", addr); 1238 } 1239 r = ((long) (sbr + v)) & ~0x80000000; 1240 goto simple; 1241 1242 case 0x40000000: 1243 /* 1244 * In p1 space, must not be in shadow region. 1245 */ 1246 if (v < pcb.pcb_p1lr) { 1247 error("address %x out of segment", addr); 1248 } 1249 r = (Address) (pcb.pcb_p1br + v); 1250 break; 1251 1252 case 0x00000000: 1253 /* 1254 * In p0 space, must not be off end of region. 1255 */ 1256 if (v >= pcb.pcb_p0lr) { 1257 error("address %x out of segment", addr); 1258 } 1259 r = (Address) (pcb.pcb_p0br + v); 1260 break; 1261 1262 default: 1263 /* do nothing */ 1264 break; 1265 } 1266 /* 1267 * For p0/p1 address, user-level page table should be in 1268 * kernel virtual memory. Do second-level indirect by recursing. 1269 */ 1270 if ((r & 0x80000000) == 0) { 1271 error("bad p0br or p1br in pcb"); 1272 } 1273 r = vmap(r); 1274 simple: 1275 /* 1276 * "r" is now the address of the pte of the page 1277 * we are interested in; get the pte and paste up the physical address. 1278 */ 1279 fseek(corefile, r, 0); 1280 n = fread(&pte, sizeof(pte), 1, corefile); 1281 if (n != 1) { 1282 error("page table botch (fread at %x returns %d)", r, n); 1283 } 1284 if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { 1285 error("page no valid or reclamable"); 1286 } 1287 return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); 1288 } 1289 1290 /* 1291 * Extract a bit field from an integer. 1292 */ 1293 1294 public integer extractField (s) 1295 Symbol s; 1296 { 1297 integer n, nbytes, r; 1298 1299 n = 0; 1300 nbytes = size(s); 1301 if (nbytes > sizeof(n)) { 1302 printf("[bad size in extractField -- word assumed]\n"); 1303 nbytes = sizeof(n); 1304 } 1305 popn(nbytes, &n); 1306 r = n >> (s->symvalue.field.offset mod BITSPERBYTE); 1307 r &= ((1 << s->symvalue.field.length) - 1); 1308 return r; 1309 } 1310 1311 /* 1312 * Change the length of a value in memory according to a given difference 1313 * in the lengths of its new and old types. 1314 */ 1315 1316 public loophole (oldlen, newlen) 1317 integer oldlen, newlen; 1318 { 1319 integer n, i; 1320 1321 n = newlen - oldlen; 1322 if (n > 0) { 1323 for (i = 0; i < n; i++) { 1324 sp[i] = '\0'; 1325 } 1326 } 1327 sp += n; 1328 } 1329