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

1.1     ! root        1: #include "cpass2.h"
        !             2: #include "ctype.h"
        !             3: #ifndef lint
        !             4: static char sccsid[] = "@(#)local2.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             5: #endif
        !             6: 
        !             7: /*
        !             8:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             9:  */
        !            10: 
        !            11: # ifdef FORT
        !            12: int ftlab1, ftlab2;
        !            13: # endif
        !            14: /* a lot of the machine dependent parts of the second pass */
        !            15: #ifdef FORT
        !            16: #   define fltfun 0
        !            17: #else
        !            18:     extern int fltfun;
        !            19: #endif
        !            20: # define BITMASK(n) ((1L<<(n))-1)
        !            21: 
        !            22: 
        !            23: int toff = 0;    /* number of stack locations used for args */
        !            24: int maxtoff;
        !            25: void stmove();
        !            26: void eval_field();
        !            27: void shiftreg();
        !            28: void incraddr();
        !            29: 
        !            30: /* everything you never wanted to know about condition codes */
        !            31: 
        !            32: char *
        !            33: ccodes[] =     { "eq", "ne", "le", "lt", "ge", "gt", "ls", "cs", "cc", "hi" };
        !            34: 
        !            35: char *
        !            36: fccodes[] =    { "eq", "neq", "le", "lt", "ge", "gt" };
        !            37: 
        !            38: char *
        !            39: fnegccodes[] = { "neq", "eq", "nle", "nlt", "nge", "ngt" };
        !            40: 
        !            41: /* logical relations when compared in reverse order (cmp R,L) */
        !            42: 
        !            43: #ifdef FORT
        !            44: short revrel[] = { EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
        !            45: #else
        !            46: extern short revrel[];
        !            47: #endif
        !            48: 
        !            49: /* negated logical relations -- integer comparisons only */
        !            50: 
        !            51: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;
        !            52: 
        !            53: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
        !            54: 
        !            55: zzzcode( p, c, cookie ) NODE *p; 
        !            56: {
        !            57: 
        !            58:        register m,temp;
        !            59:        NODE *s;
        !            60: 
        !            61:        switch( c ){
        !            62:        /* BCDEFGHIJKLMNOPRSTVWXabcdfglmrtv` '0-~ */
        !            63: 
        !            64:        case 'C':
        !            65:                switch (p->in.left->in.op) {
        !            66: 
        !            67:                  case ICON:    print_str("\tjbsr\t");
        !            68:                                acon(p->in.left);
        !            69:                                return;
        !            70: 
        !            71:                  case REG:
        !            72:                                if (indexreg(p->in.left)){
        !            73:                                        /* already in an address register */
        !            74:                                        print_str("\tjsr\t");
        !            75:                                        adrput(p->in.left);
        !            76:                                        putchar('@');
        !            77:                                        return;
        !            78:                                } /* else fall through */
        !            79: 
        !            80:                  case NAME:
        !            81:                  case OREG:    print_str("\tmovl\t");
        !            82:                                adrput(p->in.left);
        !            83:                                print_str(",a0\n\tjsr\ta0@");
        !            84:                                return;
        !            85: 
        !            86:                  default:      cerror("bad subroutine name");
        !            87:                }
        !            88: 
        !            89:        case 'E': /* load doubles with overly complex addressing */
        !            90:            {
        !            91:                /*
        !            92:                 * accomplished by simplifying addressing, then
        !            93:                 * falling through to case 'D'. 
        !            94:                 */
        !            95:                expand(p, cookie, "     lea     AR,A2\n");
        !            96:                /* 
        !            97:                 * we would like, at this point, just to paint over
        !            98:                 * p with  the place where we have the address calculated
        !            99:                 * and be done with it. too bad we can't: reclaim
        !           100:                 * needs to look at it. So we must RECUR here
        !           101:                 */
        !           102:                resc[1].tn.op = OREG;
        !           103:                resc[1].tn.lval = 0;
        !           104:                resc[1].tn.type = INCREF(DOUBLE);
        !           105:                zzzcode( &resc[1],  'D', cookie );
        !           106:                return;
        !           107:            }
        !           108:                
        !           109: 
        !           110:        case 'D': /* load-store doubles with auto-incr/decr addressing */
        !           111:                {
        !           112:                /* cases are: ASSIGN, or rewrite LEAF-node */
        !           113: #              define FORW     0
        !           114: #              define REVR     1
        !           115:                static char * lrewrite[] = { "\tmovl\tA.,A1\n\tmovl\tU.,U1\n",
        !           116:                                             "\tmovl\tU.,U1\n\tmovl\tA.,A1\n"};
        !           117:                static char * asreg[]    = { "\tmovl\tAR,AL\n\tmovl\tUR,UL\n",
        !           118:                                             "\tmovl\tUR,UL\n\tmovl\tAR,AL\n"};
        !           119:                char **rstring;
        !           120:                NODE * q;
        !           121:                if (p->in.op == ASSIGN){
        !           122:                    rstring = asreg; q = p->in.left;
        !           123:                } else {
        !           124:                    rstring = lrewrite; q = p;
        !           125:                }
        !           126:                if (q->in.op == UNARY MUL && q->in.left->in.op == ASG MINUS)
        !           127:                    expand( p, cookie, rstring[REVR] );
        !           128:                else
        !           129:                    expand( p, cookie, rstring[FORW] );
        !           130: #              undef FORW
        !           131: #              undef REVR
        !           132:                }
        !           133:                return;
        !           134: 
        !           135:        case 'K':
        !           136:                /*
        !           137:                 * 68881 floating point source operand
        !           138:                 * This is essentially the same as AR, but
        !           139:                 * in addition we check for the opportunity
        !           140:                 * to use floating-point immediate mode.
        !           141:                 * Only supported by the assembler in
        !           142:                 * coprocessor instructions.
        !           143:                 */
        !           144:                switch(optype(p->in.op)) {
        !           145:                case LTYPE:
        !           146:                        break;
        !           147:                case UTYPE:
        !           148:                        if (p->in.op != UNARY MUL)
        !           149:                                p = p->in.left;
        !           150:                        break;
        !           151:                case BITYPE:
        !           152:                        p = p->in.right;
        !           153:                        break;
        !           154:                }
        !           155:                if (p->in.op == FCON) {
        !           156:                        floatimmed(p);
        !           157:                } else {
        !           158:                        adrput(p);
        !           159:                }
        !           160:                return;
        !           161:                
        !           162:        case 'L':
        !           163:                m = p->in.left->in.type;
        !           164:                goto suffix;
        !           165: 
        !           166:        case 'R':
        !           167:                m = p->in.right->in.type;
        !           168:                goto suffix;
        !           169: 
        !           170:        case 'B':
        !           171:                m = p->in.type;         /* fall into suffix: */
        !           172: 
        !           173:        suffix: 
        !           174:                switch(m) {
        !           175:                case CHAR:
        !           176:                case UCHAR:
        !           177:                        c = 'b';
        !           178:                        break;
        !           179:                case SHORT:
        !           180:                case USHORT:
        !           181:                        c = 'w';
        !           182:                        break;
        !           183:                default:
        !           184:                        c = 'l';
        !           185:                        break;
        !           186:                }
        !           187:                putchar(c);
        !           188:                return;
        !           189: 
        !           190:        case 'F':
        !           191:                /*
        !           192:                 * print type characters for the source operand of
        !           193:                 * a 68881 floating point instruction.
        !           194:                 */
        !           195:                switch(optype(p->in.op)) {
        !           196:                case LTYPE:
        !           197:                        break;
        !           198:                case UTYPE:
        !           199:                        if (p->in.op != UNARY MUL)
        !           200:                                p = p->in.left;
        !           201:                        break;
        !           202:                case BITYPE:
        !           203:                        p = p->in.right;
        !           204:                        break;
        !           205:                }
        !           206:                /*
        !           207:                 * at this point, p is assumed to have matched
        !           208:                 * the shape SFLOAT_SRCE (cf. special())
        !           209:                 */
        !           210:                if (p->in.op == SCONV)
        !           211:                        p = p->in.left;
        !           212:                goto float_suffix;
        !           213: 
        !           214:        case 'G':
        !           215:                /*
        !           216:                 * print type character for the left subtree
        !           217:                 */
        !           218:                p = p->in.left;
        !           219:                if (p->in.op == SCONV)
        !           220:                        p = p->in.left;
        !           221:                goto float_suffix;
        !           222: 
        !           223:        case '.':
        !           224:        float_suffix:
        !           225:                if (p->in.op == REG && iscreg(p->tn.rval)) {
        !           226:                        /*
        !           227:                         * source is coprocessor reg; data
        !           228:                         * is in extended precision
        !           229:                         */
        !           230:                        putchar('x');
        !           231:                        return;
        !           232:                }
        !           233:                /*
        !           234:                 * print type character for the root node
        !           235:                 */
        !           236:                switch(BTYPE(p->in.type)) {
        !           237:                case CHAR:
        !           238:                        c = 'b';
        !           239:                        break;
        !           240:                case SHORT:
        !           241:                        c = 'w';
        !           242:                        break;
        !           243:                case FLOAT:
        !           244:                        c = 's';
        !           245:                        break;
        !           246:                case DOUBLE:
        !           247:                        c = 'd';
        !           248:                        break;
        !           249:                case UCHAR:
        !           250:                case USHORT:
        !           251:                        /*
        !           252:                         * the 68881 sign-extends integer operands
        !           253:                         */
        !           254:                        cerror("compiler botched unsigned operand");
        !           255:                        /*NOTREACHED*/
        !           256:                default:
        !           257:                        c = 'l';
        !           258:                        break;
        !           259:                }
        !           260:                putchar(c);
        !           261:                return;
        !           262:                
        !           263:        case 'N':  /* logical ops, turned into 0-1 */
        !           264:                /* use register given by RESC1 */
        !           265:                branch(m=getlab());
        !           266:                /* FALL THROUGH */
        !           267: 
        !           268:        make_boolean:
        !           269:                deflab( p->bn.label );
        !           270:                temp = getlr( p, '1' )->tn.rval;
        !           271:                printf( "       clrl    %s\n", rnames[temp]);
        !           272:                markused(temp);
        !           273:                deflab( m );
        !           274:                return;
        !           275: 
        !           276:        case 'H':
        !           277:                cbgen(p->in.op, p->in.left->in.type, p->bn.label,
        !           278:                        p->bn.reversed, FCCODES);
        !           279:                return;
        !           280: 
        !           281:        case 'I':
        !           282:                cbgen(p->in.op, p->in.left->in.type, p->bn.label,
        !           283:                        p->bn.reversed, CCODES);
        !           284:                return;
        !           285: 
        !           286:                /* stack management macros */
        !           287:        case '-':
        !           288:                print_str( "sp@-" );
        !           289:        case 'P':
        !           290:                toff += 4;
        !           291:                if (toff > maxtoff) maxtoff = toff;
        !           292:                return;
        !           293: 
        !           294:        case '0':
        !           295:                toff = 0; return;
        !           296: 
        !           297:        case '~':
        !           298:                /* complimented CR */
        !           299:                p->in.right->tn.lval = ~p->in.right->tn.lval;
        !           300:                conput( getlr( p, 'R' ) );
        !           301:                p->in.right->tn.lval = ~p->in.right->tn.lval;
        !           302:                return;
        !           303: 
        !           304:        case 'M':
        !           305:                /* negated CR */
        !           306:                p->in.right->tn.lval = -p->in.right->tn.lval;
        !           307:        case 'O':
        !           308:                conput( getlr( p, 'R' ) );
        !           309:                p->in.right->tn.lval = -p->in.right->tn.lval;
        !           310:                return;
        !           311: 
        !           312:        case 'T':
        !           313:                /* Truncate longs for type conversions:
        !           314:                    INT|UNSIGNED -> CHAR|UCHAR|SHORT|USHORT
        !           315:                   increment offset to second word */
        !           316: 
        !           317:                m = p->in.type;
        !           318:                p = p->in.left;
        !           319:                switch( p->in.op ){
        !           320:                case NAME:
        !           321:                case OREG:
        !           322:                        if (p->in.type==SHORT || p->in.type==USHORT)
        !           323:                          p->tn.lval += (m==CHAR || m==UCHAR) ? 1 : 0;
        !           324:                        else p->tn.lval += (m==CHAR || m==UCHAR) ? 3 : 2;
        !           325:                        return;
        !           326:                case REG:
        !           327:                        return;
        !           328:                default:
        !           329:                        cerror( "Illegal ZT type conversion" );
        !           330:                        return;
        !           331: 
        !           332:                        }
        !           333: 
        !           334:        case 't':
        !           335:                /*
        !           336:                 * Lengthen little (unsigned) things. Try to be smart
        !           337:                 * about instruction sequences.
        !           338:                 */
        !           339:                s = p->in.left;
        !           340:                m = s->in.type;
        !           341:                if (ISUNSIGNED(m)){
        !           342:                    /* zero-extending into temp register */
        !           343:                    if ( istnode(s) && s->tn.rval == resc[0].tn.rval ){
        !           344:                        /* must use andl instructions */
        !           345:                        print_str_str( "        andl    #0x", (m==UCHAR)?"ff":"ffff");
        !           346:                    } else {
        !           347:                        print_str_str_nl( "     moveq   #0,", rnames[ resc[0].tn.rval ] );
        !           348:                        printf( "       mov%c   ", (m==UCHAR)?'b':'w');
        !           349:                        adrput( s );
        !           350:                    }
        !           351:                    putchar(','); print_str_nl(rnames[ resc[0].tn.rval ] );
        !           352:                } else {
        !           353:                    /* sign-extending into temp register */
        !           354:                    if (!(istnode(s) && s->tn.rval == resc[0].tn.rval) ){
        !           355:                        /* not already in its register */
        !           356:                        printf( "       mov%c   ", (m==CHAR)?'b':'w');
        !           357:                        adrput( s );
        !           358:                        putchar(','); print_str_nl(rnames[ resc[0].tn.rval ] );
        !           359:                    }
        !           360:                    /* sign-extend */
        !           361:                    if (m == CHAR)
        !           362:                        print_str_str_nl( "     extw    ", rnames[resc[0].tn.rval]);
        !           363:                    if (p->in.type != SHORT && p->in.type != USHORT)
        !           364:                        print_str_str_nl( "     extl    ", rnames[resc[0].tn.rval]);
        !           365:                }
        !           366:                return;
        !           367: 
        !           368:        case 'W':       /* structure size */
        !           369:                if( p->in.op == STASG )
        !           370:                        print_d(p->stn.stsize);
        !           371:                else    cerror( "Not a structure" );
        !           372:                return;
        !           373: 
        !           374:        case 'S':  /* structure assignment */
        !           375:                stmove( p, cookie );
        !           376:                return;
        !           377: 
        !           378:        case 'X':{      /* indexed effective address */
        !           379:                NODE fake,*lp,*rp;
        !           380:                int flags;
        !           381:                lp = p->in.left;
        !           382:                rp = p->in.right;
        !           383:                R2PACKFLGS(flags, rp->in.type == SHORT, 0, 0);
        !           384:                fake.in.op = OREG;
        !           385:                fake.tn.rval = R2PACK(lp->in.left->tn.rval, rp->tn.rval, flags);
        !           386:                fake.tn.name = "\0";
        !           387:                fake.tn.lval = lp->in.right->tn.lval;
        !           388:                oregput(&fake);
        !           389:                return;
        !           390:                }
        !           391: 
        !           392:        case 'a':
        !           393:                /* assign something to a bit field */
        !           394:        case 'b':
        !           395:                /* extract a bit field */
        !           396:        case 'c':
        !           397:                /* compare bit field with constant for CC only */
        !           398:                eval_field( p, c, cookie);
        !           399:                return;
        !           400: 
        !           401:        case 'f': /* floating-point operation */
        !           402:                /* since the floating-point format may be changed with a
        !           403:                 * compile-time switch, we need to go think about this
        !           404:                 */
        !           405:                floatcode( p, cookie );
        !           406:                fltused++;
        !           407:                return;
        !           408:        case 'g': /* floating-point conversion to normal register */
        !           409:                /* anything that looks like a floating type conversion
        !           410:                 * or a floating-register load or store comes here.
        !           411:                 */
        !           412:                floatconv( p, c, cookie );
        !           413:                fltused++;
        !           414:                return;
        !           415: 
        !           416:        case 'm': /* multiplication by a constant */
        !           417:                conmul( p, cookie );
        !           418:                return;
        !           419: 
        !           420:        case 'd': /* division by a constant */
        !           421:                condiv( p, cookie );
        !           422:                return;
        !           423: 
        !           424:        case 'r': /* remainder by a constant */
        !           425:                conrem( p, cookie );
        !           426:                return;
        !           427: 
        !           428:        case ' ': /* leaf-type for effect only */
        !           429:                /*
        !           430:                 * usually this will generate NO code.
        !           431:                 * the exception is INCR or ASG MINUS, as in
        !           432:                 * *p++, *--p;
        !           433:                 * these are recognized as side effects of addressing 
        !           434:                 * modes, so have not been dealt with by higher functions.
        !           435:                 */
        !           436:                if (p->in.op == UNARY MUL){
        !           437:                    if (p->in.left->in.op == INCR){
        !           438:                        printf("        addql   #%d, %s\n",
        !           439:                        tlen(p), rnames[p->in.left->in.left->tn.rval]);
        !           440:                    } else if (p->in.left->in.op == ASG MINUS){
        !           441:                        printf("        subql   #%d, %s\n",
        !           442:                        tlen(p), rnames[p->in.left->in.left->tn.rval]);
        !           443:                    }
        !           444:                }
        !           445:                return;
        !           446: 
        !           447:        case 'l': /* lea or addl instruction, as appropriate */
        !           448:                if (p->in.left->tn.rval == resc[0].tn.rval){
        !           449:                    /* really a += */
        !           450:                    expand( p, cookie, "        addZR   AR,A1\n");
        !           451:                } else {
        !           452:                    /* really is a 3-address lea */
        !           453:                    expand( p, cookie, "        lea     AL@(0,AR:ZR),A1\n");
        !           454:                }
        !           455:                return;
        !           456: 
        !           457:        case 'v': /* generate trapv for signed arithmetic */
        !           458:                trapv(p->in.type);
        !           459:                return;
        !           460: 
        !           461:        case 'V': /* generate bound-testing code */
        !           462:                bound_test(p, cookie);
        !           463:                return;
        !           464: 
        !           465:        default:
        !           466:                cerror( "illegal zzzcode" );
        !           467:        }
        !           468: }
        !           469: 
        !           470: #define checkout if (resc[opno].tn.op != REG) cerror("struct-assign botch")
        !           471: 
        !           472: NODE *
        !           473: cpytmp( l, opno ) NODE *l;
        !           474: {
        !           475:        NODE *new;
        !           476:        print_str( (l->in.op == REG)||(ISPTR(l->in.type))? "    movl    " : "   lea     ");
        !           477:        adrput( l );
        !           478:        checkout;
        !           479:        new = &resc[opno];
        !           480:        new->tn.type = ISPTR(l->in.type)?l->in.type:INCREF(l->in.type);
        !           481:        markused(new->tn.rval);
        !           482:        putchar(','); print_str_nl(rnames[new->tn.rval] );
        !           483:        return new;
        !           484: }
        !           485: 
        !           486: 
        !           487: void
        !           488: stmove( p , cookie ) register NODE *p;
        !           489: {
        !           490:        register NODE *l, *r;
        !           491:        register size, i;
        !           492:        extern NODE resc[];
        !           493:        int opno = 1;
        !           494:        int rcopy;
        !           495:        int xsize;
        !           496:        int labl;
        !           497:        int loopcode;
        !           498:        register char *cnt, *lhs, *rhs;
        !           499: 
        !           500:        char **moves;
        !           501: #      define MOVBSTRNG        0
        !           502: #      define MOVWSTRNG        1
        !           503: #      define MOVLSTRNG        2
        !           504:        static char * asgstrings[] = {
        !           505:                "       movb    AR,AL\n",
        !           506:                "       movw    AR,AL\n",
        !           507:                "       movl    AR,AL\n",
        !           508:        };
        !           509:        static char * argstrings[] = {
        !           510:                "       movb    AR,sp@-\n",
        !           511:                "       movw    AR,sp@-\n",
        !           512:                "       movl    AR,sp@-\n",
        !           513:        };
        !           514: 
        !           515:        if( p->in.op == STASG ){
        !           516:            l = p->in.left;
        !           517:            r = p->in.right;
        !           518:            moves = asgstrings;
        !           519:        } else if( p->in.op == STARG ){  /* store an arg onto the stack */
        !           520:            /*
        !           521:             * "r" and "l" are obviously misnomers here.
        !           522:             * they should be "from" and, perhaps, "to".
        !           523:             */
        !           524:            r = p->in.left;
        !           525:            checkout;
        !           526:            l = &resc[opno++];
        !           527:            markused(l->tn.rval);
        !           528:            moves = argstrings;
        !           529:        } else 
        !           530:            cerror( "STASG bad" );
        !           531: 
        !           532:        if ( r->in.op == ICON )
        !           533:            r->in.op = NAME;
        !           534:        /*
        !           535:         * avoid complicated memory operands
        !           536:         */
        !           537:        if (l->in.op == OREG && R2TEST(l->tn.rval)) {
        !           538:            l = cpytmp( l, opno++ );
        !           539:        }
        !           540:        if (r->in.op == OREG && R2TEST(r->tn.rval)) {
        !           541:            r = cpytmp( r, opno++ );
        !           542:        }
        !           543:        size = p->stn.stsize;
        !           544:        xsize = size + (size&1); /* must be even */
        !           545: 
        !           546:        /*
        !           547:         * now we make a totally arbitrary decision about
        !           548:         * when to loop, and when to emit straight-line code.
        !           549:         */
        !           550: 
        !           551:        if (size <= 8){
        !           552:            /* straight-line */
        !           553:            NODE xxx;
        !           554: 
        !           555:            /* the MIT strategy -- gross, no? */
        !           556:            if( l->in.op != REG && ISPTR(l->in.type))
        !           557:                l = cpytmp( l, opno++ );
        !           558:            if( r->in.op != REG && ISPTR(r->in.type))
        !           559:                r = cpytmp( r, opno++ );
        !           560:            xxx.in.op = STASG;
        !           561:            xxx.in.left = l;
        !           562:            xxx.in.right = r;
        !           563:            if( r->tn.op == REG ){
        !           564:                r->tn.op = OREG;
        !           565:                r->tn.type = DECREF(r->tn.type);
        !           566:            }
        !           567:            if( l->in.op == REG ) l->in.op = OREG;
        !           568:            r->tn.lval += size;
        !           569:            l->tn.lval += size;
        !           570: 
        !           571:            switch (size&03){
        !           572:                /* do special cases */
        !           573:            case 1:
        !           574:            case 3:
        !           575:                r->tn.lval -= 1;
        !           576:                l->tn.lval -= 1;
        !           577:                expand( &xxx, cookie, moves[MOVBSTRNG] );
        !           578:                if ((size&03) == 1) break;
        !           579:                /* case 3 falls through */
        !           580:            case 2:
        !           581:                r->tn.lval -= 2;
        !           582:                l->tn.lval -= 2;
        !           583:                expand( &xxx, cookie, moves[MOVWSTRNG] );
        !           584:            }
        !           585:            size -= size&03;
        !           586:            /* assert( size%4 == 0 ) */
        !           587:            while( size ){ /* simple load/store loop */
        !           588:                r->tn.lval -= 4;
        !           589:                l->tn.lval -= 4;
        !           590:                size -= 4;
        !           591:                expand( &xxx, cookie, moves[MOVLSTRNG] );
        !           592:            }
        !           593:        } else {
        !           594:            /* loop code */
        !           595:            loopcode = size >= 20;
        !           596:            if (loopcode) {
        !           597:                cnt = rnames[resc[0].tn.rval];
        !           598:                printf("        mov%c   #%d,%s\n", (size<(1<<16))?'w':'l',
        !           599:                    size/4-1, cnt);
        !           600:            }
        !           601:            if ( !istnode(l)){
        !           602:                if (l->tn.op==OREG && !R2TEST(l->tn.rval)
        !           603:                  && istreg(l->tn.rval) && l->tn.lval==0)
        !           604:                    l->tn.op=REG;
        !           605:                else
        !           606:                    l = cpytmp( l, opno++ );
        !           607:            }
        !           608:            if ( !istnode(r) ){
        !           609:                r = cpytmp( r, opno++ );
        !           610:                rcopy = 1; /* this is not our real rhs */
        !           611:            } else
        !           612:                rcopy = 0;
        !           613:            lhs = rnames[l->tn.rval];
        !           614:            rhs = rnames[r->tn.rval];
        !           615:            if (p->in.op==STARG){
        !           616:                /*
        !           617:                 * structure argument:
        !           618:                 *    push space on stack (lea sp@(size),sp)
        !           619:                 *    copy sp to a temp register we can bomb
        !           620:                 *    go for it.
        !           621:                 */
        !           622:                if (xsize <(1<<16))
        !           623:                    printf(  "  lea     sp@(-%d),sp\n", xsize);
        !           624:                else
        !           625:                    printf( "   subl    #%d,sp\n", xsize);
        !           626:                printf("        movl    sp,%s\n", lhs);
        !           627:            }
        !           628:            if (loopcode) {
        !           629:                print_label(labl= getlab());
        !           630:                /* now emit the 2-instruction loop */
        !           631:                printf("        movl    %s@+,%s@+\n", rhs, lhs);
        !           632:                printf("        dbra    %s,L%d\n", cnt, labl);
        !           633:                if (size>=(1<<16)){
        !           634:                    /* "long dbra" */
        !           635:                    printf("    clrw    %s\n", cnt);
        !           636:                    printf("    subql   #1,%s\n", cnt);
        !           637:                    printf("    jcc     L%d\n", labl);
        !           638:                }
        !           639:            } else {
        !           640:                /* use autoincrement mode in an unrolled loop */
        !           641:                int n;
        !           642:                for (n = 0; n < size/4; n++)
        !           643:                    printf("    movl    %s@+,%s@+\n", rhs, lhs);
        !           644:            }
        !           645:            switch (size&03) {
        !           646:                /* oops -- stuff leftover */
        !           647:            case 3:
        !           648:                printf("        movw    %s@+,%s@+\n", rhs, lhs);
        !           649:                /* fall thorugh */
        !           650:            case 1:
        !           651:                printf("        movb    %s@,%s@\n", rhs, lhs);
        !           652:                break;
        !           653:            case 2:
        !           654:                printf("        movw    %s@,%s@\n", rhs, lhs);
        !           655:                break;
        !           656:            }
        !           657:            if (cookie&(INBREG|INTBREG) && !rcopy){
        !           658:                /* oh damn, must repair damage */
        !           659:                int temp;
        !           660:                temp = p->stn.stsize;
        !           661:                p->stn.stsize &= ~0x3;
        !           662:                if (size <(1<<16))
        !           663:                    expand( p, FOREFF, "        lea     AR@(-ZW),AR\n");
        !           664:                else
        !           665:                    expand( p, FOREFF, "        subl    #ZW,AR\n");
        !           666:                p->stn.stsize = temp;
        !           667:            }
        !           668:        }
        !           669:        if (p->in.op==STARG){
        !           670:            /* keep toff up-to-date */
        !           671:            if (xsize<3){
        !           672:                /* must pad */
        !           673:                printf("        subqw   #2,sp\n");
        !           674:                xsize = 4;
        !           675:            }
        !           676:            toff += xsize;
        !           677:            if (toff>maxtoff) maxtoff= toff;
        !           678:        } else {
        !           679:            r = p->in.right;
        !           680:            if ( r->in.op == NAME )
        !           681:                r->in.op = ICON;
        !           682:            else if (!(cookie&SANY) && r->tn.op==OREG && !ISPTR(r->tn.type)){
        !           683:                /* we get to make up a (choke) address here */
        !           684:                if (r->tn.lval == 0){
        !           685:                    r->in.op = REG;
        !           686:                    r->tn.type = INCREF(r->tn.type);
        !           687:                } else 
        !           688:                    cerror("trapped in a multiple-structue-assigment");
        !           689:            }
        !           690:        }
        !           691: }
        !           692: 
        !           693: #undef checkout
        !           694: 
        !           695: /*
        !           696:  * alignfield(p, byteoff)
        !           697:  *     Align an operand for a 68020 bit field operation.  If byteoff
        !           698:  *     is nonzero, subtract it (it was previously added to the offset
        !           699:  *     part of p->in.left, possibly resulting in an odd offset). Then
        !           700:  *     longword-align the offset, assuming that names and activation
        !           701:  *     records are longword-aligned.
        !           702:  */
        !           703: static
        !           704: alignfield(p, byteoff)
        !           705:        register NODE *p;       /* assumed to be FLD op */
        !           706:        int byteoff;
        !           707: {
        !           708:        register NODE *lp;      /* assumed to be operand address */
        !           709:        int fieldoff, fieldsize, residue;
        !           710: 
        !           711:        lp = p->in.left;
        !           712:        switch( lp->in.op ){
        !           713:        case NAME:
        !           714:        case ICON:
        !           715:        case OREG:
        !           716:                if (byteoff) {
        !           717:                        /* undo it */
        !           718:                        lp->tn.lval -= byteoff;
        !           719:                }
        !           720:                residue = lp->tn.lval % (SZLONG/SZCHAR);
        !           721:                if (residue < 0) {
        !           722:                        /*
        !           723:                         * careful about AUTOs --
        !           724:                         * the offsets are negative
        !           725:                         */
        !           726:                        residue += (SZLONG/SZCHAR);
        !           727:                }
        !           728:                fieldoff = UPKFOFF(p->tn.rval) + residue*SZCHAR;
        !           729:                fieldsize = UPKFSZ(p->tn.rval);
        !           730:                if (fieldoff + fieldsize <= SZLONG) {
        !           731:                        /*
        !           732:                         * take bytes away from the operand address,
        !           733:                         * and put bits back in the field offset.
        !           734:                         */
        !           735:                        lp->tn.lval -= residue;
        !           736:                        p->tn.rval = PKFIELD(fieldsize, fieldoff);
        !           737:                }
        !           738:                break;
        !           739:        default:
        !           740:                cerror( "illegal address in alignfield" );
        !           741:                break;
        !           742:        }
        !           743: }
        !           744: 
        !           745: expandfield(p)
        !           746:     register NODE *p;
        !           747: {
        !           748:     printf( "{#%d:#%d}", UPKFOFF(p->tn.rval), UPKFSZ(p->tn.rval) );
        !           749: }
        !           750: 
        !           751: void
        !           752: eval_field( p, c, cookie )
        !           753:     NODE *p;
        !           754:     char c;
        !           755: {
        !           756:     register temp, m;
        !           757:     register NODE *l, *r;
        !           758:     int lobyte, hibyte;
        !           759:     char *regname;
        !           760:     NODE *fieldnode;
        !           761:     int conval;
        !           762: 
        !           763:     l = p->in.left;
        !           764:     r = p->in.right;
        !           765:     fieldnode = (c == 'b') ? p : p->in.left;
        !           766:     lobyte = (SZINT - fldshf - 1)/SZCHAR;  /* byte containing low-order bit  */
        !           767:     hibyte = (SZINT -fldshf -fldsz)/SZCHAR;/* byte containing high-order bit */
        !           768:     if (fieldnode->in.left->tn.op == REG){
        !           769:        if ( ISPTR(fieldnode->in.left->tn.type)){
        !           770:            fieldnode->in.left->tn.op = OREG;
        !           771:        } else {
        !           772:            /* always use longword accesses to registers */
        !           773:            hibyte = 0;
        !           774:            temp = SZINT;
        !           775:            p->in.type = UNSIGNED;
        !           776:            goto longonly;
        !           777:        }
        !           778:     } 
        !           779:        
        !           780:     if (lobyte==hibyte){
        !           781:        /* ok to do byte accesses to memory */
        !           782:        temp = SZCHAR;
        !           783:        p->in.type = UCHAR;
        !           784:     } else if ((hibyte&1) || (hibyte < (lobyte-1))){
        !           785:        /* must do longword access */
        !           786:        hibyte = 0;
        !           787:        temp = SZINT; 
        !           788:        p->in.type = UNSIGNED;
        !           789:     } else {
        !           790:        /* word access */
        !           791:        temp = SZSHORT;
        !           792:        p->in.type = USHORT;
        !           793:     }
        !           794: 
        !           795:     /* adjust shift value, paint over left type and address */
        !           796:     fldshf = temp - (SZINT-fldshf -(hibyte*SZCHAR));
        !           797:     if (hibyte){
        !           798:        incraddr( fieldnode, hibyte);
        !           799:     }
        !           800:     
        !           801: longonly:
        !           802: 
        !           803:     switch (c){
        !           804:     case 'a':
        !           805:        /* assignment of a value to a bit field */
        !           806:        /* the two cases are: constant r-h-s, and variable r-h-s */
        !           807:        /* the constant case has several interesting sub-cases   */
        !           808:        if (r->tn.op == ICON){
        !           809:            /* easy case */
        !           810:            conval = r->tn.lval;
        !           811:            m = r->tn.lval;
        !           812:            if (fldsz == 1) {
        !           813:                /* very easy case */
        !           814:                print_str_d( (m&1)?"    bset    #":"    bclr    #", fldshf); putchar(',');
        !           815:                adrput( l );
        !           816:            } else {
        !           817:                /* 
        !           818:                 * wide field:
        !           819:                 * depending on field size and alignment, we may
        !           820:                 * have to do word or longword accesses
        !           821:                 */
        !           822:                if (m==0){
        !           823:                    /* clearing entire field */
        !           824:                    if (fldshf==0 && fldsz == temp){
        !           825:                        /* no masking involved -- whole unit */
        !           826:                        expand( p, cookie, "    clrZB   AL");
        !           827:                    } else {
        !           828:                        expand( p, cookie, "    andZB   #N,AL");
        !           829:                    }
        !           830:                } else if ( m==-1 || m==BITMASK(fldsz)){
        !           831:                    /* setting entire field */
        !           832:                    if (fldshf==0 && fldsz == temp){
        !           833:                        /* no masking involved -- whole unit */
        !           834:                        if (fldsz == SZCHAR) {
        !           835:                            expand( p, cookie, "        st      AL");
        !           836:                        } else {
        !           837:                            expand( p, cookie, "        movZB   #CR,AL");
        !           838:                        }
        !           839:                    } else {
        !           840:                        expand( p, cookie, "    orZB    #M,AL" );
        !           841:                    }
        !           842:                } else {
        !           843:                    /* -- inserting value -- */
        !           844:                    if (fldshf==0 && fldsz == temp){
        !           845:                        /* no masking involved -- whole unit */
        !           846:                        expand( p, cookie, "    movZB   #CR,AL");
        !           847:                    } else {                    
        !           848:                        m &= BITMASK(fldsz);
        !           849:                        r->tn.lval = m<<fldshf;
        !           850:                        expand(p, cookie, "     andZB   #N,AL\n orZB    #CR,AL");
        !           851:                    }
        !           852:                }
        !           853:            }
        !           854:            /* restore old ICON value in case we want to use it as
        !           855:               the result of the assignment */
        !           856:            r->tn.lval = conval;
        !           857:        } else {
        !           858:            /* non-constant */
        !           859:            /* there are only two cases here : 
        !           860:               shifting and masking, or
        !           861:               not shifting or masking
        !           862:            */
        !           863:            if (fldsz == temp && fldshf == 0){
        !           864:                /* direct move */
        !           865:                expand( p, cookie, "    movZB   AR,AL");
        !           866:            } else if (use68020) {
        !           867:                /* the normal, ugly case, with 68020 instructions */
        !           868:                alignfield(fieldnode, hibyte);
        !           869:                expand( p, cookie, "    bfins   AR,AL");
        !           870:                expandfield(fieldnode);
        !           871:            } else {
        !           872:                /* the normal, ugly case, with 68010 instructions */
        !           873:                /* clear field in destination */
        !           874:                expand( p, cookie, "    andZB   #N,AL\n");
        !           875:                /* move value to temp and adjust */
        !           876:                temp = fldshf;
        !           877:                fldshf = 0;
        !           878:                if (r->tn.op == REG && istreg(r->tn.rval) && (cookie&FOREFF)){
        !           879:                    /* do it in place */
        !           880:                    regname = rnames[r->tn.rval];
        !           881:                    /* mask source to the right number of bits, and */
        !           882:                    expand( p, cookie, "        andZB   #M,AR\n");
        !           883:                    /* shift into place */
        !           884:                    shiftreg( temp, regname , -1, 0, 'l', UNSIGNED);
        !           885:                    /* combine source into destination */
        !           886:                    expand( p, cookie, "        orZB    AR,AL");
        !           887:                } else {
        !           888:                    /* must copy over */
        !           889:                    rmove( resc[0].tn.rval, r->tn.rval, UNSIGNED );
        !           890:                    expand( p, cookie, "        andZB   #M,A1\n");
        !           891:                    regname = rnames[ resc[0].tn.rval ];
        !           892:                    shiftreg( temp, regname , -1, 0, 'l', UNSIGNED);
        !           893:                    expand( p, cookie, "        orZB    A1,AL");
        !           894:                }
        !           895:            }
        !           896:        }
        !           897:        p->in.type = UNSIGNED;
        !           898:        return;
        !           899: 
        !           900:     case 'b':
        !           901:        /* extracting field value -- either for CC or for value */
        !           902:        if (cookie & FORCC){
        !           903: compare_with_zero:
        !           904:            /* only extracting value to compare it with zero */
        !           905:            if (fldsz == 1){
        !           906:                /* snap case -- so long as fields are unsigned! */
        !           907:                print_str_d( "  btst    #", fldshf); putchar(',');
        !           908:                adrput( l );
        !           909:            } else if (fldsz == temp && fldshf == 0){
        !           910:                /* direct memory test */
        !           911:                expand( p, cookie, "    tstZB   AL");
        !           912:            } else {
        !           913:                /*
        !           914:                 * move value into a register -- and with mask to set CC.
        !           915:                 * We would have to worry about setting the N condition
        !           916:                 * here, but our unsigned-ness prevents this from being
        !           917:                 * a problem.
        !           918:                 */
        !           919:                if (l->tn.op == REG && istreg(l->tn.rval)){
        !           920:                    expand( p, cookie, "        andl    #M,AL");
        !           921:                } else {
        !           922:                    expand( p, cookie, 
        !           923:                        "       movZB   AL,A1\n andZB   #M,A1");
        !           924:                }
        !           925:            }
        !           926:        } else {
        !           927:            /* extracting value for value's sake */
        !           928:            if (l->tn.op == REG && istreg(l->tn.rval)){
        !           929:                regname = rnames[ l->tn.rval ];
        !           930:                if (use68020 && fldshf != 0) {
        !           931:                    alignfield(fieldnode, hibyte);
        !           932:                    expand( p, cookie, "        bfextu  AL");
        !           933:                    expandfield(fieldnode);
        !           934:                    putchar(','); print_str(regname);
        !           935:                } else {
        !           936:                    shiftreg( -fldshf, regname , resc[0].tn.rval, 0, 'l', UNSIGNED);
        !           937:                    fldshf = 0;
        !           938:                    expand( p, cookie,  "       andl    #M,AL");
        !           939:                }
        !           940:            } else {
        !           941:                regname = rnames[ resc[0].tn.rval ];
        !           942:                if (use68020 && fldshf != 0) {
        !           943:                    alignfield(fieldnode, hibyte);
        !           944:                    expand( p, cookie, "        bfextu  AL");
        !           945:                    expandfield(fieldnode);
        !           946:                    putchar(','); print_str(regname);
        !           947:                } else {
        !           948:                    if (temp != SZINT){
        !           949:                        print_str_str_nl("      moveq   #0,", regname );
        !           950:                    }
        !           951:                    expand( p, cookie, "        movZB   AL,A1");
        !           952:                    if (fldsz != temp || fldshf != 0){
        !           953:                        putchar('\n');
        !           954:                        shiftreg( -fldshf, regname, -1, 0, 'l', UNSIGNED);
        !           955:                        fldshf = 0;
        !           956:                        expand( p, cookie,      "       andZB   #M,A1");
        !           957:                    }
        !           958:                }
        !           959:            }
        !           960:        }
        !           961: 
        !           962:        fieldnode->in.type = UNSIGNED;
        !           963:        return;
        !           964: 
        !           965:     case 'c':
        !           966:        /* comparison of field value with constant value for CC only */
        !           967:        m = r->tn.lval;
        !           968:        if (m==0) goto compare_with_zero;
        !           969:        r->tn.lval = m << fldshf;
        !           970:        if (temp == fldsz && fldshf == 0 ){
        !           971:            /* compare directly to memory */
        !           972:            expand(p, cookie, " cmpZB   #CR,AL");
        !           973:        } else if (l->tn.op == REG && istreg(l->tn.rval) && cookie&FOREFF){
        !           974:            /* munge in place */
        !           975:            expand( p, cookie," andZB   #M,AL\n cmpZB   #CR,AL");
        !           976:        } else {
        !           977:            /* move to register, mask, compare */
        !           978:            expand( p, cookie,
        !           979:                "       movZB   AL,A1\n andZB   #M,A1\n cmpZB   #CR,A1");
        !           980:        }
        !           981:     }
        !           982: 
        !           983: }
        !           984: 
        !           985: /* routine used by the field-evaluation code to emit shifting instructions.
        !           986:    "val" is the amount to shift, s is the name of the register to shift,
        !           987:    and "reg" is the register NUMBER of a helper, if one is available.
        !           988:    If val<0, we're doing right shifts
        !           989:    If needclr != 0, must clear lower word after swap.
        !           990: */
        !           991: void
        !           992: shiftreg( val, s , reg, needclr, typechar, type )
        !           993:     char *s;
        !           994:     char typechar;
        !           995: {
        !           996:     char *t;
        !           997:     char *shift = "lsll";
        !           998:     int lshift;
        !           999:     if (val < 0 ){
        !          1000:        shift = "lsrl";
        !          1001:        val =   -val;
        !          1002:        lshift = 0;
        !          1003:     } else{
        !          1004:        lshift = 1;
        !          1005:        shift[0] = (ISUNSIGNED(type) || ISPTR(type))? 'l' : 'a';
        !          1006:     }
        !          1007:     shift[3] = typechar; /* ugly hack */
        !          1008:     if (val > 16 ){
        !          1009:        if (reg >= 0){
        !          1010:            printf("    movl    #%d,%s\n", val, t=rnames[ reg ]);
        !          1011:            printf("    %s      %s,%s\n", shift, t, s);
        !          1012:            trapv(type);
        !          1013:            return;
        !          1014:        }
        !          1015:        if (!(chk_ovfl && shift[0] == 'a')){
        !          1016:            print_str_str_nl("  swap    ", s);
        !          1017:            if (needclr&&lshift)
        !          1018:                print_str_str_nl("      clrw    ", s);
        !          1019:            val -= 16;
        !          1020:        }
        !          1021:     }
        !          1022:     while (val > 0){
        !          1023:        if (val> 8){
        !          1024:            printf("    %s      #8,%s\n", shift, s);
        !          1025:            val -= 8;
        !          1026:        } else {
        !          1027:            if (val==1 && lshift)
        !          1028:                printf("        add%c   %s,%s\n", typechar, s,s);
        !          1029:            else
        !          1030:                printf("        %s      #%d,%s\n", shift, val, s);
        !          1031:            val = 0;
        !          1032:        }
        !          1033:        trapv(type);
        !          1034:     }
        !          1035: }
        !          1036: 
        !          1037: void
        !          1038: incraddr( p , v)
        !          1039:        register NODE *p; 
        !          1040:        long v;
        !          1041: {
        !          1042:        /* bump the address p by the value b. */
        !          1043:        if( p->in.op == FLD ){
        !          1044:                p = p->in.left;
        !          1045:        }
        !          1046:        switch( p->in.op ){
        !          1047:        case NAME:
        !          1048:        case ICON:
        !          1049:        case OREG:
        !          1050:                p->tn.lval += v;
        !          1051:                break;
        !          1052:        default:
        !          1053:                cerror( "illegal incraddr address" );
        !          1054:                break;
        !          1055: 
        !          1056:        }
        !          1057: }
        !          1058: 
        !          1059: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
        !          1060: 
        !          1061: insput( p ) register NODE *p; 
        !          1062: {
        !          1063: #ifndef IEEECCODES
        !          1064:        printf(ccodes[p->in.op-EQ]);
        !          1065: #else   IEEECCODES
        !          1066:        if (ISFLOATING(p->in.left->in.type)) {
        !          1067:                printf(fccodes[p->in.op-EQ]);
        !          1068:        } else {
        !          1069:                printf(ccodes[p->in.op-EQ]);
        !          1070:        }
        !          1071: #endif  IEEECCODES
        !          1072: }
        !          1073: 
        !          1074: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
        !          1075: 
        !          1076: /*
        !          1077:  * Generate conditional branches from a relational operator.
        !          1078:  * The exact form of the branch depends on:
        !          1079:  * 1. whether or not the compared operands have floating point types
        !          1080:  * 2. whether or not the coprocessor condition code is used
        !          1081:  * 3. whether the operator has been negated.
        !          1082:  */
        !          1083: 
        !          1084: cbgen( o, type, label, reversed, mode )
        !          1085:        int o;          /* relational op {EQ, NE, LT, LE, ...} */
        !          1086:        TWORD type;     /* operand type - determines opcode */
        !          1087:        int label;      /* destination label */
        !          1088:        int reversed;   /* =1 if op is to be negated */
        !          1089:        int mode;       /* if FCCODES, use coprocessor condition codes */
        !          1090: {
        !          1091:        char *prefix;
        !          1092:        char *opname;
        !          1093: 
        !          1094: #ifndef IEEECCODES
        !          1095:        if (reversed) {
        !          1096:                /* treat !(a < b) as (a >= b) */
        !          1097:                o = negrel[o-EQ];
        !          1098:        }
        !          1099:        if (mode == FCCODES) {
        !          1100:                prefix = "fj";
        !          1101:                opname = fccodes[o-EQ];
        !          1102:        } else {
        !          1103:                prefix = "j";
        !          1104:                opname = ccodes[o-EQ];
        !          1105:        }
        !          1106: #else  IEEECCODES
        !          1107:        if (ISFLOATING(type)) {
        !          1108:                prefix = (mode == FCCODES ? "fj" : "jf");
        !          1109:                opname = (reversed ? fnegccodes[o-EQ] : fccodes[o-EQ]);
        !          1110:        } else {
        !          1111:                prefix = "j";
        !          1112:                if (reversed)
        !          1113:                        o = negrel[o-EQ];
        !          1114:                opname = ccodes[o-EQ];
        !          1115:        }
        !          1116: #endif IEEECCODES
        !          1117:        printf("        %s%s    L%d\n", prefix, opname, label);
        !          1118: }
        !          1119: 
        !          1120: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
        !          1121: 
        !          1122: #ifdef FORT
        !          1123: branch(lab)
        !          1124:        int lab;
        !          1125: {
        !          1126:        printf("        jra     L%d\n", lab);
        !          1127: }
        !          1128: #endif FORT

unix.superglobalmegacorp.com

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