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