#ifndef lint
-static char sccsid[] = "@(#)local2.c 1.7 (Berkeley) %G%";
+static char sccsid[] = "@(#)local2.c 1.8 (Berkeley) %G%";
#endif
# include "pass2.h"
}
}
+anyfloat(p, q)
+ NODE *p, *q;
+{
+ register TWORD tp, tq;
+
+ tp = p->in.type;
+ tq = q->in.type;
+ return (tp == FLOAT || tp == DOUBLE || tq == FLOAT || tq == DOUBLE);
+}
+
prtype(n) NODE *n;
{
switch (n->in.type)
return;
}
- case 'M': /* initiate ediv for mod and unsigned div */
- {
+ case 'M': { /* initiate ediv for mod and unsigned div */
register char *r;
m = getlr(p, '1')->tn.rval;
r = rname(m);
printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
deflab(m);
}
- }
return;
+ }
- case 'U':
- /* Truncate int for type conversions:
- LONG|ULONG -> CHAR|UCHAR|SHORT|USHORT
- SHORT|USHORT -> CHAR|UCHAR
- increment offset to correct byte */
- {
- register NODE *p1;
- int dif;
-
- p1 = p->in.left;
- switch( p1->in.op ){
- case NAME:
- case OREG:
- dif = tlen(p1)-tlen(p);
- p1->tn.lval += dif;
- adrput(p1);
- p1->tn.lval -= dif;
- return;
- default:
- cerror( "Illegal ZU type conversion" );
- return;
- }
- }
-
- case 'T': /* rounded structure length for arguments */
- {
- int size;
-
- size = p->stn.stsize;
+ case 'T': { /* rounded structure length for arguments */
+ int size = p->stn.stsize;
SETOFF( size, 4);
printf("movab -%d(sp),sp", size);
return;
- }
+ }
case 'S': /* structure assignment */
stasg(p);
printf("\n");
return;
+ case 'U': /* SCONV */
+ case 'V': /* SCONV with FORCC */
+ sconv(p, c == 'V');
+ break;
+
+ case 'Z':
+ p = p->in.right;
+ switch (p->in.type) {
+ case SHORT: {
+ short w = p->tn.lval;
+ p->tn.lval = w;
+ break;
+ }
+ case CHAR: {
+ char c = p->tn.lval;
+ p->tn.lval = c;
+ break;
+ }
+ }
+ printf("$%d", p->tn.lval);
+ break;
+
default:
cerror( "illegal zzzcode" );
- }
}
+}
#define MOVB(dst, src, off) { \
putstr("\tmovb\t"); upput(src, off); putchar(','); \
}
}
+/*
+ * Generate code for storage conversions.
+ */
+sconv(p, forcc)
+ NODE *p;
+{
+ register NODE *l, *r;
+ register wfrom, wto;
+ int oltype;
+
+ l = getlr(p, '1');
+ oltype = l->in.type, l->in.type = r->in.type;
+ r = getlr(p, 'L');
+ wfrom = tlen(r), wto = tlen(l);
+ if (wfrom == wto) /* e.g. int -> unsigned */
+ goto done;
+ /*
+ * Conversion in registers requires care
+ * as cvt and movz instruction don't work
+ * as expected (they end up as plain mov's).
+ */
+ if (l->in.op == REG && r->in.op == REG) {
+ if (ISUNSIGNED(r->in.type)) { /* unsigned, mask */
+ if (r->tn.lval != l->tn.lval) {
+ printf("\tandl3\t$%d,", (1<<(wto*SZCHAR))-1);
+ adrput(r);
+ putchar(',');
+ } else
+ printf("\tandl2\t$%d,", (1<<(wto*SZCHAR))-1);
+ adrput(l);
+ } else { /* effect sign-extend */
+ int shift = (sizeof (int)-wto)*SZCHAR;
+ printf("\tshll\t$%d,", shift);
+ adrput(r); putchar(','); adrput(l);
+ printf("\n\tshar\t$%d,", shift);
+ adrput(l); putchar(','); adrput(l);
+ if (wfrom != sizeof (int)) {
+ /*
+ * Must mask if result is shorter than
+ * the width of a register (to account
+ * for register treatment).
+ */
+ printf("\n\tandl2\t$%d,",(1<<(wfrom*SZCHAR))-1);
+ adrput(l);
+ } else
+ forcc = 0;
+ }
+ /*
+ * If condition codes are required and the last thing
+ * we did was mask the result, then we must generate a
+ * test of the appropriate type.
+ */
+ if (forcc) {
+ printf("\n\tcmp");
+ prtype(l);
+ putchar('\t');
+ printf("$0,");
+ adrput(l);
+ }
+ } else {
+ /*
+ * Conversion with at least one parameter in memory.
+ */
+ if (wfrom < wto) { /* expanding datum */
+ if (ISUNSIGNED(r->in.type)) {
+ printf("\tmovz");
+ prtype(r);
+ /*
+ * If target is a register, generate
+ * movz?l so optimizer can compress
+ * argument pushes.
+ */
+ if (l->in.op == REG)
+ putchar('l');
+ else
+ prtype(l);
+ } else {
+ printf("\tcvt");
+ prtype(r), prtype(l);
+ }
+ putchar('\t');
+ adrput(r);
+ } else { /* shrinking dataum */
+ int off = wfrom - wto;
+ if (l->in.op == REG) {
+ printf("\tmovz");
+ prtype(l);
+ putchar('l');
+ } else {
+ printf("\tcvt");
+ prtype(l), prtype(r);
+ }
+ putchar('\t');
+ switch (r->in.op) {
+ case NAME: case OREG:
+ r->tn.lval += off;
+ adrput(r);
+ r->tn.lval -= off;
+ break;
+ case REG: case ICON: case UNARY MUL:
+ adrput(r);
+ break;
+ default:
+ cerror("sconv: bad shrink op");
+ /*NOTREACHED*/
+ }
+ }
+ putchar(',');
+ adrput(l);
+ }
+ putchar('\n');
+done:
+ l->in.type = oltype;
+}
+
rmove( rt, rs, t ) TWORD t;{
printf( " movl %s,%s\n", rname(rs), rname(rt) );
if(t==DOUBLE)
/* do local tree transformations and optimizations */
# define RV(p) p->in.right->tn.lval
# define nncon(p) ((p)->in.op == ICON && (p)->in.name[0] == 0)
- register int o = p->in.op;
- register int i;
+ register int o, i;
+ register NODE *l, *r;
- /* change unsigned mods and divs to logicals (mul is done in mip & c2) */
- if(optype(o) == BITYPE && ISUNSIGNED(p->in.left->in.type)
- && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
- switch(o) {
- case DIV:
- case ASG DIV:
- p->in.op = RS;
- RV(p) = i;
- break;
- case MOD:
- case ASG MOD:
- p->in.op = AND;
- RV(p)--;
- break;
- default:
- return;
+ switch (o = p->in.op) {
+
+ case DIV: case ASG DIV:
+ case MOD: case ASG MOD:
+ /*
+ * Change unsigned mods and divs to
+ * logicals (mul is done in mip & c2)
+ */
+ if (ISUNSIGNED(p->in.left->in.type) && nncon(p->in.right) &&
+ (i = ispow2(RV(p))) >= 0) {
+ if (o == DIV || o == ASG DIV) {
+ p->in.op = RS;
+ RV(p) = i;
+ } else {
+ p->in.op = AND;
+ RV(p)--;
+ }
+ if (asgop(o))
+ p->in.op = ASG p->in.op;
+ }
+ return;
+
+ case SCONV:
+ l = p->in.left;
+ /* clobber conversions w/o side effects */
+ if (!anyfloat(p, l) && l->in.op != PCONV &&
+ tlen(p) == tlen(l)) {
+ if (l->in.op != FLD)
+ l->in.type = p->in.type;
+ ncopy(p, l);
+ l->in.op = FREE;
+ }
+ return;
+
+ case ASSIGN:
+ /*
+ * Try to zap storage conversions of non-float items.
+ */
+ r = p->in.right;
+ if (r->in.op == SCONV && !anyfloat(r->in.left, r)) {
+ int wdest, wconv, wsrc;
+ wdest = tlen(p->in.left);
+ wconv = tlen(r);
+ /*
+ * If size doesn't change across assignment or
+ * conversion expands src before shrinking again
+ * due to the assignment, delete conversion so
+ * code generator can create optimal code.
+ */
+ if (wdest == wconv ||
+ (wdest == (wsrc = tlen(r->in.left)) && wconv > wsrc)) {
+ p->in.right = r->in.left;
+ r->in.op = FREE;
+ }
}
- if(asgop(o))
- p->in.op = ASG p->in.op;
+ return;
}
# endif
}
}
# endif
+strip(p) register NODE *p; {
+ NODE *q;
+
+ /* strip nodes off the top when no side effects occur */
+ for( ; ; ) {
+ switch( p->in.op ) {
+ case SCONV: /* remove lint tidbits */
+ q = p->in.left;
+ ncopy( p, q );
+ q->in.op = FREE;
+ break;
+ /* could probably add a few more here */
+ default:
+ return;
+ }
+ }
+ }
+
myreader(p) register NODE *p; {
+ strip( p ); /* strip off operations with no side effects */
walkf( p, hardops ); /* convert ops to function calls */
canon( p ); /* expands r-vals for fileds */
walkf( p, optim2 );
#ifndef lint
-static char sccsid[] = "@(#)table.c 1.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)table.c 1.5 (Berkeley) %G%";
#endif
# include "pass2.h"
NAREG|NASL, RESC1|RESCC,
" ldZL AL\n cvZLl A1\n",
-/* cast to longer types */
-SCONV, INAREG|INTAREG|FORCC,
- SAREG|AWD, TCHAR,
- SANY, TUSHORT,
- NAREG|NASL, RESC1|RESCC,
- " cvtbw AL,A1\n andl2 $0xffff,A1\n",
-
-/* casts to shorter types */
-SCONV, INAREG|INTAREG|FORCC,
- SAREG|SCON, ANYFIXED,
- SANY, ANYUSIGNED,
- NAREG|NASL, RESC1|RESCC,
- " movzZRl AL,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
- SNAME, ANYFIXED,
- SANY, ANYUSIGNED,
- NAREG|NASL, RESC1|RESCC,
- " movzZRl ZU,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
- SSOREG, ANYFIXED,
- SANY, ANYUSIGNED,
- NAREG|NASL, RESC1|RESCC,
- " movzZRl ZU,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
- SAREG|SCON, ANYFIXED,
- SANY, ANYFIXED,
- NAREG|NASL, RESC1|RESCC,
- " cvtZRl AL,A1\n",
-
-SCONV, INAREG|INTAREG|FORCC,
- SNAME, ANYFIXED,
+SCONV, INAREG|INTAREG,
+ SAREG|AWD, ANYFIXED,
SANY, ANYFIXED,
NAREG|NASL, RESC1|RESCC,
- " cvtZRl ZU,A1\n",
+ "ZU",
SCONV, INAREG|INTAREG|FORCC,
- SSOREG, ANYFIXED,
+ SAREG|AWD, ANYFIXED,
SANY, ANYFIXED,
NAREG|NASL, RESC1|RESCC,
- " cvtZRl ZU,A1\n",
+ "ZV",
INIT, FOREFF,
SCON, TANY,
" cmpl AL,AR\nZP",
OPLOG, FORCC,
- SAREG|AWD, TSHORT|TUSHORT,
- SCON , TUSHORT,
+ AWD, TUSHORT,
+ SCON, TANY,
NAREG, RESCC,
" movzwl AL,A1\n cmpw A1,AR\nZP",
-OPLOG, FORCC,
- SAREG|AWD, TSHORT|TUSHORT,
- SAREG|AWD, TSHORT|TUSHORT,
- 0, RESCC,
- " cmpw AL,AR\nZP",
-
-OPLOG, FORCC,
- SAREG|AWD, TCHAR|TUCHAR,
- SCON , TUCHAR,
- NAREG, RESCC,
- " movzbl AL,A1\n cmpb A1,AR\nZP",
-
-OPLOG, FORCC,
- SAREG|AWD, TCHAR|TUCHAR,
- SAREG|AWD, TCHAR|TUCHAR,
- 0, RESCC,
- " cmpb AL,AR\nZP",
OPLOG, FORCC,
SAREG|AWD, TSHORT|TUSHORT,
- SSCON, TANY,
+ SCON, TANY,
0, RESCC,
- " cmpw AL,AR\nZP",
-
+ " cmpw AL,ZZ\nZP",
OPLOG, FORCC,
SAREG|AWD, TSHORT|TUSHORT,
" cmpw AL,AR\nZP",
OPLOG, FORCC,
- SAREG|AWD, TCHAR|TUCHAR,
- SAREG|AWD, TCHAR|TUCHAR,
- 0, RESCC,
- " cmpb AL,AR\nZP",
+ AWD, TUCHAR,
+ SCON, TANY,
+ NAREG, RESCC,
+ " movzbl AL,A1\n cmpb A1,AR\nZP",
OPLOG, FORCC,
- SAREG|AWD, TSHORT|TUSHORT,
- SSCON, TANY,
+ SAREG|AWD, TCHAR|TUCHAR,
+ SCON, TANY,
0, RESCC,
- " cmpw AL,AR\nZP",
+ " cmpb AL,ZZ\nZP",
OPLOG, FORCC,
SAREG|AWD, TCHAR|TUCHAR,
- SCCON, TANY,
+ SAREG|AWD, TCHAR|TUCHAR,
0, RESCC,
" cmpb AL,AR\nZP",