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