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