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