Annotation of researchv9/cmd/sun/c2/register.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)register.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: #include "as.h"
        !            10: #include "c2.h"
        !            11: 
        !            12: extern struct ins_bkt *sopcode();
        !            13: extern NODE *insert_label();
        !            14: extern struct oper *newoperand();
        !            15: extern unsigned short make_touchop();
        !            16: int fortranprog = 0;
        !            17: static struct sym_bkt *skyname;
        !            18: #if TRACKSP
        !            19: extern int spoffset; /* track a6-a7 distance */
        !            20: #endif TRACKSP
        !            21: 
        !            22: extern struct ins_bkt *moveq, *subql, *addql;
        !            23: 
        !            24: #define NREG (FP7REG-D0REG+1)
        !            25: #define CONSRC 0
        !            26: #define CONDST 1
        !            27: struct regcon {
        !            28:     struct oper con;
        !            29:     subop_t size;
        !            30: } regcon[ NREG ][2];
        !            31: 
        !            32: #define NMEM   100     /* totally arbitrary number */
        !            33: static struct memcon {
        !            34:     struct oper addr;
        !            35:     subop_t     size;
        !            36:     struct oper value;
        !            37: } memcon[ NMEM ];
        !            38: int nmem = 0; /* max memcon slot taken */
        !            39: 
        !            40: int bytesize[] = { 
        !            41:        1,      /* SUBOP_B */
        !            42:        2,      /* SUBOP_W */
        !            43:        4,      /* SUBOP_L */
        !            44:        4,      /* SUBOP_S */
        !            45:        8,      /* SUBOP_D */
        !            46:        12,     /* SUBOP_X */
        !            47:        12      /* SUBOP_P */
        !            48:     };
        !            49:     
        !            50: #define BYTESIZE( s ) (bytesize[ (int)(s)])
        !            51: 
        !            52: int
        !            53: dead_areg( p )
        !            54: NODE *p;
        !            55: {
        !            56:     register i;
        !            57:     regmask m; m = p->rlive;
        !            58:     for (i=A6REG-1; i>=A0REG; i--)
        !            59:        if (!inmask(i, m )) 
        !            60:            return i;
        !            61:     return -1;
        !            62: }
        !            63: 
        !            64: int
        !            65: dead_dreg( p )
        !            66: NODE *p;
        !            67: {
        !            68:     register i;
        !            69:     regmask m; m = p->rlive;
        !            70:     for (i=A0REG-1; i>=D0REG; i--)
        !            71:        if (!inmask(i, m )) 
        !            72:            return i;
        !            73:     return -1;
        !            74: }
        !            75: 
        !            76: 
        !            77: int
        !            78: cancache( o ) register struct oper *o;
        !            79: {
        !            80:     /*
        !            81:      * currently, the only memory references we can cache are stack 
        !            82:      * bound variables (and FORTRAN locals)
        !            83:      */
        !            84:     extern int Xperimental;
        !            85: 
        !            86:     if (Xperimental)
        !            87:        switch (o->type_o){
        !            88:        case T_REG:
        !            89:        case T_IMMED:
        !            90:        case T_PREDEC:
        !            91:        case T_POSTINC: return 0;
        !            92:        default:        return 1; /* slut */
        !            93:        }
        !            94:     if (o->type_o == T_DEFER || o->type_o == T_DISPL)
        !            95:        if (o->reg_o == FPREG || fortranprog && (o->reg_o==A0REG+4 || o->reg_o==A0REG+5))
        !            96:            return 1;
        !            97:     return 0;
        !            98: }
        !            99: 
        !           100: static int
        !           101: istmp( o ) register struct oper *o;
        !           102: {
        !           103:     if ((o->type_o==T_DEFER && o->reg_o==FPREG)
        !           104:     ||  (o->type_o==T_DISPL && o->reg_o==FPREG && o->value_o>=0)) 
        !           105:            return 1;
        !           106:     return 0;
        !           107: }
        !           108: 
        !           109: static int
        !           110: isindir( o ) struct oper *o;
        !           111: {
        !           112:     switch (o->type_o){
        !           113:     case T_DEFER :
        !           114:        if (o->value_o == A6REG) return 0;
        !           115:        else return 1;
        !           116:     case T_DISPL:
        !           117:        if (o->reg_o == A6REG) return 0;
        !           118:        else return 1;
        !           119:     case T_INDEX:
        !           120:        return 1;
        !           121:     default:
        !           122:        return 0;
        !           123:     }
        !           124: }
        !           125: 
        !           126: struct oper *
        !           127: get_regcon( regno )
        !           128:     int regno;
        !           129: {
        !           130:     return &regcon[regno][CONSRC].con;
        !           131: }
        !           132: 
        !           133: void
        !           134: forgetall()
        !           135: {
        !           136:     register regno;
        !           137:     for (regno=0; regno< NREG ; regno++){
        !           138:        regcon[regno][CONSRC].con.type_o = T_NULL;
        !           139:        regcon[regno][CONDST].con.type_o = T_NULL;
        !           140:     }
        !           141:     nmem = 0;
        !           142: }
        !           143: 
        !           144: static void
        !           145: forgetlocals(forgetsky)
        !           146: {
        !           147:     register regno;
        !           148:     register struct sym_bkt *sk;
        !           149:     register struct oper *sp;
        !           150:     sk =  (forgetsky) ? (struct sym_bkt *)-1 : skyname ;
        !           151:     for (regno=0; regno< NREG ; regno++){
        !           152:        if ( (sp= &regcon[regno][CONSRC].con)->type_o!=T_NULL
        !           153:        && sp->type_o!=T_IMMED && sp->sym_o != sk)
        !           154:            sp->type_o = T_NULL;
        !           155:        regcon[regno][CONDST].con.type_o = T_NULL; /* always */
        !           156:     }
        !           157:     nmem = 0;
        !           158: }
        !           159: 
        !           160: static struct memcon *
        !           161: memfind( o, l, inexact, startaddr, startn )
        !           162:     register struct oper *o;
        !           163:     subop_t l;
        !           164:     int *inexact;
        !           165:     struct memcon *startaddr;
        !           166:     int *startn;
        !           167: {
        !           168:     /*
        !           169:      * lookup this operand at this length in the memory/constant
        !           170:      * table. Return pointer to the slot where we find it. If
        !           171:      * the address-length correspondence is inexact, set *inexact.
        !           172:      * Assume cancache(o).
        !           173:      * Assume there is no aliasing problem in the memory table.
        !           174:      */
        !           175:     register i;
        !           176:     register struct memcon *mo;
        !           177:     register operand_t t=o->type_o;
        !           178:     int membegin = 0, memend, conbegin, conend;
        !           179:     int r;
        !           180:     switch (t){
        !           181:     case T_DISPL: 
        !           182:        r = o->reg_o;
        !           183:        /* FALL THROUGH */
        !           184:     case T_ABSS:
        !           185:     case T_ABSL:
        !           186:     case T_NORMAL:
        !           187:        membegin = o->value_o; 
        !           188:        memend = membegin + BYTESIZE(l)-1;
        !           189:        break;
        !           190:     case T_DEFER:
        !           191:        r = o->value_o;
        !           192:        memend = membegin + BYTESIZE(l)-1;
        !           193:     }
        !           194:     for (i= *startn, mo = startaddr; --i >= 0; mo++ )
        !           195:        if (mo->addr.type_o != T_NULL && t == mo->addr.type_o ){
        !           196:            switch ( t ){
        !           197:            case T_ABSS:
        !           198:            case T_ABSL:
        !           199:            case T_NORMAL:
        !           200:                if (o->sym_o != mo->addr.sym_o) continue;
        !           201:                conbegin = mo->addr.value_o;
        !           202:                goto compare;
        !           203:            case T_DISPL:
        !           204:                if (mo->addr.reg_o != r) continue;
        !           205:                conbegin = mo->addr.value_o;
        !           206:                goto compare;
        !           207:            case T_DEFER:
        !           208:                if (mo->addr.value_o != r) continue;
        !           209:                conbegin = 0;
        !           210:            compare:
        !           211:                conend = conbegin + BYTESIZE(mo->size)-1;
        !           212:                if ( membegin< conend && conbegin < memend ){
        !           213:                    *inexact = ! (membegin==conbegin && l==mo->size);
        !           214:                    *startn = i;
        !           215:                    return mo;
        !           216:                }
        !           217:            }
        !           218:        }
        !           219:     *startn = 0;
        !           220:     return NULL;
        !           221: }
        !           222: 
        !           223: struct oper *
        !           224: memlookup( o, l )
        !           225: {
        !           226:     /* abstract away the "inexact" problem from memfind() */
        !           227:     int inexact;
        !           228:     int ntable = nmem;
        !           229:     struct memcon *m = &memcon[-1];
        !           230: 
        !           231:     while ( (m=memfind( o, l, &inexact, m+1, &ntable)) != NULL )
        !           232:        if ( !inexact ) return (&m->value);
        !           233:     return NULL;
        !           234: }
        !           235: 
        !           236: int
        !           237: regfind( o, l, inexact, firstreg, firstpart, part )
        !           238:     register struct oper *o;
        !           239:     subop_t l;
        !           240:     int *inexact;
        !           241:     register firstpart;
        !           242:     int *part;
        !           243: {
        !           244:     /*
        !           245:      * lookup this operand at this length in the register
        !           246:      * table. Return the register number that matched. If
        !           247:      * the address-length correspondence is inexact, set *inexact.
        !           248:      * Assume cancache(o) or o->type_o==T_IMMED.
        !           249:      */
        !           250:     register i,j;
        !           251:     register struct regcon *mo;
        !           252:     register operand_t t=o->type_o;
        !           253:     int membegin , memend, conbegin, conend;
        !           254:     int r;
        !           255:     switch (t){
        !           256:     case T_DISPL: 
        !           257:        r = o->reg_o;
        !           258:        /* FALL THROUGH */
        !           259:     case T_ABSS:
        !           260:     case T_ABSL:
        !           261:     case T_NORMAL:
        !           262:        membegin = o->value_o; 
        !           263:        memend = membegin + BYTESIZE(l);
        !           264:        break;
        !           265:     case T_DEFER:
        !           266:        r = o->value_o;
        !           267:        membegin = 0;
        !           268:        memend = BYTESIZE(l);
        !           269:     }
        !           270:     for (i=firstreg ; i<NREG; i++ ){
        !           271:        for (j=firstpart; j<=CONDST; j++){
        !           272:            mo = & regcon[i][j];
        !           273:            if (mo->con.type_o != T_NULL && t == mo->con.type_o ){
        !           274:                switch ( t ){
        !           275:                case T_IMMED:
        !           276:                    if ((mo->con.flags_o & O_FLOAT) != (o->flags_o & O_FLOAT)){
        !           277:                        break;
        !           278:                    } else if (mo->con.flags_o & O_FLOAT ){
        !           279:                        if (mo->con.fval_o == o->fval_o){
        !           280:                            *inexact = 0;
        !           281:                             return    i;
        !           282:                        }
        !           283:                    } else if (mo->con.value_o == o->value_o
        !           284:                        &&  mo->con.sym_o == o->sym_o ){
        !           285:                            *inexact = 0;
        !           286:                             return    i;
        !           287:                    }
        !           288:                    break;
        !           289:                case T_ABSS:
        !           290:                case T_ABSL:
        !           291:                case T_NORMAL:
        !           292:                    if (o->sym_o != mo->con.sym_o) continue;
        !           293:                    conbegin = mo->con.value_o;
        !           294:                    goto compare;
        !           295:                case T_DISPL:
        !           296:                    conbegin = mo->con.value_o;
        !           297:                    if (mo->con.reg_o != r) continue;
        !           298:                    goto compare;
        !           299:                case T_DEFER:
        !           300:                    conbegin = 0;
        !           301:                    if (mo->con.value_o != r) continue;
        !           302:                compare:
        !           303:                    conend = conbegin + BYTESIZE(mo->size);
        !           304:                    if ( membegin< conend && conbegin < memend ){
        !           305:                        *inexact = ! (membegin==conbegin && l==mo->size);
        !           306:                        *part = j;
        !           307:                        return i;
        !           308:                    }
        !           309:                }
        !           310:            }
        !           311:        }
        !           312:        firstpart = CONSRC;
        !           313:     }
        !           314:     return -1;
        !           315: }
        !           316: 
        !           317: int
        !           318: reglookup( o, l )
        !           319:     struct oper *o;
        !           320:     subop_t l;
        !           321: {
        !           322:     /* abstract away the "inexact" problem from regfind() */
        !           323:     int inexact, part;
        !           324:     int r;
        !           325:     r = regfind( o, l, &inexact, D0REG, CONSRC, &part );
        !           326:     if ( inexact ) return -1;
        !           327:     else return r;
        !           328: }
        !           329: 
        !           330: static void
        !           331: meminsert( o , v, l )
        !           332:     struct oper *o;
        !           333:     struct oper *v;
        !           334:     subop_t l;
        !           335: {
        !           336:     /*
        !           337:      * look for a free slot in the memcon table to insert an entry.
        !           338:      * try to add at the end, but if the table is complete, then look
        !           339:      * for holes. If we still cannot find anything, just forget it.
        !           340:      * Assume that our caller already tried for an address match
        !           341:      * and would have inserted by easier means if possible.
        !           342:      */
        !           343:     struct memcon *m;
        !           344:     if (nmem < NMEM){
        !           345:        /* regular case */
        !           346:        m = &memcon[nmem++];
        !           347:     } else {
        !           348:        /* have to search */
        !           349:        for (m= &memcon[0]; m > &memcon[NMEM-1]; m++){
        !           350:            if (m->addr.type_o == T_NULL) goto gotone;
        !           351:        }
        !           352:        return ; /* oh, just forget it */
        !           353:     }
        !           354: gotone:
        !           355:     m->addr = *o;
        !           356:     m->size = l;
        !           357:     m->value = *v;
        !           358: }
        !           359: 
        !           360: static void
        !           361: put_in_mem_table( o, v, l)
        !           362:     struct oper *o;
        !           363:     struct oper *v;
        !           364:     subop_t l;
        !           365: {
        !           366:     /*
        !           367:      * put this address/value in the memcon table
        !           368:      * deal with aliasing. This is tricky.
        !           369:      */
        !           370:     int nalias = 0, nexact = 0;
        !           371:     int inexact, ntabl = nmem;
        !           372:     struct memcon * m;
        !           373:     int  src, dest, nbytes ;
        !           374:     union stuff{ /* KNOWS ABOUT 68000 MEMORY LAYOUT !!! */
        !           375:     char bytes[4];
        !           376:     short words[2];
        !           377:     long  longword;
        !           378:     } mine, his;
        !           379:     int sympart = v->sym_o!=NULL;
        !           380: 
        !           381: 
        !           382:     /* initialize my equivalencing structure */
        !           383:     mine.longword = 0L;
        !           384:     if (!sympart)
        !           385:        switch (l){
        !           386:        case SUBOP_B: mine.bytes[0] = v->value_o; break;
        !           387:        case SUBOP_W: mine.words[0] = v->value_o; break;
        !           388:        default:      mine.longword = v->value_o; break;
        !           389:        }
        !           390: 
        !           391:     m = &memcon[-1];
        !           392:     while( (m=memfind( o, l, &inexact, m+1, &ntabl  )) != NULL ){
        !           393:        if (inexact) {
        !           394:            /*
        !           395:             * either the address or the length don't agree.
        !           396:             * fix up the current entry as appropriate, then continue.
        !           397:             */
        !           398:            if (sympart || m->value.sym_o != NULL){
        !           399:                /*
        !           400:                 * had or will have symbolic part
        !           401:                 * cannot deal with inexact matches
        !           402:                 */
        !           403:                m->addr.type_o = T_NULL; /* forget it */
        !           404:                continue;
        !           405:            }
        !           406:            /* fill in his equivalencing structure */
        !           407:            his.longword = 0L;
        !           408:            switch (m->size){
        !           409:            case SUBOP_B: his.bytes[0] = m->value.value_o; break;
        !           410:            case SUBOP_W: his.words[0] = m->value.value_o; break;
        !           411:            default:      his.longword = m->value.value_o; break;
        !           412:            }
        !           413:            if (o->value_o >= m->addr.value_o){
        !           414:                /* new starts after old */
        !           415:                src  = 0;
        !           416:                dest = o->value_o - m->addr.value_o;
        !           417:            } else {
        !           418:                src  = m->addr.value_o - o->value_o ;
        !           419:                dest = 0;
        !           420:            }
        !           421:            nbytes = BYTESIZE( l );
        !           422:            if (nbytes > BYTESIZE( m->size )-dest )
        !           423:                nbytes = BYTESIZE(m->size)-dest;
        !           424:            while (nbytes--){
        !           425:                his.bytes[dest++] = mine.bytes[src++];
        !           426:            }
        !           427:            /* shovel back */
        !           428:            switch (m->size){
        !           429:            case SUBOP_B: m->value.value_o = his.bytes[0]; break;
        !           430:            case SUBOP_W: m->value.value_o = his.words[0]; break;
        !           431:            default:      m->value.value_o = his.longword; break;
        !           432:            }
        !           433:            nalias++;
        !           434:        } else {
        !           435:            m->value = *v;
        !           436:            nexact++;
        !           437:        }
        !           438:     }
        !           439:     if ((nalias && nexact) || (nalias>4))
        !           440:        sys_error("Multiple aliasing in memory table\n");
        !           441:     if (nalias==0 && nexact==0){
        !           442:        /* new entry -- stick it in. */
        !           443:        meminsert( o , v, l );
        !           444:     }
        !           445: }
        !           446: 
        !           447: 
        !           448: static void
        !           449: forgetop( o, l )
        !           450:     struct oper *o;
        !           451:     subop_t l;
        !           452: {
        !           453:     int r, inexact, part;
        !           454:     int ntable = nmem;
        !           455:     struct memcon *m = &memcon[-1];
        !           456: 
        !           457:     r = D0REG;
        !           458:     part = CONSRC;
        !           459:     while( (r = regfind( o, l, &inexact, r, part, &part )) >= D0REG){
        !           460:        regcon[ r ][ part ].con.type_o = T_NULL;
        !           461:        if ( ++part > CONDST ){
        !           462:            r++;
        !           463:            part = CONSRC;
        !           464:        }
        !           465:     }
        !           466: 
        !           467:     while ( (m=memfind( o, l, &inexact, m+1, &ntable)) != NULL )
        !           468:        m->addr.type_o = T_NULL;
        !           469: }
        !           470: 
        !           471: static void
        !           472: substitute( p, op, new )
        !           473:     NODE *p;
        !           474:     struct oper *op, *new;
        !           475: {
        !           476:     /*
        !           477:      * p is an instruction.
        !           478:      * op points to an operand of that instruction.
        !           479:      * new points to a (register) operand structure that we want to
        !           480:      * substitute for the one op addresses.
        !           481:      * Do the substitution and calculate the new properties of p
        !           482:      */
        !           483:     *op = *new;
        !           484:     installinstruct( p, p->instr );
        !           485:     p->rlive = compute_normal( p, p->forw->rlive);
        !           486: }
        !           487: 
        !           488: static int
        !           489: track_cc( n )
        !           490:     NODE *n;
        !           491: {
        !           492:     /*
        !           493:      * we just moved a constant into a register.
        !           494:      * look for subsequent compares/ tests of
        !           495:      * the register, followed by jumps, even after cc is kilt
        !           496:      */
        !           497:     register struct oper *op2, *comperand;
        !           498:     struct oper *o;
        !           499:     register NODE *p;
        !           500:     NODE *target;
        !           501:     subop_t so;
        !           502:     long v, compval;
        !           503:     static struct oper conz = { T_IMMED, 0, 0, NULL, 0, 0, 0  };
        !           504:     int didchange = 0;
        !           505: 
        !           506:     if (n->op==OP_MOVE){
        !           507:        op2 = n->ref[1];
        !           508:        comperand = n->ref[0];
        !           509:        if (comperand->type_o != T_IMMED) return 0;
        !           510:     } else { 
        !           511:        /* CLR */
        !           512:        op2 = n->ref[0];
        !           513:        comperand = &conz;
        !           514:     }
        !           515:     if (!deladdr(op2)) return 0;
        !           516:     so = n->subop;
        !           517:     v = comperand->value_o;
        !           518:     for (p = n->forw; p->op!=OP_FIRST ; p = p->forw){
        !           519:        switch (p->op){
        !           520:        case OP_LABEL:
        !           521:                continue;
        !           522:        case OP_JUMP:
        !           523:            if (p->subop==JALL){
        !           524:                if (p->luse == p->back){
        !           525:                     /* selfloop */
        !           526:                     break;
        !           527:                 }
        !           528:                /* follow! */
        !           529:                p = p->luse->back;
        !           530:                continue;
        !           531:            }
        !           532:            break;
        !           533:        case OP_TST:
        !           534:            if ( sameops( p->ref[0], op2 ) && p->subop==so){
        !           535:                if (comperand->sym_o!=NULL) break;
        !           536:                compval = 0;
        !           537:                goto regcmp;
        !           538:            }
        !           539:            break;
        !           540:        case OP_CMP:
        !           541:            if ( !sameops(p->ref[1], op2 ) ) break;
        !           542:            if ( (o=p->ref[0])->type_o != T_IMMED ) break;
        !           543:            if ( o->sym_o != comperand->sym_o ) break;
        !           544:            compval = o->value_o;
        !           545:        regcmp:
        !           546:            p=p->forw;
        !           547:            if (p->op==OP_JUMP){
        !           548:                /* this is it */
        !           549:                if (inmask( CCREG, p->luse->rlive ) || 
        !           550:                    (p->subop!=JALL && inmask( CCREG, p->forw->rlive)))
        !           551:                    break; /* too hard -- must do the cmp */
        !           552:                switch(p->subop){
        !           553:                case JEQ: compval = v==compval; break;
        !           554:                case JNE: compval = v!=compval; break;
        !           555:                case JLE: compval = v<=compval; break;
        !           556:                case JGE: compval = v>=compval; break;
        !           557:                case JLT: compval = v< compval; break;
        !           558:                case JGT: compval = v> compval; break;
        !           559:                case JCC: compval = ((unsigned)v) >= ((unsigned)compval); break;
        !           560:                case JLS: compval = ((unsigned)v) <= ((unsigned)compval); break;
        !           561:                case JHI: compval = ((unsigned)v) >  ((unsigned)compval); break;
        !           562:                case JCS: compval = ((unsigned)v) <  ((unsigned)compval); break;
        !           563:                case JALL: compval = 1;         break;
        !           564:                case JNONE: compval = 0;        break;
        !           565:                default: goto nojmp;
        !           566:                }
        !           567:                if (compval) target = p->luse;
        !           568:                else{
        !           569:                    target = p->forw;
        !           570:                    if (target->op!=OP_LABEL)
        !           571:                        target = insert_label(target);
        !           572:                }
        !           573:                cannibalize( p=new(), "jra" );
        !           574:                p->op = OP_JUMP;
        !           575:                newreference( target, p);
        !           576:                p->ruse = p->rset = regmask0;
        !           577:                p->rlive = target->rlive;
        !           578:                insert( p, n );
        !           579:                didchange++;
        !           580:                meter.nxjump++;
        !           581:                /*
        !           582:                 * we just created an unconditional jump. 
        !           583:                 * Follow it, just like jumps we find in code.
        !           584:                 */
        !           585:                p = p->luse->back;
        !           586:                continue;
        !           587:            }
        !           588:        }
        !           589:     nojmp:
        !           590:        break;
        !           591:     }
        !           592:     return didchange;
        !           593: }
        !           594: 
        !           595: static int
        !           596: addrlookup( o )
        !           597:     register struct oper *o;
        !           598: {
        !           599:     struct oper q;
        !           600:     int regname;
        !           601:     /*
        !           602:      * assume that o points to an index mode, indirect address node.
        !           603:      * find the memory address through which we are indirecting
        !           604:      * and see if we already have it in an address register. If so, we
        !           605:      * can simplify the addressing mode in disindex().
        !           606:      */
        !           607:     if (o->flags_o&O_PREINDEX) return -1;
        !           608:     if (o->flags_o&O_BSUPRESS){
        !           609:        q.type_o = T_NORMAL;
        !           610:        q.value_o = o->disp_o;
        !           611:        q.sym_o = o->sym_o;
        !           612:        q.flags_o = o->flags_o&O_COMPLEX;
        !           613:     } else {
        !           614:        q.type_o = T_DISPL;
        !           615:        q.reg_o = o->reg_o;
        !           616:        q.value_o = o->disp_o;
        !           617:        q.sym_o = o->sym_o;
        !           618:        q.flags_o = o->flags_o&O_COMPLEX;
        !           619:        if (q.value_o == 0 && q.sym_o == NULL)
        !           620:            q.type_o = T_DEFER;
        !           621:     }
        !           622:     if (!cancache( &q)) return -1;
        !           623:     regname = reglookup( &q, SUBOP_L );
        !           624:     if (areg(regname)) return regname;
        !           625:     return -1;
        !           626: }
        !           627: 
        !           628: static void
        !           629: disindex( o, regname )
        !           630:     register struct oper *o;
        !           631:     int regname;
        !           632: {
        !           633:     register flags;
        !           634:     /*
        !           635:      * o points to an operand of type T_INDEX with the O_INDIRECT flag set.
        !           636:      * o is not preindexed. The memory cell through which o indirects is
        !           637:      * also contained in the A register named by regname. o can be simplified
        !           638:      * because of this: secondary displacement becomes primary displacement,
        !           639:      * post indexing becomes pre indexing, and the operand is no longer indirect.
        !           640:      * it may be simplified to T_DEFER, T_DISPL, or T_INDEX.
        !           641:      */
        !           642:     flags = o->flags_o & ~O_INDIRECT;
        !           643:     o->reg_o = regname;
        !           644:     o->disp_o = o->disp2_o;
        !           645:     o->sym_o  = o->sym2_o;
        !           646:     if (flags&O_COMPLEX2)
        !           647:        flags = (flags & ~O_COMPLEX2) | O_COMPLEX;
        !           648:     if (flags&O_WDISP2)
        !           649:        flags = (flags & ~O_WDISP2)|O_WDISP;
        !           650:     else if (flags&O_LDISP2)
        !           651:        flags = (flags & ~O_LDISP2)|O_LDISP;
        !           652:     if ((flags & O_POSTINDEX) == 0){
        !           653:        if (o->disp_o == 0 && o->sym_o == NULL){
        !           654:            o->type_o = T_DEFER;
        !           655:        } else {
        !           656:            o->type_o = T_DISPL;
        !           657:        }
        !           658:     } else {
        !           659:        o->type_o = T_INDEX;
        !           660:        flags = (flags& ~O_POSTINDEX)|O_PREINDEX;
        !           661:     }
        !           662:     o->flags_o = flags;
        !           663: }
        !           664: 
        !           665: static void
        !           666: kill_uses( regno )
        !           667:     register int regno;
        !           668: {
        !           669:     register struct regcon *r;
        !           670:     register struct memcon *m, *l;
        !           671:     for (r = &regcon[0][CONSRC]; r <= &regcon[NREG-1][CONDST]; r++)
        !           672:        if (r->con.type_o != T_NULL && operand_uses( &r->con, regno )){
        !           673:            r->con.type_o = T_NULL;
        !           674:        }
        !           675:     for (m = &memcon[0], l = &memcon[nmem]; m < l; m++)
        !           676:        if (m->addr.type_o != T_NULL && operand_uses( &m->addr, regno)){
        !           677:            m->addr.type_o = T_NULL;
        !           678:        }
        !           679: }
        !           680: 
        !           681: void
        !           682: con_to_reg( regno, o, size )
        !           683:     struct oper *o;
        !           684:     subop_t size;
        !           685: {
        !           686:     struct regcon *r = &regcon[regno][CONSRC];
        !           687: 
        !           688:     regcon[regno][CONDST].con.type_o = T_NULL;
        !           689:     r->con =  *o;
        !           690:     if (dreg(regno))
        !           691:        r->size = size;
        !           692:     else if (areg(regno))
        !           693:        r->size = SUBOP_L;
        !           694:     else 
        !           695:        r->size = SUBOP_X;
        !           696:     if (Xperimental)
        !           697:        kill_uses( regno );
        !           698: }
        !           699: 
        !           700: static int
        !           701: use_moveq( n )
        !           702:     register NODE *n;
        !           703: {
        !           704:     NODE *p;
        !           705:     static struct oper reg  = { T_REG,   0, 0, NULL, 0, 0, 0  };
        !           706:     /*
        !           707:      * doing an immediate operation with a small constant.
        !           708:      * we can moveq the constant into a dead D register,
        !           709:      * then do operations from that register. As a bonus,
        !           710:      * we'll have the value around.
        !           711:      * Avoid the case of "movl #3,d3". This will get fixed
        !           712:      * in quicken() later on.
        !           713:      */
        !           714: 
        !           715:     if (!long_immediate(n->op)
        !           716:     || n->subop != SUBOP_L
        !           717:     || (reg.value_o=dead_dreg(n))<0
        !           718:     || !operand_ok(n->instr, &reg, n->ref[1], 0)
        !           719:     || (n->op==OP_MOVE && dreg_addr( n->ref[1] ) )){
        !           720:        return 0;
        !           721:     }
        !           722:     p = new();
        !           723:     p->nref = 2;
        !           724:     p->ref[0] = newoperand( n->ref[0] );
        !           725:     p->ref[1] = newoperand( &reg );
        !           726:     insert( p, n->back );
        !           727:     con_to_reg( reg.value_o, n->ref[0], SUBOP_L );
        !           728:     substitute( n, n->ref[0], &reg );
        !           729:     installinstruct( p, moveq );
        !           730:     p->rlive = compute_normal( p, n->rlive );
        !           731:     return 1;
        !           732: }
        !           733: 
        !           734: static void
        !           735: kill_cached_mem( n, touchop )
        !           736:     register NODE *n;
        !           737:     register touchop;
        !           738: {
        !           739:     register i;
        !           740:     /* if a local is modified, invalidate our cached value */
        !           741:     for (i=0;i<n->nref;i++){
        !           742:        if (touchop&(BW|LW|WW))
        !           743:            if (isindir(n->ref[i]))
        !           744:                forgetlocals(0);
        !           745:            else if ( cancache(n->ref[i]))
        !           746:                forgetop( n->ref[i], n->subop );
        !           747:        touchop >>= TOUCHWIDTH;
        !           748:     }
        !           749: }
        !           750: 
        !           751: dumpmem(){
        !           752:     int i,j;
        !           753:     extern char *rnames[];
        !           754:     static char sizes[] = "bwlsdxp";
        !           755:     for (i=0; i<NREG; i++){
        !           756:        printf("%s      : ", rnames[i]);
        !           757:        for (j=0; j <= 1; j++)
        !           758:            if (regcon[i][j].con.type_o == T_NULL)
        !           759:                printf("XXXX            ");
        !           760:            else{
        !           761:                printoperand( &regcon[i][j].con );
        !           762:                printf("{%c}    ", sizes[(int)regcon[i][j].size]);
        !           763:            }
        !           764:        printf("\n");
        !           765:     }
        !           766:     printf("\n");
        !           767:     for (i=0; i<nmem; i++){
        !           768:        if (memcon[i].addr.type_o != T_NULL){
        !           769:            printoperand( &memcon[i].addr );
        !           770:            printf("{%c}: ", sizes[(int)memcon[i].size]);
        !           771:            printoperand( &memcon[i].value );
        !           772:            printf("\n");
        !           773:        }
        !           774:     }
        !           775: }
        !           776: 
        !           777: static int
        !           778: substitute_move( n, o, reg, saveop )
        !           779:     register NODE *n;
        !           780:     struct oper *o, *reg, *saveop;
        !           781: {
        !           782:     if (n->instr == moveq)
        !           783:        return 0;
        !           784:     substitute( n, o, reg );
        !           785:     if (saveop->type_o==T_IMMED && cancache(n->ref[1]))
        !           786:        put_in_mem_table( n->ref[1], saveop, n->subop );
        !           787:     meter.nsaddr++;
        !           788:     return 1;
        !           789: }
        !           790: 
        !           791: /* 
        !           792:  * we really should be doing flow analysis here.
        !           793:  * lacking that, recognize special case SKY code:
        !           794:  *     1: tstw a1@(-4)
        !           795:  *        bge  1b
        !           796:  */
        !           797: # define CHECK_LABEL(n) \
        !           798:     if (n->op==OP_LABEL){ \
        !           799:        if (!(n->nref==1 && n->luse==n->forw->forw && emptymask(n->forw->rset) && n->forw->forw->op==OP_JUMP)) forgetall(); \
        !           800:        continue; }
        !           801: 
        !           802: # define IMMED_OR_SKY( o ) \
        !           803:     (o->type_o==T_IMMED || (o->type_o==T_NORMAL && o->value_o==0 && o->sym_o==skyname))
        !           804: 
        !           805: /* move to self: kill unless cc live */
        !           806: # define DELETE_SELFMOVES( n ) \
        !           807:     if ( n->ref[1]->value_o==regno && (!inmask( CCREG, n->forw->rlive) || areg(regno))){ \
        !           808:            n = deletenode( n ); meter.redunm++; didchange++; continue; }
        !           809: 
        !           810: # define SMALL_IMMED( o ) \
        !           811:     ((o)->type_o==T_IMMED && (o)->sym_o==NULL && !((o)->flags_o&O_FLOAT) && (v=(o)->value_o)>=-128 && v<=127)
        !           812: 
        !           813: int
        !           814: content()
        !           815: {
        !           816:     /*
        !           817:      * Follow the flow of control (roughly). Look at loads into
        !           818:      * registers. When a constant is loaded we know:
        !           819:      * 1) how the CC is set.
        !           820:      * 2) a cheap source of that constant.
        !           821:      * Special case if the same register is reloaded with that constant.
        !           822:      * SPECIAL HACK: Assume that the contents of the global var named
        !           823:      * "__skybase" are constant!!
        !           824:      */
        !           825:     register NODE *n;
        !           826:     register v, regno;
        !           827:     register struct oper *o;
        !           828:     struct oper *op2, *op3;
        !           829:     int didchange=0;
        !           830:     int local_read, dest_reg;
        !           831:     int i;
        !           832:     struct oper saveop;
        !           833: 
        !           834: 
        !           835:     static struct oper reg  = { T_REG,   0, 0, NULL, 0, 0, 0  };
        !           836: 
        !           837:     /* initialize constant table to empty. Find __skybase */
        !           838:     forgetall();
        !           839:     if (skyname==NULL) skyname = lookup("__skybase");
        !           840: #if TRACKSP
        !           841:     spoffset=0;
        !           842: #endif TRACKSP
        !           843: 
        !           844:     for (n=first.forw; n!=&first; n=n->forw){
        !           845:        CHECK_LABEL(n);
        !           846:        if (!ISINSTRUC(n->op)) continue;
        !           847:        dest_reg = -1;
        !           848:        if (n->nref){
        !           849:            v = make_touchop( n, n->instr->touchop_i);
        !           850:            kill_cached_mem( n, v );
        !           851:            o = n->ref[0];
        !           852:            local_read = cancache(o) && (v&(BW|LW|WW))==0;
        !           853:            if (IMMED_OR_SKY( o ) || local_read ){
        !           854:                /* do lookup -- do we already have it */
        !           855:                regno = reglookup( o, n->subop );
        !           856:                if (regno>=0 ){
        !           857:                    /* try to substitute */
        !           858:                    reg.value_o = regno;
        !           859:                    saveop = *o;
        !           860:                    if (operand_ok(n->instr, &reg, n->ref[1], 0)){
        !           861:                        if (n->op==OP_MOVE){
        !           862:                            didchange += substitute_move( n, o, &reg, &saveop );
        !           863:                            if ( datareg_addr( n->ref[1] ) ){
        !           864:                                DELETE_SELFMOVES( n );
        !           865:                                con_to_reg( n->ref[1]->value_o, &saveop, n->subop );
        !           866:                                didchange += track_cc(n);
        !           867:                                dest_reg = n->ref[1]->value_o;
        !           868:                            }
        !           869:                        } else {
        !           870:                            /* not a move -- don't think, just do it */
        !           871:                            substitute( n, o, &reg );
        !           872:                            meter.nsaddr++;
        !           873:                            didchange++;
        !           874:                        }
        !           875:                    }
        !           876:                } 
        !           877:                if (n->nref==2 && SMALL_IMMED( o )){
        !           878:                    didchange+= use_moveq( n );
        !           879:                }
        !           880:                if (local_read && (op2=memlookup(o, n->subop))!= NULL){
        !           881:                    /*
        !           882:                     * this is a local that contains an immediate at this
        !           883:                     * time. substitute the immediate value for the mem-op,
        !           884:                     * if we may.
        !           885:                     */
        !           886:                    if (operand_ok(n->instr, op2, n->ref[1], 0)){
        !           887:                        substitute( n, o, op2 );
        !           888:                        meter.nsaddr++;
        !           889:                        didchange++;
        !           890:                    }
        !           891:                }
        !           892:                if (n->op==OP_MOVE){
        !           893:                    op2 = n->ref[1];
        !           894:                    if (datareg_addr(op2)){
        !           895:                        /* move to a register */
        !           896:                        con_to_reg( op2->value_o, o, n->subop );
        !           897:                    } else if (cancache( op2)){
        !           898:                        if(o->type_o==T_IMMED )
        !           899:                            put_in_mem_table( op2, o, n->subop );
        !           900:                        else if (o->type_o==T_REG && datareg( regno=o->value_o )
        !           901:                        && (op3= &regcon[regno][CONSRC].con)->type_o == T_IMMED)
        !           902:                            put_in_mem_table( op2, op3, n->subop );
        !           903:                    }
        !           904:                    /*
        !           905:                     * we may have moved a constant into a register.
        !           906:                     * look for subsequent compares/ tests of
        !           907:                     * the register, followed by jumps, even after cc is kilt
        !           908:                     */
        !           909:                    didchange += track_cc(n);
        !           910:                    if (op2->type_o == T_REG)
        !           911:                        dest_reg = op2->value_o;
        !           912:                }
        !           913:            } else if (n->op==OP_MOVE && n->ref[0]->type_o==T_REG 
        !           914:            && cancache( n->ref[1] )){
        !           915:                /* movl d0,a6@(4) ; movl a6@(4),d1 */
        !           916:                regcon[v=n->ref[0]->value_o][CONDST].con = *(n->ref[1]);
        !           917:                regcon[v][CONDST].size = n->subop;
        !           918:                dest_reg = v;
        !           919:            } else if (n->op==OP_CALL){
        !           920:                forgetlocals(1);
        !           921:            } else if (n->op==OP_CLR){
        !           922:                didchange += track_cc(n);
        !           923:                if (n->ref[0]->type_o == T_REG)
        !           924:                    dest_reg = n->ref[0]->value_o;
        !           925:             }
        !           926:            /*
        !           927:             * try to avoid indirecting through things 
        !           928:             * of which we already know the value 
        !           929:             */
        !           930:            for (i=n->nref, v=0; v<i; v++){
        !           931:                if ((o = n->ref[v])->type_o == T_INDEX && (o->flags_o&O_INDIRECT))
        !           932:                    if ((regno = addrlookup( o )) >= 0 ){
        !           933:                        disindex( o, regno );
        !           934:                        substitute( n, o, o );
        !           935:                        meter.nsaddr++;
        !           936:                    }
        !           937:            }
        !           938:        }
        !           939:        if (!emptymask(n->rset) ){
        !           940:            /* kill a constant value */
        !           941:            register sets = n->rset.da; 
        !           942:            while (sets){
        !           943:                v = ffs(sets)-1;
        !           944:                sets ^= 1<<v;
        !           945:                if (v<24)
        !           946:                    v /=3;
        !           947:                else 
        !           948:                    v -=(24-A0REG);
        !           949:                if ( v == dest_reg )
        !           950:                    continue;
        !           951:                regcon[v][CONSRC].con.type_o = T_NULL;
        !           952:                regcon[v][CONDST].con.type_o = T_NULL;
        !           953:                if (Xperimental)
        !           954:                    kill_uses( v );
        !           955: #ifdef TRACKSP
        !           956:                if (v==SPREG){
        !           957:                    /* try to keep track of distance from a6 to a7 */
        !           958:                    track_sp( n );
        !           959:                }
        !           960: #endif TRACKSP
        !           961:            }
        !           962:            sets = n->rset.f & 0377; /* registers only, no cc */
        !           963:            while (sets){
        !           964:                v = ffs(sets)-1;
        !           965:                sets ^= 1<<v;
        !           966:                v += FP0REG;
        !           967:                if ( v == dest_reg )
        !           968:                    continue;
        !           969:                regcon[v][CONSRC].con.type_o = T_NULL;
        !           970:                regcon[v][CONDST].con.type_o = T_NULL;
        !           971:            }
        !           972:        }
        !           973:     }
        !           974:     return didchange;
        !           975: }

unix.superglobalmegacorp.com

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