Annotation of 43BSDTahoe/ucb/dbx/vax.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.