|
|
1.1 root 1: /*
2: * n1/i386/mtree2.c
3: * Machine dependent parts of the tree modifier.
4: * A conditionalization handles machines that have an 80x87.
5: * i386.
6: */
7:
8: #ifdef vax
9: #include "INC$LIB:cc1.h"
10: #else
11: #include "cc1.h"
12: #endif
13:
14: int blkflab;
15:
16: #if SPLIT_CC1
17: /*
18: * Function prolog.
19: * Clear "BLK function" label.
20: */
21: doprolog()
22: {
23: blkflab = 0;
24: }
25:
26: /*
27: * Copy auto information.
28: */
29: doautos()
30: {
31: iput(iget());
32: iput(iget());
33: }
34: #endif
35:
36: /*
37: * This function performs machine specific tree modifications.
38: * It is called from "modtree" after all of the machine
39: * independent transformations have been done.
40: * It returns either a pointer to the new tree
41: * (telling "modtree" to do another pass)
42: * or NULL (which implies that no changes were made).
43: */
44: TREE *
45: modoper(tp, ac, ptp) register TREE *tp; int ac; TREE *ptp;
46: {
47: register TREE *lp, *rp, *tp1, *tp2, *tp3;
48: register int c, op, nseg;
49: register int tt, lt, rt;
50: sizeof_t offs;
51:
52: c = ac;
53: if (c==MRETURN || c==MSWITCH || c==MINIT)
54: c = MRVALUE;
55: op = tp->t_op;
56: if (isleaf(op)) {
57: if (op==AID || op==PID) {
58: /* Modify autos and parameters to "*(%ebp+offset)". */
59: offs = tp->t_offs;
60: tp->t_op = STAR;
61: tp->t_rp = NULL;
62: tp->t_lp = tp2 = makenode(ADD, PTR);
63: tp2->t_lp = tp3 = makenode(REG, PTR);
64: tp3->t_reg = EBP;
65: tp2->t_rp = ivalnode((ival_t)offs);
66: return tp;
67: } else
68: goto done;
69: }
70:
71: /*
72: * Beat on lvalue fields.
73: */
74: if ((op==ASSIGN || (op>=AADD && op<=ASHR)
75: || (op>=INCBEF && op<=DECAFT))
76: && tp->t_lp->t_op==FIELD && tp->t_lp->t_type<FLD8)
77: return modlfld(tp, c);
78:
79: /*
80: * Non leaf.
81: * Gather up subtrees.
82: * Rewrite some things as calls to library routines.
83: */
84: tt = tp->t_type;
85: lp = tp->t_lp;
86: if (lp != NULL)
87: lt = lp->t_type;
88: rp = NULL;
89: if (op != FIELD) {
90: rp = tp->t_rp;
91: if (rp != NULL)
92: rt = rp->t_type;
93: }
94:
95: /*
96: * If there is an NDP, rewrite conversions
97: * from bytes and unsigned things
98: * and all conversions from float to fixed
99: * as calls of support routines.
100: */
101: if (isvariant(VNDP)) {
102: if (isflt(tt)) {
103: if (op==CONVERT || op==CAST) {
104: if ((lp->t_flag&T_REG) != 0
105: || (lp->t_flag&T_LEAF) == 0
106: || (lt!=S16 && lt!=S32 && lt!=F32))
107: return modxfun(tp);
108: }
109: } else if ((op>=GT && op<=LT) && isflt(lt))
110: tp->t_op += UGT-GT;
111: else if ((op==CONVERT || op==CAST) && isflt(lt))
112: return modxfun(tp);
113: }
114: switch (op) {
115:
116: case FIELD:
117: if (c != MLADDR)
118: return modefld(tp->t_lp, tp, c, 1);
119: break;
120:
121: case ASSIGN:
122: if (tt == BLK) {
123: tp = modsasg(lp, rp, tp->t_size);
124: if (c != MEFFECT)
125: tp = leftnode(STAR, tp, BLK, tp->t_size);
126: return tp;
127: }
128: break;
129:
130: case CONVERT:
131: case CAST:
132: if (modkind(tt) == modkind(lp->t_type)) {
133: lp->t_type = tt;
134: return lp;
135: }
136: }
137:
138: /*
139: * If this tree is the return value of a structure function,
140: * arrange to copy the value into a secret place
141: * and return the address of the place.
142: */
143: done:
144: if (tp->t_type==BLK && ac==MRETURN) {
145: if (blkflab == 0) {
146: blkflab = newlab();
147: nseg = newseg(SBSS);
148: genlab(blkflab);
149: bput(BLOCK);
150: iput((ival_t) tp->t_size);
151: newseg(nseg);
152: }
153: lp = makenode(LID, BLK, tp->t_size);
154: lp->t_label = blkflab;
155: lp->t_seg = SBSS;
156: return modsasg(lp, tp, tp->t_size);
157: }
158: return NULL;
159: }
160:
161: /*
162: * Given a type, return a kind that is used to see
163: * if two objects are just different names for the same bits.
164: */
165: modkind(t) register int t;
166: {
167: if (t == U8)
168: t = S8;
169: else if (t == U16)
170: t = S16;
171: else if (t == U32)
172: t = S32;
173: return t;
174: }
175:
176: /*
177: * Build a call node for the assignment of structure data.
178: * The rep and a copy operation are not used so that the ES need not be used.
179: * The type of the CALL is PTR.
180: * The size is valid.
181: */
182: TREE *
183: modsasg(lp, rp, s) register TREE *lp, *rp;
184: {
185: register TREE *tp;
186:
187: rp = leftnode(ADDR, rp, PTR);
188: rp = leftnode(ARGLST, rp, PTR);
189: rp->t_rp = ivalnode((ival_t)s);
190: lp = leftnode(ADDR, lp, PTR);
191: lp = leftnode(ARGLST, lp, PTR);
192: lp->t_rp = rp;
193: tp = makenode(GID, PTR);
194: tp->t_sp = gidpool("memcpy");
195: tp->t_seg = SANY;
196: tp = leftnode(CALL, tp, PTR);
197: tp->t_size = s;
198: tp->t_rp = lp;
199: return tp;
200: }
201:
202: /*
203: * Modify function calls.
204: * Handle functions that return objects of type "BLK"
205: * by adding a free indirection node.
206: */
207: TREE *
208: modcall(tp, c) register TREE *tp; int c;
209: {
210: fixtoptype(tp);
211: tp->t_lp = modtree(tp->t_lp, MLADDR, tp);
212: tp->t_rp = modargs(tp->t_rp, tp);
213: if (tp->t_type == BLK) {
214: tp->t_type = PTR;
215: if (c != MEFFECT)
216: tp = leftnode(STAR, tp, BLK, tp->t_size);
217: }
218: return tp;
219: }
220:
221: /*
222: * Modify argument lists.
223: */
224: TREE *
225: modargs(tp, ptp) register TREE *tp; TREE *ptp;
226: {
227: if (tp == NULL)
228: return NULL;
229: if (tp->t_op == ARGLST) {
230: tp->t_lp = modargs(tp->t_lp, tp);
231: tp->t_rp = modargs(tp->t_rp, tp);
232: return tp;
233: }
234: if (tp->t_type == BLK) {
235: tp = leftnode(ADDR, tp, PTB, tp->t_size);
236: return modtree(tp, MRVALUE, ptp);
237: }
238: return modtree(tp, MFNARG, ptp);
239: }
240:
241: static char modoptab[] = {
242: 'i', 'u', /* S8 U8 */
243: 'i', 'u', /* S16 U16 */
244: 'i', 'u', /* S32 U32 */
245: 'f', 'd', /* F32 F64 */
246: 'b', /* BLK */
247: 'i', 'i', 'i', /* FLD8 FLD16 FLD32 */
248: 'p', 'p' /* PTR PTB */
249: };
250:
251: /*
252: * Rewrite a TREE node which describes an operation
253: * that the machine cannot directly perform as a CALL to a magic routine.
254: * On the i386 we rewrite NDP floating point conversions.
255: * This used to rewrite software fp as subroutine calls,
256: * now the code tables generate the calls directly instead.
257: */
258: TREE *
259: modxfun(tp)
260: TREE *tp;
261: {
262: register TREE *lp, *rp;
263: register char *p1, *p2;
264: register TREE *tp1;
265: register int tt, lt, op;
266:
267: op = tp->t_op;
268: lp = tp->t_lp;
269: rp = tp->t_rp;
270: tt = tp->t_type;
271: if (lp != NULL)
272: lt = lp->t_type;
273: p1 = id;
274: *p1++ = '_';
275: *p1++ = modoptab[tt];
276: if (lt==F32 && tt!=F64)
277: lt = F64;
278: *p1++ = modoptab[lt];
279: p2 = "cvt";
280: while (*p1++ = *p2++)
281: ;
282: *p1 = '\0';
283: tp1 = makenode(GID, PTR);
284: tp1->t_sp = gidpool(id);
285: tp1->t_seg = SANY;
286: tp->t_op = CALL;
287: tp->t_lp = tp1;
288: tp->t_rp = lp;
289: fixtoptype(tp);
290: if (tp->t_type!=tt && tt!=F32)
291: tp = leftnode(CONVERT, tp, tt);
292: if (isrelop(op)) {
293: tp = leftnode(op, tp, TRUTH);
294: tp->t_rp = ivalnode((ival_t)0);
295: }
296: return tp;
297: }
298:
299: /*
300: * Zap a DCON into a block of memory with a double in it.
301: */
302: storedcon(tp) register TREE *tp;
303: {
304: if (tp->t_op != DCON)
305: return;
306: pool(tp);
307: tp->t_flag = T_DIR;
308: }
309:
310: /*
311: * Test if 1) the tree pointed to by "tp" is a register
312: * and 2) the operation "op" can be computed in it.
313: */
314: isokareg(tp, op) register TREE *tp; register op;
315: {
316: if (op==MUL || op==DIV || op==REM)
317: return 0;
318: if (tp->t_op!=REG || !isword(tp->t_type))
319: return 0;
320: return 1;
321: }
322:
323: /*
324: * Modify bit fields in lvalue contexts.
325: * The "tp" argument is a pointer to the tree node
326: * with the FIELD operation on the left side.
327: * This routine has two tasks.
328: * First, it rewrites the type in the FIELD node to be the type used by
329: * select to match the tree; this is also used as a flag
330: * to prevent this routine from being called twice on a node.
331: * Second, it inserts explict shift nodes to
332: * the operands and results so that all of the optimizations
333: * applied to shifts work for fields.
334: * A pointer to the new top of the tree is returned.
335: */
336: TREE *
337: modlfld(tp, c) register TREE *tp; int c;
338: {
339: register TREE *lp, *rp;
340: register lt, tt;
341: register op;
342: register bmop;
343: register MASK mask;
344:
345: op = tp->t_op;
346: tt = tp->t_type;
347: lp = tp->t_lp;
348: if (lp != NULL)
349: lt = lp->t_type;
350: if (op!=AMUL && op!=ADIV && op!=ASHL && op!=ASHR) {
351: rp = tp->t_rp;
352: rp = leftnode(SHL, rp, rp->t_type);
353: rp->t_rp = ivalnode((ival_t)lp->t_base);
354: tp->t_rp = rp;
355: }
356: if (op==AAND || op==AOR || op==AXOR || op==ASSIGN) {
357: mask = ((MASK)01<<lp->t_width) - 1;
358: mask = mask << lp->t_base;
359: bmop = AND;
360: if (op == AAND) {
361: mask = ~mask;
362: bmop = OR;
363: }
364: /* rp set above */
365: rp = leftnode(bmop, rp, rp->t_type);
366: fixtoptype(rp);
367: if (rp->t_type != rp->t_lp->t_type)
368: rp->t_lp = leftnode(CONVERT, rp->t_lp, rp->t_type);
369: rp->t_rp = ivalnode((ival_t)mask);
370: tp->t_rp = rp;
371: }
372: if (c != MEFFECT)
373: tp = modefld(tp, lp, c, 0);
374: if (isbyte(lt))
375: lp->t_type = FLD8;
376: else if (isword(lt))
377: lp->t_type = FLD16;
378: else
379: lp->t_type = FLD32;
380: return tp;
381: }
382:
383: /*
384: * Rewrite field extraction.
385: * The argument "tp" is the base of the field.
386: * The argument "fp" is a FIELD node that supplies the width and the base.
387: * The argument "flag" is true to enable the mask off in unsigned field extract.
388: */
389: TREE *
390: modefld(tp, fp, c, flag) register TREE *tp, *fp; int c, flag;
391: {
392: register int n, tt;
393: register MASK mask;
394:
395: if (isbyte(tt = tp->t_type) || isword(tt)) {
396: /* Byte and word fields. Make the top a computational type. */
397: tp = leftnode(CONVERT, tp, tt);
398: fixtoptype(tp);
399: tt = tp->t_type;
400: }
401: if (c == MFLOW) {
402: /* In a flow context, the field offset is irrelevant. */
403: mask = ((MASK)1 << fp->t_width) - 1;
404: if ((n = fp->t_base) != 0)
405: mask <<= n;
406: tp = leftnode(AND, tp, tt);
407: tp->t_rp = ivalnode((ival_t)mask);
408: return tp;
409: }
410: if (isuns(tt) || fp->t_width==1) {
411: /* Unsigned fields: shift right and mask to extract. */
412: /* Field width 1 is a special case, can be treated like unsigned. */
413: if ((n = fp->t_base) != 0) {
414: tp = leftnode(SHR, tp, tt);
415: tp->t_rp = ivalnode((ival_t)n);
416: }
417: if (flag) {
418: tp = leftnode(AND, tp, tt);
419: tp->t_rp = ivalnode(((ival_t)1 << fp->t_width) - 1);
420: }
421: return tp;
422: }
423: /* Signed fields: shift left and then right to extract and sign extend. */
424: if ((n = 32 - (fp->t_base + fp->t_width)) != 0) {
425: tp = leftnode(SHL, tp, tt);
426: tp->t_rp = ivalnode((ival_t)n);
427: }
428: if ((n = 32 - fp->t_width) != 0) {
429: tp = leftnode(SHR, tp, tt);
430: tp->t_rp = ivalnode((ival_t)n);
431: }
432: return tp;
433: }
434:
435: /*
436: * Check if a tree should have its left and right subtrees swapped.
437: * Do it if it is required.
438: * Sometimes the relational operation must be adjusted.
439: */
440: modswap(tp, ptp) register TREE *tp; TREE *ptp;
441: {
442: register TREE *lp, *rp;
443: FLAG lf, rf;
444:
445: switch (tp->t_op) {
446:
447: case ADD:
448: case MUL:
449: case AND:
450: case OR:
451: case XOR:
452: case EQ:
453: case NE:
454: case GT:
455: case GE:
456: case LT:
457: case LE:
458: case UGT:
459: case UGE:
460: case ULT:
461: case ULE:
462: lp = tp->t_lp;
463: rp = tp->t_rp;
464: lf = lp->t_flag;
465: rf = rp->t_flag;
466: if (lf!=0 || rf!=0) {
467: if ((lf&T_CON) != 0
468: || (rf&T_REG) != 0
469: || (lf!=0 && rf==0))
470: swapit(tp);
471: } else if (lp->t_cost > rp->t_cost)
472: swapit(tp);
473: }
474: }
475:
476: /*
477: * Swap subtrees.
478: * Fix up relational ops.
479: */
480: swapit(tp) register TREE *tp;
481: {
482: register TREE *xp;
483: register op;
484:
485: xp = tp->t_lp;
486: tp->t_lp = tp->t_rp;
487: tp->t_rp = xp;
488: op = tp->t_op;
489: if (isrelop(op))
490: tp->t_op = fliprel[op-EQ];
491: }
492:
493: /*
494: * Convert integer constant val to type t.
495: */
496: lval_t
497: constcvt(t, val) register int t; lval_t val;
498: {
499: if (isbyte(t))
500: val &= 0xFFL;
501: else if (isword(t))
502: val &= 0xFFFFL;
503: if (!isuns(t)) {
504: if (isbyte(t) && (val & 0x80L) != 0)
505: val |= 0xFFFFFF00L;
506: else if (isword(t) && (val & 0x8000L) != 0)
507: val |= 0xFFFF0000L;
508: }
509: return val;
510: }
511:
512: /* end of n1/i386/mtree2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.