|
|
1.1 root 1: /*
2: * n1/i8086/mtree2.c
3: * Machine dependent parts of the tree modifier.
4: * This version handles both the SMALL and the LARGE model iAPX86.
5: * A conditionalization handles machines that have an 8087.
6: */
7: #ifdef vax
8: #include "INC$LIB:cc1.h"
9: #else
10: #include "cc1.h"
11: #endif
12:
13: int blkflab;
14:
15: static char modoptab[] = {
16: 'i', 'u', 'i', 'u', 'l', 'v', 'f',
17: 'd', 'b', 'i', 'i', 'p', 'p', 'p', 'p'
18: };
19:
20:
21: #if SPLIT_CC1
22: /*
23: * Function prolog.
24: * Clear "BLK function" label.
25: */
26: doprolog()
27: {
28: blkflab = 0;
29: }
30:
31: /*
32: * Copy auto information.
33: */
34: doautos()
35: {
36: iput(iget());
37: iput(iget());
38: }
39: #endif
40:
41: /*
42: * This function performs machine specific tree modifications.
43: * It is called from "modtree" after all of the machine
44: * independent transformations have been done.
45: * It returns either a pointer to the new tree
46: * (telling "modtree" to do another pass)
47: * or NULL (which implies that no changes were made).
48: */
49: TREE *
50: modoper(tp, ac, ptp)
51: register TREE *tp;
52: TREE *ptp;
53: {
54: register TREE *lp;
55: register TREE *rp;
56: register TREE *tp1;
57: register TREE *tp2;
58: register TREE *tp3;
59: register int c;
60: register int o;
61: register int op;
62: register int tt;
63: register int nbase;
64: register int ntype;
65: register int lt;
66: register int rt;
67: register int seg;
68: register int lab;
69: register int makecall;
70:
71: c = ac;
72: if (c==MRETURN || c==MSWITCH || c==MINIT)
73: c = MRVALUE;
74: #if !ONLYSMALL&&!NDP
75: /*
76: * All fetches of float or double values are rewritten as
77: * routine calls in LARGE model.
78: * This makes the code a great deal smaller,
79: * and solves the problem of addressability on the _fpac_,
80: * which is not in the same segment as the data of the file.
81: */
82: if (isvariant(VLARGE)
83: && (ac!=MINIT && ac!=MLADDR && ac!=MRADDR)
84: && (tp->t_flag&T_LEAF) != 0
85: && isflt(tp->t_type)) {
86: tp1 = makenode(GID, LPTR);
87: if (tp->t_type == F32)
88: tp1->t_sp = gidpool("dfload");
89: else
90: tp1->t_sp = gidpool("ddload");
91: tp1->t_seg = SANY;
92: tp1 = leftnode(CALL, tp1, F64);
93: storedcon(tp);
94: if (tp->t_op == STAR)
95: tp1->t_rp = tp->t_lp;
96: else
97: tp1->t_rp = leftnode(ADDR, tp, LPTR);
98: return (tp1);
99: }
100: #endif
101: op = tp->t_op;
102: if (isleaf(op)) {
103: if (op==AID || op==PID) {
104: ntype = SPTR;
105: nbase = BP;
106: #if !ONLYSMALL
107: if (isvariant(VLARGE)) {
108: ntype = LPTR;
109: nbase = SSBP;
110: }
111: #endif
112: o = tp->t_offs;
113: tp->t_op = STAR;
114: tp->t_rp = NULL;
115: tp->t_lp = tp2 = makenode(ADD, ntype);
116: tp2->t_lp = tp3 = makenode(REG, ntype);
117: tp3->t_reg = nbase;
118: tp2->t_rp = ivalnode(o);
119: return (tp);
120: }
121: #if !ONLYSMALL
122: /* Generate links to double constants under LARGE RAM option. */
123: if ((ac != MINIT) && (op == DCON) && isvariant(VRAM) && isvariant(VLARGE)) {
124: pool(tp); /* the dcon */
125: tp->t_type = LPTR;
126: tp->t_size = 0;
127: pool(tp); /* the label */
128: tp = leftnode(STAR, tp, F64, 0);
129: return (tp);
130: }
131: /*
132: * Build up indirect links to any LID or GID items
133: * that you cannot access in a direct fashon.
134: */
135: if (ac != MINIT
136: && (op==LID || op==GID)
137: && (ptp==NULL || ptp->t_op!=CALL || tp!=ptp->t_lp)
138: && isvariant(VLARGE)) {
139: seg = tp->t_seg;
140: if (seg==SANY || seg==SDATA || seg==SBSS
141: || (seg==SPURE && isvariant(VRAM))
142: || (seg==SSTRN && notvariant(VROM))) {
143: pool(tp);
144: tp1=leftnode(STAR, tp, tp->t_type, tp->t_size);
145: tp->t_type = LPTR;
146: tp->t_size = 0;
147: return (tp1);
148: }
149: }
150: #endif
151: goto done;
152: }
153: /*
154: * Beat on lvalue fields.
155: */
156: if ((op==ASSIGN || (op>=AADD && op<=ASHR)
157: || (op>=INCBEF && op<=DECAFT))
158: && tp->t_lp->t_op==FIELD && tp->t_lp->t_type<FLD8)
159: return (modlfld(tp, c));
160: /*
161: * Non leaf.
162: * Gather up subtrees.
163: * Rewrite some things as calls to library routines.
164: */
165: tt = tp->t_type;
166: lp = tp->t_lp;
167: if (lp != NULL)
168: lt = lp->t_type;
169: rp = NULL;
170: if (op != FIELD) {
171: rp = tp->t_rp;
172: if (rp != NULL)
173: rt = rp->t_type;
174: }
175: /*
176: * Long MUL, DIV and REM are always a function call.
177: * If there is no NDP in the machine,
178: * then floating point is a routine call.
179: * If there is, we rewrite conversions from bytes and unsigned things
180: * and all conversions from float to fixed
181: * (a mode switch may be necessary).
182: */
183: makecall = 0;
184: if (islong(tt) && op>=MUL && op<=REM) {
185: ++makecall;
186: #if NDP
187: } else if (isflt(tt)) {
188: if (op==CONVERT || op==CAST) {
189: if ((lp->t_flag&T_REG) != 0
190: || (lp->t_flag&T_LEAF) == 0
191: || (lt!=S16 && lt!=S32 && lt!=F32))
192: ++makecall;
193: }
194: } else if ((op>=GT && op<=LT) && isflt(lt)) {
195: tp->t_op += UGT-GT;
196: #else
197: } else if (isflt(tt)) {
198: if (op==CONVERT || op==CAST) {
199: if (!isflt(lt))
200: ++makecall;
201: } else if ((op>=ADD && op<=REM)
202: #if !ONLYSMALL
203: || (isvariant(VLARGE) && op==NEG)
204: || (isvariant(VLARGE) && op==ASSIGN)
205: #endif
206: || (op>=AADD && op<=AREM))
207: ++makecall;
208: } else if (isrelop(op) && isflt(lt)) {
209: ++makecall;
210: #endif
211: } else if ((op==CONVERT || op==CAST) && isflt(lt))
212: ++makecall;
213: if (makecall != 0)
214: return (modxfun(tp));
215: switch (op) {
216:
217: case FIELD:
218: if (c != MLADDR)
219: return (modefld(tp->t_lp, tp, c, 1));
220: break;
221:
222: case ASSIGN:
223: if (tt == BLK) {
224: tp = modsasg(lp, rp, tp->t_size);
225: if (c != MEFFECT)
226: tp = leftnode(STAR, tp, BLK, tp->t_size);
227: return (tp);
228: }
229: break;
230:
231: case CONVERT:
232: case CAST:
233: if (modkind(tt) == modkind(lp->t_type)) {
234: lp->t_type = tt;
235: return (lp);
236: }
237: }
238: /*
239: * If this tree is the return value of a structure function,
240: * arrange to copy the value into a secret place
241: * and return the address of the place.
242: */
243: done:
244: if (tp->t_type==BLK && ac==MRETURN) {
245: if (blkflab == 0) {
246: blkflab = newlab();
247: o = newseg(SBSS);
248: genlab(blkflab);
249: bput(BLOCK);
250: iput((ival_t) tp->t_size);
251: newseg(o);
252: }
253: lp = makenode(LID, BLK, tp->t_size);
254: lp->t_label = blkflab;
255: lp->t_seg = SBSS;
256: return (modsasg(lp, tp, tp->t_size));
257: }
258: return (NULL);
259: }
260:
261: /*
262: * Given a type, return a kind that is used to see
263: * if two objects are just different names for the same bits.
264: */
265: modkind(t)
266: register t;
267: {
268: if (t == U16)
269: t = S16;
270: else if (t == U32)
271: t = S32;
272: return (t);
273: }
274:
275: /*
276: * Build a call node for the assignment of structure data.
277: * The rep and a copy operation are not used so that the ES need not be used.
278: * The type of the CALL is PTR.
279: * The size is valid.
280: */
281: TREE *
282: modsasg(lp, rp, s)
283: register TREE *lp;
284: register TREE *rp;
285: {
286: register TREE *tp;
287: int nptdt;
288:
289: nptdt = SPTR;
290: #if !ONLYSMALL
291: if (isvariant(VLARGE))
292: nptdt = LPTR;
293: #endif
294: rp = leftnode(ADDR, rp, nptdt);
295: rp = leftnode(ARGLST, rp, nptdt);
296: rp->t_rp = ivalnode(s);
297: lp = leftnode(ADDR, lp, nptdt);
298: lp = leftnode(ARGLST, lp, nptdt);
299: lp->t_rp = rp;
300: tp = makenode(GID, nptdt);
301: tp->t_sp = gidpool("blkmv");
302: tp->t_seg = SANY;
303: tp = leftnode(CALL, tp, nptdt);
304: tp->t_size = s;
305: tp->t_rp = lp;
306: return (tp);
307: }
308:
309: /*
310: * Modify function calls.
311: * Handle functions that return objects of type "BLK"
312: * by adding a free indirection node.
313: */
314: TREE *
315: modcall(tp, c)
316: register TREE *tp;
317: {
318: tp->t_lp = modtree(tp->t_lp, MLADDR, tp);
319: tp->t_rp = modargs(tp->t_rp, tp);
320: if (tp->t_type == BLK) {
321: #if !ONLYSMALL
322: if (isvariant(VLARGE))
323: tp->t_type = LPTR;
324: else
325: tp->t_type = SPTR;
326: #else
327: tp->t_type = SPTR;
328: #endif
329: if (c != MEFFECT)
330: tp = leftnode(STAR, tp, BLK, tp->t_size);
331: }
332: return (tp);
333: }
334:
335: /*
336: * Modify argument lists.
337: */
338: TREE *
339: modargs(tp, ptp)
340: register TREE *tp;
341: TREE *ptp;
342: {
343: if (tp == NULL)
344: return (NULL);
345: if (tp->t_op == ARGLST) {
346: tp->t_lp = modargs(tp->t_lp, tp);
347: tp->t_rp = modargs(tp->t_rp, tp);
348: return (tp);
349: }
350: if (tp->t_type == BLK) {
351: #if !ONLYSMALL
352: tp = leftnode(ADDR, tp,
353: (isvariant(VLARGE))?LPTB:SPTB,
354: tp->t_size);
355: #else
356: tp = leftnode(ADDR, tp, SPTB, tp->t_size);
357: #endif
358: return (modtree(tp, MRVALUE, ptp));
359: }
360: return (modtree(tp, MFNARG, ptp));
361: }
362:
363: /*
364: * Given a pointer to a TREE node that describes an operation
365: * that the machine cannot directly perform,
366: * rewrite the node as a CALL to a magic routine.
367: * On the iAPX-86 we rewrite floating point, long multiply and divide
368: * and unsigned long multiply and divide.
369: * This routine only has to handle the ASSIGN
370: * operation if IEEE format; when using DECVAX format
371: * the double=>float conversion is easy.
372: */
373: TREE *
374: modxfun(tp)
375: TREE *tp;
376: {
377: register TREE *lp, *rp;
378: register char *p1, *p2;
379: register TREE *tp1;
380: register int tt, lt, op;
381: register int nptct, nptdt;
382:
383: static char *name[] = {
384: "add",
385: "sub",
386: "mul",
387: "div",
388: "rem"
389: };
390:
391: nptdt = SPTR;
392: #if !ONLYSMALL
393: if (isvariant(VLARGE))
394: nptdt = LPTR;
395: #endif
396: tp1 = makenode(GID, nptdt);
397: op = tp->t_op;
398: lp = tp->t_lp;
399: rp = tp->t_rp;
400: tt = tp->t_type;
401: if (lp != NULL)
402: lt = lp->t_type;
403: p1 = id;
404: if (op==CONVERT || op==CAST || op==NEG) {
405: p2 = "cvt";
406: if (op == NEG)
407: p2 = "neg";
408: *p1++ = modoptab[tt];
409: if (lt==F32 && tt!=F64)
410: lt = F64;
411: *p1++ = modoptab[lt];
412: } else {
413: walk(tp, amd);
414: *p1++ = modoptab[tt];
415: if ((op==ADD || op==MUL || isrelop(op))
416: && ((lp->t_flag&T_LEAF)!=0 && (rp->t_flag&T_LEAF)==0
417: || lp->t_op==DCON && rp->t_op!=DCON)) {
418: lp = rp;
419: rp = tp->t_lp;
420: if (isrelop(op))
421: op = fliprel[op-EQ];
422: }
423: if (op==ASSIGN || (op>=AADD && op<=AREM)) {
424: *p1++ = modoptab[lt];
425: if (lp->t_op != STAR)
426: lp = leftnode(ADDR, lp, nptdt);
427: else
428: lp = lp->t_lp;
429: if (op == ASSIGN)
430: p2 = "asg";
431: else
432: p2 = name[op-AADD];
433: } else if (isrelop(op))
434: p2 = "cmp";
435: else if (op>=ADD && op<=REM)
436: p2 = name[op-ADD];
437: else
438: cbotch("modxfun");
439: storedcon(rp);
440: if (uselvalueform(op, tt, rp)) {
441: *p1++ = 'l';
442: if (rp->t_op != STAR)
443: rp = leftnode(ADDR, rp, nptdt);
444: else
445: rp = rp->t_lp;
446: } else
447: *p1++ = 'r';
448: }
449: while (*p1++ = *p2++)
450: ;
451: *p1 = 0;
452: tp1->t_sp = gidpool(id);
453: tp1->t_seg = SANY;
454: lp = leftnode(ARGLST, lp, nptdt);
455: lp->t_rp = rp;
456: tp->t_op = CALL;
457: tp->t_lp = tp1;
458: tp->t_rp = lp;
459: fixtoptype(tp);
460: if (tp->t_type!=tt && tt!=F32)
461: tp = leftnode(CONVERT, tp, tt);
462: if (isrelop(op)) {
463: tp = leftnode(op, tp, TRUTH);
464: tp->t_rp = ivalnode(0);
465: }
466: return (tp);
467: }
468:
469: /*
470: * Zap a DCON into a block of memory with a double in it.
471: */
472: storedcon(tp)
473: register TREE *tp;
474: {
475: if (tp->t_op != DCON)
476: return;
477: pool(tp);
478: tp->t_flag = T_DIR;
479: }
480:
481: /*
482: * This routine, used only by the "modxfun" routine,
483: * checks if an lvalue form of an operator routine can be used.
484: * True return if it can.
485: */
486: uselvalueform(op, tt, rp)
487: register TREE *rp;
488: {
489: if (isrelop(op)) {
490: if (rp->t_type != F64)
491: return (0);
492: } else {
493: if (rp->t_type != tt)
494: return (0);
495: }
496: if (rp->t_op==STAR || (rp->t_flag&T_DIR)!=0)
497: return (1);
498: return (0);
499: }
500:
501: /*
502: * Test if 1) the tree pointed to by "tp" is a register
503: * and 2) the operation "op" can be computed in it.
504: */
505: isokareg(tp, op)
506: register TREE *tp;
507: register op;
508: {
509: if (op==MUL || op==DIV || op==REM)
510: return (0);
511: if (tp->t_op!=REG || !isword(tp->t_type))
512: return (0);
513: return (1);
514: }
515:
516: /*
517: * Modify bit fields in lvalue contexts.
518: * The "tp" argument is a pointer to the tree node
519: * with the FIELD operation on the left side.
520: * This routine has two tasks.
521: * First, it rewrites the type in the FIELD node to be the type used by
522: * select to match the tree; this is also used as a flag
523: * to prevent this routine from being called twice on a node.
524: * Second, it inserts explict shift nodes to
525: * the operands and results so that all of the optimizations
526: * applied to shifts work for fields.
527: * A pointer to the new top of the tree is returned.
528: */
529: TREE *
530: modlfld(tp, c)
531: register TREE *tp;
532: {
533: register TREE *lp, *rp;
534: register lt, tt;
535: register op;
536: register bmop;
537: register MASK mask;
538:
539: op = tp->t_op;
540: tt = tp->t_type;
541: lp = tp->t_lp;
542: if (lp != NULL)
543: lt = lp->t_type;
544: if (op!=AMUL && op!=ADIV && op!=ASHL && op!=ASHR) {
545: rp = tp->t_rp;
546: rp = leftnode(SHL, rp, rp->t_type);
547: rp->t_rp = ivalnode(lp->t_base);
548: tp->t_rp = rp;
549: }
550: if (op==AAND || op==AOR || op==AXOR || op==ASSIGN) {
551: mask = ((MASK)01<<lp->t_width) - 1;
552: mask = mask << lp->t_base;
553: bmop = AND;
554: if (op == AAND) {
555: mask = ~mask;
556: bmop = OR;
557: }
558: /* rp set above */
559: rp = leftnode(bmop, rp, rp->t_type);
560: rp->t_rp = ivalnode(mask);
561: tp->t_rp = rp;
562: }
563: if (c != MEFFECT)
564: tp = modefld(tp, lp, c, 0);
565: if (isbyte(lt))
566: lp->t_type = FLD8;
567: else
568: lp->t_type = FLD16;
569: return (tp);
570: }
571:
572: /*
573: * This function rewrites any field extraction.
574: * The argument "tp" is the base of the field.
575: * The argument "fp" is a FIELD node that supplies the width and the base.
576: * The argument "flag" is true to enable the mask off in unsigned field extract.
577: */
578: TREE *
579: modefld(tp, fp, c, flag)
580: register TREE *tp;
581: register TREE *fp;
582: {
583: register n;
584: register tt;
585: register mw;
586: register mask;
587: register ttold;
588:
589: mw = 16;
590: if (isbyte(ttold = tt = tp->t_type)) {
591: mw = 8;
592: tp = leftnode(CONVERT, tp, tt);
593: fixtoptype(tp);
594: tt = tp->t_type;
595: }
596: if (c == MFLOW) {
597: mask = (01<<fp->t_width) - 1;
598: if ((n=fp->t_base) != 0)
599: mask <<= n;
600: tp = leftnode(AND, tp, tt);
601: tp->t_rp = ivalnode((ival_t)mask);
602: return (tp);
603: }
604: if (isuns(tt)) {
605: if ((n=fp->t_base) != 0) {
606: tp = leftnode(SHR, tp, tt);
607: tp->t_rp = ivalnode(n);
608: }
609: if (flag && (n=fp->t_width)<mw) {
610: tp = leftnode(AND, tp, tt);
611: tp->t_rp = ivalnode(((ival_t)01<<n)-1);
612: }
613: return (tp);
614: }
615: if ((n=mw-(fp->t_base+fp->t_width)) != 0) {
616: tp = leftnode(SHL, tp, tt);
617: tp->t_rp = ivalnode(n);
618: }
619: if ((n=mw-fp->t_width) != 0) {
620: tp = leftnode(SHR, tp, tt);
621: tp->t_rp = ivalnode(n);
622: }
623: if (ttold != tt)
624: tp = leftnode(CONVERT, tp, ttold);
625: return (tp);
626: }
627:
628: /*
629: * Check if a tree should have its left and right subtrees swapped.
630: * Do it if it is required.
631: * Sometimes the relational operation must be adjusted.
632: */
633: modswap(tp, ptp)
634: register TREE *tp;
635: TREE *ptp;
636: {
637: register TREE *lp, *rp;
638: FLAG lf, rf;
639:
640: switch (tp->t_op) {
641:
642: case ADD:
643: case MUL:
644: case AND:
645: case OR:
646: case XOR:
647: case EQ:
648: case NE:
649: case GT:
650: case GE:
651: case LT:
652: case LE:
653: case UGT:
654: case UGE:
655: case ULT:
656: case ULE:
657: lp = tp->t_lp;
658: rp = tp->t_rp;
659: lf = lp->t_flag;
660: rf = rp->t_flag;
661: if (lf!=0 || rf!=0) {
662: if ((lf&T_CON) != 0
663: || (rf&T_REG) != 0
664: || (lf!=0 && rf==0))
665: swapit(tp);
666: } else if (lp->t_cost > rp->t_cost)
667: swapit(tp);
668: }
669: }
670:
671: /*
672: * Swap subtrees.
673: * Fix up relational ops.
674: */
675: swapit(tp)
676: register TREE *tp;
677: {
678: register TREE *xp;
679: register op;
680:
681: xp = tp->t_lp;
682: tp->t_lp = tp->t_rp;
683: tp->t_rp = xp;
684: op = tp->t_op;
685: if (isrelop(op))
686: tp->t_op = fliprel[op-EQ];
687: }
688:
689: /*
690: * Convert integer constant val to type t.
691: */
692: lval_t
693: constcvt(t, val) register int t; lval_t val;
694: {
695: if (isbyte(t))
696: val &= 0xFFL;
697: else if (isword(t))
698: val &= 0xFFFFL;
699: if (!isuns(t)) {
700: if (isbyte(t) && (val & 0x80L) != 0)
701: val |= 0xFFFFFF00L;
702: else if (isword(t) && (val & 0x8000L) != 0)
703: val |= 0xFFFF0000L;
704: }
705: return val;
706: }
707:
708: /* end of n1/i8086/mtree2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.