Annotation of researchv9/cmd/sun/pcc/order.c, revision 1.1.1.1

1.1       root        1: # include "cpass2.h"
                      2: #ifndef lint
                      3: static char sccsid[] = "@(#)order.c 1.1 86/02/03 Copyr 1985 Sun Micro";
                      4: #endif
                      5: 
                      6: /*
                      7:  * Copyright (c) 1985 by Sun Microsystems, Inc.
                      8:  */
                      9: 
                     10: /*
                     11:  * order.c -- conditionally included 680X0 version
                     12:  */
                     13: 
                     14: 
                     15: int fltused = 0;
                     16: int floatmath = 0;
                     17: 
                     18: SUTYPE fregs;
                     19: 
                     20: extern int mina, maxa, minb, maxb; /* imported from allo.c */
                     21: extern int toff, maxtoff;
                     22: 
                     23: int maxargs = { -1 };
                     24: 
                     25: static SUTYPE zed = { 0,0,0,0 };
                     26: 
                     27: int failsafe; /* very disgusting: see offstar() for use */
                     28: 
                     29: # define SAFETY( a, reg,  b ) \
                     30:        {if ((reg & MUSTDO) && find_mustdo( a , reg )) {rewrite_rall( b, 1 );} }
                     31: # define iscnode(p) ((p)->in.op==REG && iscreg((p)->tn.rval))
                     32: 
                     33: # define max(x,y) ((x)<(y)?(y):(x))
                     34: # define min(x,y) ((x)<(y)?(x):(y))
                     35: 
                     36: # define divmulop(o) (dope[o]&(DIVFLG|MULFLG))
                     37: 
                     38: 
                     39: NODE *
                     40: double_conv( p ) register NODE *p;
                     41: {
                     42:        NODE *q    = talloc();
                     43:        q->in.op   = SCONV;
                     44:        q->in.type = DOUBLE;
                     45:        q->in.left = p;
                     46:        q->in.rall = p->in.rall;
                     47:        if (use68881) {
                     48:            q->in.su.d = max( p->in.su.d, 1 );
                     49:            q->in.su.a = 0;
                     50:            q->in.su.f = max( p->in.su.f, 1 );
                     51:        } else {
                     52:            p->in.rall = MUSTDO|D0;
                     53:            q->in.su.d = max( p->in.su.d, fregs.d );
                     54:            q->in.su.a = max( p->in.su.a, fregs.a );
                     55:            q->in.su.f = max( p->in.su.f, fregs.f );
                     56:        }
                     57:        return q;
                     58: }
                     59: 
                     60: setincr( p ) register NODE *p; 
                     61: {
                     62:        return( 0 );
                     63: }
                     64: 
                     65: niceuty( p ) register NODE *p; 
                     66: {
                     67:        return( p->in.op == UNARY MUL && p->in.type != FLOAT &&
                     68:                shumul( p->in.left) == STARNM );
                     69: }
                     70: 
                     71: setconv( p, cookie )
                     72:     NODE *p;
                     73: {
                     74:     register NODE *lp;
                     75:     TWORD t;
                     76:     
                     77:     lp = p->in.left;
                     78:     switch(p->in.type) {
                     79:     case FLOAT:
                     80:     case DOUBLE:
                     81:        /* convert from something nice to something icky */
                     82:        if ( use68881 ) {
                     83:            if (p->in.type == DOUBLE && iscnode(lp)) {
                     84:                /*
                     85:                 * no code necessary -- floating point
                     86:                 * regs are always in extended format
                     87:                 */
                     88:                TWORD t = p->in.type;
                     89:                *p = *lp;
                     90:                p->in.type = t;
                     91:                lp->in.op = FREE;
                     92:                return(1);
                     93:            }
                     94:            if (ISFLOATING(lp->in.type)) {
                     95:                /*
                     96:                 * float => double, or vice versa
                     97:                 */
                     98:                order(lp, INCREG|INTCREG|INTEMP);
                     99:                return(1);
                    100:            }
                    101:            if (ISUNSIGNED(lp->in.type)) {
                    102:                /*
                    103:                 * the 68881 doesn't deal with unsigned types;
                    104:                 * convert the unsigned operand to INT.
                    105:                 */
                    106:                register NODE *q;
                    107:                q = talloc();
                    108:                q->in.op   = SCONV;
                    109:                q->in.type = INT;
                    110:                q->in.left = lp;
                    111:                q->in.rall = lp->in.rall;
                    112:                q->in.su.d = 1;
                    113:                q->in.su.a = 0;
                    114:                q->in.su.f = 0;
                    115:                p->in.left = lp = q;
                    116:            }
                    117:            break;
                    118:        }
                    119:        failsafe = 1;
                    120:        break;
                    121:     default:
                    122:        /* check for inverse (floating type => fixed type) */
                    123:        if (lp->in.type == FLOAT || lp->in.type == DOUBLE) {
                    124:            if (use68881) {
                    125:                order(lp, INCREG|INTCREG|INTEMP);
                    126:                return(1);
                    127:            }
                    128:            failsafe = 1;
                    129:        }
                    130:        break;
                    131:     }
                    132:     if (cookie!=(INBREG|INTBREG))
                    133:        cookie = (INAREG|INTAREG|INBREG|INTBREG);
                    134:     cookie |= INTEMP;
                    135:     order( p->in.left, cookie );
                    136:     return 1;
                    137: }
                    138: 
                    139: /*
                    140:  * deal properly with the operand of a unary operator.
                    141:  */
                    142: int
                    143: setunary(p, cookie)
                    144:        NODE *p;
                    145: {
                    146:        NODE *lp;
                    147: 
                    148:        lp = p->in.left;
                    149:        if (use68881 && ISFLOATING(lp->in.type)) {
                    150:                switch(p->in.op) {
                    151:                case FCOS:
                    152:                case FSIN:
                    153:                case FTAN:
                    154:                case FACOS:
                    155:                case FASIN:
                    156:                case FATAN:
                    157:                case FCOSH:
                    158:                case FSINH:
                    159:                case FTANH:
                    160:                case FEXP:
                    161:                case F10TOX:
                    162:                case F2TOX:
                    163:                case FLOGN:
                    164:                case FLOG10:
                    165:                case FLOG2:
                    166:                case FSQR:
                    167:                case FSQRT:
                    168:                case FAINT:
                    169:                case FANINT:
                    170:                        floatsrce(lp);
                    171:                        return(1);
                    172:                case FNINT:
                    173:                        order(lp, INCREG|INTCREG);
                    174:                        return(1);
                    175:                case UNARY MINUS:
                    176:                case FABS:
                    177:                        /* don't use the 81 unless we have to */
                    178:                        order(lp, INAREG|INCREG);
                    179:                        return(1);
                    180:                default:
                    181:                        break;
                    182:                }
                    183:        }
                    184:        order(lp, INAREG|INBREG|INCREG);
                    185:        return(1);
                    186: }
                    187: 
                    188: /*
                    189:  * put p into a form acceptable as a 68881 source operand.
                    190:  */
                    191: static
                    192: floatsrce(p)
                    193:        register NODE *p;
                    194: {
                    195:        if (p->in.op == SCONV) {
                    196:                /*
                    197:                 * the 68881 converts signed ints, float, and double
                    198:                 * to internal (extended) format automatically.
                    199:                 */
                    200:                switch(p->in.left->in.type) {
                    201:                case CHAR:
                    202:                case SHORT:
                    203:                case INT:
                    204:                case LONG:
                    205:                case FLOAT:
                    206:                case DOUBLE:
                    207:                        p = p->in.left;
                    208:                        break;
                    209:                default:
                    210:                        /* must do the conversion explicitly */
                    211:                        order(p->in.left, INAREG|INTAREG|INTEMP);
                    212:                        break;
                    213:                }
                    214:        }
                    215:        switch(p->in.op) {
                    216:        case UNARY MUL:
                    217:                /* just make it addressable */
                    218:                offstar(p->in.left);
                    219:                break;
                    220:        case REG:
                    221:                /* coprocessor cannot access address registers */
                    222:                if (isbreg(p->tn.rval)) {
                    223:                        order(p, INTAREG|INAREG);
                    224:                }
                    225:                break;
                    226:        default:
                    227:                /* lacking any better ideas, put it in a register */
                    228:                if (SUTEST(p->in.su)) {
                    229:                        if (ISFLOATING(p->in.type)) {
                    230:                                order(p, INCREG|INTCREG|INTEMP);
                    231:                        } else {
                    232:                                order(p, INAREG|INTAREG|INTEMP);
                    233:                        }
                    234:                }
                    235:                break;
                    236:        }
                    237: }
                    238: 
                    239: setbin( p, cook ) register NODE *p; 
                    240: {
                    241:        register NODE *r, *l;
                    242:        NODE *p2, *q, *t;
                    243:        SUTYPE sur, sul;
                    244:        SUTYPE qcost, pcost;
                    245:        extern short revrel[]; /* for logic ops */
                    246:        int cookie, i;
                    247: 
                    248:        r = p->in.right;
                    249:        l = p->in.left;
                    250:        sur = r->in.su;
                    251:        sul = l->in.su;
                    252: 
                    253:        cookie = cook;
                    254:        if (cookie!=(INBREG|INTBREG))
                    255:            cookie = (INAREG|INTAREG|INBREG|INTBREG);
                    256:        cookie |= INTEMP;
                    257:        /* if this is one of the constrained operators, rewrite as op= */
                    258:        switch( p->in.op ){
                    259:            case GT:
                    260:            case GE:
                    261:            case LT:
                    262:            case LE:
                    263:            case EQ:
                    264:            case NE:
                    265:                        if (l->in.type != FLOAT && l->in.type != DOUBLE)
                    266:                            break;
                    267:                        if (use68881) {
                    268:                            /*
                    269:                             * figure out what, if anything, is
                    270:                             * already in a coprocessor reg
                    271:                             */
                    272:                            int lhs,rhs;
                    273:                            lhs = iscnode(l);
                    274:                            rhs = iscnode(r);
                    275:                            /*
                    276:                             * logical ops require one operand to
                    277:                             * be in a coprocessor register. table.c
                    278:                             * expects the register on the left.
                    279:                             */
                    280:                            if ( !lhs ) {
                    281:                                /* lhs is not in a coprocessor reg */
                    282:                                if ( !rhs ) {
                    283:                                    /* rhs isn't either; do harder one */
                    284:                                    if (SUGT(sur, sul)
                    285:                                      && !tshape(r, SFLOAT_SRCE)) {
                    286:                                        order(r, INCREG|INTCREG);
                    287:                                        rhs = 1;
                    288:                                    } else {
                    289:                                        order(l, INCREG|INTCREG);
                    290:                                        lhs = 1;
                    291:                                    }
                    292:                                } 
                    293:                                if (rhs) {
                    294:                                    /* rhs is, lhs isn't */
                    295:                                    int temp;
                    296:                                    p->in.op = revrel[p->in.op - EQ];
                    297:                                    p->in.left = r;
                    298:                                    p->in.right = l;
                    299:                                    r = l;
                    300:                                    l = p->in.left;
                    301:                                    temp = rhs;
                    302:                                    rhs = lhs;
                    303:                                    lhs = temp;
                    304:                                }
                    305:                            }
                    306:                            /*
                    307:                             * lhs is in a coprocessor reg
                    308:                             */
                    309:                            if ( !rhs ) {
                    310:                                /*
                    311:                                 * rhs isn't, and doesn't need to be
                    312:                                 */
                    313:                                floatsrce(r);
                    314:                            } /* !rhs */
                    315:                            return(1);
                    316:                        } /* use68881 */
                    317: 
                    318:                        /*
                    319:                         * evaluate most expensive side first. If 
                    320:                         * cheaper size has non-zero cost, may have
                    321:                         * to put first intermediate result in a temp.
                    322:                         * Actually, this should not be a problem, if
                    323:                         * the su-stuff worked.
                    324:                         */
                    325:                        /* set variable "i" if we do anything here */
                    326:                        i = 0;
                    327:                        if( SUGT( sul, sur ) && !(istnode(l)&&l->tn.rval==D0) ){
                    328:                            /* do lhs first if it is the more expensive */
                    329:                            l->in.rall = MUSTDO|D0;
                    330:                            SAFETY( r , MUSTDO|D0, l);
                    331:                            order( l, INTAREG);
                    332:                            i++;
                    333:                        }
                    334:                        if ( r->in.type == DOUBLE ){
                    335:                            /* must be addressable */
                    336:                            if ( !tshape( r, SNAME|SOREG|STARNM)){
                    337:                                r->in.rall = NOPREF;
                    338:                                order( r, INTEMP );
                    339:                                i++;
                    340:                            }
                    341:                        } else {
                    342:                            if( !(istnode(r) && r->tn.rval == D1) ){
                    343:                                r->in.rall = MUSTDO|D1;
                    344:                                SAFETY( l , MUSTDO|D1, r);
                    345:                                order( r, INTAREG);
                    346:                                i++;
                    347:                            }
                    348:                        }
                    349:                        if( !(istnode(l) && l->tn.rval == D0) ){
                    350:                            /* do lhs after if it is the less expensive */
                    351:                            l->in.rall = MUSTDO|D0;
                    352:                            order( l, INTAREG);
                    353:                            i++;
                    354:                        }
                    355:                        if (i)
                    356:                            return 1;
                    357:                        break ; /* didn't accomplish anything -- fall into general case */
                    358:            case PLUS:
                    359:            case MINUS:
                    360:                if( p->in.type == FLOAT || p->in.type == DOUBLE ){
                    361: float_ops:
                    362:                        /*
                    363:                         * evaluate most expensive side first. If 
                    364:                         * cheaper size has non-zero cost, may have
                    365:                         * to put first intermediate result in a temp.
                    366:                         * Actually, this should not be a problem, if
                    367:                         * the su-stuff worked.
                    368:                         */
                    369:                        if (r->in.type==FLOAT && (!FLOATMATH || p->in.type==DOUBLE)){
                    370:                            r = p->in.right = double_conv(r);
                    371:                        }
                    372:                        if (l->in.type==FLOAT && (!FLOATMATH || p->in.type==DOUBLE)){
                    373:                            l = p->in.left = double_conv(l);
                    374:                        }
                    375:                        /*----------------------------*/
                    376:                        if (use68881) {
                    377:                            /*
                    378:                             * figure out what, if anything, is
                    379:                             * already in a coprocessor reg.  The
                    380:                             * lhs must be a temporary.
                    381:                             */
                    382:                            int lhs,rhs;
                    383:                            lhs = (istnode(l) && iscreg(l->tn.rval));
                    384:                            rhs = (iscnode(r));
                    385:                            /*
                    386:                             * dyadic ops require one operand to
                    387:                             * be in a coprocessor register. table.c
                    388:                             * expects the register on the left.
                    389:                             */
                    390:                            if ( !lhs ) {
                    391:                                /* lhs is not in a temp coprocessor reg */
                    392:                                if ( !rhs ) {
                    393:                                    /* rhs isn't either; do harder one */
                    394:                                    if (SUGT(sur, sul)
                    395:                                      && !tshape(r, SFLOAT_SRCE)) {
                    396:                                        floatsrce(r);
                    397:                                        rhs = iscnode(r);
                    398:                                    } else {
                    399:                                        order(l, INTCREG);
                    400:                                        lhs = 1;
                    401:                                    }
                    402:                                } 
                    403:                                if ( rhs && !lhs && istnode(r)
                    404:                                  && (p->in.op == PLUS || p->in.op == MUL) ) {
                    405:                                    /*
                    406:                                     * rhs is in a writable coprocessor
                    407:                                     * reg, lhs isn't, and op is commutable
                    408:                                     */
                    409:                                    int temp;
                    410:                                    p->in.left = r;
                    411:                                    p->in.right = l;
                    412:                                    r = l;
                    413:                                    l = p->in.left;
                    414:                                    temp = rhs;
                    415:                                    rhs = lhs;
                    416:                                    lhs = temp;
                    417:                                }
                    418:                                if (!lhs) {
                    419:                                    order(l, INTCREG);
                    420:                                    lhs = 1;
                    421:                                }
                    422:                            }
                    423:                            /*
                    424:                             * lhs is in a writable coprocessor reg
                    425:                             */
                    426:                            if ( !rhs ) {
                    427:                                /*
                    428:                                 * rhs isn't, and doesn't need to be
                    429:                                 */
                    430:                                floatsrce(r);
                    431:                            } 
                    432:                            p->in.op = ASG p->in.op;
                    433:                            return(1);
                    434:                        } /* use68881 */
                    435: 
                    436:                        if (usesky) {
                    437:                            if ( p->in.op == PLUS ) {
                    438:                                /*
                    439:                                 * look for expressions of
                    440:                                 * the form (x + y*z), which the
                    441:                                 * sky board does in a single
                    442:                                 * operation.
                    443:                                 */
                    444:                                if ( l->in.op == MUL && r->in.op != MUL ) {
                    445:                                    l = r;
                    446:                                    r = p->in.left;
                    447:                                    p->in.left = l;
                    448:                                    p->in.right = r;
                    449:                                }
                    450:                                if (r->in.op == MUL) {
                    451:                                    /*
                    452:                                     * Don't even go near it
                    453:                                     * unless x,y, or z comes for free.
                    454:                                     */
                    455:                                    if (!SUTEST(l->in.su)) {
                    456:                                        l = r->in.left;
                    457:                                        r = r->in.right;
                    458:                                    } else if (!SUTEST(r->in.left->in.su)) {
                    459:                                        r = r->in.right;
                    460:                                    } else if (!SUTEST(r->in.right->in.su)) {
                    461:                                        r = r->in.left;
                    462:                                    }
                    463:                                }
                    464:                            }
                    465:                            for( i=0; i<2; i++ ){
                    466:                                if (SUGT( l->in.su, r->in.su )){
                    467:                                    p2 = l; q = r;
                    468:                                }else if (SUTEST( r->in.su )){
                    469:                                    p2 = r; q = l;
                    470:                                }else break;
                    471:                                if (p2->in.op==UNARY MUL 
                    472:                                  && rewrite_b_rall(p2->in.left, 1)){
                    473:                                    /* try to offstar, but not into a1 */
                    474:                                    failsafe = find_mustdo( q, MUSTDO|D0 );
                    475:                                    offstar(p2->in.left);
                    476:                                } else {
                    477:                                    if ( !find_mustdo( q, MUSTDO|D0) ||
                    478:                                        rewrite_rall(p2, i) )
                    479:                                        order( p2, INTAREG| INTBREG| INTEMP );
                    480:                                    else
                    481:                                        order( p2, INTEMP );
                    482:                                }
                    483:                                /* set su to zero here */
                    484:                                p2->in.su = zed;
                    485:                            } /* for */
                    486:                        } else {
                    487:                            /*
                    488:                             * do it in software
                    489:                             */
                    490:                            if (p->in.type == FLOAT){
                    491:                                /* assume rall's set up already */
                    492:                                for( i=0; i<2; i++ ){
                    493:                                    if (SUGT( l->in.su, r->in.su )){
                    494:                                        p2 = l; q = r;
                    495:                                    }else if (SUTEST( r->in.su )){
                    496:                                        p2 = r; q = l;
                    497:                                    }else break;
                    498:                                    SAFETY( q, D0|MUSTDO, p2 );
                    499:                                    failsafe = 1;
                    500:                                    order( p2, INTAREG|INTBREG );
                    501:                                    p2->in.su = zed;
                    502:                                }
                    503:                                /* are no-cost, but may be wrong */
                    504:                                if (!istnode(l) || l->tn.rval != D0)
                    505:                                    order( l, INTAREG );
                    506:                            } else {
                    507:                                /* this case is the least symmetric */
                    508:                                /* basically, must rewrite lhs as d0/d1 */
                    509:                                /* but if rhs is hard, do it first */
                    510:                                if (!istnode(l) || l->tn.rval != D0){
                    511:                                    if (SUTEST( sur )){
                    512:                                        if (r->in.op == UNARY MUL 
                    513:                                        && ( !SUTEST(sul) || rewrite_b_rall( r->in.left, 0)) ){
                    514:                                                failsafe = 1;
                    515:                                                offstar( r->in.left );
                    516:                                        } else {
                    517:                                            order( r, INTEMP );
                    518:                                        }
                    519:                                    }
                    520:                                    failsafe = 1;
                    521:                                    order( l, INTAREG );
                    522:                                }
                    523:                            }
                    524:                            p->in.op = ASG p->in.op ; /* gag */
                    525:                        }
                    526:                        /*----------------------------*/
                    527: #ifdef FLOATMATH
                    528:                        if (!FLOATMATH)
                    529: #endif
                    530:                            p->in.type = DOUBLE;
                    531:                        return 1; /* order(): try again */
                    532:                } else if (ISPTR(p->in.type)){
                    533:                    /*
                    534:                     * cute hack: we can add a short into an address register
                    535:                     * without extending it first.
                    536:                     */
                    537:                    if ( isconv( l, SHORT, -1) && p->in.op==PLUS ){
                    538:                        /* un-canonical form -- flip it */
                    539:                        p->in.left = r;
                    540:                        p->in.right = r =l;
                    541:                        l = p->in.left;
                    542:                    }
                    543:                    if ( isconv( r, SHORT, -1 ) ){
                    544:                        /*
                    545:                         * if this is being evaluated into an address 
                    546:                         * register or for argument, delete the conversion
                    547:                         */
                    548:                        if ( (cook==FORARG || (cook&(INBREG|INTBREG)
                    549:                                && !(cook&~(INBREG|INTBREG))))
                    550:                        && l->tn.op==REG
                    551:                        && tshape( r->in.left, SAREG|STAREG|SBREG|STBREG|SNAME|SOREG|STARREG) ){
                    552:                            if (cook==FORARG && r->in.left->tn.op != REG){
                    553:                                order( r->in.left, INAREG|INTAREG|INBREG|INTBREG );
                    554:                            }
                    555:                            /* lhs should be in an address register,
                    556:                               and should be writeable if SCONV operand
                    557:                               is not a register */
                    558:                            if (!isbreg(l->tn.rval)
                    559:                              || !istreg(l->tn.rval) && r->in.left->in.op != REG) {
                    560:                                order( l, INBREG|INTBREG );
                    561:                            }
                    562:                            p->in.right = r->in.left;
                    563:                            r->in.op = FREE;
                    564:                            return 1;
                    565:                        } else if (p->in.op == PLUS) {
                    566:                            /* otherwise, we were better off the other way */
                    567:                            /* flip back */
                    568:                            p->in.left = r;
                    569:                            p->in.right = r =l;
                    570:                            l = p->in.left;
                    571:                        }
                    572:                    }
                    573:                }
                    574:                break;
                    575:            case MUL:
                    576:            case DIV:
                    577:            case MOD:
                    578:                if( p->in.type == FLOAT || p->in.type == DOUBLE ){
                    579:                        goto float_ops;
                    580:                }
                    581:                if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type))
                    582: 
                    583:                        break;
                    584:                if(use68020) 
                    585:                        break;
                    586: d0_d1:
                    587:                /* copied from Setasop */
                    588:                sul = l->in.su;
                    589:                sur = r->in.su;
                    590:                /* use q to designate the more expensive side, p2 the cheaper */
                    591:                if (!SUGT(sur, sul)){
                    592:                        q = l; p2 = r; pcost = sur;
                    593:                } else {
                    594:                        q = r; p2 = l; pcost = sul;
                    595:                }
                    596:                if( SUTEST(sul) && SUTEST(sur) ){
                    597:                    SAFETY( p2, q->in.rall, q );
                    598:                }
                    599:                        
                    600:                /* do code emission, most expensive side first */
                    601:                if (!istnode( q ) ){
                    602:                  order( q, INAREG|INTAREG);
                    603:                }
                    604:                if ( SUTEST( pcost ) && !istnode( p2 )){
                    605:                  order( p2 ,INAREG|INTAREG);
                    606:                }
                    607:                if ( !istnode( l ) || l->tn.rval != D0 ){
                    608:                    l->tn.rall = MUSTDO | D0;
                    609:                    order( l, INTAREG);
                    610:                }
                    611:                if (logop(p->in.op)){
                    612:                    if ( !istnode( r )||r->tn.rval != D1 ){
                    613:                        r->tn.rall = MUSTDO | D1;
                    614:                        order( r, INTAREG);
                    615:                    }
                    616:                } else {
                    617:                    if ( SUTEST( sur ) && (!istnode( r )||r->tn.rval != D1)){
                    618:                        r->tn.rall = MUSTDO | D1;
                    619:                        order( r, INTAREG);
                    620:                    }
                    621:                    p->in.op = ASG p->in.op;
                    622:                }
                    623:                return 1; /* go try 'gain */
                    624:            case CHK:
                    625:                /*
                    626:                 * the rhs of a CHK operator is an ordered pair
                    627:                 * of integers.  We load the lhs first, regardless
                    628:                 * of what the bounds cost, since both the bounds
                    629:                 * and the lhs must be in hand simultaneously.
                    630:                 */
                    631:                if (!istnode(l) || !isareg(l->tn.lval)) {
                    632:                    SAFETY(r, MUSTDO|D0, l);
                    633:                    order(l, INTAREG|INAREG);
                    634:                    return(1);
                    635:                }
                    636:                return(0);
                    637:        } /* switch */
                    638: 
                    639:        if( !SUTEST( r->in.su ) ){
                    640:                /* rhs is addressable */
                    641:                if( logop( p->in.op ) ){
                    642:                        if ( l->in.op==UNARY MUL 
                    643:                        && l->in.type!=FLOAT && shumul(l->in.left)!=STARREG ) {
                    644:                            offstar( l->in.left );
                    645:                        } else  if ( !(l->in.op==REG && isareg(l->tn.rval))) {
                    646:                            /* lhs is not in a data register */
                    647:                            switch (l->in.type) {
                    648:                            case FLOAT:
                    649:                            case DOUBLE:
                    650:                                /* lhs must be in d0/d1 */
                    651:                                if (r->in.op == REG && r->tn.rval == D0) {
                    652:                                    goto reverse;
                    653:                                }
                    654:                                break;
                    655:                            case CHAR:
                    656:                            case UCHAR:
                    657:                                /* bytes cannot be in address registers */
                    658:                                if (l->in.op == REG && isbreg(l->tn.rval)) {
                    659:                                    break;
                    660:                                }
                    661:                                /* fall through */
                    662:                            default:
                    663:                            reverse:
                    664:                                if ( r->in.op == REG && isareg(r->tn.rval)
                    665:                                  && !SUTEST(l->in.su) ) {
                    666:                                    /*
                    667:                                     * rhs is in a data register, lhs
                    668:                                     * isn't, and doesn't have to be
                    669:                                     */
                    670:                                    p->in.left = r;
                    671:                                    p->in.right = l;
                    672:                                    p->in.op = revrel[p->in.op - EQ];
                    673:                                    return(1);
                    674:                                }
                    675:                            }
                    676:                            order( l, cookie );
                    677:                        } else {
                    678:                            /*
                    679:                             * if here, must be a logical operator for 0-1 value
                    680:                             * and we don't have 2 registers, as we would prefer
                    681:                             */
                    682:                            int m;
                    683:                            cbranch( p, -1, m=getlab() );
                    684:                            p->in.op = CCODES;
                    685:                            p->bn.label = m;
                    686:                            order( p, INTAREG );
                    687:                        } 
                    688:                        return( 1 );
                    689:                }
                    690:                if ( !istnode( l ) ){
                    691:                    if (commuteop(p->in.op) && istnode(r)) {
                    692:                        /* commutative op - put temp node on the left */
                    693:                        p->in.right = l;
                    694:                        p->in.left = r;
                    695:                    } else {
                    696:                        order( l, cookie&(INTAREG|INTBREG) );
                    697:                        return( 1 );
                    698:                    }
                    699:                }
                    700:                if ( divmulop(p->in.op) && r->in.op == REG
                    701:                  && isbreg(r->tn.rval)) {
                    702:                    order( r, INAREG|INTAREG );
                    703:                    return( 1 );
                    704:                }
                    705:                /* rewrite */
                    706:                return( 0 );
                    707:        }
                    708:        /* now, rhs is complicated */
                    709:        /* do the harder side first */
                    710:        /* be careful of D0, D1 usage */
                    711: 
                    712:        if (SUGT(l->in.su, r->in.su)) {
                    713:                /* lhs first; put into register */
                    714:                SAFETY(r, MUSTDO|D0, l);
                    715:                order(l, cookie&(INTAREG|INTBREG));
                    716:                return( 1 );
                    717:        }
                    718:        /* try to make rhs addressable */
                    719:        if(r->in.op == UNARY MUL) {
                    720:                failsafe = find_mustdo( l, D0|MUSTDO) ;
                    721:                if (l->in.su.d >= nfree(STAREG)) {
                    722:                        /* lhs needs all available d-registers;
                    723:                           do not use double indexing */
                    724:                        failsafe |= 1;
                    725:                }
                    726:                offstar( r->in.left );
                    727:                return(1);
                    728:        }
                    729:        if (SUGT(r->in.su , l->in.su)){
                    730:                /* rhs first; put into register */
                    731:                SAFETY( l, MUSTDO|D0, r);
                    732:                /* anything goes on rhs */
                    733:                order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); 
                    734:                return( 1 );
                    735:        }
                    736:        if (!istnode(l)) {
                    737:                SAFETY(r, MUSTDO|D0, l);
                    738:                order(l, cookie&(INTAREG|INTBREG));
                    739:                return( 1 );
                    740:        }
                    741:        if (!istnode(r)) {
                    742:                SAFETY(l, MUSTDO|D0, r);
                    743:                order(r, INTAREG|INAREG|INTBREG|INBREG|INTEMP);
                    744:                return( 1 );
                    745:        }
                    746:        /* rewrite */
                    747:        return( 0 );
                    748: }
                    749: 
                    750: setstr( p, cook ) register NODE *p; 
                    751: { 
                    752:        /* structure assignment */
                    753:        if (p->in.right->in.op != REG){
                    754:                order( p->in.right, INTBREG );
                    755:                return(1);
                    756:        }
                    757:        p = p->in.left;
                    758:        if ( p->in.op != NAME && p->in.op != OREG ){
                    759:                if ( p->in.op != UNARY MUL ) cerror( "bad setstr");
                    760:                order( p->in.left, INTBREG );
                    761:                return( 1 );
                    762:        }
                    763:        if( p->in.op == OREG && !R2TEST(p->tn.rval) && istreg(p->tn.rval)
                    764:            && p->tn.lval == 0){
                    765:                /* cheat -- rewrite this as a REG */
                    766:                p->in.op = REG;
                    767:                return (1);
                    768:        }
                    769: #ifdef FORT
                    770:        /* Pascal does struct assignment of things that ain't structs!! */
                    771:        if (ISARY(p->in.type)){
                    772:            p->in.type = STRTY;
                    773:            return(1);
                    774:        }
                    775: #endif
                    776:        return( 0 );
                    777: }
                    778: 
                    779: setasg( p , cookie ) 
                    780:        register NODE *p; 
                    781: {
                    782:        /* setup for assignment operator */
                    783:        register NODE *r, *l;
                    784:        int failsave = failsafe;
                    785: 
                    786:        r = p->in.right;
                    787:        l = p->in.left;
                    788: 
                    789:        if ( !SUGT( r->in.su , l->in.su )) goto do_lhs;
                    790: /*     if ((p->in.type == DOUBLE || p->in.type == FLOAT) 
                    791: /*     && iscnode(p->in.right)){
                    792: /*         order( p->in.right, INAREG|SOREG|SNAME|SCON );
                    793: /*         return 1;
                    794: /*     }
                    795: */
                    796:        if( SUTEST( r->in.su ) && r->in.op != REG ){
                    797:            failsafe |=  SUTEST( l->in.su ); /* conservative guess */
                    798:            if( r->in.op == UNARY MUL ){
                    799:                offstar( r->in.left );
                    800:            }else{
                    801:                if (p->in.type == DOUBLE && r->in.type == FLOAT) 
                    802:                    p->in.right = r = double_conv( r );
                    803:                if (!use68020 || !use68881) {
                    804:                    /*
                    805:                     * more goddamn complications from register parameters:
                    806:                     * if the lhs needs D0 for a multiply, for instance,
                    807:                     * then we must be careful not to
                    808:                     * evaluate the rhs into D0. 
                    809:                     */
                    810:                    SAFETY( l, MUSTDO|D0, r );
                    811:                }
                    812:                order( r, INAREG|INBREG|INCREG|SOREG|SNAME|SCON );
                    813:            }
                    814:            failsafe = failsave;
                    815:            return(1);
                    816:        }
                    817: do_lhs:
                    818:        if( l->in.op == UNARY MUL )
                    819:                if (!tshape( l, STARREG|STARNM ) 
                    820:                    || p->in.type == DOUBLE){
                    821:                    /* sorry, we're too feeble to *P++ with double pointers */
                    822:                        failsafe |=  SUTEST( r->in.su ); /* conservative guess */
                    823:                        failsafe |=  r->tn.su.d >= fregs.d;
                    824:                        offstar( l->in.left );
                    825:                        failsafe = failsave;
                    826:                        return(1);
                    827:                }
                    828:        if (l->in.op==FLD && l->in.left->in.op==UNARY MUL ){
                    829:                failsafe |=  SUTEST( r->in.su ); /* conservative guess */
                    830:                offstar( l->in.left->in.left );
                    831:                failsafe = failsave;
                    832:                return(1);
                    833:        }
                    834:        /* if things are really strange, get rhs into a register */
                    835:        if( r->in.op != REG ) {
                    836:                order( r, INAREG|INBREG|INCREG );
                    837:                failsafe = failsave;
                    838:                return( 1 );
                    839:        }
                    840:        /* for fields, rhs must be in a data register */
                    841:        if( l->in.op == FLD && r->in.op == REG && isbreg(r->tn.rval) ) {
                    842:                order( r, INAREG|INTAREG );
                    843:                failsafe = failsave;
                    844:                return( 1 );
                    845:        }
                    846:        return(0);
                    847: }
                    848: 
                    849: find_mustdo( p, regname ) register NODE *p;
                    850: {
                    851:     /* if there are any ops here that require use of reg regname,  return
                    852:      * 1 else return 0;
                    853:      */
                    854: redo:
                    855:     if (p->in.rall == regname) return 1;
                    856:     if (p->in.type == DOUBLE && p->in.rall == regname-1) return 1;
                    857:     switch( optype(p->in.op) ){
                    858:     case LTYPE: return 0;
                    859:     case BITYPE:
                    860:                if (find_mustdo(p->in.right, regname)) return 1;
                    861:                /* else fall through */
                    862:     }
                    863:     p = p->in.left;
                    864:     goto redo; /* go 'round again */
                    865: }
                    866: 
                    867: int
                    868: rewrite_rall( n, trybreg ) NODE *n;
                    869: {
                    870:        register int i, reg;
                    871:        register TWORD t = n->in.type;
                    872: 
                    873:        /* find a temporary home for n */
                    874:        reg = -1;
                    875:        for( i = D2; i <= maxa; i++){
                    876:            if( istreg(i) && busy[i] == 0){
                    877:                if (t==DOUBLE && ((i&1) || !( istreg(i+1) && busy[i+1] == 0)))
                    878:                    continue; /* too bad */
                    879:                reg = i; break;
                    880:            }
                    881:        }
                    882:        if (reg < 0 && trybreg && t!=CHAR && t!= UCHAR) {
                    883:            /* we are DESPARATE! */
                    884:            for( i = minb; i <= maxb; i++){
                    885:                if( istreg(i) && busy[i] == 0){
                    886:                    if (t==DOUBLE && ((i&1) || !( istreg(i+1) && busy[i+1] == 0)))
                    887:                        continue; /* too bad */
                    888:                    reg = i; break;
                    889:                }
                    890:            }
                    891:        }
                    892:        if ( reg < 0 ) return 0;
                    893:        n->in.rall = (MUSTDO | reg);
                    894:        return 1;
                    895: }
                    896: 
                    897: int
                    898: rewrite_b_rall( n, a0ok )
                    899:     NODE *n;
                    900: {
                    901:        register int i, reg;
                    902: 
                    903:        /* find a temporary home for n in the b-registers */
                    904:        /* get out of the hair of a0/a1     */
                    905:        reg = -1;
                    906:        for( i = minb+2; i <= maxb; i++){
                    907:            if( istreg(i) && busy[i] == 0){
                    908:                reg = i; break;
                    909:            }
                    910:        }
                    911:        if (reg<0 && a0ok && busy[minb]==0)
                    912:            reg = minb;
                    913:        if ( reg < 0) return 0; /*failure*/
                    914:        n->in.rall = MUSTDO | reg;
                    915:        /* if this is a prospective oreg -- keep going */
                    916:        if (n->in.op == PLUS || n->in.op == MINUS){
                    917:            n = n->in.left;
                    918:            if (n->in.op != REG || !isareg( n->tn.rval ) )
                    919:                n->in.rall = MUSTDO | reg;
                    920:        }
                    921:        return 1;
                    922: }
                    923: 
                    924: NODE *
                    925: hard_rew( p ) register NODE *p;
                    926: {
                    927:        register NODE *lp, *p2;
                    928:        register int i, reg;
                    929:        /* do rewriting for non-reg lhs of hard op='s */
                    930: 
                    931:        lp = p->in.left;
                    932:        switch(lp->in.op){
                    933:            default:
                    934:                return p;
                    935:            case REG:
                    936:                if(istreg(lp->tn.rval)) return p;
                    937:            case NAME:
                    938:            case OREG:
                    939:            case UNARY MUL:
                    940:            case FLD:
                    941:                break;
                    942:            }
                    943: 
                    944:        if (odebug){
                    945:            printf("hard_rew( %o ):\n", p);
                    946:            fwalk( p, eprint, 0);
                    947:        }
                    948: 
                    949:        if( lp->in.op == UNARY MUL ){
                    950:                NODE *llp = lp->in.left;
                    951:                offstar( llp );
                    952:                if ( llp->in.op == PLUS && llp->in.right->in.op != ICON ) {
                    953:                        /* de-index */
                    954:                        order(llp, INTBREG|INBREG);
                    955:                }
                    956:        }
                    957:        if( lp->in.op == FLD && lp->in.left->in.op == UNARY MUL ){
                    958:                NODE *lllp = lp->in.left->in.left;
                    959:                offstar( lllp );
                    960:                if ( lllp->in.op == PLUS && lllp->in.right->in.op != ICON ) {
                    961:                        /* de-index */
                    962:                        order(lllp, INTBREG|INBREG);
                    963:                }
                    964:        }
                    965:        if( lp->in.op == FLD ) lp = lp->in.left;
                    966: 
                    967:        /* mimic code from reader.c */
                    968:        p2 = tcopy( p );
                    969:        p->in.op = ASSIGN;
                    970:        reclaim( p->in.right, RNULL, 0 );
                    971:        p->in.right = p2;
                    972:        canon(p);
                    973:        rallo( p, p->in.rall );
                    974:        lp = p2->in.left;
                    975:        /* if we are doing a floating op, we'll let the caller finish it off */
                    976:        if(p->in.type == DOUBLE || p->in.type == FLOAT)
                    977:            return p2;
                    978:        /* if we must, rewrite rhs, too */
                    979:        if (SUGT( p2->in.right->in.su , lp->in.su )){
                    980:            SAFETY( lp, p2->in.right->in.rall, p2->in.right );
                    981:            order( p2->in.right, INTAREG|INTBREG );
                    982:        }
                    983:        SAFETY( p2->in.right, lp->in.rall, lp );
                    984:        order( lp, INTBREG|INTAREG );
                    985:        
                    986:        return p->in.right;
                    987: }
                    988: 
                    989: setasop( p, cookie ) register NODE *p; 
                    990: {
                    991:        /* setup for =ops */
                    992:        register SUTYPE sul, sur;
                    993:        register NODE *r, *l;
                    994:        register NODE *q, *p2;
                    995:        SUTYPE pcost;
                    996: 
                    997:        r = p->in.right;
                    998:        l = p->in.left;
                    999:        sul = l->in.su;
                   1000:        sur = r->in.su;
                   1001: 
                   1002:        switch( p->in.op ){
                   1003:          case ASG PLUS:
                   1004:          case ASG MINUS:
                   1005:          case ASG OR:
                   1006:          case ASG ER:
                   1007:          case ASG AND:
                   1008:                if (p->in.type == FLOAT || p->in.type == DOUBLE ) {
                   1009: floatops:
                   1010:                    /*
                   1011:                     * lhs in dreg or AWD, rhs in dreg or AWD.
                   1012:                     */
                   1013: 
                   1014:                    /*
                   1015:                     * if the lhs is not a temp node, then we need to let
                   1016:                     * a op= b ; be rewritten as...
                   1017:                     * a = (a) op= b;
                   1018:                     */
                   1019:                    /* HOWEVER!:
                   1020:                     * if rhs is expensive, we gotta do it first!
                   1021:                     */
                   1022:                    if (r->in.type==FLOAT && p->in.type==DOUBLE){
                   1023:                        r = p->in.right = double_conv(r);
                   1024:                    }
                   1025: 
                   1026:                    if (use68881) {
                   1027:                        /*
                   1028:                         * if lhs is already a coprocessor reg, all
                   1029:                         * we have to do is clean up the rhs a little.
                   1030:                         */
                   1031:                        int rhs = 0;
                   1032:                        if (iscnode(l)) {
                   1033:                            floatsrce(r);
                   1034:                            return(1);
                   1035:                        }
                   1036:                        if ( SUGT(sur, sul) ) {
                   1037:                            /* rhs is hard -- do it first */
                   1038:                            floatsrce(r);
                   1039:                            rhs = 1;
                   1040:                        }
                   1041:                        p = hard_rew(p);
                   1042:                        l = p->in.left;
                   1043:                        r = p->in.right;
                   1044:                        if ( istnode(r) && iscreg(r->tn.rval)
                   1045:                          && (p->in.op == ASG PLUS || p->in.op == ASG MUL) ) {
                   1046:                            /*
                   1047:                             * commute -- we can do this because hard_rew
                   1048:                             * assigns the result of p to the lhs
                   1049:                             */
                   1050:                            p->in.left = r;
                   1051:                            p->in.right = l;
                   1052:                            l = r;
                   1053:                            r = p->in.right;
                   1054:                            rhs = 0;
                   1055:                        } else {
                   1056:                            /*
                   1057:                             * put lhs in a coprocessor reg
                   1058:                             */
                   1059:                            order(l, INCREG|INTCREG);
                   1060:                        }
                   1061:                        /*
                   1062:                         * if rhs hasn't been dealt with yet, do it
                   1063:                         */
                   1064:                        if (!rhs) {
                   1065:                            floatsrce(r);
                   1066:                        }
                   1067:                        return(1);
                   1068:                    } /* use68881 */
                   1069: 
                   1070:                    if (usesky){
                   1071:                        /*
                   1072:                         * check for pivot operation ( x += y * z )
                   1073:                         * only do if one of x,y,z is free
                   1074:                         */
                   1075:                        int pivoting = 0;
                   1076:                        if (p->in.op == ASG PLUS && r->in.op == MUL) {
                   1077:                            if (!SUTEST(sul)) {
                   1078:                                setbin(r, INTAREG|INAREG|INTEMP);
                   1079:                                return(1);
                   1080:                            }
                   1081:                            if (!SUTEST(r->in.left->in.su)
                   1082:                              || !SUTEST(r->in.right->in.su)) {
                   1083:                                pivoting = 1;
                   1084:                            }
                   1085:                        }
                   1086:                        /*
                   1087:                         * on the sky board, "op=" ops can be done
                   1088:                         * with lhs in memory. However, we must stay
                   1089:                         * away from a0/a1.
                   1090:                         */
                   1091:                        if (SUGT(sur,sul)){
                   1092:                            /* must do rhs first */
                   1093:                            if (pivoting) {
                   1094:                                if (SUTEST(r->in.left->in.su)) {
                   1095:                                    r = r->in.left;
                   1096:                                } else {
                   1097:                                    r = r->in.right;
                   1098:                                }
                   1099:                                pivoting = 0;
                   1100:                            }
                   1101:                            if (r->in.op == UNARY MUL
                   1102:                              && rewrite_b_rall(r->in.left, 0)) {
                   1103:                                /* make addressable, avoiding a1 */
                   1104:                                offstar(r->in.left);
                   1105:                            } else if (!find_mustdo(l, MUSTDO|D0)
                   1106:                              || rewrite_rall(r, 0)) {
                   1107:                                order(r, INAREG|INTAREG|INTEMP);
                   1108:                            } else {
                   1109:                                order(r, INTEMP);
                   1110:                            }
                   1111:                            r->in.su = zed;
                   1112:                        }
                   1113:                        /*
                   1114:                         * deal with lhs
                   1115:                         */
                   1116:                        if (SUTEST(sul)) {
                   1117:                            if (l->in.op == UNARY MUL
                   1118:                              && rewrite_b_rall( l->in.left, 0 )) {
                   1119:                                /* make addressable, avoiding a1 */
                   1120:                                offstar( l->in.left );
                   1121:                            } else {
                   1122:                                /* failing that, try rewriting */
                   1123:                                p = hard_rew(p);
                   1124:                                l = p->in.left;
                   1125:                                r = p->in.right;
                   1126:                                if (pivoting) {
                   1127:                                    if (SUTEST(r->in.left->in.su)) {
                   1128:                                        r = r->in.left;
                   1129:                                    } else {
                   1130:                                        r = r->in.right;
                   1131:                                    }
                   1132:                                    pivoting = 0;
                   1133:                                }
                   1134:                                if (!find_mustdo(r, MUSTDO|D0)
                   1135:                                  || rewrite_rall(l, 0)) {
                   1136:                                    order(l, INAREG|INTAREG|INTEMP);
                   1137:                                } else {
                   1138:                                    order(l, INTEMP);
                   1139:                                }
                   1140:                            }
                   1141:                        }
                   1142:                        /*
                   1143:                         * deal with rhs, if necessary
                   1144:                         */
                   1145:                        if (pivoting) {
                   1146:                            if (SUTEST(r->in.left->in.su)) {
                   1147:                                r = r->in.left;
                   1148:                            } else {
                   1149:                                r = r->in.right;
                   1150:                            }
                   1151:                        }
                   1152:                        if (SUTEST(r->in.su)){
                   1153:                            if (r->in.op == UNARY MUL
                   1154:                              && rewrite_b_rall(r->in.left, 0)) {
                   1155:                                /* make addressable, avoiding a1 */
                   1156:                                offstar(r->in.left);
                   1157:                            } else {
                   1158:                                order(r, INAREG|INTAREG|INTEMP);
                   1159:                            }
                   1160:                        }
                   1161:                        return 1;
                   1162:                    } else if ( !istnode(l) ){
                   1163:                        if (SUTEST( sur )){
                   1164:                            if (!SUTEST(sul) && r->in.type == FLOAT){
                   1165:                                r->in.rall = MUSTDO|D1;
                   1166:                                order( r, INAREG );
                   1167:                            } else {
                   1168:                                /* may not want it in a register, 
                   1169:                                in case lhs needs  the register */
                   1170:                                if (rewrite_rall(r, 0)){
                   1171:                                    order( r, INAREG|INTAREG|INBREG|INTBREG|INCREG|INTCREG );
                   1172:                                } else {
                   1173:                                    r->in.rall = NOPREF;
                   1174:                                    order( r, INTEMP );
                   1175:                                }
                   1176:                            }
                   1177:                        }
                   1178:                        /* lhs is either easy or is an address */
                   1179:                        /*
                   1180:                         * if its an address, we must, unhappily,
                   1181:                         * evaluate it AWAY from a0/a1, which will
                   1182:                         * be clobbered by the operation.
                   1183:                         */
                   1184:                        if (l->in.op == UNARY MUL && l->in.left->in.op != REG){
                   1185:                            failsafe = 1; /* keep away from d0/d1!! */
                   1186:                            if ( rewrite_b_rall( l->in.left, 0 )  )
                   1187:                                offstar( l->in.left );
                   1188:                            else 
                   1189:                                order( l->in.left, INTEMP );
                   1190:                        } else 
                   1191:                            l->in.rall = MUSTDO|D0;
                   1192:                        /* p->in.op = NOASG p->in.op; */
                   1193:                        goto rew_lhs;
                   1194:                    }
                   1195:                            
                   1196:                    if (r->in.type == DOUBLE ){
                   1197:                        if ( !tshape( r, SNAME|SOREG|STARNM)){
                   1198:                            r->in.rall = NOPREF;
                   1199:                            order( r, INTEMP );
                   1200:                        }
                   1201:                    } else {
                   1202:                        if( !(istnode(r) && r->tn.rval == D1) ){
                   1203:                            r->in.rall = MUSTDO|D1;
                   1204:                            order( r, INTAREG);
                   1205:                        }
                   1206:                    }
                   1207:                    if ( !(istnode(l) && l->tn.rval == D0) ){
                   1208:                        l->in.rall = MUSTDO|D0;
                   1209:                        order( l, INTAREG);
                   1210:                    }
                   1211: 
                   1212:                    return 1;
                   1213:                } else if (ISPTR(p->in.type)
                   1214:                  && (p->in.op==ASG PLUS || p->in.op==ASG MINUS)
                   1215:                  && isconv(r, SHORT, -1)
                   1216:                  && l->in.op== REG && isbreg(l->tn.rval)) {
                   1217:                    p->in.right = r->in.left;
                   1218:                    r->in.op = FREE;
                   1219:                    return 1;
                   1220:                } else {
                   1221:                    if ((p->in.right->in.op != REG || 
                   1222:                    isbreg(p->in.right->tn.rval)) && !SUTEST( sul )) {
                   1223:                        order(p->in.right,INAREG|INTAREG);
                   1224:                        return(1);
                   1225:                    } else break;
                   1226:                }
                   1227: 
                   1228:          case ASG MUL:
                   1229:          case ASG DIV:
                   1230:          case ASG MOD:
                   1231:                /*
                   1232:                 * This is difficult: These ops require the lhs in d0 and the
                   1233:                 * rhs in d1. This means that whichever side gets evaluated
                   1234:                 * first will monopolize one of these strategic registers for
                   1235:                 * the whole time the other side is being evaluated. This is
                   1236:                 * not acceptable if the less-expensive side ALSO requires
                   1237:                 * evaluation of one of these constrained ops. So we must be
                   1238:                 * very careful here. First, we assume that there are, indeed,
                   1239:                 * enough registers for us to play with, otherwise off-storing
                   1240:                 * should already have been taken care of by the wonders of 
                   1241:                 * portable code generation. So what we'll do is find a free
                   1242:                 * register NOT in the set {d0,d1}, and force evaluation of the
                   1243:                 * more expensive side into that register, then rewrite the 
                   1244:                 * requirements for that side. Hold on.
                   1245:                 */
                   1246: 
                   1247:                if (p->in.type == FLOAT || p->in.type == DOUBLE)
                   1248:                    goto floatops;
                   1249:                if( p->in.type != INT && p->in.type != UNSIGNED && !ISPTR(p->in.type))
                   1250:                        break;
                   1251:                if(use68020)
                   1252:                        break;
                   1253: 
                   1254:                /* we can only do these into d0 */
                   1255: d0_d1:
                   1256:                /* if things already look optimum, we must already have been this way once */
                   1257:                if (istnode(p->in.left) && !SUTEST( p->in.right->tn.su )){
                   1258:                    order( p->in.right, INTAREG );
                   1259:                    return 1;
                   1260:                }
                   1261:                p = hard_rew( p );
                   1262:                sul = p->in.left->in.su;
                   1263:                /* use q to designate the more expensive side, p2 the cheaper */
                   1264:                if ( !SUGT( sur, sul )){ q = p->in.left;  p2 = p->in.right; pcost = sur; }
                   1265:                        else { q = p->in.right; p2 = p->in.left;  pcost = sul; }
                   1266:                if( SUTEST( sul ) && SUTEST( sur )){
                   1267:                    SAFETY( p2, q->in.rall, q );
                   1268:                }
                   1269:                        
                   1270:                /* do code emission, most expensive side first */
                   1271:                if (!istnode( q ) ){
                   1272:                  order( q, INAREG|INTAREG);
                   1273:                }
                   1274:                if ( SUTEST( pcost ) && !istnode( p2 )){
                   1275:                  order( p2 ,INAREG|INTAREG);
                   1276:                }
                   1277:                if ( !istnode( p->in.left ) || p->in.left->tn.rval != D0 ){
                   1278:                    p->in.left->tn.rall = MUSTDO | D0;
                   1279:                    order( p->in.left, INTAREG );
                   1280:                }
                   1281:                if ( SUTEST(sur) &&(!istnode(p->in.right)||p->in.right->tn.rval!=D1)){
                   1282:                    p->in.right->tn.rall = MUSTDO | D0;
                   1283:                    order( p->in.right, INTAREG );
                   1284:                }
                   1285: 
                   1286:                return(1);
                   1287: 
                   1288:          case ASG LS:
                   1289:          case ASG RS:
                   1290:                if (l->in.op != REG){
                   1291:                        /* must rewrite as lhs = ((lhs) op= rhs) */
                   1292:                        /* if we must, rewrite rhs, too */
                   1293:                        if (SUGT( sur , sul)){
                   1294:                            SAFETY( l, MUSTDO|D0, r );
                   1295:                            order( r, INAREG|INBREG );
                   1296:                        }
                   1297:                        /* lhs is either easy or is an address */
                   1298:                        if (SUTEST( sul )){
                   1299:                            if (l->in.op == UNARY MUL)
                   1300:                                offstar( l->in.left );
                   1301:                            else if (l->in.op == FLD &&
                   1302:                                l->in.left->in.op == UNARY MUL)
                   1303:                                offstar( l->in.left->in.left);
                   1304:                        }
                   1305:                        goto rew_lhs;
                   1306:                }
                   1307:                if (r->in.op == REG && isareg(r->tn.rval)
                   1308:                  || (r->in.op==ICON && r->tn.lval>=1 && r->tn.lval<=8))
                   1309:                    break;
                   1310:                order(r,INAREG|INTAREG);
                   1311:                return(1);
                   1312: 
                   1313:        }
                   1314: 
                   1315:        /*
                   1316:         * What we have here is an asop which could POSSIBLY be done to memory
                   1317:         * if we desire it. Luckily we have the cookie as a parameter to make
                   1318:         * this decision. If we do it to memory, then we just want to evaluate
                   1319:         * the lhs to an address. If we do it for a value, we have to evaluate
                   1320:         * the lhs for a value, then store afterwards.
                   1321:         */
                   1322:        if (SUTEST( sul ) && !SUGT( sur,sul )){
                   1323:            /* since an lhs can only be an address ... */
                   1324:            if (l->in.op == UNARY MUL){
                   1325:                failsafe |= SUTEST( sur ); /* conservative guess */
                   1326:                offstar( l->in.left );
                   1327:            } else if (l->in.op == FLD){
                   1328:                if (l->in.left->in.op == UNARY MUL)
                   1329:                    offstar( l->in.left->in.left);
                   1330:                return 0; /* rewrite as something sane */
                   1331:            }
                   1332:            if (cookie&FOREFF){
                   1333:                /* for effect only! */
                   1334:                return 1;
                   1335:            }
                   1336:            /* otherwise, rewrite as (lhs1) = ((lhs2) op= rhs) */
                   1337: rew_lhs:
                   1338:            ncopy( p2=talloc(), p);
                   1339:            p->in.op    = ASSIGN;
                   1340:            p->in.right = p2;
                   1341:            l = p->in.left  = tcopy( p2->in.left );
                   1342:            SAFETY( p2->in.right, MUSTDO|D0, p2->in.left );
                   1343:            if (l->in.op == UNARY MUL && shumul(l->in.left) == STARREG) {
                   1344:                /*
                   1345:                 * Beware side effects lurking in lhs.  We now
                   1346:                 * have two copies -- side effects of one copy must
                   1347:                 * be eliminated.  Note that (lhs2) will be evaluated first.
                   1348:                 */
                   1349:                if (l->in.left->in.op == ASG MINUS) {
                   1350:                    /* predecrement -- keep side effect in (lhs2),
                   1351:                       delete side effect in (lhs1) */
                   1352:                    q = l->in.left;
                   1353:                } else {
                   1354:                    /* postincrement -- keep side effect in (lhs1),
                   1355:                       delete side effect in (lhs2) */
                   1356:                    q = p2->in.left->in.left;
                   1357:                }
                   1358:                l = q->in.left;  /* = REG */
                   1359:                r = q->in.right; /* = ICON */
                   1360:                *q = *l;
                   1361:                l->in.op = FREE;
                   1362:                r->in.op = FREE;
                   1363:            }
                   1364:            order( p2->in.left, INAREG|INBREG );
                   1365:            return 1;
                   1366:        }
                   1367:        if( SUTEST( sur )){
                   1368:            /* evaluate rhs into a register, then go try again */
                   1369:            SAFETY( l, MUSTDO|D0, r );
                   1370:            order( r, INAREG|INBREG );
                   1371:            return 1;
                   1372:        }
                   1373:        if (divmulop(p->in.op) && r->in.op == REG && isbreg(r->tn.rval)) {
                   1374:            order(r, INAREG|INTAREG);
                   1375:            return(1);
                   1376:        }
                   1377:        if (l->in.op == UNARY MUL && shumul(l->in.left) == STARREG) {
                   1378:            goto rew_lhs;
                   1379:        }
                   1380:        return 0;
                   1381: }
                   1382: 
                   1383: /*
                   1384:  * returns number of free registers of a given type.  This wouldn't
                   1385:  * be necessary if the SU-numbers were strictly followed; however,
                   1386:  * double indexing ties up more registers than sucomp assumes, and
                   1387:  * should not be attempted unless a spare register exists.
                   1388:  */
                   1389: int
                   1390: nfree(cookie)
                   1391: {
                   1392:     register r;
                   1393:     register n;
                   1394:     n = 0;
                   1395:     for (r = 0; r < REGSZ; r++) {
                   1396:        if ((rstatus[r]&cookie) && !busy[r])
                   1397:            n++;
                   1398:     }
                   1399:     return n;
                   1400: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.