Annotation of researchv9/cmd/sun/as/eaddr.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static  char sccsid[] = "@(#)eaddr.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: /* eaddr - put in stuff for an effective address */
        !            10: 
        !            11: #include "as.h"
        !            12: 
        !            13: #define forward_ref(o) ((o)->sym_o && !((o)->sym_o->attr_s&S_DEF))
        !            14: 
        !            15: operand_t displacement();
        !            16: 
        !            17: eaddr(opptr, size ,wrtflag)
        !            18:        register struct oper *opptr;
        !            19:        subop_t size;
        !            20: {
        !            21:        int reg = (int)opptr->value_o;
        !            22:        int was_displ;
        !            23:        if (opptr->flags_o & O_BFLD)
        !            24:            PROG_ERROR(E_OPERAND); /* unexpected bit field */
        !            25:        switch(opptr->type_o) {
        !            26:        case T_REG:
        !            27:                if (areg(reg) || dreg(reg))
        !            28:                        wcode[0] |= (int)opptr->value_o;
        !            29:                else 
        !            30:                PROG_ERROR(E_REG) ;
        !            31:                break;
        !            32:        case T_DEFER:
        !            33:                wcode[0] |= (((int)opptr->value_o) & 07) | 020;
        !            34:                break;
        !            35:        case T_POSTINC:
        !            36:                wcode[0] |= (((int)opptr->value_o) & 07) | 030;
        !            37:                break;
        !            38:        case T_PREDEC:
        !            39:                wcode[0] |= (reg & 07) | 040;
        !            40:                break;
        !            41:        case T_DISPL:
        !            42:                if (reg<-32768 || reg>32767 || opptr->sym_o && 
        !            43:                !(opptr->sym_o->attr_s&S_DEF) ){
        !            44:                    if (ext_instruction_set)
        !            45:                        {
        !            46:                        /* looks like a potential index mode */
        !            47:                        opptr->disp_o = reg;
        !            48:                        opptr->value_o = 0;
        !            49:                        was_displ = 1;
        !            50:                        goto  indexmode;
        !            51:                    }else{
        !            52:                        if ( !pcreg(opptr->reg_o) || (opptr->flags_o) ) 
        !            53:                        PROG_ERROR(E_OPERAND);
        !            54:                    }
        !            55:                }
        !            56:                if (areg(opptr->reg_o)) {
        !            57:                        wcode[0] |= (opptr->reg_o & 07) | 050;
        !            58:                        rel_val(opptr, SUBOP_W, 0);     /* install displacement */
        !            59:                } else {
        !            60:                        wcode[0] |= 072;
        !            61:                        if (opptr->sym_o)
        !            62:                                { /* relocatable or external */
        !            63:                                if (opptr->sym_o && opptr->sym_o->attr_s & S_DEF)
        !            64:                                        { /* symbol is defined in this assembly */
        !            65:                                        opptr->sym_o = 0;
        !            66:                                        }
        !            67:                                opptr->value_o -= dot + code_length ; /* bias offset */
        !            68:                                rel_val(opptr, SUBOP_W, 1); /* install displacement */
        !            69:                                }
        !            70:                                else
        !            71:                                { /* absolute */
        !            72:                                rel_val(opptr, SUBOP_W, 0); /* install displacement */
        !            73:                                }
        !            74:                        }
        !            75:                break;
        !            76:        case T_PCPLUS:
        !            77:                /* especially called from ctrl_op to do external PC@() addressing */
        !            78:                /* looks a lot like the above */
        !            79:                wcode[0] |= 072;
        !            80:                opptr->value_o -= dot + code_length ; /* bias offset */
        !            81:                rel_val(opptr, SUBOP_W, 1); /* <== PC-relative relocation */
        !            82:                break;
        !            83:        case T_INDEX:
        !            84:                was_displ = 0;
        !            85:        indexmode:
        !            86:                if (pcreg(opptr->reg_o))
        !            87:                        {
        !            88:                        wcode[0] |= 073;
        !            89:                        if (opptr->sym_o) opptr->disp_o -= dot+code_length ;
        !            90:                        index(opptr, was_displ);        /* compute index word */
        !            91:                        if (opptr->sym_o) opptr->disp_o += dot+code_length ;
        !            92:                        } 
        !            93:                else 
        !            94:                        {
        !            95:                        wcode[0] |= (opptr->reg_o & 07) | 060;
        !            96:                        index(opptr, was_displ);        /* compute index word */
        !            97:                        }
        !            98:                break;
        !            99:        case T_ABSS:
        !           100: short_absolute:
        !           101:                wcode[0] |= 070;
        !           102:                rel_val(opptr, SUBOP_W, 0);     /* install short address */
        !           103:                break;
        !           104:        case T_NORMAL:
        !           105:                /*
        !           106:                 * Heretofore, this has been handled as long absolute, making
        !           107:                 * the most expensive addressing mode the default one, and the
        !           108:                 * only one used by c programs. Because of the rules of C, this
        !           109:                 * is probably a quite reasonable assumption. But assembly-
        !           110:                 * language programmers might be more tricky in their placement
        !           111:                 * of code and data, and might be able to use short absolute.
        !           112:                 * They might even be able to use PC-relative in an intellegent
        !           113:                 * manner.
        !           114:                 */
        !           115:                /* we have three choices of addressing modes to
        !           116:                 * use: absolute long, absolute short, and PC
        !           117:                 * relative.  The latter two are the same size,
        !           118:                 * but for entirely different applications. One
        !           119:                 * is for reaching low memory, and the other is
        !           120:                 * for reaching nearby data in the text segment.
        !           121:                 */
        !           122:                if (cansdi){
        !           123:                    switch (displacement( opptr, !wrtflag, 0, 0, 0 )){
        !           124:                    case T_ABSS:
        !           125:                        wcode[0] |= 070;
        !           126:                        break;
        !           127:                    case T_PCPLUS:
        !           128:                        wcode[0] |= 072;
        !           129:                        break;
        !           130:                    case T_ABSL:
        !           131:                        wcode[0] |= 071;
        !           132:                        break;
        !           133:                    default:
        !           134:                        sys_error("Unfamiliar sdi address mode in ea:\n %s\n", iline);
        !           135:                    }
        !           136:                    break;
        !           137:                }
        !           138:                /* else FALL THROUGH */
        !           139:        case T_ABSL:
        !           140:                wcode[0] |= 071;
        !           141:                rel_val(opptr, SUBOP_L, 0);
        !           142:                break;
        !           143:        case T_IMMED:
        !           144:                wcode[0] |= 074;
        !           145:                rel_val(opptr, (size == SUBOP_B)? SUBOP_W:size, 0);     /* change bytes to words */
        !           146:                break;
        !           147:        default:
        !           148:                sys_error("Unrecognized address mode in:\n %s\n", iline);
        !           149:        }
        !           150: }
        !           151: 
        !           152: static
        !           153: vshort_absolute(opptr)
        !           154:     register struct oper *opptr;
        !           155: {
        !           156:     if (opptr->sym_o==0 && -128 <= opptr->value_o && opptr->value_o <= 127){
        !           157:        return 1;
        !           158:     } 
        !           159:     return 0;
        !           160: }
        !           161: 
        !           162: static
        !           163: short_absolute(opptr)
        !           164:     register struct oper *opptr;
        !           165: {
        !           166:     if (d2flag
        !           167:        || (opptr->sym_o==0 && -32768 <= opptr->value_o && opptr->value_o <= 32767 )){
        !           168:        rel_val(opptr, SUBOP_W, 0);
        !           169:        return 1;
        !           170:     } 
        !           171:     return 0;
        !           172: }
        !           173: 
        !           174: static
        !           175: long_absolute(opptr, pc_ok, null_ok, indexing, was_displ)
        !           176:     struct oper *opptr;
        !           177: {
        !           178:     /* the form of last resort. Must always succeed */
        !           179:     int sdiflavor;
        !           180:     if (pass==1 && cansdi && opptr->sym_o && !(opptr->sym_o->attr_s&S_DEF)  ){
        !           181:        if (indexing || was_displ) sdiflavor = SDIX;
        !           182:        else if (null_ok) sdiflavor = SDI6;
        !           183:        else sdiflavor = SDIP;
        !           184:        (void)makeddi( opptr, dot+code_length, sdiflavor, !pc_ok);
        !           185:     }
        !           186:     rel_val( opptr, SUBOP_L, 0);
        !           187:     return 1;
        !           188: }
        !           189: 
        !           190: pc_relative(opptr)
        !           191:     struct oper *opptr;
        !           192: {
        !           193:        register struct sym_bkt *sym = opptr->sym_o;
        !           194:        if (sym && (sym->attr_s & S_DEF) && 
        !           195:            (sym->csect_s == cur_csect_name
        !           196:            ||(rflag  && sym->csect_s != C_BSS))){
        !           197:            /* looks like pc-relative is a real possibility */
        !           198:            if (pass==1){
        !           199:                (void)makesdi( opptr, dot+code_length, SDIP);
        !           200:                rel_val( opptr, SUBOP_W, 0);
        !           201:                return 1;
        !           202:            } else {
        !           203:                register int offset = opptr->value_o - (dot + code_length);
        !           204: 
        !           205:                if ( offset >= -32768L  && offset <= 32767L){
        !           206:                    opptr->value_o -= dot + code_length;
        !           207:                    opptr->sym_o = 0; /* no relocation */
        !           208:                    rel_val(opptr, SUBOP_W, 0); /* install displacement */
        !           209:                    return 1;
        !           210:                }
        !           211:            }
        !           212:        }
        !           213:        return 0;
        !           214: }
        !           215: 
        !           216: static operand_t
        !           217: displacement( opptr, pc_ok, null_ok, indexing, was_displ )
        !           218:     register struct oper *opptr;
        !           219:     int pc_ok, null_ok, indexing, was_displ;
        !           220: {
        !           221:     /* we have three choices of addressing modes to
        !           222:      * use: absolute long, absolute short, and PC
        !           223:      * relative.  The latter two are the same size,
        !           224:      * but for entirely different applications. One
        !           225:      * is for reaching low memory, and the other is
        !           226:      * for reaching nearby data in the text segment.
        !           227:      */
        !           228:     if (null_ok && opptr->sym_o == 0 && opptr->value_o == 0 ){
        !           229:        return T_NULL;
        !           230:     } else if (indexing && vshort_absolute(opptr)){
        !           231:        return T_INDEX;
        !           232:     } else if (short_absolute(opptr)){
        !           233:        return T_ABSS;
        !           234:     } else if ( pc_ok &&  cansdi && pc_relative(opptr) ){
        !           235:        return T_PCPLUS;
        !           236:     } else {
        !           237:        long_absolute( opptr, pc_ok, null_ok, indexing, was_displ );
        !           238:        return T_ABSL;
        !           239:     }
        !           240: }
        !           241: 
        !           242: /*
        !           243:  * index -     Use data in operand structure to compute an index word.
        !           244:  */
        !           245: 
        !           246: static
        !           247: index(opptr, was_displ)
        !           248:        register struct oper *opptr;
        !           249:        int was_displ;
        !           250: {
        !           251:        register int indexval = 0;
        !           252:        int displ1=0, displ2=0, shortform;
        !           253:        int c, f, reg;
        !           254: 
        !           255:        reg = opptr->value_o;
        !           256:        if (areg(reg) || dreg(reg))
        !           257:            indexval = reg << 12;
        !           258:        else PROG_ERROR(E_REG);
        !           259:        if (opptr->flags_o&O_LINDEX) indexval |= 0x0800;
        !           260:        switch (opptr->scale_o){
        !           261:        case 1 : break;
        !           262:        case 2 : indexval |= 1<<9; break;
        !           263:        case 4 : indexval |= 2<<9; break;
        !           264:        case 8 : indexval |= 3<<9; break;
        !           265:        }
        !           266:        opptr->value_o = opptr->disp_o;
        !           267:        f = opptr->flags_o;
        !           268:        c = code_length >>1;
        !           269:        code_length += 2;
        !           270:        if (f&O_WDISP){
        !           271:            /* force word displacement */
        !           272:            if ( opptr->disp_o < -32768 || opptr->disp_o > 32767
        !           273:              || opptr->sym_o && opptr->sym_o->csect_s == 0 )
        !           274:                PROG_ERROR(E_OFFSET) ;
        !           275:            shortform = 0;
        !           276:            displ1 = 2<<4; 
        !           277:            rel_val(opptr,SUBOP_W , 0);
        !           278:        }else if (f&O_LDISP || (ext_instruction_set && !cansdi)){
        !           279:            /* force long displacement */
        !           280:            shortform = 0;
        !           281:            displ1 = 3<<4; 
        !           282:            rel_val(opptr,SUBOP_L , 0);
        !           283:        }else{
        !           284:            shortform =  (!(f & (O_BSUPRESS|O_POSTINDEX|O_INDIRECT))
        !           285:                && (f&O_PREINDEX) );
        !           286:            if (ext_instruction_set && cansdi && !(f&O_BDISP)){
        !           287:                if (pass == 1 && forward_ref(opptr)) {
        !           288:                    prog_error(E_FORWARD);
        !           289:                }
        !           290:                switch (displacement(opptr, 0 , 1, shortform, was_displ)){
        !           291:                case T_NULL: /* displacement is 0 */
        !           292:                    displ1 = 1<<4; 
        !           293:                    break;
        !           294:                case T_INDEX: /* displacement is small */
        !           295:                    break;
        !           296:                case T_ABSS: /* displacement is moderate */
        !           297:                    displ1 = 2<<4; 
        !           298:                    shortform = 0;
        !           299:                    break;
        !           300:                case T_ABSL: /* displacement is huge*/
        !           301:                    displ1 = 3<<4; 
        !           302:                    shortform = 0;
        !           303:                    break;
        !           304:                }
        !           305:            }
        !           306:            /* else !ext_instruction_set: use short form */
        !           307:            if (shortform || (f&O_BDISP)){
        !           308:                if (opptr->disp_o < -128 || opptr->disp_o > 127
        !           309:                  || opptr->sym_o && opptr->sym_o->csect_s == 0)
        !           310:                    PROG_ERROR(E_OFFSET) ;
        !           311:                indexval |= opptr->disp_o & 0377;
        !           312:                wcode[c] = indexval; /* install index word */
        !           313:                return;
        !           314:            }
        !           315:        }
        !           316:        /* long form indexing */
        !           317:        /* first displacement */
        !           318:        if (f&O_BSUPRESS)
        !           319:            indexval |= 1<<7; /* base  supress */
        !           320:        if (!(f&(O_PREINDEX|O_POSTINDEX)))
        !           321:            indexval |= 1<<6; /* index supress */
        !           322:        indexval |= displ1 | (1<<8);
        !           323:        if (!(f&O_INDIRECT))
        !           324:            displ2 = 0; /* no indirection */
        !           325:        else {
        !           326:            opptr->value_o = opptr->disp2_o;
        !           327:            opptr->sym_o = opptr->sym2_o;
        !           328:            if (f&O_LDISP2 || !cansdi){
        !           329:                /* long displacement */
        !           330:                displ2 = 3;
        !           331:                rel_val(opptr,SUBOP_L , 0);
        !           332:            }else if (f&O_WDISP2){
        !           333:                /* word displacement */
        !           334:                if (opptr->disp2_o < -32768 || opptr->disp2_o > 32767
        !           335:                  || opptr->sym2_o && opptr->sym2_o->csect_s == 0)
        !           336:                    PROG_ERROR(E_OFFSET) ;
        !           337:                displ2 = 2;
        !           338:                rel_val(opptr,SUBOP_W , 0);
        !           339:            } else {
        !           340:                if (pass == 1 && forward_ref(opptr)) {
        !           341:                    prog_error(E_FORWARD);
        !           342:                }
        !           343:                switch (displacement( opptr, 0, 1, 0, 0 )){
        !           344:                case T_NULL:
        !           345:                    displ2 = 1; break;
        !           346:                case T_ABSS:
        !           347:                    displ2 = 2; break;
        !           348:                case T_ABSL:
        !           349:                    displ2 = 3; break;
        !           350:                }
        !           351:            }
        !           352:            indexval |= displ2 | ((f&O_POSTINDEX)?(1<<2):0);
        !           353:            
        !           354:        }
        !           355:        wcode[c] = indexval; /* install index word */
        !           356: }

unix.superglobalmegacorp.com

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