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