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