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