Annotation of coherent/b/bin/as/tabbld.c.exp, 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;    /* 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 'm':
                    340:                        optDoc |= MODRM_BYTE;   break;
                    341:                case 'a':
                    342:                        optDoc |= ADD_REG;      break;
                    343:                case 'L':
                    344:                        optDoc |= LOCK_OP;      break;
                    345:                case 'l':
                    346:                        optDoc |= AFTER_LOCK;   break;
                    347:                case 'R':
                    348:                        optDoc |= REP_INSTR;    break;
                    349:                case 'r':
                    350:                        optDoc |= AFTER_REP;    break;
                    351:                case 'X':
                    352:                        optDoc |= XTENDS;       break;
                    353:                case 't':
                    354:                        optDoc |= TWO_OP_MULT;  break;
                    355:                case 'P':
                    356:                        optDoc |= USE_REG;      break;
                    357:                default:
                    358:                        error("Illegal flag %x in '%s'", *p, optf);
                    359:                        return;
                    360:                }
                    361:        }
                    362: }
                    363: 
                    364: /* 
                    365:  * pick a random production. 
                    366:  * may retry if random production is wrong mode.
                    367:  */
                    368: static int
                    369: pickRand(this)
                    370: register oper *this;
                    371: {
                    372:        int i;
                    373:        char c, *p, state, work[20];
                    374: 
                    375:        if (bswitch && this->badct) {
                    376:                p = this->badlist;
                    377:                i = randl() % this->badct;
                    378:        }
                    379:        else {
                    380:                p = this->goodlist;
                    381:                i = randl() % this->goodct;
                    382:        }
                    383: 
                    384:        for (state = 0; c = *p; p++) {
                    385:                if (state) {
                    386:                        if (isspace(c))
                    387:                                state = 0;
                    388:                        continue;
                    389:                }
                    390:                if (isspace(c))
                    391:                        continue;
                    392:                if (!i--)
                    393:                        break;
                    394:                state = 1;
                    395:        }
                    396: 
                    397:        if (!c)
                    398:                error("Logic error in produce");
                    399: 
                    400:        /* put it out finding any internal productions */
                    401:        for (i = 0;;) {
                    402:                if (('%' == (c = *p++)) || isalnum(c)) {
                    403:                        work[i++] = c;
                    404:                        continue;
                    405:                }
                    406:                if (i) {        /* we have a word */
                    407:                        work[i] = '\0';
                    408:                        i = 0;
                    409:                        if(!produce(work))
                    410:                                return (0);
                    411:                }
                    412:                if (!c || isspace(c))
                    413:                        break;
                    414:                fputc(c, otp);
                    415:                if (',' == c)
                    416:                        fputc(' ', otp);
                    417:        }
                    418:        return (1);
                    419: }
                    420: 
                    421: /*
                    422:  * Produce an operand. Returns 1 on success 0 for a wrong
                    423:  * production for a limited test. That is if we are testing
                    424:  * all small stuff this returns 0 is asked to produce %eax
                    425:  */
                    426: static int
                    427: produce(n)
                    428: char *n;
                    429: {
                    430:        register int j;
                    431:        register oper *this;
                    432: 
                    433: #ifdef TRACE
                    434:        fprintf(otp, "{%s}", n);
                    435: #endif
                    436:        for (j = 0; j < operct; j++) {
                    437:                this = opertab + j;
                    438: 
                    439:                if (!strcmp(n, this->name)) {
                    440:                        if (lswitch && !(this->flag & X_LARGE))
                    441:                                return (0);     /* fail */
                    442:                        if (sswitch && !(this->flag & X_SMALL))
                    443:                                return (0);     /* fail */
                    444: 
                    445:                        while (!pickRand(this))
                    446:                                ;
                    447:                        return (1);
                    448:                }
                    449:        }
                    450: 
                    451:        if (sswitch && ('%' == n[0])) /* remove % from regs is small tst */
                    452:                n++;
                    453: 
                    454:        fprintf(otp, "%s", n);
                    455:        return (1);
                    456: }
                    457: 
                    458: /*
                    459:  * make test file entrys.
                    460:  */
                    461: static void
                    462: makeTst(n, j)
                    463: char *n;
                    464: {
                    465:        register funs *f;
                    466:        register opts *this;
                    467:        register int i;
                    468: 
                    469: 
                    470:        this = optab + j;
                    471:        f = funtab + this->fun;
                    472: 
                    473:        /* can we do this */
                    474:        if (lswitch)    /* large only test */
                    475:                for (i = 0; i < f->operands; i++)
                    476:                        if (!(opertab[f->ap[i]].flag & X_LARGE))
                    477:                                return;
                    478: 
                    479:        if (sswitch)    /* small only test */
                    480:                for (i = 0; i < f->operands; i++)
                    481:                        if (!(opertab[f->ap[i]].flag & X_SMALL))
                    482:                                return;
                    483: 
                    484:        if ((tmask && !(f->opt & tmask)) || (f->opt & nmask))
                    485:                return;
                    486: 
                    487:        fprintf(otp, "\t%s\t", n);
                    488:        if (sswitch) {  /* reverse operands */
                    489:                for (i = f->operands; i--; ) {
                    490:                        if (1 != (f->operands - i))
                    491:                                fprintf(otp, ", ");
                    492:                        produce(opertab[f->ap[i]].name);
                    493:                }
                    494:        }
                    495:        else {          
                    496:                for (i = 0; i < f->operands; i++) {
                    497:                        if (i)
                    498:                                fprintf(otp, ", ");
                    499:                        produce(opertab[f->ap[i]].name);
                    500:                }
                    501:        }
                    502:        fprintf(otp, "\t/ %04x %04x\n", opt, opcode);
                    503: }
                    504: 
                    505: /*
                    506:  * Produce Document lines.
                    507:  */
                    508: void
                    509: makeDoc(f)
                    510: register funs *f;
                    511: {
                    512:        int i;
                    513: 
                    514:        if (-1 == curgen)
                    515:                fprintf(odp, "%s %d 2!", opc, lineno);
                    516:        else
                    517:                fprintf(odp, "%s %d 1!", thisGen, lineno);
                    518: 
                    519:        if (optDoc & PFX_0F)
                    520:                fprintf(odp, "0F ");
                    521: 
                    522:        if (optDoc & FLOAT_PFX)
                    523:                fprintf(odp, "9B ");
                    524: 
                    525:        if ((opcode & 0xff00) || (optDoc & MODRM_BYTE))
                    526:                fprintf(odp, "%02x ", (opcode >> 8) & 255);
                    527: 
                    528:        if (optDoc & MODRM_BYTE)
                    529:                fprintf(odp, "/%o", opcode & 7);
                    530:        else
                    531:                fprintf(odp, "%02x", opcode & 255);
                    532: 
                    533:        if (optDoc & USE_REG)
                    534:                fprintf(odp, " /r");
                    535: 
                    536:        if (optDoc & ADD_REG)
                    537:                fprintf(odp, " +r");
                    538: 
                    539:        fprintf(odp, "\t\\fB%s\\fR", opc);
                    540: 
                    541:        if (f->operands) {
                    542:                fprintf(odp, "\t\\fI");
                    543:                for (i = 0; i < f->operands; i++) {
                    544:                        char *n = opertab[f->ap[i]].name;
                    545: 
                    546:                        if (i)
                    547:                                fprintf(odp, ",");
                    548: 
                    549:                        fprintf(odp, "%s", strcmp(n, "atdx") ? n : "(dx)");
                    550:                }
                    551:                fprintf(odp, "\\fR");
                    552:        }
                    553:        if (*comment) {
                    554:                if (!f->operands)
                    555:                        fprintf(odp, "\t");
                    556:                fprintf(odp, "\t%s", comment);
                    557:        }
                    558:        fputc('\n', odp);
                    559: }
                    560: 
                    561: /*
                    562:  * Build opcode and function entrys.
                    563:  */
                    564: opBld()
                    565: {
                    566:        char operand[3][10];
                    567:        register opts *this;
                    568:        register funs *f;
                    569:        int i, j, k;
                    570: 
                    571:        /* m[0-9]+ are all really m at this level */
                    572:        strcpy(operand[0], op1);
                    573:        strcpy(operand[1], op2);
                    574:        strcpy(operand[2], op3);
                    575:        for (i = 0; i < 3; i++) {
                    576:                if ('m' == operand[i][0] && 
                    577:                    '0' <= operand[i][1] &&
                    578:                    '9' >= operand[i][1])
                    579:                        strcpy(operand[i], "m8");
                    580:        }
                    581: 
                    582:        if (operand[2][0]) {
                    583:                ct = 3;
                    584:                sprintf(fname, "S_%04x_%s_%s_%s",
                    585:                        opt, operand[0], operand[1], operand[2]);
                    586:        }
                    587:        else if (operand[1][0]) {
                    588:                ct = 2;
                    589:                sprintf(fname, "S_%04x_%s_%s", opt, operand[0], operand[1]);
                    590:        }
                    591:        else if (operand[0][0]) {
                    592:                ct = 1;
                    593:                sprintf(fname, "S_%04x_%s", opt, operand[0]);
                    594:        }
                    595:        else {
                    596:                ct = 0;
                    597:                sprintf(fname, "S_%04x", opt);
                    598:        }
                    599: 
                    600:        for (j = 0; j < funct; j++)
                    601:                if (!strcmp(funtab[j].name, fname)) {
                    602:                        f = funtab + j;
                    603:                        break;
                    604:                }
                    605: 
                    606:        if (j == funct) {       /* not found build one */
                    607:                EXPAND(fun);
                    608:                f = funtab + j;
                    609:                f->name = newcpy(fname);
                    610:                f->opt = opt;
                    611:                f->operands = ct;
                    612:                f->type = "OP";
                    613:                f->ap[0] = findOpr(operand[0]);
                    614:                f->ap[1] = findOpr(operand[1]);
                    615:                f->ap[2] = findOpr(operand[2]);
                    616:        }
                    617: 
                    618:        i = opct;
                    619:        EXPAND(op);
                    620:        this = optab + i;
                    621: 
                    622:        for (k = 0; k < i; k++) {
                    623:                if (!strcmp(optab[k].name, opc)) {
                    624:                        this->name = optab[k].name;
                    625:                        break;
                    626:                }
                    627:        }
                    628: 
                    629:        if (k == i)
                    630:                this->name = newcpy(opc);
                    631: 
                    632:        this->fun = j;
                    633:        this->opcode = opcode;
                    634:        this->gen = curgen;
                    635:        this->hash = -2;
                    636:        this->lineno = lineno;
                    637: 
                    638:        if (!(opt & AMBIG_MATCH)) {
                    639:                makeTst(opc, i);
                    640:                makeDoc(f);
                    641:        }
                    642: }
                    643: 
                    644: /*
                    645:  * Find operand on table or report error.
                    646:  */
                    647: findOpr(name)
                    648: char *name;
                    649: {
                    650:        int i;
                    651: 
                    652:        if (!name[0])
                    653:                return (-1);
                    654: 
                    655:        for (i = 0; i < operct; i++)
                    656:                if (!strcmp(opertab[i].name, name))
                    657:                        return (i);
                    658: 
                    659:        error("undefined operand %s", name);
                    660: }
                    661: 
                    662: /*
                    663:  * Comparison routine by inverse name length, then name, then order given.
                    664:  */
                    665: compr1(p1, p2)
                    666: register opts *p1, *p2;
                    667: {
                    668:        register i;
                    669: 
                    670:        /* long names then short */
                    671:        if (i = strlen(p2->name) - strlen(p1->name))
                    672:                return (i);
                    673: 
                    674:        /* alpha order */
                    675:        if (i = strcmp(p1->name, p2->name))
                    676:                return(i);
                    677: 
                    678:        return (p1->lineno - p2->lineno); /* in order given */
                    679: }
                    680: 
                    681: /*
                    682:  * Comparison routine by name length, then name, then input position.
                    683:  */
                    684: compr2(p1, p2)
                    685: register opts *p1, *p2;
                    686: {
                    687:        register i;
                    688: 
                    689:        /* short names then long */
                    690:        if (i = strlen(p1->name) - strlen(p2->name))
                    691:                return (i);
                    692: 
                    693:        /* alpha order */
                    694:        if (i = strcmp(p1->name, p2->name))
                    695:                return (i);
                    696: 
                    697:        return (p1->lineno - p2->lineno); /* in order given */
                    698: }
                    699: 
                    700: /*
                    701:  * Organize tables.
                    702:  */
                    703: reorgData()
                    704: {
                    705:        register opts *this, *that, *last;
                    706:        char *p;
                    707:        int i, j, k;
                    708: 
                    709:        /* sort for creating allntab */
                    710:        qsort(optab, opct, sizeof(*optab), compr1);
                    711: 
                    712:        for (i = 0; i < opct; i++) { /* scan opcodes */
                    713:                this = optab + i;
                    714: 
                    715:                this->len = k = strlen(this->name);
                    716:                if (NULL == (p = strstr(allntab, this->name))) {
                    717:                        /* if name not on list build */
                    718:                        j = allnct;
                    719:                        NEWN(alln, k);
                    720:                        strcpy(allntab + j, this->name);
                    721:                }
                    722:                else
                    723:                        j = p - allntab;
                    724: 
                    725:                this->pt = j;
                    726:        }
                    727: 
                    728:        /* sort for creating prefTab */
                    729:        qsort(optab, opct, sizeof(*optab), compr2);
                    730: 
                    731:        for (last = optab, nameCt = i = 0; i < opct; i++) { /* scan opcodes */
                    732:                this = optab + i;
                    733:                this->lineno = -1;
                    734:                this->count  = 0;
                    735:                if (-1 == this->fun) { /* general name */
                    736:                        /* scan for reference */
                    737:                        for (j = 0; j < opct; j++) {
                    738:                                that = optab + j;
                    739:                                if (-2 != that->hash ||
                    740:                                    this->gen != that->gen)
                    741:                                        continue;
                    742:                                that->gen = i;  /* general ref marked */
                    743:                                that->hash = -1;
                    744:                                this->count++;
                    745:                                if (!strcmp(this->name, that->name))
                    746:                                        that->hash = -3; /* no unique name */
                    747:                        }
                    748:                }
                    749: 
                    750:                /* 
                    751:                 * count names and mark first name in seq
                    752:                 * by leaving its pointer and count intact.
                    753:                 */
                    754:                if (strcmp(last->name, this->name)) {
                    755:                        if (!last->count)
                    756:                                last->count = this - last;
                    757:                        last = this;
                    758:                        nameCt++;
                    759:                }
                    760:                else
                    761:                        this->pt = this->len = 0;
                    762:        }
                    763:        last->count = (this - last) + 1;
                    764: }
                    765: 
                    766: /*
                    767:  * Output all tables.
                    768:  */
                    769: outData()
                    770: {
                    771:        register opts *this, *that;
                    772:        register funs *f;
                    773:        regs *r;
                    774:        char *p, work[20];
                    775:        int i, j, k, l;
                    776: 
                    777:        fprintf(ohp, "/*\n");
                    778:        fprintf(ohp, " * 80386 assembler header file.\n");
                    779:        fprintf(ohp, " * Generated by tabbld\n");
                    780:        fprintf(ohp, " */\n\n");
                    781: 
                    782:        fprintf(ofp, "/*\n");
                    783:        fprintf(ofp, " * 80386 assembler table file.\n");
                    784:        fprintf(ofp, " * Generated by tabbld\n");
                    785:        fprintf(ofp, " */\n");
                    786:        fprintf(ofp, "#include <stdio.h>\n");
                    787:        fprintf(ofp, "#include <asm.h>\n");
                    788:        fprintf(ofp, "#include <y_tab.h>\n");
                    789:        fprintf(ofp, "#include <symtab.h>\n\n");
                    790: 
                    791:        fprintf(ohp, "/* operand types */\n");
                    792:        /* dump base operand types */
                    793:        for (i = 0; i < operct; i++)
                    794:                if (j = opertab[i].base)
                    795:                        fprintf(ohp, "#define %-9s %2d\n", opertab[i].name, j);
                    796: 
                    797:        /* dump function table */
                    798:        fprintf(ohp, "\n/* instruction types */\n");
                    799:        fprintf(ofp, "readonly symt typTab[] = {\n");
                    800:        for (i = 0; i < funct;) {
                    801:                f = funtab + i;
                    802:                fprintf(ohp, "#define %-21s %2d\n", f->name, i);
                    803:                fprintf(ofp, " /* %-21s */ { %10s, 0x%04x, %d",
                    804:                        f->name,
                    805:                        f->type,
                    806:                        f->opt & 0xffff,
                    807:                        f->operands);
                    808:                for (j = 0; j < f->operands; j++)
                    809:                        fprintf(ofp, ", %s", opertab[f->ap[j]].name);
                    810:                fprintf(ofp, " }%s\n", ((++i < funct) ? "," : ""));
                    811:        }
                    812:        fprintf(ofp, "};\n\n");
                    813: 
                    814:        /* dump the name hash */
                    815:        fprintf(ofp, "readonly char charLump[] = {");
                    816:        i = 0;
                    817:        for (p = allntab; *p;) {
                    818:                switch (i++) {
                    819:                case 0:
                    820:                        fprintf(ofp, "\n\t");
                    821:                        break;
                    822:                case 10:
                    823:                        i = 0;
                    824:                default:
                    825:                        fprintf(ofp, " ");
                    826:                }
                    827:                fprintf(ofp, "'%c'", *p++);
                    828:                if (*p)
                    829:                        fprintf(ofp, ",");
                    830:        }
                    831:        fprintf(ofp, "\n};\n\n");
                    832: 
                    833:        /*
                    834:         * dump preftab first generic opcodes then regular.
                    835:         * opcode is now used to point to the preftab address.
                    836:         * for generic opcodes.
                    837:         * lineno is now used tp point to the preftab address
                    838:         * for processed opcodes that need hash pointers
                    839:         * and zero for other processed opcodes.
                    840:         */
                    841:        fprintf(ofp, "readonly opc prefTab[] = {\n");
                    842:        for (lastp = i = 0; i < opct; i++) {
                    843:                this = optab + i;
                    844:                if (this->fun != -1)    /* non generic opcode */
                    845:                        continue;
                    846: 
                    847:                work[0] = '\0';
                    848:                this->opcode = lastp;
                    849: 
                    850:                fputc('\n', ofp);
                    851:                for (j = 0; j < opct; j++) {
                    852:                        that = optab + j;
                    853:                        if (that->gen != i || that->fun == -1)
                    854:                                continue;
                    855:                        that->lineno = 0;
                    856:                        /* remember first of each name */
                    857:                        if(strcmp(work, that->name)) {
                    858:                                k = j;
                    859:                                optab[k].lineno = l = lastp;
                    860:                                strcpy(work, that->name);
                    861:                        }
                    862:                        fprintf(ofp,
                    863:                                "\t{ 0x%04x, %21s },\t/* %-10s %d */\n",
                    864:                                that->opcode & 0xffff,
                    865:                                funtab[that->fun].name,
                    866:                                that->name,
                    867:                                lastp);
                    868:                        lastp++;
                    869:                }
                    870:        }
                    871:        fputc('\n', ofp);
                    872: 
                    873:        /* do non generic opcodes */
                    874:        for (i = 0; i < opct; i++) {
                    875:                this = optab + i;
                    876:                /* regular first opcode */
                    877:                if (this->fun != -1 && this->len) {
                    878:                        if (-1 != this->lineno) { /* matches end of generic */
                    879:                                this->opcode = this->lineno;
                    880:                                continue;
                    881:                        }
                    882:                        k = lastp;      /* save lastp */
                    883:                        for (j = i; j < opct;) {
                    884:                                that = optab + j;
                    885:                                if (strcmp(this->name, that->name))
                    886:                                        break;
                    887:                                if (-1 == that->fun) {
                    888:                                        errors++;
                    889:                                        fprintf(stderr, "odd order %s",
                    890:                                                that->name);
                    891:                                        break;
                    892:                                }
                    893:                                fprintf(ofp,
                    894:                                   "\t{ 0x%04x, %21s }%s\t/* %-10s %d */\n",
                    895:                                        that->opcode & 0xffff,
                    896:                                        funtab[that->fun].name,
                    897:                                        ((++j != opct) ? "," : ""),
                    898:                                        that->name,
                    899:                                        lastp);
                    900:                                lastp++;
                    901:                        }
                    902:                        this->opcode = k;
                    903:                }
                    904:        }
                    905:        fprintf(ofp, "};\n\n");
                    906: 
                    907:        free(funtab);
                    908: 
                    909:        /* set up hash table to mark */
                    910:        htab = alloc(nameCt * sizeof(*htab));
                    911:        fprintf(ohp, "#define OPCOUNT %d /* count of opcodes */\n", nameCt);
                    912: 
                    913:        for (i = 0; i < nameCt; i++)
                    914:                htab[i] = -1;
                    915: 
                    916:        /* mark all items that hash direct */
                    917:        for (i = 0; i < opct; i++) {
                    918:                this = optab + i;
                    919: 
                    920:                this->hash = -2;
                    921:                if (!this->len)
                    922:                        continue;
                    923:                memcpy(work, allntab + this->pt, this->len);
                    924:                work[this->len] = '\0';
                    925:                j = hash(work) % nameCt;
                    926: 
                    927:                if (htab[j] != -1) {    /* hole taken get it next pass */
                    928:                        this->hash = -1;
                    929:                        continue;
                    930:                }
                    931:                htab[j] = i;    /* hash table points to entry */
                    932:        }
                    933: 
                    934:        /* mark items that hash indirect */
                    935:        for (i = 0; i < opct; i++) {
                    936:                this = optab + i;
                    937:                if (-1 != this->hash)   /* pass unmarked items */
                    938:                        continue;
                    939: 
                    940:                 /* find a hole */
                    941:                for (k = 0;(k < nameCt) && (htab[k] != -1); k++)
                    942:                        ;
                    943:                if (k == nameCt) {
                    944:                        errors++;
                    945:                        fprintf(stderr, "Insufficient holes in table");
                    946:                        continue;
                    947:                }
                    948:                htab[k] = i;    /* hash table points to entry */
                    949: 
                    950:                /* where does this hash to */
                    951:                memcpy(work, allntab + this->pt, this->len);
                    952:                work[this->len] = '\0';
                    953:                j = hash(work) % nameCt;
                    954: 
                    955:                /* find the end of the chain */
                    956:                while(-2 != (j = (that = optab + htab[j])->hash))
                    957:                        ;
                    958: 
                    959:                that->hash = k;
                    960:                this->hash = -2;
                    961:        }
                    962: 
                    963:        fprintf(ofp, "readonly nhash hashCodes[] = {\n");
                    964:        for (i = 0; i < nameCt;) {
                    965:                j = htab[i++];
                    966:                if (j < 0 || j > opct) {
                    967:                        errors++;
                    968:                        fprintf(stderr, "Unplaned hole in table");
                    969:                        fprintf(ofp, "\t{-1, 0, 0, 0, 0 }, /* JUNK */\n");
                    970:                        continue;
                    971:                }
                    972:                this = optab + j;
                    973: 
                    974:                memcpy(work, allntab + this->pt, this->len);
                    975:                work[this->len] = '\0';
                    976:                fprintf(ofp, "\t{%4d, %4d, %2d, %2d, %4d }%c /* %-12s %d */\n",
                    977:                        ((this->hash < 0) ? -1 : this->hash),
                    978:                        this->pt,
                    979:                        this->len,
                    980:                        this->count,    /* entries on pref table */
                    981:                        this->opcode,   /* entry on pref table */
                    982:                        ((i == nameCt) ? ' ' : ','),
                    983:                        work,
                    984:                        i - 1);
                    985:        }
                    986:        fprintf(ofp, "};\n\n");
                    987: 
                    988:        fprintf(ohp,
                    989:                "#define SYMCOUNT %d\t/* count of predefined symbols */\n",
                    990:                regct + 1);
                    991: 
                    992:        fprintf(ofp, "psym symtab[] = {\n");
                    993:        fprintf(ofp,    /* too fancy for the basic mechinism */
                    994:                "\t{NULL, IDENTIFIER, 0, 0, 1, 0, symtab, 0, 0, \".\" },\n");
                    995:        for (i = 0; i < regct; ) {
                    996:                r = regtab + i++;
                    997: 
                    998:                j = 0;
                    999:                if (NULL == strstr(r->ytype, "REG"))
                   1000:                        strcpy(work, r->name);
                   1001:                else {
                   1002:                        sprintf(work, "%%%s", r->name);
                   1003:                        switch(r->ytype[0]) {
                   1004:                        case 'S':       /* SEG_REG */
                   1005:                                j = 0x800;
                   1006:                                break;
                   1007:                        case 'C':       /* CTL_REG */
                   1008:                                j = 0x400;
                   1009:                                break;
                   1010:                        case 'D':       /* DEB_REG */
                   1011:                                j = 0x200;
                   1012:                                break;
                   1013:                        case 'T':       /* TST_REG */
                   1014:                                j = 0x100;
                   1015:                                break;
                   1016:                        }
                   1017:                        r->ytype = "REG";
                   1018:                }
                   1019:                fprintf(ofp,
                   1020:                  "\t{ NULL, %10s, %d, %d, 0, %d, NULL, 0, 0, \"%s\" }%s\n",
                   1021:                  r->ytype,
                   1022:                  r->loc,
                   1023:                  r->len,
                   1024:                  j,
                   1025:                  work,
                   1026:                  ((i < regct) ? "," : ""));
                   1027:        }
                   1028:        fprintf(ofp, "};\n");
                   1029: }
                   1030: 
                   1031: /*
                   1032:  * Process opcode files.
                   1033:  */
                   1034: main(argc, argv)
                   1035: char *argv[];
                   1036: {
                   1037:        int c, subtest;
                   1038:        extern char *optarg;
                   1039:        extern int optind;
                   1040: 
                   1041:        for (subtest = 0; EOF != (c = getopt(argc, argv, "blst:n:?"));) {
                   1042:                subtest = 1;    /* any options are a subtest */
                   1043:                switch (c) {
                   1044:                case 'b':
                   1045:                        bswitch = 1;
                   1046:                        break;
                   1047:                case 'l':
                   1048:                        lswitch = 1;
                   1049:                        break;
                   1050:                case 's':
                   1051:                        sswitch = 1;
                   1052:                        break;
                   1053:                case 't':
                   1054:                        sscanf(optarg, "%x", &tmask);
                   1055:                        break;
                   1056:                case 'n':
                   1057:                        sscanf(optarg, "%x", &nmask);
                   1058:                        break;
                   1059:                case '?':
                   1060:                default:
                   1061:                        fprintf(stderr,
                   1062:         "usage: tabbld [-bls] [-t bits_to_match] [-n bits_not_to_match]\n");
                   1063:                        exit (1);
                   1064:                }
                   1065:        }
                   1066:                        
                   1067:        /*
                   1068:         * These are nessisary as long as this runs small model.
                   1069:         * otherwise this thing runs out of space.
                   1070:         */
                   1071:        START(op,  1000);
                   1072:        START(fun, 250);
                   1073:        START(oper, 100);
                   1074:        START(alln, 2000);
                   1075:        START(reg, 100);
                   1076: 
                   1077:        otp = xopen("test.s", "w");
                   1078:        if (subtest) {
                   1079:                fprintf(otp, "\t.ttl\tSubtest of asm 386 ");
                   1080:                if (bswitch | lswitch | sswitch)
                   1081:                        fputc('-', otp);
                   1082:                if (bswitch)
                   1083:                        fputc('b', otp);
                   1084:                if (lswitch)
                   1085:                        fputc('t', otp);
                   1086:                if (sswitch)
                   1087:                        fputc('s', otp);
                   1088:                if (tmask)
                   1089:                        fprintf(otp, " -t %x", tmask);
                   1090:                if (nmask)
                   1091:                        fprintf(otp, " -n %x", nmask);
                   1092:                fputc('\n', otp);
                   1093:                odp = ohp = ofp = xopen("/dev/null", "w");
                   1094:        }
                   1095:        else {
                   1096:                fprintf(otp, "\t.ttl\tFull test of asm 386\n");
                   1097:                ofp = xopen("symtab.c", "w");   /* symbol table */
                   1098:                ohp = xopen("symtab.h", "w");   /* header file */
                   1099:                odp = xopen("document", "w");   /* document file */
                   1100:        }
                   1101:        fprintf(otp, "\t.llen\t100\n");
                   1102:        fprintf(otp, "abc:\n");
                   1103:        
                   1104:        /*
                   1105:         * Process file.
                   1106:         */
                   1107:        while (NULL != (line = getline(stdin, &lineno))) {
                   1108:                switch (*line) {
                   1109:                case '+':
                   1110:                        sscanf(line + 2, "%d", &state);
                   1111:                        continue;
                   1112:                case 0:
                   1113:                        if (1 == state) {       /* pass through comments */
                   1114:                                if (-1 == curgen)
                   1115:                                        fprintf(odp, "%s %d 2!\t%s\n",
                   1116:                                                ((optDoc & INDEF_JMP) ? "ja" : opc),
                   1117:                                                lineno, comment);
                   1118:                                else
                   1119:                                        fprintf(odp, "%s %d 1!\t%s\n",
                   1120:                                                thisGen, lineno, comment);
                   1121:                        }
                   1122:                        continue;
                   1123:                }
                   1124:                switch(state) {
                   1125:                case 0: /* test stream directives. */
                   1126:                        buildTst();
                   1127:                        break;
                   1128:                case 1: /* opcodes */
                   1129:                        buildOp();
                   1130:                        break;
                   1131:                case 2: /* registers */
                   1132:                        buildReg();
                   1133:                        break;
                   1134:                case 3: /* assembler directives */
                   1135:                        buildDir();
                   1136:                }
                   1137:        }
                   1138:        fclose(otp);
                   1139: 
                   1140:        if (subtest)
                   1141:                return (0);
                   1142: 
                   1143:        reorgData();
                   1144:        outData();
                   1145:        if (errors)
                   1146:                fprintf(stderr, "%d error%c detected\n", errors, 
                   1147:                        (1 == errors) ? ' ' : 's');
                   1148:        showStats(errors ? 1 : 0);
                   1149: 
                   1150:        return (0);
                   1151: }

unix.superglobalmegacorp.com

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