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