|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)bound.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: #include "cpass2.h"
10: #include "ctype.h"
11:
12: int failsafe; /* very disgusting: see offstar() for use */
13:
14: # define SAFETY( a, reg, b ) \
15: {if ((reg & MUSTDO) && find_mustdo( a , reg )) {rewrite_rall( b, 1 );} }
16: # define isareg(r) (rstatus[r]&SAREG)
17: # define iscnode(p) (p->in.op==REG && iscreg(p->tn.rval))
18:
19: # define max(x,y) ((x)<(y)?(y):(x))
20: # define min(x,y) ((x)<(y)?(x):(y))
21:
22:
23: static char *unsigned_branches[2] = { "jcs", "jls"};
24: static char *signed_branches[2] = { "jlt", "jle"};
25:
26: trapv(type)
27: {
28: if (chk_ovfl){
29: if (!ISPTR(type) && !ISUNSIGNED(type)){
30: print_str( " trapv\n" );
31: }
32: }
33: }
34:
35:
36: #ifdef NOTDEF
37: chksize(p)
38: NODE *p;
39: {
40: /* check size of result after a multiply instruction */
41: int chklab = getlab();
42: int oklab;
43: int type = p->in.type;
44: int lb, ub;
45: char *regname = rnames[p->in.left->tn.rval];
46: if (chk_ovfl){
47: if (use68020){
48: switch(type){
49: case CHAR:
50: printf("\t.data\nL%d:\t.long\t-0x80,0x7f\n\t.text\n", chklab);
51: break;
52: case UCHAR:
53: printf("\t.data\nL%d:\t.long\t0,0xff\n\t.text\n", chklab);
54: break;
55: case SHORT:
56: printf("\t.data\nL%d:\t.long\t-0x8000,0x7fff\n\t.text\n", chklab);
57: break;
58: case USHORT:
59: printf("\t.data\nL%d:\t.long\t0,0xffff\n\t.text\n", chklab);
60: break;
61: default:
62: trapv( type );
63: return;
64: }
65: printf(" chk2l L%d,%s\n", chklab, regname);
66: return;
67: }else {
68: oklab = getlab();
69: switch(type){
70: case CHAR:
71: lb = -128; ub = 127;
72: break;
73: case SHORT:
74: lb = -32768; ub = 32767;
75: signed:
76: printf(" cmpl #%#x,%s\n", lb, regname);
77: break;
78: case UCHAR:
79: ub = 255;
80: break;
81: case USHORT:
82: ub = 0xffff;
83: break;
84: default:
85: trapv( type );
86: return;
87: }
88: printf(" jlt L%d\n", chklab);
89: printf(" cmpl #%#x,%s\n", ub, regname);
90: printf(" jle L%d\n", oklab);
91: printf("L%d: chk #-1,%s\n", chklab, regname);
92: printf("L%d:\n", oklab);
93: }
94: }
95: }
96: #endif
97:
98: /* generate a copy of p ; p should be simple */
99:
100: static char *
101: rcopy(p)
102: NODE *p;
103: {
104: NODE *temp;
105: int r;
106:
107: if (busy[D0] && busy[D1])
108: return(NULL);
109: temp = tcopy(p);
110: order(temp, INTAREG);
111: r = temp->tn.rval;
112: reclaim(temp, RNULL, FOREFF);
113: return(rnames[r]);
114: }
115:
116: bound_test( p, cookie )
117: register NODE *p;
118: {
119: register NODE *expr, *lb, *ub;
120: register t = p->in.type;
121: NODE *bounds = p->in.right;
122: int chklab, oklab;
123: char *size;
124: char **branch;
125: NODE *copy;
126: char *regname;
127:
128: expr = p->in.left;
129: lb = bounds->in.left;
130: ub = bounds->in.right;
131: if (!chk_ovfl){
132: order( expr, cookie );
133: return;
134: }
135: regname = rnames[expr->tn.rval];
136: /*
137: * see if we can use the chk or chkl instructions.
138: * For nonzero lower bounds, try to generate a copy and
139: * subtract the lower bound. In array subscripting the
140: * lower bound must be subtracted anyway; c2 may be able
141: * to identify this as a cse.
142: */
143: if (lb->in.op == ICON && lb->in.name[0] == '\0' &&
144: ub->in.op == ICON && ub->in.name[0] == '\0' ){
145: /* constant bounds */
146: switch(t){
147: case CHAR:
148: printf(" extw %s\n", regname );
149: p->in.type = expr->in.type = SHORT;
150: goto use_chkw;
151: case UCHAR:
152: printf(" andw #0xff,%s\n", regname );
153: p->in.type = expr->in.type = SHORT;
154: /* FALL THROUGH */
155: case SHORT:
156: use_chkw:
157: if (lb->tn.lval) {
158: char *regcopy = rcopy(expr);
159: if (regcopy == NULL) goto long_case;
160: regname = regcopy;
161: printf(" subw #0x%x,%s\n", lb->tn.lval, regname);
162: }
163: if (ub->tn.lval - lb->tn.lval < 0x8000) {
164: printf(" chk #0x%x,%s\n", ub->tn.lval-lb->tn.lval,
165: regname);
166: } else {
167: printf(" cmpw #0x%x,%s\n", ub->tn.lval-lb->tn.lval,
168: regname);
169: oklab = getlab();
170: printf(" jls L%d\n", oklab);
171: printf(" chk #-1,%s\n", regname);
172: printf("L%d:\n", oklab);
173: }
174: break;
175: case USHORT:
176: if (ub->tn.lval <= 0x7fff) goto use_chkw;
177: printf(" andl #0xffff,%s\n", regname);
178: p->in.type = expr->in.type = INT;
179: /* FALL THROUGH */
180: default:
181: if (lb->tn.lval == -32768 && ub->tn.lval == 32767) {
182: /* common case, can be done without long literals */
183: char *regcopy = rcopy(expr);
184: if (regcopy == NULL) goto long_case;
185: regname = regcopy;
186: printf(" extl %s\n", regname);
187: expand(p, cookie, " cmpl AL,");
188: printf("%s\n", regname);
189: oklab = getlab();
190: printf(" jeq L%d\n", oklab);
191: printf(" chk #-1,%s\n", regname);
192: printf("L%d:\n", oklab);
193: break;
194: }
195: if (lb->tn.lval) {
196: char *regcopy = rcopy(expr);
197: if (regcopy == NULL) goto long_case;
198: regname = regcopy;
199: printf(" subl #0x%x,%s\n", lb->tn.lval, regname);
200: }
201: if (use68020 && (unsigned)(ub->tn.lval-lb->tn.lval) < 0x80000000) {
202: printf(" chkl #0x%x,%s\n", ub->tn.lval-lb->tn.lval,
203: regname);
204: } else {
205: printf(" cmpl #0x%x,%s\n", ub->tn.lval-lb->tn.lval,
206: regname);
207: oklab = getlab();
208: printf(" jls L%d\n", oklab);
209: printf(" chk #-1,%s\n", regname);
210: printf("L%d:\n", oklab);
211: }
212: break;
213: }
214: return;
215: long_case:
216: if (use68020) {
217: /* use chk2l */
218: switch(t){
219: case CHAR:
220: case UCHAR:
221: size = "byte"; break;
222: case SHORT:
223: case USHORT:
224: size = "word"; break;
225: default:
226: size = "long"; break;
227: }
228: chklab = getlab();
229: printf(" .data\nL%d: .%s %d,%d\n .text\n",
230: chklab, size, lb->tn.lval, ub->tn.lval);
231: printf(" chk2%c L%d,%s\n", size[0], chklab, regname);
232: return;
233: }
234: }
235: /* can't use any chk instructions -- do cmp & branch */
236: branch = unsigned_branches;
237: if (ISUNSIGNED(t) || ISPTR(t))
238: branch = unsigned_branches;
239: else
240: branch = signed_branches;
241: chklab = getlab();
242: oklab = getlab();
243: if (adjacent(lb, ub)) {
244: /*
245: * bounds are in adjacent memory operands
246: */
247: if (SUTEST(lb->in.su))
248: order(lb, SOREG);
249: p->in.right = lb;
250: if (use68020) {
251: expand( p, FORCC, " chk2ZB AR,AL\n");
252: p->in.right = bounds;
253: reclaim( lb, RNULL, FOREFF );
254: reclaim( ub, RNULL, FOREFF );
255: return;
256: } else {
257: expand( p, FORCC, " cmpZB AR,AL\n");
258: printf(" %s L%d\n", branch[0], chklab);
259: expand( p, FORCC, " cmpZB UR,AL\n");
260: printf(" %s L%d\n", branch[1], oklab);
261: reclaim( lb, RNULL, FOREFF );
262: reclaim( ub, RNULL, FOREFF );
263: /* finish up below */
264: }
265: } else {
266: /*
267: * lower bound
268: */
269: if (SUTEST(lb->in.su)) {
270: order( lb, INTAREG|INTEMP|SOREG );
271: }
272: p->in.right = lb;
273: expand( p, FORCC, " cmpZB AR,AL\n");
274: printf(" %s L%d\n", branch[0], chklab);
275: reclaim( lb, RNULL, FOREFF );
276: /*
277: * upper bound
278: */
279: if (SUTEST(ub->in.su)) {
280: order( ub, INTAREG|INTEMP|SOREG );
281: }
282: p->in.right = ub;
283: expand( p, FORCC, " cmpZB AR,AL\n");
284: printf(" %s L%d\n", branch[1], oklab);
285: reclaim( ub, RNULL, FOREFF );
286: }
287:
288: printf("L%d: chk #-1,%s\n", chklab, regname);
289: printf("L%d:\n", oklab);
290: p->in.right = bounds;
291:
292: }
293:
294:
295: #define true 1
296: #define false 0
297:
298: /*
299: * are operands p and q adjacent
300: * (in the sense assumed by upput() and adrput())?
301: */
302: int
303: adjacent(p,q)
304: register NODE *p,*q;
305: {
306: register NODE *lp, *lq;
307: register o;
308: int result;
309: CONSZ temp;
310:
311: o = p->in.op;
312: if (o != q->in.op)
313: return false;
314: switch(o) {
315: case NAME:
316: case OREG:
317: p->tn.lval+= SZINT/SZCHAR;
318: result = equal(p,q);
319: p->tn.lval-= SZINT/SZCHAR;
320: return result;
321: case UNARY MUL:
322: lp = p->in.left;
323: lq = q->in.left;
324: if (lp->in.op == PLUS && lq->in.op == PLUS) {
325: lp = lp->in.right;
326: lq = lq->in.right;
327: if (lp->in.op == ICON && lq->in.op == ICON) {
328: if (lp->tn.lval+SZINT/SZCHAR == lq->tn.lval) {
329: lp->tn.lval += SZINT/SZCHAR;
330: result = equal(p,q);
331: lp->tn.lval -= SZINT/SZCHAR;
332: return result;
333: }
334: }
335: }
336: break;
337: }
338: return false;
339: }
340:
341: /*
342: * equal(p,q) : returns 1 if expressions p and q are equivalent,
343: * in the sense that they always return the same value given
344: * the same initial values of their operands. Note that if
345: * either p or q contains operators producing side-effects,
346: * equal(p,q) = 0.
347: */
348:
349: int
350: equal(p,q)
351: register NODE *p,*q;
352: {
353: register char *pn,*qn;
354: register o;
355:
356: if (p == q)
357: return true;
358: if (p == NIL || q == NIL)
359: return false;
360: o = p->in.op;
361: if (o != q->in.op)
362: return false;
363: if (p->in.type != q->in.type)
364: return false;
365: switch(optype(o)) {
366: case UTYPE:
367: if (callop(o))
368: return false;
369: return equal(p->in.left, q->in.left);
370: case BITYPE:
371: if (callop(o) || asgop(o))
372: return false;
373: if (equal(p->in.left, q->in.left))
374: return equal(p->in.right, q->in.right);
375: return false;
376: default:
377: /* leaf nodes */
378: switch (o) {
379: case ICON:
380: case OREG:
381: case NAME:
382: pn = p->tn.name;
383: qn = q->tn.name;
384: if (pn != NULL && qn != NULL) {
385: if ( *pn == *qn
386: && (*pn == '\0' || strcmp(pn,qn) == 0) ) {
387: return (p->tn.lval == q->tn.lval);
388: }
389:
390: } else if (pn == qn) { /* == NULL */
391: return ( p->tn.lval == q->tn.lval );
392: }
393: return false;
394: case REG:
395: return(p->tn.rval == q->tn.rval);
396: case FCON:
397: return(p->fpn.dval == q->fpn.dval);
398: }
399: }
400: return false;
401: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.