|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.