BSD 4_4 release
[unix-history] / usr / src / old / pcc / ccom.tahoe / local2.c
index f884455..158d04e 100644 (file)
@@ -1,6 +1,6 @@
-# ifndef lint
-static char sccsid[] = "@(#)local2.c   1.24 (Berkeley) %G%";
-# endif
+#ifndef lint
+static char sccsid[] = "@(#)local2.c   1.32 (Berkeley) 2/29/88";
+#endif
 
 # include "pass2.h"
 # include <ctype.h>
 
 # include "pass2.h"
 # include <ctype.h>
@@ -103,7 +103,8 @@ rname(r)
        register int r;
 {
 
        register int r;
 {
 
-       ent_mask |= 1<<r;
+       if (!istreg(r))
+               ent_mask |= 1<<r;
        return(rnames[r]);
 }
 
        return(rnames[r]);
 }
 
@@ -272,7 +273,7 @@ zzzcode( p, c ) register NODE *p; {
                /* case constant <= 1 is handled by optim() in pass 1 */
                /* case constant < 0x80000000 is handled in table */
                switch( p->in.op ) {
                /* case constant <= 1 is handled by optim() in pass 1 */
                /* case constant < 0x80000000 is handled in table */
                switch( p->in.op ) {
-               /* case DIV: handled in hardops() */
+               /* case DIV: handled in optim2() */
                case MOD:
                        if( p->in.left->in.op == REG &&
                            p->in.left->tn.rval == resc->tn.rval )
                case MOD:
                        if( p->in.left->in.op == REG &&
                            p->in.left->tn.rval == resc->tn.rval )
@@ -337,11 +338,16 @@ zzzcode( p, c ) register NODE *p; {
                }
 
        case 'D':       /* INCR and DECR */
                }
 
        case 'D':       /* INCR and DECR */
-               zzzcode(p->in.left, 'U');
+               if (p->in.left->in.type == FLOAT)
+                       expand(p, INAREG, "movl\tAL,A1");
+               else if (p->in.left->in.type == DOUBLE)
+                       expand(p, INAREG, "ldd\tAL\n\tstd\tA1");
+               else
+                       zzzcode(p->in.left, 'U');
                putstr("\n      ");
 
        case 'E':       /* INCR and DECR, FOREFF */
                putstr("\n      ");
 
        case 'E':       /* INCR and DECR, FOREFF */
-               if (p->in.right->tn.lval == 1)
+               if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1)
                        {
                        putstr(p->in.op == INCR ? "inc" : "dec");
                        prtype(p->in.left);
                        {
                        putstr(p->in.op == INCR ? "inc" : "dec");
                        prtype(p->in.left);
@@ -349,6 +355,15 @@ zzzcode( p, c ) register NODE *p; {
                        adrput(p->in.left);
                        return;
                        }
                        adrput(p->in.left);
                        return;
                        }
+               else if (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE) {
+                       if (c == 'E' || p->in.left->in.type == FLOAT)
+                               expand(p, INAREG, "ldZL\tAL\n\t");
+                       if (p->in.op == INCR)
+                               expand(p, INAREG, "addZL\tAR\n\tstZL\tAL");
+                       else /* DECR */
+                               expand(p, INAREG, "subZL\tAR\n\tstZL\tAL");
+                       return;
+                       }
                putstr(p->in.op == INCR ? "add" : "sub");
                prtype(p->in.left);
                putstr("2       ");
                putstr(p->in.op == INCR ? "add" : "sub");
                prtype(p->in.left);
                putstr("2       ");
@@ -363,6 +378,8 @@ zzzcode( p, c ) register NODE *p; {
 
        case 'I':       /* produce value of bitfield assignment */
                        /* avoid shifts -- shifts are SLOW on this machine */
 
        case 'I':       /* produce value of bitfield assignment */
                        /* avoid shifts -- shifts are SLOW on this machine */
+                       /* XXX this wouldn't be necessary if we were smarter
+                              and masked BEFORE shifting XXX */
                {
                register NODE *r = p->in.right;
                if(r->in.op == ICON && r->tn.name[0] == '\0') {
                {
                register NODE *r = p->in.right;
                if(r->in.op == ICON && r->tn.name[0] == '\0') {
@@ -403,17 +420,16 @@ zzzcode( p, c ) register NODE *p; {
                }
 
        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("\tclrl\t%s\n\tmovl\t", r);
+               putstr("clrl\t");
+               adrput(resc);
+               putstr("\n\tmovl\t");
                adrput(p->in.left);
                adrput(p->in.left);
-               printf(",%s\n", rname(m+1));
-               if(!ISUNSIGNED(p->in.type)) {   /* should be MOD */
-                       m = getlab();
-                       printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
-                       deflab(m);
-               }
+               putchar(',');
+               upput(resc, SZLONG);
+               printf("\n\tjgeq\tL%d\n\tmnegl\t$1,", m = getlab());
+               adrput(resc);
+               putchar('\n');
+               deflab(m);
                return;
        }
 
                return;
        }
 
@@ -617,10 +633,21 @@ stasg(p)
                 * Can we ever get a register conflict with R1 here?
                 */
                putstr("\tmovab\t");
                 * Can we ever get a register conflict with R1 here?
                 */
                putstr("\tmovab\t");
-               adrput(l);
-               putstr(",r1\n\tmovab\t");
-               adrput(r);
-               printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size);
+               if(r->in.op == OREG && r->tn.rval == R1)
+               {
+                       adrput(r);
+                       printf(",r0\n\tmovab\t");
+                       adrput(l);
+                       putstr(",r1\n");
+               }
+               else
+               {
+                       adrput(l);
+                       putstr(",r1\n\tmovab\t");
+                       adrput(r);
+                       printf(",r0\n");
+               }
+               printf("\tmovl\t$%d,r2\n\tmovblk\n", size);
                rname(R2);
                break;
        }
                rname(R2);
                break;
        }
@@ -734,6 +761,8 @@ static char convtab[SZINT/SZCHAR + 1] = {
  *     ignored and the high bits of the source are copied.  (Note
  *     that zero-extension is not a problem for immediate
  *     constants.)
  *     ignored and the high bits of the source are copied.  (Note
  *     that zero-extension is not a problem for immediate
  *     constants.)
+ * Another problem -- condition codes for a conversion with a
+ *     register source reflect the source rather than the destination.
  */
 sconv(p, forcc)
        NODE *p;
  */
 sconv(p, forcc)
        NODE *p;
@@ -801,8 +830,9 @@ sconv(p, forcc)
                }
                srctype = dsttype;
                srclen = dstlen;
                }
                srctype = dsttype;
                srclen = dstlen;
-               if ((val = src->tn.lval) & 1 << dstlen * SZCHAR - 1) {
-                       src->tn.lval = -(val | ~((1 << dstlen * SZCHAR) - 1));
+               val = -src->tn.lval & ((1 << dstlen * SZCHAR) - 1);
+               if ((unsigned) val < 64) {
+                       src->tn.lval = val;
                        ++neg;          /* MNEGx may be shorter */
                }
        }
                        ++neg;          /* MNEGx may be shorter */
                }
        }
@@ -816,15 +846,14 @@ sconv(p, forcc)
                        adrput(dst);
                        putstr("\n\tmovab\t4(sp),sp");
                        if (forcc) {
                        adrput(dst);
                        putstr("\n\tmovab\t4(sp),sp");
                        if (forcc) {
-                               /* inverted test */
-                               putstr("\n\tcmpl\t$0,");
+                               putstr("\n\ttstl\t");
                                adrput(dst);
                        }
                        return;
                }
                genconv(ISUNSIGNED(srctype),
                        srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
                                adrput(dst);
                        }
                        return;
                }
                genconv(ISUNSIGNED(srctype),
                        srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
-                       src, dst);
+                       src, dst, forcc);
                return;
        }
 
                return;
        }
 
@@ -835,9 +864,9 @@ sconv(p, forcc)
                                val = (1 << dstlen * SZCHAR) - 1;
                                if (src->tn.rval == dst->tn.rval)
                                        /* conversion in place */
                                val = (1 << dstlen * SZCHAR) - 1;
                                if (src->tn.rval == dst->tn.rval)
                                        /* conversion in place */
-                                       printf("andl2\t$%#x,", val);
+                                       printf("andl2\t$%ld,", val);
                                else {
                                else {
-                                       printf("andl3\t$%#x,", val);
+                                       printf("andl3\t$%ld,", val);
                                        adrput(src);
                                        putchar(',');
                                }
                                        adrput(src);
                                        putchar(',');
                                }
@@ -858,16 +887,14 @@ sconv(p, forcc)
                        adrput(dst);
                        putstr("\n\tmovab\t4(sp),sp");
                        if (forcc) {
                        adrput(dst);
                        putstr("\n\tmovab\t4(sp),sp");
                        if (forcc) {
-                               /* inverted test */
-                               putstr("\n\tcmpl\t$0,");
+                               putstr("\n\ttstl\t");
                                adrput(dst);
                        }
                        return;
                }
                tmp = talloc();
                                adrput(dst);
                        }
                        return;
                }
                tmp = talloc();
-               if ((src->in.op == UNARY MUL &&
-                   ((src->in.left->in.op == NAME ||
-                    (src->in.left->in.op == ICON)))) ||
+               if ((src->in.op == NAME) ||
+                   (src->in.op == UNARY MUL && src->in.left->in.op == ICON) ||
                    (src->in.op == OREG && !R2TEST(src->tn.rval))) {
                        /* we can increment src's address & pun it */
                        *tmp = *src;
                    (src->in.op == OREG && !R2TEST(src->tn.rval))) {
                        /* we can increment src's address & pun it */
                        *tmp = *src;
@@ -885,20 +912,21 @@ sconv(p, forcc)
                        tmp->tn.op = OREG;
                        tmp->tn.lval = srclen - dstlen;
                }
                        tmp->tn.op = OREG;
                        tmp->tn.lval = srclen - dstlen;
                }
-               genconv(ISUNSIGNED(dsttype), dstlen, SZINT/SZCHAR, tmp, dst);
+               genconv(ISUNSIGNED(dsttype), dstlen, SZINT/SZCHAR, tmp, dst, forcc);
                tmp->in.op = FREE;
                return;
        }
 
        genconv(neg ? -1 : ISUNSIGNED(dsttype),
                srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
                tmp->in.op = FREE;
                return;
        }
 
        genconv(neg ? -1 : ISUNSIGNED(dsttype),
                srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
-               src, dst);
+               src, dst, forcc);
 }
 
 }
 
-genconv(srcflag, srclen, dstlen, src, dst)
+genconv(srcflag, srclen, dstlen, src, dst, forcc)
        int srcflag;
        register int srclen, dstlen;
        NODE *src, *dst;
        int srcflag;
        register int srclen, dstlen;
        NODE *src, *dst;
+       int forcc;
 {
        if (srclen != dstlen) {
                if (srcflag > 0 && srclen < dstlen)
 {
        if (srclen != dstlen) {
                if (srcflag > 0 && srclen < dstlen)
@@ -915,6 +943,17 @@ genconv(srcflag, srclen, dstlen, src, dst)
        adrput(src);
        putchar(',');
        adrput(dst);
        adrput(src);
        putchar(',');
        adrput(dst);
+
+       /*
+        * This hack is made necessary by architecture problems
+        *      described above
+        */
+       if (forcc && src->in.op == REG && srclen > dstlen) {
+               putstr("\n\ttst");
+               prlen(dstlen);
+               putchar('\t');
+               adrput(dst);
+       }
 }
 
 rmove( rt, rs, t ) TWORD t; {
 }
 
 rmove( rt, rs, t ) TWORD t; {
@@ -955,12 +994,13 @@ callreg(p) NODE *p; {
 base( p ) register NODE *p; {
        register int o = p->in.op;
 
 base( p ) register NODE *p; {
        register int o = p->in.op;
 
-       if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
+       if( o==ICON && p->in.name[0] != '\0' ) return( 100 ); /* ie no base reg */
        if( o==REG ) return( p->tn.rval );
     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
                return( p->in.left->tn.rval );
     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
                return( p->tn.rval + 0200*1 );
        if( o==REG ) return( p->tn.rval );
     if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
                return( p->in.left->tn.rval );
     if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
                return( p->tn.rval + 0200*1 );
+       if( o==NAME ) return( 100 + 0200*1 );
        return( -1 );
        }
 
        return( -1 );
        }
 
@@ -999,6 +1039,7 @@ makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
                case ICON:
                case REG:
                case OREG:
                case ICON:
                case REG:
                case OREG:
+               case NAME:
                        t = q;
                        break;
 
                        t = q;
                        break;
 
@@ -1097,6 +1138,11 @@ shumul( p ) register NODE *p; {
        return( 0 );
        }
 
        return( 0 );
        }
 
+special( p, shape ) register NODE *p; {
+       if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1);
+       else return(0);
+}
+
 adrcon( val ) CONSZ val; {
        printf(ACONFMT, val);
        }
 adrcon( val ) CONSZ val; {
        printf(ACONFMT, val);
        }
@@ -1382,6 +1428,23 @@ optim2( p ) register NODE *p; {
 
        switch( o = p->in.op ) {
 
 
        switch( o = p->in.op ) {
 
+       case ASG PLUS:
+       case ASG MINUS:
+       case ASG MUL:
+       case ASG OR:
+               /* simple ASG OPSIMP -- reduce range of constant rhs */
+               l = p->in.left;
+               r = p->in.right;
+               if( tlen(l) < SZINT/SZCHAR &&
+                   r->in.op==ICON && r->in.name[0]==0 ){
+                       mask = (1 << tlen(l) * SZCHAR) - 1;
+                       if( r->tn.lval & (mask & ~(mask >> 1)) )
+                               r->tn.lval |= ~mask;
+                       else
+                               r->tn.lval &= mask;
+                       }
+               break;
+
        case AND:
        case ASG AND:
                r = p->in.right;
        case AND:
        case ASG AND:
                r = p->in.right;
@@ -1389,21 +1452,30 @@ optim2( p ) register NODE *p; {
                        /* check for degenerate operations */
                        l = p->in.left;
                        mask = (1 << tlen(l) * SZCHAR) - 1;
                        /* check for degenerate operations */
                        l = p->in.left;
                        mask = (1 << tlen(l) * SZCHAR) - 1;
-                       if( ISUNSIGNED(r->in.type) ) {
-                               i = (r->tn.lval & mask);
+                       if( o == ASG AND || ISUNSIGNED(r->in.type) ) {
+                               i = r->tn.lval & mask;
                                if( i == mask ) {
                                if( i == mask ) {
+                                       /* redundant mask */
                                        r->in.op = FREE;
                                        ncopy(p, l);
                                        l->in.op = FREE;
                                        break;
                                        }
                                else if( i == 0 )
                                        r->in.op = FREE;
                                        ncopy(p, l);
                                        l->in.op = FREE;
                                        break;
                                        }
                                else if( i == 0 )
+                                       /* all bits masked off */
                                        goto zero;
                                        goto zero;
-                               else
-                                       r->tn.lval = i;
+                               r->tn.lval = i;
+                               if( tlen(l) < SZINT/SZCHAR ){
+                                       /* sign extend */
+                                       if( r->tn.lval & (mask & ~(mask >> 1)) )
+                                               r->tn.lval |= ~mask;
+                                       else
+                                               r->tn.lval &= mask;
+                                       }
                                }
                        else if( r->tn.lval == mask &&
                                 tlen(l) < SZINT/SZCHAR ) {
                                }
                        else if( r->tn.lval == mask &&
                                 tlen(l) < SZINT/SZCHAR ) {
+                               /* use movz instead of and */
                                r->in.op = SCONV;
                                r->in.left = l;
                                r->in.right = 0;
                                r->in.op = SCONV;
                                r->in.left = l;
                                r->in.right = 0;
@@ -1421,7 +1493,10 @@ optim2( p ) register NODE *p; {
                if( p->in.type == FLOAT || p->in.type == DOUBLE ||
                    l->in.type == FLOAT || l->in.type == DOUBLE )
                        return;
                if( p->in.type == FLOAT || p->in.type == DOUBLE ||
                    l->in.type == FLOAT || l->in.type == DOUBLE )
                        return;
-               if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL )
+               if( l->in.op == PCONV )
+                       return;
+               if( (l->in.op == CALL || l->in.op == UNARY CALL) &&
+                   l->in.type != INT && l->in.type != UNSIGNED )
                        return;
 
                /* Only trust it to get it right if the size is the same */
                        return;
 
                /* Only trust it to get it right if the size is the same */
@@ -1469,6 +1544,21 @@ optim2( p ) register NODE *p; {
        case LT:
        case GE:
        case GT:
        case LT:
        case GE:
        case GT:
+               if( p->in.left->in.op == SCONV &&
+                   p->in.right->in.op == SCONV ) {
+                       l = p->in.left;
+                       r = p->in.right;
+                       if( l->in.type == DOUBLE &&
+                           l->in.left->in.type == FLOAT &&
+                           r->in.left->in.type == FLOAT ) {
+                               /* nuke the conversions */
+                               p->in.left = l->in.left;
+                               p->in.right = r->in.left;
+                               l->in.op = FREE;
+                               r->in.op = FREE;
+                               }
+                       /* more? */
+                       }
                (void) degenerate(p);
                break;
 
                (void) degenerate(p);
                break;