|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Optimized blitter minterm function generator
5: *
6: * Copyright 1995,1996 Bernd Schmidt
7: * Copyright 1996 Alessandro Bissacco
8: *
9: * Overkill, n: cf. genblitter
10: */
11:
12: #include "sysconfig.h"
13: #include "sysdeps.h"
14:
15: #include "config.h"
16: #include "options.h"
17:
18: static void nop(int);
19:
20: #if 0
21: typedef struct alloc_hdr
22: {
23: int size;
24: struct alloc_hdr *next, *prev;
25: void *from, *from2;
26: } *ahead;
27:
28: static struct alloc_hdr ah_top = { 0, &ah_top, &ah_top, 0, 0 };
29:
30: int nbytesmalloced = 0;
31: int malloc_cnt = 0;
32:
33: static void *xmalloc(int sz)
34: {
35: ahead mem = (ahead)malloc(sz + sizeof(struct alloc_hdr));
36: mem->size = sz;
37: mem->next = &ah_top;
38: mem->prev = ah_top.prev;
39: ah_top.prev->next = mem;
40: ah_top.prev = mem;
41:
42: mem->from = __builtin_return_address(0);
43: mem->from2 = __builtin_return_address(1);
44:
45: malloc_cnt++;
46: nbytesmalloced += sz;
47:
48: return mem + 1;
49: }
50:
51: static void *xrealloc(void *mem, int sz)
52: {
53: if (mem == NULL)
54: return xmalloc(sz);
55: else {
56: ahead m = (ahead)mem;
57: m--;
58:
59: nbytesmalloced += sz - m->size;
60: m->size = sz;
61: return ((ahead)realloc(m, sz + sizeof(struct alloc_hdr))) + 1;
62: }
63: }
64:
65: static void xfree(void *mem)
66: {
67: ahead m = (ahead)mem;
68:
69: m--;
70:
71: m->next->prev = m->prev;
72: m->prev->next = m->next;
73: nbytesmalloced -= m->size;
74: malloc_cnt--;
75: free(m);
76: }
77: #else
78: #define xmalloc malloc
79: #define xfree free
80: #define xrealloc realloc
81: #endif
82:
83: typedef struct tree_n {
84: enum tree_op { op_and, op_or, op_xor, op_not, op_a, op_b, op_c } op;
85: struct tree_n *left, *right;
86: } *tree;
87:
88: static struct tree_n TRA = { op_a, NULL, NULL }, TRB = { op_b, NULL, NULL }, TRC = { op_c, NULL, NULL };
89: static tree tree_a = &TRA, tree_b = &TRB, tree_c = &TRC;
90:
91: typedef struct {
92: tree *trees;
93: int space;
94: int ntrees;
95: } tree_vec;
96:
97: static tree best_tree, main_tree;
98: static int best_cost = 65535;
99:
100: static void kill_tree(tree *t)
101: {
102: if (*t != NULL && *t != tree_a && *t != tree_b && *t != tree_c) {
103: if ((*t)->left) kill_tree(&(*t)->left);
104: if ((*t)->right) kill_tree(&(*t)->right);
105: xfree(*t);
106: }
107: *t = NULL;
108: }
109:
110: static tree dup_tree(tree t)
111: {
112: if (t == NULL || t == tree_a || t == tree_b || t == tree_c)
113: return t;
114: else {
115: tree nt = (tree)xmalloc(sizeof(struct tree_n));
116: nt->op = t->op;
117: nt->left = dup_tree(t->left);
118: nt->right = dup_tree(t->right);
119: return nt;
120: }
121: }
122:
123: static tree new_op_tree(enum tree_op op, tree l, tree r)
124: {
125: tree t;
126: if (op == op_not && l->op == op_not) {
127: t = l->left;
128: xfree(l);
129: return t;
130: }
131: t = (tree)xmalloc(sizeof(struct tree_n));
132: t->left = l;
133: t->right = r;
134: t->op = op;
135: return t;
136: }
137:
138: static int tree_cst(tree t, int *nota, int *notb, int *notc)
139: {
140: switch(t->op) {
141: case op_a:
142: case op_b:
143: case op_c:
144: return 0;
145: case op_not:
146: switch (t->left->op) {
147: case op_a:
148: if (*nota)
149: return 0;
150: *nota = 1;
151: return 4;
152:
153: case op_b:
154: if (*notb)
155: return 0;
156: *notb = 1;
157: return 4;
158:
159: case op_c:
160: if (*notc)
161: return 0;
162: *notc = 1;
163: return 4;
164: #if 0
165: case op_not:
166: return tree_cst(t->left->left, nota, notb, notc);
167: #endif
168: default:
169: break;
170: }
171: return 3 + tree_cst(t->left, nota, notb, notc);
172:
173: case op_and:
174: case op_xor:
175: case op_or:
176: return 3 + tree_cst(t->left, nota, notb, notc) + tree_cst(t->right, nota, notb, notc);
177: }
178: return 0;
179: }
180:
181: static int tree_cost(tree t)
182: {
183: int a = 0,b = 0,c = 0;
184:
185: return tree_cst(t,&a,&b,&c);
186: }
187:
188: static int eval(tree t)
189: {
190: int v = tree_cost(t);
191: if (v < best_cost) {
192: best_cost = v;
193: if (best_tree != NULL)
194: kill_tree(&best_tree);
195: best_tree = dup_tree(t);
196: }
197: return v;
198: }
199:
200: static int tree_equal(tree a, tree b)
201: {
202: unsigned long mask = 0;
203: int i;
204: tree t2, t3;
205:
206: if (a == b)
207: return 1;
208: if (a->op != b->op)
209: return 0;
210: if (a->op == op_not)
211: return tree_equal(a->left, b->left);
212:
213: if (a->op != op_xor && a->op != op_or && a->op != op_and)
214: return 0;
215:
216: if (tree_equal(a->left, b->left))
217: return tree_equal(a->right, b->right);
218:
219: for (i = 0, t2 = a; t2->op == a->op; t2 = t2->right, i++)
220: ;
221: for (t3 = b; t3->op == b->op; t3 = t3->right, i--)
222: ;
223:
224: if (i != 0)
225: return 0;
226:
227: t2 = a;
228: for (;;) {
229: tree ttmp;
230: tree t3;
231:
232: if (t2->op == a->op)
233: ttmp = t2->left;
234: else
235: ttmp = t2;
236:
237: t3 = b;
238: for (i = 0;; i++) {
239: tree ttmp2;
240:
241: if (t3->op == b->op)
242: ttmp2 = t3->left;
243: else
244: ttmp2 = t3;
245:
246: if ((mask & (1 << i)) == 0 && tree_equal(ttmp, ttmp2)) {
247: mask |= 1 << i;
248: break;
249: }
250:
251: if (t3->op != b->op)
252: return 0;
253:
254: t3 = t3->right;
255: }
256:
257: if (t2->op != a->op)
258: break;
259:
260: t2 = t2->right;
261: }
262: return 1;
263: }
264:
265: static int tree_isnormal(tree t)
266: {
267: if ((t->op == op_xor || t->op == op_and || t->op == op_or)
268: && t->left->op == t->op)
269: return 0;
270: return 1;
271: }
272:
273: static void normalize(tree *t)
274: {
275: if (*t == NULL)
276: return;
277:
278: if ((*t)->op == op_not && (*t)->left->op == op_not) {
279: tree t2 = (*t)->left->left;
280: xfree((*t)->left);
281: xfree(*t);
282: *t = t2;
283: }
284:
285: while (((*t)->op == op_xor || (*t)->op == op_and || (*t)->op == op_or)
286: && (*t)->left->op == (*t)->op)
287: {
288: tree tmp = (*t)->left->left;
289: (*t)->left->left = (*t)->left->right;
290: (*t)->left->right = (*t)->right;
291: (*t)->right = (*t)->left;
292: (*t)->left = tmp;
293: }
294: normalize(&(*t)->left);
295: normalize(&(*t)->right);
296: }
297:
298: static void add_vec(tree_vec *tv, tree t)
299: {
300: if (!tree_isnormal(t))
301: nop(2);
302:
303: if (tv == NULL) {
304: eval(t);
305: kill_tree(&t);
306: } else {
307: int i;
308: for (i = 0; i < tv->ntrees; i++)
309: if (tree_equal(tv->trees[i], t)) {
310: kill_tree(&t);
311: return;
312: }
313:
314: if (tv->ntrees == tv->space) {
315: tv->trees = (tree *)xrealloc(tv->trees, sizeof(tree)*(tv->space += 40));
316: }
317: tv->trees[tv->ntrees++] = t;
318: }
319: }
320:
321: static void kill_vec(tree_vec *tv)
322: {
323: int i;
324: for (i = 0; i < tv->ntrees; i++)
325: kill_tree(tv->trees + i);
326: xfree(tv->trees);
327: }
328:
329: static void init_vec(tree_vec *tv)
330: {
331: tv->ntrees = tv->space = 0;
332: tv->trees = NULL;
333: }
334:
335: static void do_sprint_tree(char *s, tree *t)
336: {
337: switch ((*t)->op) {
338: case op_a:
339: strcat(s, "srca");
340: break;
341: case op_b:
342: strcat(s, "srcb");
343: break;
344: case op_c:
345: strcat(s, "srcc");
346: break;
347:
348: case op_and:
349: strcat(s, "(");
350: do_sprint_tree(s, &(*t)->left);
351: strcat(s, " & ");
352: while ((*t)->right->op == op_and) {
353: t = &(*t)->right;
354: do_sprint_tree(s, &(*t)->left);
355: strcat(s, " & ");
356: }
357: do_sprint_tree(s, &(*t)->right);
358: strcat(s, ")");
359: break;
360:
361: case op_or:
362: strcat(s, "(");
363: do_sprint_tree(s, &(*t)->left);
364: strcat(s, " | ");
365: while ((*t)->right->op == op_or) {
366: t = &(*t)->right;
367: do_sprint_tree(s, &(*t)->left);
368: strcat(s, " | ");
369: }
370: do_sprint_tree(s, &(*t)->right);
371: strcat(s, ")");
372: break;
373:
374: case op_xor:
375: strcat(s, "(");
376: do_sprint_tree(s, &(*t)->left);
377: strcat(s, " ^ ");
378: while ((*t)->right->op == op_xor) {
379: t = &(*t)->right;
380: do_sprint_tree(s, &(*t)->left);
381: strcat(s, " ^ ");
382: }
383: do_sprint_tree(s, &(*t)->right);
384: strcat(s, ")");
385: break;
386:
387: case op_not:
388: strcat(s, "~");
389: do_sprint_tree(s,&(*t)->left);
390: break;
391: }
392: }
393:
394: static void sprint_tree(char *s, tree t)
395: {
396: tree tt = dup_tree(t);
397: *s = 0;
398: do_sprint_tree(s, &tt);
399: kill_tree(&tt);
400: }
401:
402: static int treecmp(tree a, tree b)
403: {
404: if (b->op != a->op)
405: return 1;
406:
407: if (a == b)
408: return 0;
409:
410: if (a->op == op_not)
411: return treecmp(a->left, b->left);
412:
413: return 1;
414: }
415:
416: static int issrc(tree t)
417: {
418: return t->op == op_a || t->op == op_b || t->op == op_c;
419: }
420:
421: static void do_opt(tree, tree_vec *, int);
422: static void opt_xor(tree t, tree_vec *tv);
423: static void opt_distrib(tree t, tree_vec *tv);
424: static void opt_demorgan(tree t, tree_vec *tv);
425:
426: static void opt_not(tree_vec *tv_dst, tree_vec *tv_src)
427: {
428: int i;
429: for (i = 0; i < tv_src->ntrees; i++) {
430: tree t = tv_src->trees[i];
431:
432: add_vec(tv_dst, new_op_tree(op_not, dup_tree(t), NULL));
433: }
434: }
435:
436: static void demorgan(tree t, tree_vec *tv)
437: {
438: tree newt = NULL, t_l = NULL;
439: int neednot = 0;
440:
441: if (t->op == op_not && (t->left->op == op_and || t->left->op == op_or))
442: t_l = dup_tree(t->left);
443: else if (t->op == op_and || t->op == op_or)
444: t_l = dup_tree(t), neednot = 1;
445: else
446: return;
447:
448: if (t_l->op == op_and)
449: t_l->op = op_or;
450: else
451: t_l->op = op_and;
452:
453: t_l->left = new_op_tree(op_not, t_l->left, NULL);
454: t_l->right = new_op_tree(op_not, t_l->right, NULL);
455: normalize(&t_l);
456:
457: if (neednot) {
458: tree_vec tv2;
459: int i;
460:
461: init_vec(&tv2);
462: opt_xor(t_l, &tv2);
463: opt_distrib(t_l, &tv2);
464: add_vec(&tv2, t_l);
465: #if 0
466: for (i = 0; i < tv2.ntrees; i++) {
467: add_vec(tv, new_op_tree(op_not, dup_tree(tv2.trees[i]), NULL));
468: }
469: #endif
470: opt_not(tv, &tv2);
471: kill_vec(&tv2);
472: } else {
473: opt_xor(t_l, tv);
474: opt_distrib(t_l, tv);
475: add_vec(tv, t_l);
476: }
477: }
478:
479: static void opt_xor(tree t, tree_vec *tv)
480: {
481: tree_vec tv1, tv2;
482: tree tt1, tt2;
483: int i;
484:
485: enum tree_op top, sop;
486: tree t1, t2, t3;
487: int n1 = 0, n2 = 0, ok1 = 0, ok2 = 0;
488:
489: top = t->op;
490: if (top != op_or)
491: return;
492:
493: sop = t->left->op;
494: if (sop != op_and || t->right->op != sop)
495: return;
496:
497: if (t->left->left->op == op_not) {
498: n1 = 1;
499: t1 = t->left->left->left;
500: } else {
501: t1 = t->left->left;
502: }
503:
504: if (t->left->right->op == op_not) {
505: n2 = 1;
506: t2 = t->left->right->left;
507: } else {
508: t2 = t->left->right;
509: }
510:
511: if (t->right->left->op == op_not) {
512: if (n1 == 0 && tree_equal(t->right->left->left, t1))
513: ok1++;
514: if (n2 == 0 && tree_equal(t->right->left->left, t2))
515: ok2++;
516: } else {
517: if (n1 == 1 && tree_equal(t->right->left, t1))
518: ok1++;
519: if (n2 == 1 && tree_equal(t->right->left, t2))
520: ok2++;
521: }
522:
523: if (t->right->right->op == op_not) {
524: if (n1 == 0 && tree_equal(t->right->right->left, t1))
525: ok1++;
526: if (n2 == 0 && tree_equal(t->right->right->left, t2))
527: ok2++;
528: } else {
529: if (n1 == 1 && tree_equal(t->right->right, t1))
530: ok1++;
531: if (n2 == 1 && tree_equal(t->right->right, t2))
532: ok2++;
533: }
534:
535: if (ok1 != 1 || ok2 != 1)
536: return;
537:
538: t3 = new_op_tree(op_xor, dup_tree(t1), dup_tree(t2));
539: if (n1 == n2)
540: t3 = new_op_tree(op_not, t3, NULL);
541: normalize(&t3);
542: add_vec(tv, t3);
543:
544: init_vec(&tv1); init_vec(&tv2);
545: tt1 = new_op_tree(op_not, dup_tree(t1), NULL);
546: tt2 = new_op_tree(op_not, dup_tree(t2), NULL);
547:
548: do_opt(tt1, &tv1, 0); do_opt(tt2, &tv2, 0);
549: kill_tree(&tt1); kill_tree(&tt2);
550:
551: for (i = 0; i < tv1.ntrees; i++) {
552: t3 = new_op_tree(op_xor, dup_tree(tv1.trees[i]), dup_tree(t2));
553: if (n1 != n2)
554: t3 = new_op_tree(op_not, t3, NULL);
555: normalize(&t3);
556: add_vec(tv, t3);
557: }
558:
559: for (i = 0; i < tv2.ntrees; i++) {
560: t3 = new_op_tree(op_xor, dup_tree(t1), dup_tree(tv2.trees[i]));
561: if (n1 != n2)
562: t3 = new_op_tree(op_not, t3, NULL);
563: normalize(&t3);
564: add_vec(tv, t3);
565: }
566:
567: for (i = 0; i < tv1.ntrees; i++) {
568: int j;
569:
570: for (j = 0; j < tv2.ntrees; j++) {
571: t3 = new_op_tree(op_xor, dup_tree(tv1.trees[i]), dup_tree(tv2.trees[j]));
572: if (n1 == n2)
573: t3 = new_op_tree(op_not, t3, NULL);
574: normalize(&t3);
575: add_vec(tv, t3);
576: }
577: }
578:
579: kill_vec(&tv1); kill_vec(&tv2);
580: }
581:
582: static tree opt_factor_tree(tree old, tree f, enum tree_op top, enum tree_op sop,
583: tree *remainder)
584: {
585: tree t1 = old;
586: tree t2 = NULL;
587: *remainder = NULL;
588:
589: for (;;) {
590: int found_factor = 0;
591: tree t3 = NULL;
592: tree t4;
593:
594: if (t1->op == top)
595: t4 = t1->left;
596: else
597: t4 = t1;
598:
599: if (t4->op != sop) {
600: if (*remainder == NULL)
601: *remainder = dup_tree(t4);
602: else
603: *remainder = new_op_tree(top, *remainder, dup_tree(t4));
604: } else {
605: for (;;) {
606: tree t5;
607:
608: if (t4->op == sop)
609: t5 = t4->left;
610: else
611: t5 = t4;
612:
613: if (treecmp(t5, f) != 0) {
614: if (t3 == NULL)
615: t3 = dup_tree(t5);
616: else
617: t3 = new_op_tree(sop, t3, dup_tree(t5));
618: } else
619: found_factor = 1;
620:
621: if (t4->op != sop)
622: break;
623: t4 = t4->right;
624: }
625: if (!found_factor) {
626: if (*remainder == NULL)
627: *remainder = t3;
628: else
629: *remainder = new_op_tree(top, *remainder, t3);
630: } else {
631: if (t2 == NULL)
632: t2 = t3;
633: else
634: t2 = new_op_tree(top, t2, t3);
635: }
636: }
637:
638: if (t1->op != top)
639: break;
640:
641: t1 = t1->right;
642: }
643: if (t2 == NULL || t2->op != top) {
644: if (*remainder != NULL)
645: kill_tree(remainder);
646: if (t2 != NULL)
647: kill_tree(&t2);
648: return NULL;
649: }
650: return t2;
651: }
652:
653: static void opt_distrib(tree t, tree_vec *tv)
654: {
655: enum tree_op top, sop;
656: tree t1;
657:
658: top = t->op;
659:
660: if (top != op_and && top != op_or)
661: return;
662:
663: sop = t->left->op;
664: if ((top == op_and && sop != op_or) || (top == op_or && sop != op_and))
665: return;
666: #if 0
667: t1 = t->right;
668: for (;;) {
669: if (t1->op == sop)
670: break;
671: if (t1->op != top)
672: return;
673: if (t1->left->op != sop)
674: return;
675: t1 = t1->right;
676: }
677: #endif
678:
679: t1 = t->left;
680: for (;;) {
681: tree t3, t4, t5;
682:
683: if (t1->op == sop)
684: t3 = t1->left;
685: else
686: t3 = t1;
687:
688: t4 = opt_factor_tree(t, t3, top, sop, &t5);
689: if (t4 != NULL) {
690: tree_vec tv2;
691: int i;
692:
693: init_vec(&tv2);
694: normalize(&t4);
695: do_opt(t4, &tv2, 0);
696: kill_tree(&t4);
697:
698: for (i = 0; i < tv2.ntrees; i++) {
699: t4 = new_op_tree(sop, dup_tree(t3), dup_tree(tv2.trees[i]));
700: if (t5 != NULL)
701: t4 = new_op_tree(top, t4, dup_tree(t5));
702: normalize(&t4);
703: if (t5 != NULL) {
704: demorgan(t4, tv);
705: opt_xor(t4, tv);
706: }
707: add_vec(tv, t4);
708: }
709: kill_vec(&tv2);
710:
711: if (t5 != NULL)
712: kill_tree(&t5);
713: }
714: if (t1->op != sop)
715: break;
716: t1 = t1->right;
717: }
718: }
719:
720: struct perm_data {
721: int n;
722: int *a;
723: tree_vec *tvar;
724: tree_vec *tvparent;
725: enum tree_op op;
726: int neednot;
727: int didmorgan;
728: };
729:
730: static void allperms(struct perm_data *pd, int p,
731: void (*f)(struct perm_data *))
732: {
733: if (p == pd->n)
734: f(pd);
735: else {
736: int i;
737: for (i = p; i < pd->n; i++) {
738: int tmp = pd->a[i];
739: pd->a[i] = pd->a[p];
740: pd->a[p] = tmp;
741: allperms(pd, p + 1, f);
742: tmp = pd->a[i];
743: pd->a[i] = pd->a[p];
744: pd->a[p] = tmp;
745: }
746: }
747:
748: }
749:
750: static void optimize(tree_vec *tv, tree subt, enum tree_op top)
751: {
752: tree_vec sub_tv;
753: int i;
754:
755: if (subt->op != top) {
756: add_vec(tv, dup_tree(subt));
757: return;
758: }
759:
760: init_vec(&sub_tv);
761: optimize(&sub_tv, subt->right, top);
762:
763: for (i = 0; i < sub_tv.ntrees; i++) {
764: tree t1 = new_op_tree(top, dup_tree(subt->left), dup_tree(sub_tv.trees[i]));
765: demorgan(t1, tv);
766: opt_xor(t1, tv);
767: opt_distrib(t1, tv);
768: add_vec(tv, t1);
769: }
770: kill_vec(&sub_tv);
771: }
772:
773: static void do_opt_perm_1(struct perm_data *pd, int i, tree rhs)
774: {
775: int j = pd->a[i];
776: int k;
777:
778: i++;
779: for (k = 0; k < pd->tvar[j].ntrees; k++) {
780: tree lhs;
781:
782: if (rhs == NULL)
783: lhs = dup_tree(pd->tvar[j].trees[k]);
784: else
785: lhs = new_op_tree(pd->op, dup_tree(pd->tvar[j].trees[k]), dup_tree(rhs));
786:
787: if (i < pd->n) {
788: do_opt_perm_1(pd, i, lhs);
789: } else {
790: normalize(&lhs);
791:
792: if (pd->neednot) {
793: int i;
794: tree_vec tvs;
795: init_vec(&tvs);
796:
797: optimize(&tvs, lhs, lhs->op);
798: #if 0
799: for (i = 0; i < tvs.ntrees; i++)
800: add_vec(pd->tvparent, new_op_tree(op_not, dup_tree(tvs.trees[i]), NULL));
801: #endif
802: opt_not(pd->tvparent, &tvs);
803: kill_vec(&tvs);
804: } else
805: optimize(pd->tvparent, lhs, lhs->op);
806: }
807:
808: kill_tree(&lhs);
809: }
810: nop(j);
811: }
812:
813: void nop(int a)
814: {
815: }
816:
817: static void do_opt_perm(struct perm_data *pd)
818: {
819: do_opt_perm_1(pd, 0, NULL);
820: }
821:
822: static void do_opt(tree t, tree_vec *tv, int did_morgan)
823: {
824: /* if (!did_morgan)
825: demorgan(t, tv);
826: opt_distrib(t, tv);
827: opt_xor(t, tv);*/
828:
829: if ((t->op == op_and || t->op == op_or)
830: || (t->op == op_not
831: && (t->left->op == op_and || t->left->op == op_or)))
832: {
833: int i, j;
834: struct perm_data pd;
835: tree t2, t3;
836: int neednot = t->op == op_not;
837:
838: if (neednot)
839: t3 = t->left;
840: else
841: t3 = t;
842:
843: pd.didmorgan = did_morgan;
844: pd.op = t3->op;
845: pd.neednot = neednot;
846: pd.tvparent = tv;
847: pd.n = 2;
848:
849: t2 = t3->right;
850: while (t2->op == t3->op) {
851: pd.n++;
852: t2 = t2->right;
853: }
854:
855: pd.a = (int *)xmalloc(sizeof(int)*pd.n);
856: pd.tvar = (tree_vec *)xmalloc(sizeof(tree_vec)*pd.n);
857: for (i = 0; i < pd.n; i++)
858: pd.a[i] = i;
859:
860: t2 = t3; i = 0;
861: while (t2->op == t3->op) {
862: init_vec(pd.tvar + i);
863: do_opt(t2->left, pd.tvar + i, neednot && did_morgan);
864: t2 = t2->right;
865: i++;
866: }
867: init_vec(pd.tvar + i);
868: do_opt(t2, pd.tvar + i, 0);
869:
870: allperms(&pd, 0, do_opt_perm);
871:
872: for (i = 0; i < pd.n; i++) {
873: kill_vec(pd.tvar + i);
874: }
875: xfree(pd.tvar);
876: xfree(pd.a);
877: } else {
878: demorgan(t, tv);
879: opt_xor(t, tv);
880: opt_distrib(t, tv);
881: add_vec(tv, dup_tree(t));
882: }
883: }
884:
885: static int bitset(int mt, int bit)
886: {
887: return mt & (1 << bit);
888: }
889:
890: static char buffer[4096];
891:
892: static int generate_expr(int minterm, int print)
893: {
894: int result = 0;
895: int firstor = 1;
896: int bits = 0;
897: int i;
898: int expr_bit[8], expr_dc[8], nexp = 0;
899: int expr_used[8];
900: tree t, t1 = NULL;
901:
902: if (minterm == 0) {
903: if (print)
904: printf("0");
905: return 0;
906: }
907: if (minterm == 0xFF) {
908: if (print)
909: printf("0xFFFFFFFF");
910: return 0;
911: }
912:
913: for(i=0; i<8; i++) {
914: if (bitset(minterm, i) && !bitset(bits,i)) {
915: int j;
916: int dontcare = 0;
917: int firstand = 1;
918: int bitbucket[8], bitcount;
919:
920: bits |= 1<<i;
921: bitcount = 1; bitbucket[0] = i;
922: for(j=1; j<8; j *= 2) {
923: int success = 1;
924: int k;
925: for(k=0; k < bitcount; k++) {
926: if (!bitset(minterm, bitbucket[k] ^ j)) {
927: success = 0;
928: }
929: }
930: if (success) {
931: int l;
932: dontcare |= j;
933: for(l=bitcount; l < bitcount*2; l++) {
934: bitbucket[l] = bitbucket[l-bitcount] ^ j;
935: bits |= 1 << bitbucket[l];
936: }
937: bitcount *= 2;
938: }
939: }
940: expr_used[nexp] = 1;
941: expr_dc[nexp] = dontcare;
942: expr_bit[nexp++] = i;
943: }
944: }
945:
946: t1 = NULL;
947: for (i = 0; i < nexp; i++) {
948: int j, firstand = 1;
949: tree t2 = NULL;
950:
951: for (j = 1; j < 8; j *= 2) {
952: if (!(expr_dc[i] & j)) {
953: tree t3 = j == 1 ? tree_c : j == 2 ? tree_b : tree_a;
954:
955: if ((expr_bit[i] & j) == 0)
956: t3 = new_op_tree(op_not, t3, NULL);
957:
958: if (t2 != NULL)
959: t2 = new_op_tree(op_and, t3, t2);
960: else
961: t2 = t3;
962: result |= (j == 1 ? 4 : j == 2 ? 2 : 1);
963: }
964: }
965: if (t1 != NULL)
966: t1 = new_op_tree(op_or, t2, t1);
967: else
968: t1 = t2;
969: }
970: if (t1 != NULL) {
971: best_tree = NULL;
972: best_cost = 65535;
973: normalize(&t1);
974: main_tree = t1;
975: do_opt(main_tree, NULL, 0);
976: sprint_tree(buffer, best_tree);
977: printf("%s", buffer);
978: kill_tree(&main_tree);
979: kill_tree(&best_tree);
980: }
981:
982: return result;
983: }
984:
985: static void print_expr(int minterm)
986: {
987: generate_expr(minterm, 1);
988: printf("\n");
989: }
990:
991: static void print_tree(tree t)
992: {
993: char buf[32768];
994:
995: sprint_tree(buf, t);
996: printf("%s\n", buf);
997: }
998:
999: static void generate_optable(void)
1000: {
1001: int minterm;
1002: printf(" /* This file generated automatically - do not edit */\n\n");
1003: printf("#include \"genblitter.h\"\n\n");
1004: printf("struct blitop blitops[256] = {\n");
1005: for (minterm = 0; minterm < 256; minterm++) {
1006: int r;
1007: printf(" /* %02x */ { \"", minterm);
1008: r = generate_expr(minterm, 1);
1009: printf("\", %d }%s\n", r, minterm == 255 ? "" : ",");
1010: fflush(stdout);
1011: }
1012: printf("};\n");
1013: }
1014:
1015: int main(int argc, char **argv)
1016: {
1017: #if 0
1018: tree t, t1, t2, t3;
1019: tree_vec tv1;
1020: int i;
1021:
1022: t1 = new_op_tree(op_or, tree_b, tree_a);
1023: t2 = new_op_tree(op_or, tree_c, tree_a);
1024: t3 = new_op_tree(op_not, new_op_tree(op_xor, tree_c, tree_b), NULL);
1025:
1026: t = new_op_tree(op_and, t1, new_op_tree(op_and, t2, t3));
1027: init_vec(&tv1);
1028:
1029: opt_distrib(t, &tv1);
1030: for (i = 0; i < tv1.ntrees; i++)
1031: print_tree(tv1.trees[i]);
1032: kill_vec(&tv1);
1033: #endif
1034: generate_optable();
1035:
1036: return 0;
1037: }
1038:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.