Annotation of coherent/b/bin/as/tabbld.c, revision 1.1.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.