|
|
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.