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