Annotation of researchv9/cmd/sun/c2/hardexp.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)hardexp.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 oper * newoperand();
                     13: extern struct optree * newtree();
                     14: 
                     15: void
                     16: ocomplex( operation, subop1, subop2 )
                     17:     char operation;
                     18:     struct oper * subop1, *subop2;
                     19: {
                     20:     register struct optree *otp;
                     21:     otp = newtree();
                     22:     otp->left_t = newoperand( subop1 );
                     23:     otp->right_t = subop2 ? newoperand( subop2 ) : NULL;
                     24:     otp->op_t = operation;
                     25:     subop1->sym_o = (struct sym_bkt *)otp;
                     26:     subop1->flags_o |= O_COMPLEX;
                     27: }
                     28: 
                     29: 
                     30: static void
                     31: valcomplex( op )
                     32:     struct oper *op;
                     33: {
                     34:     register struct optree *tp;
                     35:     register struct oper *r, *l;
                     36:     register int * vp;
                     37:     struct sym_bkt *sp;
                     38:     int operation;
                     39:     vp = (op->type_o == T_INDEX) ? &op->disp_o : &op->value_o;
                     40:     if (op->flags_o&O_COMPLEX){
                     41:        tp = (struct optree *)op->sym_o;
                     42:        operation = tp->op_t;
                     43:        l = tp->left_t ;
                     44:        valcomplex( l );
                     45:        if ((r=tp->right_t) == NULL)
                     46:            operation = -operation; /* so we can tell unary SUB from binary */
                     47:        else 
                     48:            valcomplex( r );
                     49:        if (l->sym_o || (r && r->sym_o)) {
                     50:            if ( operation == SUB
                     51:            && !(l->flags_o&O_COMPLEX) && !(r->flags_o&O_COMPLEX) 
                     52:            && l->sym_o->csect_s == r->sym_o->csect_s
                     53:            && l->sym_o->csect_s != C_TEXT
                     54:            && l->sym_o->attr_s&S_DEF && r->sym_o->attr_s&S_DEF
                     55:            && l->sym_o->value_s >= 0 && r->sym_o->value_s >= 0 ){
                     56:                /* 
                     57:                 * special case: it is ok to subtract two symbols in data
                     58:                 * space, as long as we know their values.
                     59:                 */
                     60:                *vp = l->sym_o->value_s - r->sym_o->value_s;
                     61:                goto uncomplex;
                     62:            }
                     63:            return;
                     64:        }
                     65:        switch( operation ){
                     66:        case ADD: *vp = l->value_o + r->value_o; break;
                     67:        case SUB: *vp = l->value_o - r->value_o; break;
                     68:        case MUL: *vp = l->value_o * r->value_o; break;
                     69:        case DIV: *vp = l->value_o / r->value_o; break;
                     70:        case -SUB: *vp = - l->value_o; break;
                     71:        case -NOT: *vp = ~ l->value_o; break;
                     72:        }
                     73:     uncomplex:
                     74:        op->flags_o &= ~O_COMPLEX;
                     75:        op->sym_o = NULL;
                     76:        if (op->type_o == T_INDEX
                     77:          && !(op->flags_o&(O_INDIRECT|O_BSUPRESS|O_PREINDEX|O_POSTINDEX))
                     78:          && op->disp_o >= -32768 && op->disp_o <= 32767) {
                     79:            /* a T_DISPL disguised as a T_INDEX */
                     80:            op->type_o = T_DISPL;
                     81:            op->value_o = op->disp_o;
                     82:            op->disp_o = 0;
                     83:        }
                     84:        freeoperand(l);
                     85:        freeoperand(r);
                     86:        freetree(tp);
                     87:     } else {
                     88:        if ( op->sym_o == NULL ) return ;
                     89:        sp = op->sym_o;
                     90:        if ((sp->attr_s & S_DEF) == 0) return ;
                     91:        if ( sp->csect_s == C_UNDEF  ) {
                     92:            *vp += sp->value_s;
                     93:            op->sym_o = NULL;
                     94:        }
                     95:     }
                     96:     return ;
                     97: }
                     98: 
                     99:     
                    100: void
                    101: rectify()
                    102: {
                    103:     /* look at all operands. Try to fix up the complex ones */
                    104:     register NODE *np;
                    105:     register struct oper *op;
                    106:     register struct optree *tp;
                    107:     register opno, nops;
                    108:     struct sym_bkt * sp;
                    109:     short m;
                    110: 
                    111:     for (np=first.forw; np!= &first; np = np->forw){
                    112:        if (np->op==OP_LABEL){
                    113:            np->nref = np->name->nuse_s;
                    114:            continue;
                    115:        }
                    116:        nops = np->nref;
                    117:        for (opno=0; opno<nops; opno++){
                    118:            op = np->ref[opno];
                    119:            if (op->flags_o&O_COMPLEX || op->sym_o)
                    120:                valcomplex( op );
                    121:        }
                    122:        switch( np->op){
                    123:        case OP_BRANCH:
                    124:        case OP_DBRA:
                    125:            if (op->type_o==T_NORMAL &&
                    126:            !(op->flags_o&O_COMPLEX) && op->value_o==0 ){
                    127:            /* make jump references point right at the label node */
                    128:                sp = op->sym_o;
                    129:                if (sp->attr_s&S_DEF && sp->csect_s == C_TEXT){
                    130:                    np->luse = sp->where_s;
                    131:                    np->lnext = np->luse->luse;
                    132:                    np->luse->luse = np;
                    133:                    switch( np->op){
                    134:                    case OP_BRANCH: np->op = OP_JUMP; break;
                    135:                    case OP_DBRA:   np->op = OP_DJMP; break;
                    136:                    }
                    137:                    freeoperand(op);
                    138:                    np->nref--;
                    139:                    continue;
                    140:                }
                    141:            }
                    142:            break;
                    143:        case OP_MOVEM:
                    144:            /* try to fix up register use mask */
                    145:            np->ruse = addmask( np->ruse, movemmask( np->subop, RMASK, np->ref ));
                    146:            np->rset = addmask( np->rset, movemmask( np->subop, WMASK, np->ref ));
                    147:            break;
                    148:        case OP_MOVE:
                    149:            /*
                    150:             * look for set pattern:
                    151:             *      movw        pc@(6,d?:w),d0
                    152:             *      jmp pc@(2,d0:w)
                    153:             * Lnnn:
                    154:             *  .word   Lyyy-Lnnn
                    155:             *    :         :
                    156:             *    :         :
                    157:             * This is a C-style switch.
                    158:             * When we find one of these, we want to treat it specially,
                    159:             * so that flow-analysis will recognize it as a multi-way 
                    160:             * branch, and not as an unknown branch. So:
                    161:             *    Make the jmp instruction a OP_JUMP, JIND op/subop;
                    162:             *    Make the .word pseudoops OP_CSWITCH, and make them
                    163:             *        reference Lyyy like branches reference their labels.
                    164:             */
                    165:            /* make sure we recognize the set pattern */
                    166:            if (np->subop!=SUBOP_W 
                    167:            || (op=np->ref[0])->type_o!= T_INDEX || op->reg_o != PCREG
                    168:            ||  op->disp_o!=6  || op->value_o>=A0REG 
                    169:            || (op=np->ref[1])->type_o!= T_REG || op->value_o != D0REG)
                    170:                    break;
                    171:            np = np->forw;
                    172:            if (np->op!=OP_BRANCH || (op=np->ref[0])->type_o!=T_INDEX
                    173:            ||  op->reg_o!=PCREG || op->disp_o!=2 || op->value_o!=D0REG
                    174:            ||  op->flags_o!=(O_WINDEX|O_PREINDEX) )
                    175:                    break;
                    176:            /* following operand must be label */
                    177:            if (np->forw->op!=OP_LABEL)
                    178:                    break;
                    179:            /* all looks good: fiddle the jmp instruction */
                    180:            np->op = OP_JUMP;
                    181:            np->subop = JIND;
                    182:            freeoperand( op );
                    183:            newreference( np->forw, np);
                    184:            np->nref=0;
                    185:            np = np->forw;
                    186:            np->nref += np->name->nuse_s;
                    187:            np= np->forw;
                    188:            while (np->op==OP_WORD){
                    189:                int i;
                    190:                register NODE *csw;
                    191:                NODE *next;
                    192:                np->op = OP_CSWITCH;
                    193:                next = np->forw;
                    194:                for (i=0; i<np->nref; i++){
                    195:                    op = np->ref[i];
                    196:                    if (!(op->flags_o&O_COMPLEX)) continue; /* trouble */
                    197:                    /* CSWITCH can handle only one operand */
                    198:                    if (i>0){
                    199:                        /* this will never happen */
                    200:                        csw = new();
                    201:                        csw->back = next->back;
                    202:                        csw->back->forw = next->back = csw;
                    203:                        csw->forw=next;
                    204:                        csw->op = OP_CSWITCH;
                    205:                        csw->instr = np->instr;
                    206:                        csw->nref = 0;
                    207:                    } else {
                    208:                        csw = np;
                    209:                    }
                    210:                    tp = (struct optree *)op->sym_o;
                    211:                    freeoperand( tp->right_t );
                    212:                    csw->luse = tp->left_t->sym_o->where_s;
                    213:                    csw->lnext = csw->luse->luse;
                    214:                    csw->luse->luse = csw;
                    215:                    freeoperand( tp->left_t );
                    216:                    freetree( tp );
                    217:                }
                    218:                np->nref = 0;
                    219:                np = next;
                    220:            }
                    221:            np=np->back; /* so the for-loop increment will do the right thing */
                    222:            break;
                    223:        }
                    224:     }
                    225:     if (first.forw != first.back){
                    226:        /*
                    227:         * if this routine is non-empty, then we want to make sure that
                    228:         * its entry-point has at least one reference. Most routines get
                    229:         * this through the .globl pseudo-op, but class static routine
                    230:         * will not. Thus we make sure here.
                    231:         */
                    232:        for (np=first.forw; np != &first ; np=np->forw )
                    233:            if (np->op == OP_LABEL ){
                    234:                np->nref++;
                    235:                break;
                    236:            }
                    237:     }
                    238: }

unix.superglobalmegacorp.com

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