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: }

Defined functions

beginproc defined in line 997; used 2 times
dostep defined in line 599; used 4 times
endprogram defined in line 576; used 1 times
findformat defined in line 340; used 3 times
findnextaddr defined in line 672; used 2 times
getdisp defined in line 879; used 7 times
nextaddr defined in line 638; used 3 times
printdata defined in line 355; used 1 times
printdisp defined in line 264; used 10 times
printerror defined in line 488; used 2 times
printinst defined in line 62; used 4 times
printndata defined in line 394; used 1 times
printninst defined in line 78; used 1 times
printop defined in line 100; used 3 times
printsig defined in line 547; used 1 times
printvalue defined in line 457; used 1 times
setbp defined in line 936; used 2 times
skipfunc defined in line 658; used 1 times
unsetbp defined in line 966; used 2 times

Defined variables

fpenames defined in line 533; used 3 times
illinames defined in line 527; used 3 times
pc defined in line 51; used 16 times
prtaddr defined in line 52; used 4 times
rcsid defined in line 11; never used
savelist defined in line 929; used 5 times
sccsid defined in line 8; never used

Defined struct's

Savelist defined in line 922; used 1 times

Defined typedef's

Address defined in line 32; used 32 times
Byte defined in line 33; used 4 times
Savelist defined in line 920; used 5 times
Word defined in line 34; used 1 times
  • in line 44

Defined macros

ARGP defined in line 38; never used
BITSPERBYTE defined in line 43; used 1 times
  • in line 44
BITSPERWORD defined in line 44; never used
BP_ERRNO defined in line 911; never used
BP_OP defined in line 910; used 1 times
CALLSIZE defined in line 995; used 1 times
FRP defined in line 39; never used
NREG defined in line 36; never used
PROGCTR defined in line 41; used 12 times
STKP defined in line 40; never used
nargspassed defined in line 46; never used
Last modified: 1986-03-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2032
Valid CSS Valid XHTML 1.0 Strict