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