Annotation of researchv9/cmd/sun/pcc/local2.c, revision 1.1.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.