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