Annotation of coherent/b/bin/as/tabbld.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Build code tables for 80386 assembler.
        !             3:  * Also build .h file and assembler test file.
        !             4:  */
        !             5: #include <misc.h>
        !             6: #include <ctype.h>
        !             7: #include "asflags.h"
        !             8: 
        !             9: typedef struct opts opts;
        !            10: typedef struct funs funs;
        !            11: typedef struct regs regs;
        !            12: typedef struct oper oper;
        !            13: 
        !            14: char *allntab;         /* all names table */
        !            15: short allnct, allnlen;
        !            16: 
        !            17: short *htab;           /* hash table */
        !            18: 
        !            19: struct oper {  /* operand types for test builder */
        !            20:        char *name;
        !            21:        int  base;              /* != 0 if equate must be built for this type */
        !            22:        short flag;             /* flag bits */
        !            23:        unsigned goodct;        /* number of good items on this list */
        !            24:        char *goodlist;         /* valid productions for this type */
        !            25:        unsigned badct;         /* number of bad items on this list */
        !            26:        char *badlist;          /* bad productions to test error checking */
        !            27: } *opertab;
        !            28: short operct, operlen;
        !            29: 
        !            30: /* oper flags */
        !            31: #define X_LARGE        1       /* contains 386 mode stuff */
        !            32: #define X_SMALL 2      /* contains 286 mode stuff */
        !            33: 
        !            34: struct opts {          /* opcode table */
        !            35:        char *name;
        !            36:        short opcode;
        !            37:        short hash;
        !            38:        short gen;              /* index into gentab */
        !            39:        short pt;               /* index into alltab */
        !            40:        short len;              /* length in alltab */
        !            41:        short fun;              /* index into fun */
        !            42:        short count;            /* count of items with this name */
        !            43:        short lineno;           /* line number on source table */
        !            44: } *optab;
        !            45: short opct, oplen;
        !            46: 
        !            47: struct funs {
        !            48:        char *name;
        !            49:        char *type;     /* yacc type */
        !            50:        short opt;      /* generation type */
        !            51:        char operands;  /* operand ct */
        !            52:        char ap[3];     /* operands */
        !            53: } *funtab;
        !            54: short funct, funlen;
        !            55: 
        !            56: struct regs {
        !            57:        char *name;
        !            58:        char *ytype;
        !            59:        short loc;
        !            60:        short len;
        !            61: } *regtab;
        !            62: short regct, reglen;
        !            63: 
        !            64: #define START(n, m) n##tab = alloc((n##len = m) * sizeof(*n##tab))
        !            65: 
        !            66: /* expander for tables */
        !            67: #define EXPAND(n) if((n##len <= (++n##ct)) \
        !            68:  && (NULL == (n##tab = realloc(n##tab, ((n##len += 10) * sizeof(*n##tab)))))) \
        !            69:        outSpace(__LINE__)
        !            70: 
        !            71: /* expander for allnames */
        !            72: #define NEWN(n, r) if((n##len <= (n##ct += r)) \
        !            73:  && (NULL == (n##tab = realloc(n##tab, n##len += 10)))) \
        !            74:        outSpace(__LINE__)
        !            75: 
        !            76: extern char *realloc(), *strstr(), *getline(), *newcpy();
        !            77: extern unsigned short hash();
        !            78: extern char *comment;  /* from getline() */
        !            79: 
        !            80: static FILE *ofp, *ohp, *otp, *odp, *oxp;      /* output files */
        !            81: static char *line;     /* input line */
        !            82: static int lineno = 1; /* line number */
        !            83: static int state;      /* opcodes, registers commands */
        !            84: static int curgen;     /* index to current general name */
        !            85: static unsigned nameCt;        /* name count */
        !            86: static int lastp;      /* last entry on prefTab */
        !            87: static short ct, opcode, opt;
        !            88: static unsigned long optDoc;
        !            89: static char fname[22], opc[10], op1[10], op2[10], op3[10], cmd[10], yt[10];
        !            90: static char thisGen[10];
        !            91: static errors;         /* error count */
        !            92: 
        !            93: /* test selector switches */
        !            94: static unsigned tmask = 0;             /* reject any not on this mask */
        !            95: static unsigned nmask = 0;             /* take any on this mask */
        !            96: static unsigned lswitch;               /* do large ops only */
        !            97: static unsigned sswitch;               /* do small ops only */
        !            98: static unsigned bswitch;               /* produce error test */
        !            99: 
        !           100: /*
        !           101:  * Report error.
        !           102:  */
        !           103: error(s)
        !           104: char *s;
        !           105: {
        !           106:        fprintf(stderr, "%d: %r\n", lineno, &s);
        !           107:        errors++;
        !           108: }
        !           109: 
        !           110: /*
        !           111:  * Out of space. or normal end.
        !           112:  */
        !           113: outSpace(line)
        !           114: {
        !           115:        if (line)
        !           116:                fprintf(stderr, "Out of space at %d\n", line);
        !           117:        showStats(1);
        !           118: }
        !           119: 
        !           120: /*
        !           121:  * Show generation statistics and exit.
        !           122:  */
        !           123: showStats(n)
        !           124: {
        !           125:        fprintf(stderr, "opct = %d, funct = %d, lineno = %d, ",
        !           126:                opct, funct, lineno);
        !           127:        fprintf(stderr, "regct = %d, operct = %d, allnct = %d\n",
        !           128:                regct, operct, allnct);
        !           129:        exit(n);
        !           130: }
        !           131: 
        !           132: /*
        !           133:  * Build test alternatives.
        !           134:  * Line starts with [.bB] for base type [!eE] for extra type.
        !           135:  * Caps for 386 productions, lower for 286 productions, punctuation for mixed.
        !           136:  * Base types are the operand types actually on opcodes.
        !           137:  * ? delimits bad choices.
        !           138:  */
        !           139: void
        !           140: buildTst()
        !           141: {
        !           142:        register struct oper *this;
        !           143:        register char *p;
        !           144:        static int base;
        !           145:        int state, c;
        !           146: 
        !           147:        EXPAND(oper);
        !           148:        this = opertab + operct - 1;
        !           149: 
        !           150:        switch (line[0]) {      /* mark base and extra */
        !           151:        case '.':
        !           152:                this->base = ++base;
        !           153:        case '!':
        !           154:                this->flag = (X_LARGE|X_SMALL);
        !           155:                break;
        !           156:        case 'B':
        !           157:                this->base = ++base;
        !           158:        case 'E':
        !           159:                this->flag = X_LARGE;
        !           160:                break;
        !           161:        case 'b':
        !           162:                this->base = ++base;
        !           163:        case 'e':
        !           164:                this->flag = X_SMALL;
        !           165:                break;
        !           166:        default:
        !           167:                operct--;
        !           168:                error("Bad test line");
        !           169:                return;
        !           170:        }
        !           171: 
        !           172:        for (p = line + 2; (c = *p) && !isspace(c); p++)
        !           173:                ;
        !           174:        *p++ = '\0';
        !           175:        this->name = newcpy(line + 2);
        !           176: 
        !           177:        /* Count the valid productions on the line */
        !           178:        this->goodlist = p;
        !           179:        for (state = 0; c = *p; p++) {
        !           180:                if (state) {    /* in a production */
        !           181:                        if (!isspace(c)) {
        !           182:                                if ('?' == c)
        !           183:                                        break;
        !           184:                                continue;
        !           185:                        }
        !           186:                        state = 0;
        !           187:                        continue;
        !           188:                }
        !           189:                if (isspace(c))
        !           190:                        continue;
        !           191:                if ('?' == c)
        !           192:                        break;
        !           193:                this->goodct++;
        !           194:                state = 1;
        !           195:        }
        !           196:        *p++ = '\0';
        !           197:        this->goodlist = newcpy(this->goodlist);
        !           198:        if (!c)
        !           199:                return;
        !           200: 
        !           201:        /* count the invalid productions on the line */
        !           202:        this->badlist = p;
        !           203:        for (state = this->badct = 0; c = *p; p++) {
        !           204:                if (state) {
        !           205:                        if (!isspace(c))
        !           206:                                continue;
        !           207:                        state = 0;
        !           208:                        continue;
        !           209:                }
        !           210:                if (isspace(c))
        !           211:                        continue;
        !           212:                this->badct++;
        !           213:                state = 1;
        !           214:        }
        !           215:        this->badlist = newcpy(this->badlist);
        !           216: }
        !           217: 
        !           218: /*
        !           219:  * Build assembler directives.
        !           220:  */
        !           221: buildDir()
        !           222: {
        !           223:        register funs *f;
        !           224:        register opts *this;
        !           225:        int i, j;
        !           226: 
        !           227:        sscanf(line, "%d %s %s %s", &opcode, opc, cmd, yt);
        !           228:        sprintf(fname, "S_%s", cmd);
        !           229: 
        !           230:        for (j = 0; j < funct; j++)
        !           231:                if (!strcmp(funtab[j].name, fname))
        !           232:                        break;
        !           233: 
        !           234:        if (j == funct) {       /* not found build one */
        !           235:                EXPAND(fun);
        !           236:                f = funtab + j;
        !           237:                f->name = newcpy(fname);
        !           238:                f->opt = f->operands = 0;
        !           239:                f->type = newcpy(yt);
        !           240:        }
        !           241: 
        !           242: 
        !           243:        if (!strcmp(opc, "-"))  /* no opcode generated */
        !           244:                return;
        !           245: 
        !           246:        i = opct;
        !           247:        EXPAND(op);
        !           248:        this = optab + i;
        !           249:        this->name = newcpy(opc);
        !           250:        this->fun = j;
        !           251:        this->opcode = opcode;
        !           252:        this->gen = -1;
        !           253:        this->hash = -2;
        !           254:        this->lineno = lineno;
        !           255: }
        !           256: 
        !           257: /*
        !           258:  * Build register name entrys.
        !           259:  */
        !           260: void
        !           261: buildReg()
        !           262: {
        !           263:        register regs *new;
        !           264:        char name[20], ytype[20];
        !           265: 
        !           266:        EXPAND(reg);
        !           267:        new = regtab + regct - 1;
        !           268: 
        !           269:        sscanf(line,
        !           270:                 "%s %s %d %d",
        !           271:                 name, ytype, &new->loc, &new->len);
        !           272:        new->name  = newcpy(name);
        !           273:        new->ytype = newcpy(ytype);
        !           274: }
        !           275: 
        !           276: /*
        !           277:  * Read and preprocess opcode
        !           278:  */
        !           279: void
        !           280: buildOp()
        !           281: {
        !           282:        register opts *this;
        !           283:        char optf[8], *p;
        !           284: 
        !           285:        optDoc = opc[0] = op1[0] = op2[0] = op3[0] = '\0';
        !           286:        sscanf(line, "%s %s", optf, opc);
        !           287: 
        !           288:        if ('G' == optf[0]) {   /* general opcode */
        !           289:                curgen = -1;
        !           290:                if(opc[0]) {
        !           291:                        for (curgen = 0; curgen < opct; curgen++) {
        !           292:                                if (!strcmp(opc, optab[curgen].name)) {
        !           293:                                        error("Dup Gen %s", opc);
        !           294:                                        return;
        !           295:                                }
        !           296:                        }
        !           297:                        strcpy(thisGen, opc);
        !           298: 
        !           299:                        fprintf(odp, "%s %d 0!", opc, lineno);
        !           300:                        fprintf(odp, "\t\\fB%s\\fR\t\t%s\n",
        !           301:                                 opc, comment);
        !           302: 
        !           303:                        EXPAND(op);
        !           304:                        this = optab + curgen;
        !           305:                        this->name = newcpy(opc);
        !           306:                        this->fun = -1;
        !           307:                        this->hash = -1;
        !           308:                        this->gen = curgen; /* self pointing */
        !           309:                        this->lineno = lineno;
        !           310:                }
        !           311:                return;
        !           312:        }                       
        !           313: 
        !           314:        if (!opc[0])
        !           315:                error("Null name");
        !           316: 
        !           317:        sscanf(line, "%s %x %s %s %s %s", optf, &opcode, opc, op1, op2, op3);
        !           318: 
        !           319:        for (p = optf; ; p++) {
        !           320:                switch(*p) {
        !           321:                case 0:
        !           322:                case '-':
        !           323:                        opt = optDoc;
        !           324:                        opBld();                return;
        !           325:                case 'A':
        !           326:                        optDoc |= AMBIG_MATCH;  break;
        !           327:                case 'i':
        !           328:                        optDoc |= INDEF_JMP;    break;
        !           329:                case 'w':
        !           330:                        optDoc |= WORD_MODE;    break;
        !           331:                case 'd':
        !           332:                        optDoc |= LONG_MODE;    break;
        !           333:                case 'F':
        !           334:                        optDoc |= FLOAT_ESC;    break;
        !           335:                case 'f':
        !           336:                        optDoc |= FLOAT_PFX;    break;
        !           337:                case 'p':
        !           338:                        optDoc |= PFX_0F;       break;
        !           339:                case '0':
        !           340:                case '1':
        !           341:                case '2':
        !           342:                case '3':
        !           343:                case '4':
        !           344:                case '5':
        !           345:                case '6':
        !           346:                case '7':
        !           347:                case '8':
        !           348:                        optDoc |= MODRM_BYTE;   break;
        !           349:                case 'a':
        !           350:                        optDoc |= ADD_REG;      break;
        !           351:                case 'L':
        !           352:                        optDoc |= LOCK_OP;      break;
        !           353:                case 'l':
        !           354:                        optDoc |= AFTER_LOCK;   break;
        !           355:                case 'R':
        !           356:                        optDoc |= REP_INSTR;    break;
        !           357:                case 'r':
        !           358:                        optDoc |= AFTER_REP;    break;
        !           359:                case 'X':
        !           360:                        optDoc |= XTENDS;       break;
        !           361:                case 't':
        !           362:                        optDoc |= TWO_OP_MULT;  break;
        !           363:                case 'P':
        !           364:                        optDoc |= USE_REG;      break;
        !           365:                default:
        !           366:                        error("Illegal flag %x in '%s'", *p, optf);
        !           367:                        return;
        !           368:                }
        !           369:        }
        !           370: }
        !           371: 
        !           372: /* 
        !           373:  * pick a random production. 
        !           374:  * may retry if random production is wrong mode.
        !           375:  */
        !           376: static int
        !           377: pickRand(this)
        !           378: register oper *this;
        !           379: {
        !           380:        int i;
        !           381:        char c, *p, state, work[20];
        !           382: 
        !           383:        if (bswitch && this->badct) {
        !           384:                p = this->badlist;
        !           385:                i = randl() % this->badct;
        !           386:        }
        !           387:        else {
        !           388:                p = this->goodlist;
        !           389:                i = randl() % this->goodct;
        !           390:        }
        !           391: 
        !           392:        for (state = 0; c = *p; p++) {
        !           393:                if (state) {
        !           394:                        if (isspace(c))
        !           395:                                state = 0;
        !           396:                        continue;
        !           397:                }
        !           398:                if (isspace(c))
        !           399:                        continue;
        !           400:                if (!i--)
        !           401:                        break;
        !           402:                state = 1;
        !           403:        }
        !           404: 
        !           405:        if (!c)
        !           406:                error("Logic error in produce");
        !           407: 
        !           408:        /* put it out finding any internal productions */
        !           409:        for (i = 0;;) {
        !           410:                if (('%' == (c = *p++)) || isalnum(c)) {
        !           411:                        work[i++] = c;
        !           412:                        continue;
        !           413:                }
        !           414:                if (i) {        /* we have a word */
        !           415:                        work[i] = '\0';
        !           416:                        i = 0;
        !           417:                        if(!produce(work))
        !           418:                                return (0);
        !           419:                }
        !           420:                if (!c || isspace(c))
        !           421:                        break;
        !           422:                fputc(c, otp);
        !           423:                if (',' == c)
        !           424:                        fputc(' ', otp);
        !           425:        }
        !           426:        return (1);
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * Produce an operand. Returns 1 on success 0 for a wrong
        !           431:  * production for a limited test. That is if we are testing
        !           432:  * all small stuff this returns 0 is asked to produce %eax
        !           433:  */
        !           434: static int
        !           435: produce(n)
        !           436: char *n;
        !           437: {
        !           438:        register int j;
        !           439:        register oper *this;
        !           440: 
        !           441: #ifdef TRACE
        !           442:        fprintf(otp, "{%s}", n);
        !           443: #endif
        !           444:        for (j = 0; j < operct; j++) {
        !           445:                this = opertab + j;
        !           446: 
        !           447:                if (!strcmp(n, this->name)) {
        !           448:                        if (lswitch && !(this->flag & X_LARGE))
        !           449:                                return (0);     /* fail */
        !           450:                        if (sswitch && !(this->flag & X_SMALL))
        !           451:                                return (0);     /* fail */
        !           452: 
        !           453:                        while (!pickRand(this))
        !           454:                                ;
        !           455:                        return (1);
        !           456:                }
        !           457:        }
        !           458: 
        !           459:        if (sswitch && ('%' == n[0])) /* remove % from regs is small tst */
        !           460:                n++;
        !           461: 
        !           462:        fprintf(otp, "%s", n);
        !           463:        return (1);
        !           464: }
        !           465: 
        !           466: /*
        !           467:  * make test file entrys.
        !           468:  */
        !           469: static void
        !           470: makeTst(n, j)
        !           471: char *n;
        !           472: {
        !           473:        register funs *f;
        !           474:        register opts *this;
        !           475:        register int i;
        !           476: 
        !           477: 
        !           478:        this = optab + j;
        !           479:        f = funtab + this->fun;
        !           480: 
        !           481:        /* can we do this */
        !           482:        if (lswitch)    /* large only test */
        !           483:                for (i = 0; i < f->operands; i++)
        !           484:                        if (!(opertab[f->ap[i]].flag & X_LARGE))
        !           485:                                return;
        !           486: 
        !           487:        if (sswitch)    /* small only test */
        !           488:                for (i = 0; i < f->operands; i++)
        !           489:                        if (!(opertab[f->ap[i]].flag & X_SMALL))
        !           490:                                return;
        !           491: 
        !           492:        if ((tmask && !(f->opt & tmask)) || (f->opt & nmask))
        !           493:                return;
        !           494: 
        !           495:        fprintf(otp, "\t%s\t", n);
        !           496:        if (sswitch) {  /* reverse operands */
        !           497:                for (i = f->operands; i--; ) {
        !           498:                        if (1 != (f->operands - i))
        !           499:                                fprintf(otp, ", ");
        !           500:                        produce(opertab[f->ap[i]].name);
        !           501:                }
        !           502:        }
        !           503:        else {          
        !           504:                for (i = 0; i < f->operands; i++) {
        !           505:                        if (i)
        !           506:                                fprintf(otp, ", ");
        !           507:                        produce(opertab[f->ap[i]].name);
        !           508:                }
        !           509:        }
        !           510:        fprintf(otp, "\t/ %04x %04x\n", opt, opcode);
        !           511: }
        !           512: 
        !           513: /*
        !           514:  * Produce Document lines.
        !           515:  */
        !           516: void
        !           517: makeDoc(f)
        !           518: register funs *f;
        !           519: {
        !           520:        int i;
        !           521: 
        !           522:        if (-1 == curgen)
        !           523:                fprintf(odp, "%s %d 2!", opc, lineno);
        !           524:        else
        !           525:                fprintf(odp, "%s %d 1!", thisGen, lineno);
        !           526: 
        !           527:        if (optDoc & PFX_0F)
        !           528:                fprintf(odp, "0F ");
        !           529: 
        !           530:        if (optDoc & FLOAT_PFX)
        !           531:                fprintf(odp, "9B ");
        !           532: 
        !           533:        if ((opcode & 0xff00) || (optDoc & MODRM_BYTE))
        !           534:                fprintf(odp, "%02x ", (opcode >> 8) & 255);
        !           535: 
        !           536:        if (optDoc & MODRM_BYTE)
        !           537:                fprintf(odp, "/%o", opcode & 7);
        !           538:        else
        !           539:                fprintf(odp, "%02x", opcode & 255);
        !           540: 
        !           541:        if (optDoc & USE_REG)
        !           542:                fprintf(odp, " /r");
        !           543: 
        !           544:        if (optDoc & ADD_REG)
        !           545:                fprintf(odp, " +r");
        !           546: 
        !           547:        fprintf(odp, "\t\\fB%s\\fR", opc);
        !           548: 
        !           549:        if (f->operands) {
        !           550:                fprintf(odp, "\t\\fI");
        !           551:                for (i = 0; i < f->operands; i++) {
        !           552:                        char *n = opertab[f->ap[i]].name;
        !           553: 
        !           554:                        if (i)
        !           555:                                fprintf(odp, ",");
        !           556: 
        !           557:                        fprintf(odp, "%s", strcmp(n, "atdx") ? n : "(dx)");
        !           558:                }
        !           559:                fprintf(odp, "\\fR");
        !           560:        }
        !           561:        if (*comment) {
        !           562:                if (!f->operands)
        !           563:                        fprintf(odp, "\t");
        !           564:                fprintf(odp, "\t%s", comment);
        !           565:        }
        !           566:        fputc('\n', odp);
        !           567: }
        !           568: 
        !           569: /*
        !           570:  * Build opcode and function entrys.
        !           571:  */
        !           572: opBld()
        !           573: {
        !           574:        register opts *this;
        !           575:        register funs *f;
        !           576:        int i, j, k;
        !           577: 
        !           578:        if (op3[0]) {
        !           579:                ct = 3;
        !           580:                sprintf(fname, "S_%04x_%s_%s_%s", opt, op1, op2, op3);
        !           581:        }
        !           582:        else if (op2[0]) {
        !           583:                ct = 2;
        !           584:                sprintf(fname, "S_%04x_%s_%s", opt, op1, op2);
        !           585:        }
        !           586:        else if (op1[0]) {
        !           587:                ct = 1;
        !           588:                sprintf(fname, "S_%04x_%s", opt, op1);
        !           589:        }
        !           590:        else {
        !           591:                ct = 0;
        !           592:                sprintf(fname, "S_%04x", opt);
        !           593:        }
        !           594: 
        !           595:        for (j = 0; j < funct; j++)
        !           596:                if (!strcmp(funtab[j].name, fname)) {
        !           597:                        f = funtab + j;
        !           598:                        break;
        !           599:                }
        !           600: 
        !           601:        if (j == funct) {       /* not found build one */
        !           602:                EXPAND(fun);
        !           603:                f = funtab + j;
        !           604:                f->name = newcpy(fname);
        !           605:                f->opt = opt;
        !           606:                f->operands = ct;
        !           607:                f->type = "OP";
        !           608:                f->ap[0] = findOpr(op1);
        !           609:                f->ap[1] = findOpr(op2);
        !           610:                f->ap[2] = findOpr(op3);
        !           611:        }
        !           612: 
        !           613:        i = opct;
        !           614:        EXPAND(op);
        !           615:        this = optab + i;
        !           616: 
        !           617:        for (k = 0; k < i; k++) {
        !           618:                if (!strcmp(optab[k].name, opc)) {
        !           619:                        this->name = optab[k].name;
        !           620:                        break;
        !           621:                }
        !           622:        }
        !           623: 
        !           624:        if (k == i)
        !           625:                this->name = newcpy(opc);
        !           626: 
        !           627:        this->fun = j;
        !           628:        this->opcode = opcode;
        !           629:        this->gen = curgen;
        !           630:        this->hash = -2;
        !           631:        this->lineno = lineno;
        !           632: 
        !           633:        if (!(opt & AMBIG_MATCH)) {
        !           634:                makeTst(opc, i);
        !           635:                makeDoc(f);
        !           636:        }
        !           637: }
        !           638: 
        !           639: /*
        !           640:  * Find operand on table or report error.
        !           641:  */
        !           642: findOpr(name)
        !           643: char *name;
        !           644: {
        !           645:        int i;
        !           646: 
        !           647:        if (!name[0])
        !           648:                return (-1);
        !           649: 
        !           650:        for (i = 0; i < operct; i++)
        !           651:                if (!strcmp(opertab[i].name, name))
        !           652:                        return (i);
        !           653: 
        !           654:        error("undefined operand %s", name);
        !           655: }
        !           656: 
        !           657: /*
        !           658:  * Comparison routine by inverse name length, then name, then order given.
        !           659:  */
        !           660: compr1(p1, p2)
        !           661: register opts *p1, *p2;
        !           662: {
        !           663:        register i;
        !           664: 
        !           665:        /* long names then short */
        !           666:        if (i = strlen(p2->name) - strlen(p1->name))
        !           667:                return (i);
        !           668: 
        !           669:        /* alpha order */
        !           670:        if (i = strcmp(p1->name, p2->name))
        !           671:                return(i);
        !           672: 
        !           673:        return (p1->lineno - p2->lineno); /* in order given */
        !           674: }
        !           675: 
        !           676: /*
        !           677:  * Comparison routine by name length, then name, then input position.
        !           678:  */
        !           679: compr2(p1, p2)
        !           680: register opts *p1, *p2;
        !           681: {
        !           682:        register i;
        !           683: 
        !           684:        /* short names then long */
        !           685:        if (i = strlen(p1->name) - strlen(p2->name))
        !           686:                return (i);
        !           687: 
        !           688:        /* alpha order */
        !           689:        if (i = strcmp(p1->name, p2->name))
        !           690:                return (i);
        !           691: 
        !           692:        return (p1->lineno - p2->lineno); /* in order given */
        !           693: }
        !           694: 
        !           695: /*
        !           696:  * Organize tables.
        !           697:  */
        !           698: reorgData()
        !           699: {
        !           700:        register opts *this, *that, *last;
        !           701:        char *p;
        !           702:        int i, j, k;
        !           703: 
        !           704:        /* sort for creating allntab */
        !           705:        qsort(optab, opct, sizeof(*optab), compr1);
        !           706: 
        !           707:        for (i = 0; i < opct; i++) { /* scan opcodes */
        !           708:                this = optab + i;
        !           709: 
        !           710:                this->len = k = strlen(this->name);
        !           711:                if (NULL == (p = strstr(allntab, this->name))) {
        !           712:                        /* if name not on list build */
        !           713:                        j = allnct;
        !           714:                        NEWN(alln, k);
        !           715:                        strcpy(allntab + j, this->name);
        !           716:                }
        !           717:                else
        !           718:                        j = p - allntab;
        !           719: 
        !           720:                this->pt = j;
        !           721:        }
        !           722: 
        !           723:        /* sort for creating prefTab */
        !           724:        qsort(optab, opct, sizeof(*optab), compr2);
        !           725: 
        !           726:        for (last = optab, nameCt = i = 0; i < opct; i++) { /* scan opcodes */
        !           727:                this = optab + i;
        !           728:                this->lineno = -1;
        !           729:                this->count  = 0;
        !           730:                if (-1 == this->fun) { /* general name */
        !           731:                        /* scan for reference */
        !           732:                        for (j = 0; j < opct; j++) {
        !           733:                                that = optab + j;
        !           734:                                if (-2 != that->hash ||
        !           735:                                    this->gen != that->gen)
        !           736:                                        continue;
        !           737:                                that->gen = i;  /* general ref marked */
        !           738:                                that->hash = -1;
        !           739:                                this->count++;
        !           740:                                if (!strcmp(this->name, that->name))
        !           741:                                        that->hash = -3; /* no unique name */
        !           742:                        }
        !           743:                }
        !           744: 
        !           745:                /* 
        !           746:                 * count names and mark first name in seq
        !           747:                 * by leaving its pointer and count intact.
        !           748:                 */
        !           749:                if (strcmp(last->name, this->name)) {
        !           750:                        if (!last->count)
        !           751:                                last->count = this - last;
        !           752:                        last = this;
        !           753:                        nameCt++;
        !           754:                }
        !           755:                else
        !           756:                        this->pt = this->len = 0;
        !           757:        }
        !           758:        last->count = (this - last) + 1;
        !           759: }
        !           760: 
        !           761: /*
        !           762:  * Output all tables.
        !           763:  */
        !           764: outData()
        !           765: {
        !           766:        register opts *this, *that;
        !           767:        register funs *f;
        !           768:        regs *r;
        !           769:        char *p, work[20];
        !           770:        int i, j, k, l;
        !           771: 
        !           772:        fprintf(ohp, "/*\n");
        !           773:        fprintf(ohp, " * 80386 assembler header file.\n");
        !           774:        fprintf(ohp, " * Generated by tabbld\n");
        !           775:        fprintf(ohp, " */\n\n");
        !           776: 
        !           777:        fprintf(ofp, "/*\n");
        !           778:        fprintf(ofp, " * 80386 assembler table file.\n");
        !           779:        fprintf(ofp, " * Generated by tabbld\n");
        !           780:        fprintf(ofp, " */\n");
        !           781:        fprintf(ofp, "#include <stdio.h>\n");
        !           782:        fprintf(ofp, "#include <asm.h>\n");
        !           783:        fprintf(ofp, "#include <y_tab.h>\n");
        !           784:        fprintf(ofp, "#include <symtab.h>\n\n");
        !           785: 
        !           786:        fprintf(ohp, "/* operand types */\n");
        !           787:        /* dump base operand types */
        !           788:        for (i = 0; i < operct; i++)
        !           789:                if (j = opertab[i].base)
        !           790:                        fprintf(ohp, "#define %-9s %2d\n", opertab[i].name, j);
        !           791: 
        !           792:        /* dump function table */
        !           793:        fprintf(ohp, "\n/* instruction types */\n");
        !           794:        fprintf(ofp, "symt typTab[] = {\n");
        !           795:        for (i = 0; i < funct;) {
        !           796:                f = funtab + i;
        !           797:                fprintf(ohp, "#define %-21s %2d\n", f->name, i);
        !           798:                fprintf(ofp, " /* %-21s */ { %10s, 0x%04x, %d",
        !           799:                        f->name,
        !           800:                        f->type,
        !           801:                        f->opt & 0xffff,
        !           802:                        f->operands);
        !           803:                for (j = 0; j < f->operands; j++)
        !           804:                        fprintf(ofp, ", %s", opertab[f->ap[j]].name);
        !           805:                fprintf(ofp, " }%s\n", ((++i < funct) ? "," : ""));
        !           806:        }
        !           807:        fprintf(ofp, "};\n\n");
        !           808: 
        !           809:        /* dump the name hash */
        !           810:        fprintf(ofp, "char charLump[] = {");
        !           811:        i = 0;
        !           812:        for (p = allntab; *p;) {
        !           813:                switch (i++) {
        !           814:                case 0:
        !           815:                        fprintf(ofp, "\n\t");
        !           816:                        break;
        !           817:                case 10:
        !           818:                        i = 0;
        !           819:                default:
        !           820:                        fprintf(ofp, " ");
        !           821:                }
        !           822:                fprintf(ofp, "'%c'", *p++);
        !           823:                if (*p)
        !           824:                        fprintf(ofp, ",");
        !           825:        }
        !           826:        fprintf(ofp, "\n};\n\n");
        !           827: 
        !           828:        /*
        !           829:         * dump preftab first generic opcodes then regular.
        !           830:         * opcode is now used to point to the preftab address.
        !           831:         * for generic opcodes.
        !           832:         * lineno is now used tp point to the preftab address
        !           833:         * for processed opcodes that need hash pointers
        !           834:         * and zero for other processed opcodes.
        !           835:         */
        !           836:        fprintf(ofp, "opc prefTab[] = {\n");
        !           837:        for (lastp = i = 0; i < opct; i++) {
        !           838:                this = optab + i;
        !           839:                if (this->fun != -1)    /* non generic opcode */
        !           840:                        continue;
        !           841: 
        !           842:                work[0] = '\0';
        !           843:                this->opcode = lastp;
        !           844: 
        !           845:                fputc('\n', ofp);
        !           846:                for (j = 0; j < opct; j++) {
        !           847:                        that = optab + j;
        !           848:                        if (that->gen != i || that->fun == -1)
        !           849:                                continue;
        !           850:                        that->lineno = 0;
        !           851:                        /* remember first of each name */
        !           852:                        if(strcmp(work, that->name)) {
        !           853:                                k = j;
        !           854:                                optab[k].lineno = l = lastp;
        !           855:                                strcpy(work, that->name);
        !           856:                        }
        !           857:                        fprintf(ofp,
        !           858:                                "\t{ 0x%04x, %21s },\t/* %-10s %d */\n",
        !           859:                                that->opcode & 0xffff,
        !           860:                                funtab[that->fun].name,
        !           861:                                that->name,
        !           862:                                lastp);
        !           863:                        lastp++;
        !           864:                }
        !           865:        }
        !           866:        fputc('\n', ofp);
        !           867: 
        !           868:        /* do non generic opcodes */
        !           869:        for (i = 0; i < opct; i++) {
        !           870:                this = optab + i;
        !           871:                /* regular first opcode */
        !           872:                if (this->fun != -1 && this->len) {
        !           873:                        if (-1 != this->lineno) { /* matches end of generic */
        !           874:                                this->opcode = this->lineno;
        !           875:                                continue;
        !           876:                        }
        !           877:                        k = lastp;      /* save lastp */
        !           878:                        for (j = i; j < opct;) {
        !           879:                                that = optab + j;
        !           880:                                if (strcmp(this->name, that->name))
        !           881:                                        break;
        !           882:                                if (-1 == that->fun) {
        !           883:                                        errors++;
        !           884:                                        fprintf(stderr, "odd order %s",
        !           885:                                                that->name);
        !           886:                                        break;
        !           887:                                }
        !           888:                                fprintf(ofp,
        !           889:                                   "\t{ 0x%04x, %21s }%s\t/* %-10s %d */\n",
        !           890:                                        that->opcode & 0xffff,
        !           891:                                        funtab[that->fun].name,
        !           892:                                        ((++j != opct) ? "," : ""),
        !           893:                                        that->name,
        !           894:                                        lastp);
        !           895:                                lastp++;
        !           896:                        }
        !           897:                        this->opcode = k;
        !           898:                }
        !           899:        }
        !           900:        fprintf(ofp, "};\n\n");
        !           901: 
        !           902:        free(funtab);
        !           903: 
        !           904:        /* set up hash table to mark */
        !           905:        htab = alloc(nameCt * sizeof(*htab));
        !           906:        fprintf(ohp, "#define OPCOUNT %d /* count of opcodes */\n", nameCt);
        !           907: 
        !           908:        for (i = 0; i < nameCt; i++)
        !           909:                htab[i] = -1;
        !           910: 
        !           911:        /* mark all items that hash direct */
        !           912:        for (i = 0; i < opct; i++) {
        !           913:                this = optab + i;
        !           914: 
        !           915:                this->hash = -2;
        !           916:                if (!this->len)
        !           917:                        continue;
        !           918:                memcpy(work, allntab + this->pt, this->len);
        !           919:                work[this->len] = '\0';
        !           920:                j = hash(work) % nameCt;
        !           921: 
        !           922:                if (htab[j] != -1) {    /* hole taken get it next pass */
        !           923:                        this->hash = -1;
        !           924:                        continue;
        !           925:                }
        !           926:                htab[j] = i;    /* hash table points to entry */
        !           927:        }
        !           928: 
        !           929:        /* mark items that hash indirect */
        !           930:        for (i = 0; i < opct; i++) {
        !           931:                this = optab + i;
        !           932:                if (-1 != this->hash)   /* pass unmarked items */
        !           933:                        continue;
        !           934: 
        !           935:                 /* find a hole */
        !           936:                for (k = 0;(k < nameCt) && (htab[k] != -1); k++)
        !           937:                        ;
        !           938:                if (k == nameCt) {
        !           939:                        errors++;
        !           940:                        fprintf(stderr, "Insufficient holes in table");
        !           941:                        continue;
        !           942:                }
        !           943:                htab[k] = i;    /* hash table points to entry */
        !           944: 
        !           945:                /* where does this hash to */
        !           946:                memcpy(work, allntab + this->pt, this->len);
        !           947:                work[this->len] = '\0';
        !           948:                j = hash(work) % nameCt;
        !           949: 
        !           950:                /* find the end of the chain */
        !           951:                while(-2 != (j = (that = optab + htab[j])->hash))
        !           952:                        ;
        !           953: 
        !           954:                that->hash = k;
        !           955:                this->hash = -2;
        !           956:        }
        !           957: 
        !           958:        fprintf(ofp, "nhash hashCodes[] = {\n");
        !           959:        for (i = 0; i < nameCt;) {
        !           960:                j = htab[i++];
        !           961:                if (j < 0 || j > opct) {
        !           962:                        errors++;
        !           963:                        fprintf(stderr, "Unplaned hole in table");
        !           964:                        fprintf(ofp, "\t{-1, 0, 0, 0, 0 }, /* JUNK */\n");
        !           965:                        continue;
        !           966:                }
        !           967:                this = optab + j;
        !           968: 
        !           969:                memcpy(work, allntab + this->pt, this->len);
        !           970:                work[this->len] = '\0';
        !           971:                fprintf(ofp, "\t{%4d, %4d, %2d, %2d, %4d }%c /* %-12s %d */\n",
        !           972:                        ((this->hash < 0) ? -1 : this->hash),
        !           973:                        this->pt,
        !           974:                        this->len,
        !           975:                        this->count,    /* entries on pref table */
        !           976:                        this->opcode,   /* entry on pref table */
        !           977:                        ((i == nameCt) ? ' ' : ','),
        !           978:                        work,
        !           979:                        i - 1);
        !           980:        }
        !           981:        fprintf(ofp, "};\n\n");
        !           982: 
        !           983:        fprintf(ohp,
        !           984:                "#define SYMCOUNT %d\t/* count of predefined symbols */\n",
        !           985:                regct + 1);
        !           986: 
        !           987:        fprintf(ofp, "psym symtab[] = {\n");
        !           988:        fprintf(ofp,    /* too fancy for the basic mechinism */
        !           989:                "\t{NULL, IDENTIFIER, 0, 0, 1, 0, symtab, 0, 0, \".\" },\n");
        !           990:        for (i = 0; i < regct; ) {
        !           991:                r = regtab + i++;
        !           992: 
        !           993:                j = 0;
        !           994:                if (NULL == strstr(r->ytype, "REG"))
        !           995:                        strcpy(work, r->name);
        !           996:                else {
        !           997:                        sprintf(work, "%%%s", r->name);
        !           998:                        switch(r->ytype[0]) {
        !           999:                        case 'S':       /* SEG_REG */
        !          1000:                                j = 0x800;
        !          1001:                                break;
        !          1002:                        case 'C':       /* CTL_REG */
        !          1003:                                j = 0x400;
        !          1004:                                break;
        !          1005:                        case 'D':       /* DEB_REG */
        !          1006:                                j = 0x200;
        !          1007:                                break;
        !          1008:                        case 'T':       /* TST_REG */
        !          1009:                                j = 0x100;
        !          1010:                                break;
        !          1011:                        }
        !          1012:                        r->ytype = "REG";
        !          1013:                }
        !          1014:                fprintf(ofp,
        !          1015:                  "\t{ NULL, %10s, %d, %d, 0, %d, NULL, 0, 0, \"%s\" }%s\n",
        !          1016:                  r->ytype,
        !          1017:                  r->loc,
        !          1018:                  r->len,
        !          1019:                  j,
        !          1020:                  work,
        !          1021:                  ((i < regct) ? "," : ""));
        !          1022:        }
        !          1023:        fprintf(ofp, "};\n");
        !          1024: }
        !          1025: 
        !          1026: /*
        !          1027:  * Process opcode files.
        !          1028:  */
        !          1029: main(argc, argv)
        !          1030: char *argv[];
        !          1031: {
        !          1032:        int c, subtest;
        !          1033:        extern char *optarg;
        !          1034:        extern int optind;
        !          1035: 
        !          1036:        for (subtest = 0; EOF != (c = getopt(argc, argv, "blst:n:?"));) {
        !          1037:                subtest = 1;    /* any options are a subtest */
        !          1038:                switch (c) {
        !          1039:                case 'b':
        !          1040:                        bswitch = 1;
        !          1041:                        break;
        !          1042:                case 'l':
        !          1043:                        lswitch = 1;
        !          1044:                        break;
        !          1045:                case 's':
        !          1046:                        sswitch = 1;
        !          1047:                        break;
        !          1048:                case 't':
        !          1049:                        sscanf(optarg, "%x", &tmask);
        !          1050:                        break;
        !          1051:                case 'n':
        !          1052:                        sscanf(optarg, "%x", &nmask);
        !          1053:                        break;
        !          1054:                case '?':
        !          1055:                default:
        !          1056:                        fprintf(stderr,
        !          1057:         "usage: tabbld [-bls] [-t bits_to_match] [-n bits_not_to_match]\n");
        !          1058:                        exit (1);
        !          1059:                }
        !          1060:        }
        !          1061:                        
        !          1062:        /*
        !          1063:         * These are nessisary as long as this runs small model.
        !          1064:         * otherwise this thing runs out of space.
        !          1065:         */
        !          1066:        START(op,  1000);
        !          1067:        START(fun, 250);
        !          1068:        START(oper, 100);
        !          1069:        START(alln, 2000);
        !          1070:        START(reg, 100);
        !          1071: 
        !          1072:        otp = xopen("test.s", "w");
        !          1073:        if (subtest) {
        !          1074:                fprintf(otp, "\t.ttl\tSubtest of asm 386 ");
        !          1075:                if (bswitch | lswitch | sswitch)
        !          1076:                        fputc('-', otp);
        !          1077:                if (bswitch)
        !          1078:                        fputc('b', otp);
        !          1079:                if (lswitch)
        !          1080:                        fputc('t', otp);
        !          1081:                if (sswitch)
        !          1082:                        fputc('s', otp);
        !          1083:                if (tmask)
        !          1084:                        fprintf(otp, " -t %x", tmask);
        !          1085:                if (nmask)
        !          1086:                        fprintf(otp, " -n %x", nmask);
        !          1087:                fputc('\n', otp);
        !          1088:                odp = ohp = ofp = xopen("/dev/null", "w");
        !          1089:        }
        !          1090:        else {
        !          1091:                fprintf(otp, "\t.ttl\tFull test of asm 386\n");
        !          1092:                ofp = xopen("symtab.c", "w");   /* symbol table */
        !          1093:                ohp = xopen("symtab.h", "w");   /* header file */
        !          1094:                odp = xopen("document", "w");   /* document file */
        !          1095:        }
        !          1096:        fprintf(otp, "\t.llen\t100\n");
        !          1097:        fprintf(otp, "abc:\n");
        !          1098:        
        !          1099:        /*
        !          1100:         * Process file.
        !          1101:         */
        !          1102:        while (NULL != (line = getline(stdin, &lineno))) {
        !          1103:                switch (*line) {
        !          1104:                case '+':
        !          1105:                        sscanf(line + 2, "%d", &state);
        !          1106:                        continue;
        !          1107:                case 0:
        !          1108:                        if (1 == state) {       /* pass through comments */
        !          1109:                                if (-1 == curgen)
        !          1110:                                        fprintf(odp, "%s %d 2!\t%s\n",
        !          1111:                                                ((optDoc & INDEF_JMP) ? "ja" : opc),
        !          1112:                                                lineno, comment);
        !          1113:                                else
        !          1114:                                        fprintf(odp, "%s %d 1!\t%s\n",
        !          1115:                                                thisGen, lineno, comment);
        !          1116:                        }
        !          1117:                        continue;
        !          1118:                }
        !          1119:                switch(state) {
        !          1120:                case 0: /* test stream directives. */
        !          1121:                        buildTst();
        !          1122:                        break;
        !          1123:                case 1: /* opcodes */
        !          1124:                        buildOp();
        !          1125:                        break;
        !          1126:                case 2: /* registers */
        !          1127:                        buildReg();
        !          1128:                        break;
        !          1129:                case 3: /* assembler directives */
        !          1130:                        buildDir();
        !          1131:                }
        !          1132:        }
        !          1133:        fclose(otp);
        !          1134: 
        !          1135:        if (subtest)
        !          1136:                return (0);
        !          1137: 
        !          1138:        reorgData();
        !          1139:        outData();
        !          1140:        if (errors)
        !          1141:                fprintf(stderr, "%d error%c detected\n", errors, 
        !          1142:                        (1 == errors) ? ' ' : 's');
        !          1143:        showStats(errors ? 1 : 0);
        !          1144: 
        !          1145:        return (0);
        !          1146: }

unix.superglobalmegacorp.com

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