Annotation of researchv9/cmd/sun/pcc/su.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)su.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: # include "cpass2.h"
        !            10: 
        !            11: /*
        !            12:  * from order.c
        !            13:  */
        !            14: 
        !            15: 
        !            16: extern int mina, maxa, minb, maxb; /* imported from allo.c */
        !            17: int failsafe;
        !            18: extern toff, maxtoff;
        !            19: 
        !            20: # define iscnode(p) (p->in.op==REG && iscreg(p->tn.rval))
        !            21: 
        !            22: # define max(x,y) ((x)<(y)?(y):(x))
        !            23: # define min(x,y) ((x)<(y)?(x):(y))
        !            24: 
        !            25: 
        !            26: sucomp( p ) register NODE *p; 
        !            27: {
        !            28: 
        !            29:        /* set the su field in the node to the sethi-ullman
        !            30:           number, or local equivalent */
        !            31: 
        !            32:        register o, t;
        !            33:        register nr;
        !            34:        register u, tt;
        !            35:        register NODE *r, *l;
        !            36:        SUTYPE sul, sur;
        !            37:        SUTYPE tempsu;
        !            38:        static SUTYPE zed = { 0,0,0,0 };
        !            39: 
        !            40:        p->in.su = zed;
        !            41:        switch(t = optype( o=p->in.op)) {
        !            42:        case LTYPE:
        !            43:                return;
        !            44:        case UTYPE:
        !            45:                sucomp(p->in.left);
        !            46:                break;
        !            47:        case BITYPE:
        !            48:                sucomp(p->in.left);
        !            49:                sucomp(p->in.right);
        !            50:                r = p->in.right;
        !            51:                sur = r->in.su ;
        !            52:                break;
        !            53:        }
        !            54:        l = p->in.left;
        !            55:        sul = l->in.su;
        !            56:        nr = szty( tt = p->in.type );
        !            57: 
        !            58:        switch ( o ){
        !            59:        case ASG ER:
        !            60:                /* exclusive-or -- not generally computable to-memory */
        !            61:                if ( r->tn.op != ICON ) goto reg_reg_asg;
        !            62:                /* fall through */
        !            63: 
        !            64:        case ASG PLUS:
        !            65:        case ASG MINUS:
        !            66:        case ASG AND:
        !            67:        case ASG OR:
        !            68:                /* these may be done directly at memory -- looks like = */
        !            69:                if ( tt == FLOAT || tt == DOUBLE ) {
        !            70:                        goto float_asop;
        !            71:                }
        !            72:                /* fall through */
        !            73:        
        !            74:        case ASSIGN:
        !            75:                /* usually, compute rhs into a register, compute lhs, store */
        !            76:                /* could do it backwards if lhs is hairier                  */
        !            77:                if (SUSUM( sur ) > SUSUM( sul )){
        !            78: /*                 p->in.su = max( sur, sul+nr); */
        !            79:                    sur.d = max( sur.d, sul.d+nr );
        !            80:                    sur.a = max( sur.a, sul.a );
        !            81:                }else{
        !            82: /*                 p->in.su = max( sur+1, sul); */
        !            83:                    if(l->in.op == FLD) {
        !            84:                        sur.d = max(max(sur.d, sul.d),2);
        !            85:                    } else {
        !            86:                        sur.d = max(sur.d, sul.d);
        !            87:                    }
        !            88:                    sur.a = max( sur.a+1, sul.a);
        !            89:                }
        !            90:                sur.f = max( sur.f, sul.f);
        !            91:                p->in.su = sur;
        !            92:                return;
        !            93: 
        !            94:        case STASG:
        !            95:                /* compute two addresses, then use up to three more registrers */
        !            96: /*             p->in.su = max( 3, 1+max(sul,sur)); */
        !            97:                sur.d = 1+max( sur.d, sul.d );
        !            98:                t = max( sur.a, sul.a );
        !            99:                sur.a = max( 2, t );
        !           100:                p->in.su = sur;
        !           101:                return;
        !           102: 
        !           103:        case UNARY MUL:
        !           104:                if (shumul(p->in.left))
        !           105:                        return;
        !           106:                /* most other unary ops handled in default case */
        !           107:                sul.a = max( sul.a, 1); /* 1 address register to * through */
        !           108:                p->in.su = sul;
        !           109:                return;
        !           110: 
        !           111:        case CALL:
        !           112:        case UNARY CALL:
        !           113:        case STCALL:
        !           114:        case UNARY STCALL:
        !           115:                p->in.su = fregs;
        !           116:                return;
        !           117: 
        !           118:        case ASG RS:
        !           119:        case ASG LS:
        !           120:                /* if the rhs is not a small contant, this is a reg-reg op */
        !           121:                if ( r->tn.op == ICON && r->tn.lval >0 && r->tn.lval <= 8 ){
        !           122:                        /* looks like a unary op */
        !           123:                        sul.d += nr;
        !           124:                        p->in.su = sul;
        !           125:                        return;
        !           126:                }
        !           127:                /* fall through */
        !           128:        case ASG MUL:
        !           129:        case ASG DIV:
        !           130:        case ASG MOD:
        !           131:        /* compute rhs, compute lhs (or vice versa), get lhs value, op */
        !           132:                if ( tt == FLOAT || tt == DOUBLE ) {
        !           133:                        goto float_asop;
        !           134:                }
        !           135: reg_reg_asg:
        !           136:                t = SUSUM(sul)?1:0; /* number regs needed to store lhs address */
        !           137:                /* want at least 2 regs + lhs address */
        !           138:                /* if lhs is complicated, will always compute it into a reg FIRST */
        !           139:                /* p->in.su = max( t+2*nr, min(t+sur, nr+sul)); */
        !           140: /*             if (sul)
        !           141: /*                 u = max( sul, t+sur );
        !           142: /*             else
        !           143: /*                 u = sur;
        !           144: /*             p->in.su = max( u, t+2*nr);
        !           145: */
        !           146:                if (SUSUM(sul)){
        !           147:                    sur.d = max( sur.d, sul.d );
        !           148:                    sur.a = max( sur.a+t, sul.a );
        !           149:                } 
        !           150:                sur.d = max( sur.d , 2*nr );
        !           151:                sur.a = max( sur.a , t );
        !           152:                sur.f = 0;
        !           153:                p->in.su = sur;
        !           154:                return;
        !           155: 
        !           156:        case PLUS:
        !           157:        case AND:
        !           158:        case OR:
        !           159:        case ER:
        !           160:                /* commutable memory-register ops */
        !           161:                if ( tt == FLOAT || tt == DOUBLE ) {
        !           162:                        goto float_asop;
        !           163:                }
        !           164:                if (l->in.op != REG && SUSUM(sul) < SUSUM(sur)){
        !           165:                        p->in.right = l;
        !           166:                        p->in.left = r;
        !           167:                        l = r;
        !           168:                        r = p->in.right;
        !           169:                        sul = sur;
        !           170:                        sur = r->in.su ;
        !           171:                }
        !           172:                goto reg_mem_op;
        !           173: 
        !           174:        case EQ:
        !           175:        case NE:
        !           176:        case LE:
        !           177:        case GE:
        !           178:        case GT:
        !           179:        case LT:
        !           180:        case UGT:
        !           181:        case UGE:
        !           182:        case ULT:
        !           183:        case ULE:
        !           184:                    tt = l->in.type;
        !           185:                    nr = szty( tt );
        !           186:                    /* fall through */
        !           187:        case MINUS:
        !           188:        case INCR:
        !           189:        case DECR:
        !           190:                if ( tt == FLOAT || tt == DOUBLE ) {
        !           191: float_asop:
        !           192:                        if (use68881) {
        !           193:                            nr = 1;
        !           194:                            if (!SUTEST(sur)
        !           195:                              && (r->in.op != REG || !isbreg(r->tn.rval))){
        !           196:                                /* rhs is cheap */
        !           197:                                sul.f = max( sul.f, nr );
        !           198:                                p->in.su = sul;
        !           199:                                return;
        !           200:                            }
        !           201:                            /* compute rhs, lhs (or vice versa) do op */
        !           202:                            if (SUGT(sur, sul)){
        !           203:                                /*
        !           204:                                 * value of rhs, value of lhs,
        !           205:                                 * reg-reg op
        !           206:                                 */
        !           207: /*                             p->in.su = max( sur, sul+nr ); */
        !           208:                                if (commuteop(o) && !SUTEST(sul)
        !           209:                                  && (l->in.op != REG || !isbreg(l->tn.rval))){
        !           210:                                    u = max( sul.f, nr );
        !           211:                                } else {
        !           212:                                    u = nr + max( sul.f, nr );
        !           213:                                }
        !           214:                                sur.d = max( sur.d, sul.d );
        !           215:                                sur.a = max( sur.a, sul.a );
        !           216:                                sur.f = max( sur.f, u );
        !           217:                            } else {
        !           218: /*                             p->in.su = max( sul, sur+1 ); */
        !           219:                                if (r->in.op == UNARY MUL){
        !           220:                                    /*
        !           221:                                     * address of rhs, value of lhs,
        !           222:                                     * op from memory
        !           223:                                     */
        !           224:                                    sur.d = max( sur.d, sul.d   );
        !           225:                                    sur.a = max( sur.a, sul.a+1 );
        !           226:                                    sur.f = max( sul.f, sur.f+1 );
        !           227:                                } else {
        !           228:                                    /*
        !           229:                                     * value of lhs, value of rhs,
        !           230:                                     * reg-reg-op
        !           231:                                     */
        !           232:                                    sur.d = max( sul.d, sur.d );
        !           233:                                    sur.a = max( sul.a, sur.a );
        !           234:                                    sur.f = max( sul.f+1, sur.f+1 );
        !           235:                                }
        !           236:                            }
        !           237:                            p->in.su = sur;
        !           238:                            return;
        !           239:                        }
        !           240:                        /*
        !           241:                         * floating operations are calls.
        !           242:                         * They always take ALL the registers.
        !           243:                         * SIMPLE FIRST APPROXIMATION HERE.
        !           244:                         * evaluate rhs first: if lhs 
        !           245:                         * costs, then may need an extra temp.
        !           246:                         */
        !           247:                        if (SUTEST(sur) && SUTEST(sul) )
        !           248:                            u = max( sur.d, sul.d+nr);
        !           249:                        else
        !           250:                            u = max( sur.d, sul.d );
        !           251:                        tempsu.d = max( u, fregs.d );
        !           252: 
        !           253:                        u = max( sur.a, sul.a );
        !           254:                        tempsu.a = max( u, fregs.a );
        !           255:                        tempsu.f = 0;
        !           256:                        p->in.su = tempsu;
        !           257:                        return;
        !           258:                }
        !           259: reg_mem_op:
        !           260:                /* memory-register ops */
        !           261: 
        !           262:                /*
        !           263:                 * if rhs is direct, then the op is very cheap.
        !           264:                 * But if rhs is an address register, only integer
        !           265:                 * addition and subtraction are cheap.
        !           266:                 */
        !           267:                if (SUSUM(sur) == 0) {
        !           268:                    int cheap = 1;
        !           269:                    if (r->in.op == REG && isbreg(r->tn.rval)) {
        !           270:                        switch(o) {
        !           271:                        case PLUS:
        !           272:                        case MINUS:
        !           273:                        case ASG PLUS:
        !           274:                        case ASG MINUS:
        !           275:                            if (tt == CHAR || tt == UCHAR) {
        !           276:                                /* can't use addr regs in byte adds and subs */
        !           277:                                cheap = 0;
        !           278:                            }
        !           279:                            break;
        !           280:                        default:
        !           281:                            /* can't use addr regs for other ops, period */
        !           282:                            cheap = 0;
        !           283:                            break;
        !           284:                        }
        !           285:                    }
        !           286:                    if (cheap) {
        !           287:                        sul.d = max(sul.d, nr);
        !           288:                        p->in.su = sul;
        !           289:                        return;
        !           290:                    }
        !           291:                }
        !           292:                /* else must compute rhs, lhs (or vice versa) do op */
        !           293:                if (SUGT(sul, sur)) {
        !           294:                        /* lhs, rhs, reg-reg op */
        !           295: /*                     p->in.su = max( sul, sur+nr ); */
        !           296:                        u = nr + max( sur.d , nr );
        !           297:                        sur.d = max( sul.d, u );
        !           298:                        sur.a = max( sur.a, sul.a );
        !           299:                } else {
        !           300: /*                     p->in.su = max( sul, sur+1 ); */
        !           301:                        if (r->in.op == UNARY MUL){
        !           302:                            /* address of rhs, value of lhs, op from memory */
        !           303:                            sur.d = max( sur.d, sul.d   );
        !           304:                            sur.a = max( sur.a, sul.a+1 );
        !           305:                        } else if (SUGT(sur,sul)) {
        !           306:                            /* value of rhs, value of lhs, reg-reg-op */
        !           307:                            sur.d = max( sur.d, sul.d+nr );
        !           308:                            sur.a = max( sur.a, sul.a    );
        !           309:                        } else {
        !           310:                            /* value of lhs, value of rhs, reg-reg-op */
        !           311:                            sur.d = max( sul.d, sur.d+nr );
        !           312:                            sur.a = max( sul.a, sur.a    );
        !           313:                        }
        !           314:                }
        !           315:                sur.f = 0;
        !           316:                p->in.su = sur;
        !           317:                /* is there an easier way to do this? */
        !           318:                return;
        !           319: 
        !           320:        case RS:
        !           321:        case LS:
        !           322:                /* looks like a unary op if rhs is small */
        !           323:                if ( r->tn.op == ICON && r->tn.lval >0 && r->tn.lval <= 8 ){
        !           324:                        /* looks like a unary op */
        !           325:                        sul.d = max( sul.d, nr);
        !           326:                        p->in.su = sul;
        !           327:                        return;
        !           328:                }
        !           329:                /* fall through */
        !           330:        case MUL:
        !           331:        case DIV:
        !           332:        case MOD:
        !           333:                if ( tt == FLOAT || tt == DOUBLE ) {
        !           334:                        goto float_asop;
        !           335:                }
        !           336: reg_reg_op:
        !           337:                /* register-register ops */
        !           338:                /* must do one and then the other */
        !           339:                /* commutability not an issue here */
        !           340:                /* need at least two register sets */
        !           341:                if ( SUGT( sul, sur ) ){
        !           342:                    t = max( sul.d, sur.d+nr );
        !           343:                } else {
        !           344:                    t = max( sul.d+nr, sur.d );
        !           345:                }
        !           346:                sul.d = max( 2*nr, t);
        !           347:                sul.a = max( sul.a, sur.a );
        !           348:                sul.f = max( sul.f, sur.f );
        !           349:                p->in.su = sul;
        !           350:                return;
        !           351: 
        !           352:        case NAME:
        !           353:        case REG:
        !           354:        case OREG:
        !           355:        case ICON:
        !           356:        case FCON:
        !           357:                return; /* su is zero */
        !           358: 
        !           359:        case SCONV:
        !           360:                if (!ezsconv(p)){
        !           361:                        sul.d = max( sul.d, fregs.d);
        !           362:                        sul.a = max( sul.a, fregs.a);
        !           363:                } else if (use68881
        !           364:                    && (ISFLOATING(tt) || ISFLOATING(l->in.type))) {
        !           365:                        sul.f = max( sul.f, 1 );
        !           366:                        sul.d = max( sul.d, 1 );
        !           367:                } else {
        !           368:                        sul.d = max( sul.d, nr); /* normal unary */
        !           369:                }
        !           370:                p->in.su = sul;
        !           371:                break;
        !           372:        
        !           373:        case FAINT:
        !           374:        case FANINT:
        !           375:        case FNINT:
        !           376:                /* float=>integer conversion */
        !           377:                if (use68881) {
        !           378:                        sul.d = max(sul.d, 1);
        !           379:                        sul.f = max(sul.f, 1);
        !           380:                } else {
        !           381:                        /* must do subroutine call */
        !           382:                        sul.d = max(sul.d, fregs.d);
        !           383:                        sul.a = max(sul.a, fregs.a);
        !           384:                }
        !           385:                p->in.su = sul;
        !           386:                break;
        !           387: 
        !           388:        case CHK:
        !           389:                /*
        !           390:                 * this is actually a ternary operation: 
        !           391:                 * the expression to be checked,
        !           392:                 *     the lower bound,
        !           393:                 *     the upper bound.
        !           394:                 * if the upper and lower bounds are constant, then
        !           395:                 * cost is the cost of the expression, which must
        !           396:                 * always be evaluated into a data register. We
        !           397:                 * may have to evaluate the bounds, too, and this 
        !           398:                 * costs more.
        !           399:                 * we will try to use the 68010's chk instruction.
        !           400:                 * failing that, we will use the 68020's chk2 instruction.
        !           401:                 * lacking that, use compare-and-branch code.
        !           402:                 */
        !           403:                if (chk_ovfl){
        !           404:                    /*
        !           405:                     * assume we have to evaluate each of the bounds &
        !           406:                     * at the same time hold the expression.
        !           407:                     */
        !           408:                    sur.d = max( r->in.left->in.su.d, r->in.right->in.su.d);
        !           409:                    sur.a = max( r->in.left->in.su.a, r->in.right->in.su.a);
        !           410:                    sur.f = max( r->in.left->in.su.f, r->in.right->in.su.f);
        !           411:                    p->in.su.d = max( sul.d, nr+sur.d );
        !           412:                    p->in.su.a = max( sul.a, sur.a );
        !           413:                    p->in.su.f = max( sul.f, sur.f );
        !           414:                } else {
        !           415:                    p->in.su = sul;
        !           416:                }
        !           417:                break;
        !           418: 
        !           419:        default:
        !           420:                if ( t == BITYPE ){
        !           421:                        /* random binary operators */
        !           422:                        /* choose largest */
        !           423:                        t = max( sur.d, sul.d );
        !           424:                        sur.d = max( t, nr );
        !           425:                        sur.a = max( sur.a, sul.a );
        !           426:                        sur.f = max( sur.f, sul.f );
        !           427:                        p->in.su = sur;
        !           428:                        return;
        !           429:                }
        !           430:                /* must be unary */
        !           431:                if (dope[o]&INTRFLG) {
        !           432:                        /* fortran intrinsics */
        !           433:                        if (use68881) {
        !           434:                                sul.f = max(sul.f, 1);
        !           435:                        } else {
        !           436:                                /* must do subroutine call */
        !           437:                                sul.d = max(sul.d, fregs.d);
        !           438:                                sul.a = max(sul.a, fregs.a);
        !           439:                        }
        !           440:                } else {
        !           441:                        /* random unary op */
        !           442:                        sul.d = max( sul.d, nr);
        !           443:                        if (use68881 && ISFLOATING(tt)) {
        !           444:                                sul.f = max( sul.f, 1 );
        !           445:                        }
        !           446:                }
        !           447:                p->in.su = sul;
        !           448:        }
        !           449: }
        !           450: 
        !           451: int radebug = 0;
        !           452: 
        !           453: mkrall( p, r ) register NODE *p; 
        !           454: {
        !           455:        /* insure that the use of p gets done with register r; in effect, */
        !           456:        /* simulate offstar */
        !           457: 
        !           458:        if( p->in.op == FLD ){
        !           459:                p->in.left->in.rall = p->in.rall;
        !           460:                p = p->in.left;
        !           461:        }
        !           462: 
        !           463:        if( p->in.op != UNARY MUL ) return;  /* no more to do */
        !           464:        p = p->in.left;
        !           465:        if( p->in.op == UNARY MUL ){
        !           466:                p->in.rall = r;
        !           467:                p = p->in.left;
        !           468:        }
        !           469:        if( p->in.op == PLUS && p->in.right->in.op == ICON ){
        !           470:                p->in.rall = r;
        !           471:                p = p->in.left;
        !           472:        }
        !           473:        rallo( p, r );
        !           474: }
        !           475: 
        !           476: rallo( p, down ) NODE *p; 
        !           477: {
        !           478:        /* do register allocation */
        !           479:        register o, type, down1, down2, ty;
        !           480:        NODE *p2;
        !           481: 
        !           482: again:
        !           483:        if( radebug ) printf( "rallo( %o, %d )\n", p, down );
        !           484: 
        !           485:        down2 = NOPREF;
        !           486:        p->in.rall = down;
        !           487:        down1 = ( down &= ~MUSTDO );
        !           488: 
        !           489:        ty = optype( o = p->in.op );
        !           490:        type = p->in.type;
        !           491: 
        !           492: 
        !           493:        switch( o ) {
        !           494:        case UNARY MUL:
        !           495:                down1 = NOPREF;
        !           496:                break;
        !           497: 
        !           498:        case ASSIGN:    
        !           499:                down1 = NOPREF;
        !           500:                down2 = down;
        !           501:                break;
        !           502: 
        !           503:        case ASG MUL:
        !           504:        case ASG DIV:
        !           505:        case ASG MOD:
        !           506: 
        !           507:        case MUL:
        !           508:        case DIV:
        !           509:        case MOD:
        !           510:                switch(type){
        !           511:                case FLOAT:
        !           512:                    if (use68881 || usesky) break;
        !           513:                    down1 = D0|MUSTDO;
        !           514:                    down2 = D1|MUSTDO;
        !           515:                    break;
        !           516:                case INT:
        !           517:                case UNSIGNED:
        !           518:                    if (use68020) break;
        !           519:                    down1 = D0|MUSTDO;
        !           520:                    down2 = D1|MUSTDO;
        !           521:                    break;
        !           522:                case DOUBLE:
        !           523:                    if (use68881 || usesky) break;
        !           524:                    down1 = D0|MUSTDO;
        !           525:                    break;
        !           526:                default:
        !           527:                    if (ISPTR(type)){
        !           528:                        /* this is the result of (char *)(a*b) */
        !           529:                        /* treat as an unsigned or int         */
        !           530:                        if (use68020) break;
        !           531:                        down1 = D0|MUSTDO;
        !           532:                        down2 = D1|MUSTDO;
        !           533:                    }
        !           534:                    break;
        !           535:                }
        !           536:                break;
        !           537: 
        !           538:        case EQ:
        !           539:        case NE:
        !           540:        case GT:
        !           541:        case GE:
        !           542:        case LT:
        !           543:        case LE:
        !           544:                type = p->in.left->in.type;
        !           545:                /* fall through */
        !           546:        case PLUS:
        !           547:        case MINUS:
        !           548:        case ASG PLUS:
        !           549:        case ASG MINUS:
        !           550:                if (use68881 || usesky) break;
        !           551:                switch (type){
        !           552:                case FLOAT:
        !           553:                    down1 = D0|MUSTDO;
        !           554:                    down2 = D1|MUSTDO;
        !           555:                    break;
        !           556:                case DOUBLE:
        !           557:                    down1 = D0|MUSTDO;
        !           558:                    break;
        !           559:                }
        !           560:                break;
        !           561: 
        !           562:        case NOT:
        !           563:        case ANDAND:
        !           564:        case OROR:
        !           565:                down1 = NOPREF;
        !           566:                break;
        !           567: 
        !           568:        case SCONV: /* float, fix, single, or double */
        !           569:                if (use68881 || usesky) break;
        !           570:                if (ezsconv(p)) break;
        !           571:                down1 = D0|MUSTDO;
        !           572:                break;
        !           573: 
        !           574:        case FORCE:     
        !           575:                down1 = D0|MUSTDO;
        !           576:                break;
        !           577: 
        !           578:        case FNINT:     /* float=>int conversion, use biased rounding */
        !           579:                if (use68881) break;
        !           580:                down1 = D0|MUSTDO;
        !           581:                break;
        !           582: 
        !           583:        default:
        !           584:                if ((dope[o]&INTRFLG) && !use68881) {
        !           585:                        /* fortran intrinsics */
        !           586:                        down1 = D0|MUSTDO;
        !           587:                }
        !           588:        }
        !           589: 
        !           590: recur:
        !           591:        if( ty == BITYPE ) rallo( p->in.right, down2 );
        !           592:        else if( ty == LTYPE )  return;
        !           593:        /* else do tail-recursion */
        !           594:        p =  p->in.left;
        !           595:        down = down1;
        !           596:        goto again;
        !           597: 
        !           598: }
        !           599: 
        !           600: stoasg( p, o ) register NODE *p; 
        !           601: {
        !           602:        /* should the assignment op p be stored,
        !           603:           given that it lies as the right operand of o
        !           604:           (or the left, if o==UNARY MUL) */
        !           605: /*
        !           606:        if( p->in.op == INCR || p->in.op == DECR ) return;
        !           607:        if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG);
        !           608:  */
        !           609:        return( shltype(p->in.left->in.op, p->in.left ) );
        !           610: }
        !           611: 
        !           612: deltest( p ) register NODE *p; 
        !           613: {
        !           614:        /* should we delay the INCR or DECR operation p */
        !           615: # ifndef MULTILEVEL
        !           616:        if( p->in.op == INCR && p->in.left->in.op == REG && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){
        !           617:                /* STARREG */
        !           618:                return( 0 );
        !           619:                }
        !           620: # else
        !           621:        if( mlmatch(p,DEFINCDEC,INCR) && spsz( p->in.left->in.type, p->in.right->tn.lval ) ){
        !           622:                /* STARREG */
        !           623:                return( 0 );
        !           624:                }
        !           625: #endif
        !           626:        p = p->in.left;
        !           627:        return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG );
        !           628: }
        !           629: mkadrs(p) register NODE *p; 
        !           630: {
        !           631:        register o;
        !           632: 
        !           633:        o = p->in.op;
        !           634: 
        !           635:        if( asgop(o) ){
        !           636:                if( !SUGT( p->in.right->in.su , p->in.left->in.su )){
        !           637:                        if( p->in.left->in.op == UNARY MUL ){
        !           638:                                if( SUTEST( p->in.left->in.su ) )
        !           639:                                        SETSTO( p->in.left->in.left, INTEMP );
        !           640:                                else {
        !           641:                                        if (SUTEST( p->in.right->in.su ) )
        !           642:                                            SETSTO( p->in.right, INTEMP );
        !           643:                                        else 
        !           644:                                            cerror( "store finds both sides trivial" );
        !           645:                                }
        !           646:                        }
        !           647:                        else if( p->in.left->in.op == FLD 
        !           648:                            && p->in.left->in.left->in.op == UNARY MUL ){
        !           649:                                SETSTO( p->in.left->in.left->in.left, INTEMP );
        !           650:                        } else { 
        !           651:                                /* should be only structure assignment */
        !           652:                                SETSTO( p->in.left, INTEMP );
        !           653:                        }
        !           654:                }
        !           655:                else SETSTO( p->in.right, INTEMP );
        !           656:        } else {
        !           657:                if( SUGT( p->in.left->in.su , p->in.right->in.su )){
        !           658:                        SETSTO( p->in.left, INTEMP );
        !           659:                } else {
        !           660:                        SETSTO( p->in.right, INTEMP );
        !           661:                }
        !           662:        }
        !           663: }
        !           664: 
        !           665: 
        !           666: notoff( t, r, off, cp) CONSZ off; char *cp; 
        !           667: {
        !           668:        /* is it legal to make an OREG or NAME entry which has an
        !           669:        /* offset of off, (from a register of r), if the
        !           670:        /* resulting thing had type t */
        !           671: 
        !           672:        /* yes */
        !           673:        if (use68020 && isbreg(r))
        !           674:                return(0);
        !           675:        if ( off>=-32768 && off<=32767
        !           676:            && (cp == NULL || *cp=='\0') && r>=A0 && r<=SP )
        !           677:                return(0)        !           678:        return(1); /* NO */
        !           679: }
        !           680: 
        !           681: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
        !           682: 
        !           683: #define nncon(p)\
        !           684:     ((p)->in.op == ICON && ((p)->tn.name == NULL || (p)->tn.name[0] == '\0'))
        !           685: 
        !           686: /*
        !           687:  * Compile an array index expression, exploiting
        !           688:  * scaled indexing if possible.  Assume an index
        !           689:  * register is known to be available.
        !           690:  */
        !           691: do_index(p)
        !           692:        register NODE *p;
        !           693: {
        !           694:        register NODE *rp,*lp;
        !           695:        int count;
        !           696: 
        !           697:        switch(p->in.op) {
        !           698:        case REG:
        !           699:                return;
        !           700:        case MUL:
        !           701:                /*
        !           702:                 * at least one front-end doesn't do this...
        !           703:                 */
        !           704:                rp = p->in.right;
        !           705:                if (nncon(rp)) {
        !           706:                        count = -1;
        !           707:                        switch(rp->tn.lval) {
        !           708:                        case 1:
        !           709:                                count = 0;
        !           710:                                break;
        !           711:                        case 2:
        !           712:                                count = 1;
        !           713:                                break;
        !           714:                        case 4:
        !           715:                                count = 2;
        !           716:                                break;
        !           717:                        case 8:
        !           718:                                count = 3;
        !           719:                                break;
        !           720:                        }
        !           721:                        if (count >= 0) {
        !           722:                                p->in.op = LS;
        !           723:                                rp->tn.lval = count;
        !           724:                                /*
        !           725:                                 * reset type, because MULS
        !           726:                                 * changes shorts to longs, but
        !           727:                                 * ASL doesn't!
        !           728:                                 */
        !           729:                                p->in.type = p->in.left->in.type;
        !           730:                                goto leftshift;
        !           731:                        }
        !           732:                }
        !           733:                break;
        !           734:        case LS:
        !           735:        leftshift:
        !           736:                rp = p->in.right;
        !           737:                lp = p->in.left;
        !           738:                if ( lp->in.op == SCONV && lp->in.type == INT ) {
        !           739:                        if ( lp->in.left->in.type == CHAR ) {
        !           740:                                /*
        !           741:                                 * we only need convert bytes to shorts.
        !           742:                                 */
        !           743:                                lp->in.type = SHORT;
        !           744:                                p->in.type = SHORT;
        !           745:                        }
        !           746:                        else if ( use68020 && lp->in.left->in.type == SHORT
        !           747:                            && lp->in.rall == NOPREF ) {
        !           748:                                /*
        !           749:                                 * on the 68020, a conversion from short
        !           750:                                 * to int below a scale by 2,4, or 8 is
        !           751:                                 * subsumed into the addressing modes
        !           752:                                 */
        !           753:                                p->in.left = lp->in.left;
        !           754:                                lp->in.op = FREE;
        !           755:                                lp = p->in.left;
        !           756:                                p->in.type = lp->in.type;
        !           757:                        }
        !           758:                } /* lp->in.op == SCONV */
        !           759:                if (use68020 && nncon(rp) && rp->tn.lval >= 0
        !           760:                        && rp->tn.lval <= 3){
        !           761:                        /*
        !           762:                         * on the 68020, scaling by 2, 4, or 8 is also free
        !           763:                         */
        !           764:                        if (lp->in.op != REG || p->in.rall != NOPREF) {
        !           765:                                lp->in.rall = p->in.rall;
        !           766:                                order(lp,INTAREG|INAREG|INTBREG|INBREG);
        !           767:                        }
        !           768:                        return;
        !           769:                }
        !           770:                break;
        !           771:        case SCONV:
        !           772:                if (p->in.type == INT) {
        !           773:                        lp = p->in.left;
        !           774:                        if (lp->in.type == CHAR) {
        !           775:                                /*
        !           776:                                 * we only need convert bytes to shorts.
        !           777:                                 */
        !           778:                                p->in.type = SHORT;
        !           779:                        } /* char */
        !           780:                        else if (lp->in.type == SHORT && p->in.rall == NOPREF) {
        !           781:                                /*
        !           782:                                 * conversions from short to int
        !           783:                                 * are done by the addressing modes
        !           784:                                 */
        !           785:                                *p = *lp;
        !           786:                                lp->in.op = FREE;
        !           787:                        } /* short */
        !           788:                } /* type == INT */
        !           789:                break;
        !           790:        } /* switch */
        !           791:        order(p, INTAREG|INAREG|INTBREG|INBREG);
        !           792: } /* do_index */
        !           793: 
        !           794: /*
        !           795:  * is this expression a register or a
        !           796:  * sign-extending conversion of one?
        !           797:  */
        !           798: static int
        !           799: regsconv(p)
        !           800:        NODE *p;
        !           801: {
        !           802:        NODE *lp;
        !           803: 
        !           804:        if (p->in.op == REG)
        !           805:                return(1);
        !           806:        if (p->in.op == SCONV && p->in.type == INT) {
        !           807:                lp = p->in.left;
        !           808:                if ( (lp->in.type == SHORT || lp->in.type == CHAR)
        !           809:                        && lp->in.op == REG )
        !           810:                        return(1);
        !           811:        }
        !           812:        return(0);
        !           813: }
        !           814: 
        !           815: /*
        !           816:  * is this already a legal index?
        !           817:  */
        !           818: int
        !           819: isindex(p)
        !           820:        register NODE *p;
        !           821: {
        !           822:        register rval;
        !           823:        NODE *rp;
        !           824: 
        !           825:        if (use68020) {
        !           826:                if (p->in.op == MUL) {
        !           827:                        rp = p->in.right;
        !           828:                        if (nncon(rp)) {
        !           829:                                switch(rp->tn.lval) {
        !           830:                                case 1:
        !           831:                                case 2:
        !           832:                                case 4:
        !           833:                                case 8:
        !           834:                                        return(regsconv(p->in.left));
        !           835:                                } /* switch */
        !           836:                        } /* nncon */
        !           837:                        return(0);
        !           838:                } /* MUL */
        !           839:                if (p->in.op == LS) {
        !           840:                        rp = p->in.right;
        !           841:                        if (nncon(rp)
        !           842:                            && (rp->tn.lval >= 0 && rp->tn.lval <= 3))
        !           843:                                return(regsconv(p->in.left));
        !           844:                        return(0);
        !           845:                } /* LS */
        !           846:        } /* use68020 */
        !           847:        return(regsconv(p));
        !           848: }
        !           849: 
        !           850: /*
        !           851:  * is p a signed byte constant ? This really asks whether p is
        !           852:  * permissible in a (base+disp+index) expression.  On the 68020,
        !           853:  * anything is permissible, including relocatables.
        !           854:  */
        !           855: 
        !           856: static int
        !           857: isbcon(p, t)
        !           858:        register NODE *p;
        !           859:        TWORD t;
        !           860: {
        !           861:        int maxoff;
        !           862:        if (p == NIL)
        !           863:                return 0;
        !           864:        if (p->in.op == ICON) {
        !           865:                if (use68020)
        !           866:                        return(1);
        !           867:                maxoff = ((BTYPE(t) == DOUBLE) ? 123 : 127);
        !           868:                if (nncon(p) && p->tn.lval <= maxoff && p->tn.lval >= -maxoff)
        !           869:                        return(1);
        !           870:        }
        !           871:        return(0);
        !           872: }
        !           873: 
        !           874: /*
        !           875:  * Is p a signed short constant ? This really asks whether p
        !           876:  * is permissible in a (base+disp) expression.  On the 68020,
        !           877:  * anything is permissible, including relocatables.
        !           878:  */
        !           879: 
        !           880: static int
        !           881: isscon(p, t)
        !           882:        register NODE *p;
        !           883:        TWORD t;
        !           884: {
        !           885:        int maxoff;
        !           886:        if (p == NIL)
        !           887:                return 0;
        !           888:        if (p->in.op == ICON) {
        !           889:                if (use68020)
        !           890:                        return(1);
        !           891:                maxoff = ((BTYPE(t) == DOUBLE) ? 32763 : 32767);
        !           892:                if (nncon(p) && p->tn.lval <= maxoff && p->tn.lval >= -maxoff)
        !           893:                        return(1);
        !           894:        }
        !           895:        return(0);
        !           896: }
        !           897: 
        !           898: #define isbregnode(p) ((p)->in.op == REG && isbreg((p)->tn.rval))
        !           899: 
        !           900: /*
        !           901:  * Is a register available for indexing? This depends
        !           902:  * on context larger than the immediate expression,
        !           903:  * represented by the 'failsafe' flag. (cf., order.c)
        !           904:  * Note that we should not ask this unless it we are
        !           905:  * fairly sure we WANT to use double indexing.
        !           906:  */
        !           907: static int
        !           908: can_index(p, base, index)
        !           909:        NODE *p, *base, *index;
        !           910: {
        !           911:        if (isindex(index))     /* already got one */
        !           912:                return(1);
        !           913:        failsafe |= ((p->in.rall == D0) || (p->in.rall == D1));
        !           914:        if (failsafe) {
        !           915:                /*
        !           916:                 * We need d0, d1, or both for something; don't tie
        !           917:                 * either one up.
        !           918:                 */
        !           919:                if (!isbregnode(base) || istreg(base->tn.rval)) {
        !           920:                        /*
        !           921:                         * need a scratch register for the base, too.
        !           922:                         */
        !           923:                        return(0);      /* forget it! */
        !           924:                }
        !           925:                if(!rewrite_rall(index,1)) {
        !           926:                        return(0);
        !           927:                }
        !           928:        }
        !           929:        return(1);
        !           930: }
        !           931: 
        !           932: /*
        !           933:  * Compile memory reference expressions, attempting to make the best
        !           934:  * use of the target machine's addressing modes.  The overall plan
        !           935:  * is to put the expression into a canonical form, then select and
        !           936:  * compile a suitable subtree based on availability of registers,
        !           937:  * offset limitations, and support from the architecture.  A goal
        !           938:  * is not to evaluate any more of the tree than is necessary.
        !           939:  *
        !           940:  * On entry, we assume we have been given the left branch of a UNARY MUL,
        !           941:  * not the UNARY MUL itself.
        !           942:  *
        !           943:  * When done, we must guarantee that the resulting tree can be turned
        !           944:  * into an OREG.
        !           945:  */
        !           946: 
        !           947: offstar( p )
        !           948:        register NODE *p; 
        !           949: {
        !           950:        register NODE *lp, *rp;
        !           951: 
        !           952:        if ( (p->in.rall&MUSTDO)
        !           953:            || (p->in.op != PLUS && p->in.op != MINUS ) ) {
        !           954:                /* No chance to index */
        !           955:                if ( p->in.op != REG || !isbreg(p->tn.rval) ) {
        !           956:                        failsafe = 0;
        !           957:                        order(p, INTBREG|INBREG);
        !           958:                }
        !           959:                return;
        !           960:        }
        !           961:        /*
        !           962:         * exp is (<exp> [+-] <exp>)
        !           963:         */
        !           964:        lp = p->in.left;
        !           965:        rp = p->in.right;
        !           966:        if (!ISPTR(lp->in.type)) {
        !           967:                /*
        !           968:                 * put the pointer on the left
        !           969:                 */
        !           970:                p->in.right = lp;
        !           971:                p->in.left = rp;
        !           972:                lp = p->in.left;
        !           973:                rp = p->in.right;
        !           974:        }
        !           975:        /*
        !           976:         * u-page hack, for the kernel boys: for example,
        !           977:         * (*((struct u *) 0x4000)).u_dent.d_name[i++] = *cp;
        !           978:         */
        !           979:        if (nncon(lp) && isscon(lp) && tlen(rp) == (SZINT/SZCHAR)) {
        !           980:                /*
        !           981:                 * swap base part and index part,
        !           982:                 * then diddle the types
        !           983:                 */
        !           984:                TWORD temp;
        !           985:                p->in.right = lp;
        !           986:                p->in.left = rp;
        !           987:                lp = p->in.left;
        !           988:                rp = p->in.right;
        !           989:                temp = lp->in.type;
        !           990:                lp->in.type = rp->in.type;
        !           991:                rp->in.type = temp;
        !           992:        }
        !           993:        /*
        !           994:         * map (<exp> - <icon>) to (<exp> + <-icon>)
        !           995:         */
        !           996:        if (p->in.op == MINUS && nncon(rp)) {
        !           997:                p->in.op = PLUS;
        !           998:                rp->tn.lval = -(rp->tn.lval);
        !           999:        }
        !          1000:        /*
        !          1001:         * map ( (<exp> - <icon> ) [+-] <exp> )
        !          1002:         * to  ( (<exp> + <-icon>) [+-] <exp> )
        !          1003:         */
        !          1004:        if (lp->in.op == MINUS && nncon(lp->in.right)) {
        !          1005:                lp->in.op = PLUS;
        !          1006:                lp->in.right->tn.lval = -(lp->in.right->tn.lval);
        !          1007:        }
        !          1008:        /*
        !          1009:         * At this point, any subtractions must be done explicitly.
        !          1010:         */
        !          1011:        if ( p->in.op == MINUS ) {
        !          1012:                failsafe = 0;
        !          1013:                order(p, INTBREG|INBREG);
        !          1014:                return;
        !          1015:        }
        !          1016:        if ( lp->in.op == PLUS ) {
        !          1017: 
        !          1018:                /*
        !          1019:                 * map (<index> + <base>) + <exp>
        !          1020:                 * to  (<base> + <index>) + <exp>
        !          1021:                 */
        !          1022:                if ( !ISPTR(lp->in.left->in.type) ) {
        !          1023:                        NODE *q = lp->in.left;
        !          1024:                        lp->in.left = lp->in.right;
        !          1025:                        lp->in.right = q;
        !          1026:                }
        !          1027: 
        !          1028:                /*
        !          1029:                 * map (<base> + <index>) + <bcon>
        !          1030:                 * to  (<base> + <bcon>) + <index>
        !          1031:                 */
        !          1032:                if ( isbcon(rp) && !isbcon(lp->in.right) ) {
        !          1033:                        NODE *q = lp->in.right;
        !          1034:                        lp->in.right = rp;
        !          1035:                        rp = p->in.right = q;
        !          1036:                }
        !          1037: 
        !          1038:                /*
        !          1039:                 * Now we evaluate the expression, or enough of it so
        !          1040:                 * that the remainder can be handled by an addressing mode.
        !          1041:                 */
        !          1042:                if (isbcon(lp->in.right, p->in.type)) {
        !          1043:                        /*
        !          1044:                         * pattern is ( <base exp> + <bcon> ) + <index>
        !          1045:                         * where <bcon> is in [-127..127] for the 68010,
        !          1046:                         * or any integral constant on the 68020.
        !          1047:                         */
        !          1048:                        NODE *llp = lp->in.left;
        !          1049:                        if (SUTEST(llp->in.su) && SUTEST(rp->in.su)) {
        !          1050:                                /*
        !          1051:                                 * don't bother;
        !          1052:                                 * both <base> and <index> are messy.
        !          1053:                                 */
        !          1054:                                goto punt;
        !          1055:                        }
        !          1056:                        if (SUGT(rp->in.su, llp->in.su)){
        !          1057:                                /*
        !          1058:                                 * Index is more expensive than base.
        !          1059:                                 * Do it first, unless you have to bend
        !          1060:                                 * over backwards to do it.
        !          1061:                                 */
        !          1062:                                if (can_index(p,llp,rp)) {
        !          1063:                                        do_index(rp);   /* breg@(disp,index) */
        !          1064:                                        if (!isbregnode(llp)) {
        !          1065:                                                order(llp, INTBREG|INBREG);
        !          1066:                                        }
        !          1067:                                        return;
        !          1068:                                }
        !          1069:                                goto punt;
        !          1070:                        }
        !          1071:                        /*
        !          1072:                         * try for index
        !          1073:                         */
        !          1074:                        if (can_index(p,llp,rp)) {
        !          1075:                                /*
        !          1076:                                 * evaluate base into a <breg>
        !          1077:                                 */
        !          1078:                                if (!isbregnode(llp)) {
        !          1079:                                        order(llp, INTBREG|INBREG);
        !          1080:                                }
        !          1081:                                /*
        !          1082:                                 * evaluate <index> into a register
        !          1083:                                 */
        !          1084:                                do_index(rp);   /* breg@(disp, index) */
        !          1085:                                return;
        !          1086:                        }
        !          1087:                        /*
        !          1088:                         * can't index; instead,
        !          1089:                         * rewrite as ( <base>+<index> ) + <bcon>
        !          1090:                         */
        !          1091:                punt:   llp = lp->in.right;
        !          1092:                        lp->in.right = rp;
        !          1093:                        p->in.right = llp;
        !          1094:                        failsafe = 0;
        !          1095:                        order(lp, INTBREG|INBREG);  /* breg@(disp) */
        !          1096:                        return;
        !          1097:                } /* (<base> + <bcon>) + <index> */
        !          1098:        } /* lp == PLUS */
        !          1099: 
        !          1100:        /*
        !          1101:         * At this point, the expression is of the form
        !          1102:         *      <base part> + <index part>
        !          1103:         */
        !          1104:        if (SUTEST(lp->in.su) && SUTEST(rp->in.su)) {
        !          1105:                /*
        !          1106:                 * both <base> and <index> are messy.
        !          1107:                 */
        !          1108:                failsafe = 0;
        !          1109:                order(p, INTBREG|INBREG);       /* breg@ */
        !          1110:                return;
        !          1111:        }
        !          1112:        if ( SUGT(rp->in.su, lp->in.su) ) {
        !          1113:                /*
        !          1114:                 * index is more expensive than base.
        !          1115:                 * Do it first, unless you have to bend
        !          1116:                 * over backwards to do it.
        !          1117:                 */
        !          1118:                if (can_index(p,lp,rp)) {
        !          1119:                        do_index(rp);
        !          1120:                        if (!isbregnode(lp)){
        !          1121:                                order(lp, INTBREG|INBREG);
        !          1122:                        }
        !          1123:                        return;            /* base@(index)*/
        !          1124:                }
        !          1125:                failsafe = 0;
        !          1126:                order(p, INTBREG|INBREG);       /* base@ */
        !          1127:                return;
        !          1128:        }
        !          1129:        /*
        !          1130:         * try to make a breg@(disp) operand
        !          1131:         */
        !          1132:        if ( isscon(rp) ) {
        !          1133:                failsafe = 0;
        !          1134:                if (!isbregnode(lp)) {
        !          1135:                        order(lp, INTBREG|INBREG);
        !          1136:                }
        !          1137:                return;                         /* breg@(disp) */
        !          1138:        }
        !          1139:        /*
        !          1140:         * Do base first.
        !          1141:         */
        !          1142:        if ( !isbregnode(lp) ) {
        !          1143:                order(lp, INTBREG|INBREG);
        !          1144:        }
        !          1145:        if ( istnode(lp) && tshape(rp, SCON|SNAME|SOREG|STARNM) ) {
        !          1146:                /*
        !          1147:                 * pattern is <temp reg> + <mem operand>
        !          1148:                 * indexing doesn't buy us anything.
        !          1149:                 */
        !          1150:                failsafe = 0;
        !          1151:                order(p, INTBREG|INBREG);       /* base@ */
        !          1152:                return;
        !          1153:        }
        !          1154:        if ( can_index(p,lp,rp) ) {
        !          1155:                do_index(rp);                   /* base@(index) */
        !          1156:                return;
        !          1157:        }
        !          1158:        /*
        !          1159:         * "Either this man is dead, or my watch has stopped."
        !          1160:         */
        !          1161:        failsafe = 0;
        !          1162:        order(p, INTBREG|INBREG);       /* base@ */
        !          1163: }
        !          1164: 
        !          1165: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
        !          1166: 
        !          1167: int crslab = 2000000;  /* 68k */
        !          1168: 
        !          1169: getlab()
        !          1170: {
        !          1171:        return( crslab++ );
        !          1172: }
        !          1173: 
        !          1174: deflab( l )
        !          1175: {
        !          1176:        print_label(l);
        !          1177: }
        !          1178: 
        !          1179: #define mkmask(reg,mask) (busy[reg] ? ((mask) | (1<<(reg))) : (mask))
        !          1180: 
        !          1181: genargs( p ) register NODE *p; 
        !          1182: {
        !          1183:        register NODE *pasg;
        !          1184:        register inc;
        !          1185:        register align;
        !          1186:        register size;
        !          1187:        register TWORD type;
        !          1188:        int padflag;
        !          1189: 
        !          1190:        /* generate code for the arguments */
        !          1191: 
        !          1192:        /*  first, do the arguments on the right */
        !          1193:        while( p->in.op == CM ){
        !          1194:                genargs( p->in.right );
        !          1195:                p->in.op = FREE;
        !          1196:                p = p->in.left;
        !          1197:        }
        !          1198: 
        !          1199:        if( p->in.op == STARG ){ /* structure valued argument */
        !          1200:                /*
        !          1201:                 * We are stacking arguments in anticipation of a 
        !          1202:                 * call.
        !          1203:                 * The strategy will be to push words on the
        !          1204:                 * stack (being careful of alignment problems)
        !          1205:                 * in open code. A dbra loop is too hard here.
        !          1206:                 */
        !          1207:                size = p->stn.stsize;
        !          1208:                if( p->in.left->in.op == ICON ){
        !          1209:                        p->in.op = FREE;
        !          1210:                        p= p->in.left;
        !          1211:                        p->in.op = NAME;
        !          1212:                }
        !          1213:                else {
        !          1214:                        /* make it look beautiful... */
        !          1215:                        p->in.op = UNARY MUL;
        !          1216:                        canon( p );  /* turn it into an oreg */
        !          1217:                        if( p->in.op != OREG ){
        !          1218:                                offstar( p->in.left );
        !          1219:                                canon( p );
        !          1220:                                if( p->in.op != OREG ){
        !          1221:                                        offstar( p->in.left );
        !          1222:                                        canon( p );
        !          1223:                                        if( p->in.op != OREG ) cerror( "stuck starg" );
        !          1224:                                }
        !          1225:                        }
        !          1226:                }
        !          1227: 
        !          1228:                if (size > 16) {
        !          1229:                        /*
        !          1230:                         * big structure argument.  In its infinite wisdom,
        !          1231:                         * Pascal passes array value parameters like this.
        !          1232:                         * Twenty-two on the vomit meter.
        !          1233:                         */
        !          1234:                        int count;
        !          1235:                        int residue;
        !          1236:                        short regmask;
        !          1237:                        int savetemp;
        !          1238: 
        !          1239:                        if (size&1) size++; /* assumes ALSTACK = 16 */
        !          1240:                        toff += size;
        !          1241:                        if (toff > maxtoff) maxtoff = toff;
        !          1242:                        count = size / sizeof(long);
        !          1243:                        residue = size % sizeof(long);
        !          1244:                        /*
        !          1245:                         * a0 = &(actual argument);
        !          1246:                         */
        !          1247:                        if (p->in.op == OREG && !R2TEST(p->tn.rval)
        !          1248:                            && (p->tn.name == NULL || p->tn.name[0] == '\0')
        !          1249:                            && p->tn.lval == 0) {
        !          1250:                                p->in.op = REG;
        !          1251:                        }
        !          1252:                        if (p->in.op == REG) {
        !          1253:                            if (p->tn.rval != A0)
        !          1254:                                expand(p, RNOP, "       movl    AR,a0\n");
        !          1255:                        } else {
        !          1256:                                expand(p, RNOP, "       lea     AR,a0\n");
        !          1257:                        }
        !          1258:                        /*
        !          1259:                         * allocate and copy to top of stack
        !          1260:                         */
        !          1261:                        if (size > 0x7fff) {
        !          1262:                                printf("        subl    #%d,sp\n", size);
        !          1263:                        } else {
        !          1264:                                printf("        lea     sp@(-%d),sp\n", size);
        !          1265:                        }
        !          1266:                        print_str("     movl    sp,a1\n");
        !          1267:                        if (count > 0x7fff) {
        !          1268:                                printf("        movl    #%d,d0\n", count-1);
        !          1269:                                print_str("1:   movl    a0@+,a1@+\n");
        !          1270:                                print_str("     dbra    d0,1b\n");
        !          1271:                                print_str("     clrw    d0\n");
        !          1272:                                print_str("     subql   #1,d0\n");
        !          1273:                                print_str("     jcc     1b\n");
        !          1274:                        } else {
        !          1275:                                printf("        movw    #%d,d0\n", count-1);
        !          1276:                                print_str("1:   movl    a0@+,a1@+\n");
        !          1277:                                print_str("     dbra    d0,1b\n");
        !          1278:                        }
        !          1279:                        switch(residue) {
        !          1280:                        case 1:
        !          1281:                                print_str("     movb    a0@+,a1@+\n");
        !          1282:                                break;
        !          1283:                        case 2:
        !          1284:                                print_str("     movw    a0@+,a1@+\n");
        !          1285:                                break;
        !          1286:                        case 3:
        !          1287:                                print_str("     movw    a0@+,a1@+\n");
        !          1288:                                print_str("     movb    a0@+,a1@+\n");
        !          1289:                                break;
        !          1290:                        default:
        !          1291:                                break;
        !          1292:                        }
        !          1293:                        reclaim(p,RNULL,0);
        !          1294:                        return;
        !          1295:                } /* big structure */
        !          1296: 
        !          1297:                p->tn.lval += size;
        !          1298:                /*
        !          1299:                 * arguments must be at least sizeof(int) big around here.
        !          1300:                 * force size up to it.
        !          1301:                 */
        !          1302:                padflag = (size <= 2 ) ;
        !          1303: #ifdef FORT
        !          1304:                /* PASCAL ONLY */
        !          1305:                if (size & 1){
        !          1306:                        /*
        !          1307:                         * size is odd: last byte is peculiar.
        !          1308:                         * movb to stack is magic.
        !          1309:                         */
        !          1310:                        size -= 1;
        !          1311:                        p->tn.lval -=1;
        !          1312:                        expand( p, RNOP,"\tmovb\tAR,sp@-\n" );
        !          1313:                        toff += 2;
        !          1314:                        if (toff > maxtoff) maxtoff = toff;
        !          1315:                }
        !          1316: #endif FORT
        !          1317:                toff += size;
        !          1318:                if (toff > maxtoff) maxtoff = toff;
        !          1319:                for( ; size>0; size -= inc ){
        !          1320:                        inc = (size>2) ? 4 : 2;
        !          1321:                        p->tn.lval -= inc;
        !          1322:                        expand( p, RNOP,(inc==4)?"\tmovl\tAR,sp@-\n":"\tmovw\tAR,sp@-\n" );
        !          1323:                }
        !          1324:                if (padflag){
        !          1325:                    print_str(" subql   #2,sp\n");
        !          1326:                    toff += 2;
        !          1327:                    if (toff > maxtoff) maxtoff = toff;
        !          1328:                }
        !          1329:                reclaim(p,RNULL,0);
        !          1330:                return;
        !          1331:        }
        !          1332: 
        !          1333:        /* ordinary case */
        !          1334:        order( p, FORARG );
        !          1335: }
        !          1336: 
        !          1337: argsize( p ) register NODE *p; 
        !          1338: {
        !          1339:        register t, s;
        !          1340:        t = 0;
        !          1341:        if( p->in.op == CM ){
        !          1342:                t = argsize( p->in.left );
        !          1343:                p = p->in.right;
        !          1344:        }
        !          1345:        switch (p->in.type){
        !          1346:        case FLOAT:
        !          1347: #ifdef FLOATMATH
        !          1348:                if (FLOATMATH>1){
        !          1349:                    SETOFF( t, ALFLOAT/SZCHAR );
        !          1350:                    return( t+(SZFLOAT/SZCHAR) );
        !          1351:                }
        !          1352: #endif FLOATMATH
        !          1353:                /* else fall through */
        !          1354:        case DOUBLE:
        !          1355:                SETOFF( t, ALDOUBLE/SZCHAR );
        !          1356:                return( t+(SZDOUBLE/SZCHAR) );
        !          1357:        }
        !          1358:        if( p->in.op == STARG ){
        !          1359:                SETOFF( t, ALSTRUCT/SZCHAR );  /* alignment */
        !          1360:                s = p->stn.stsize;            /* size */
        !          1361:                s += (s & 1); /* PASCAL ONLY */
        !          1362:                if (s < SZINT/SZCHAR)
        !          1363:                    s = SZINT/SZCHAR;
        !          1364:                return( s+t );
        !          1365:        } else {
        !          1366:                SETOFF( t, ALSTACK/SZCHAR );
        !          1367:                return( t+(SZINT/SZCHAR) );
        !          1368:        }
        !          1369: }

unix.superglobalmegacorp.com

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