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