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