Annotation of researchv9/cmd/sun/as/operand.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)operand.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 <ctype.h>
                     11: 
                     12: short cinfo[128] = {
                     13:        ERR,    ERR,    ERR,    ERR,    ERR,    ERR,    ERR,    ERR,
                     14:        ERR,    SPC,    EOL,    SPC,    SPC,    SPC,    ERR,    ERR,
                     15:        ERR,    ERR,    ERR,    ERR,    ERR,    ERR,    ERR,    ERR,
                     16:        ERR,    ERR,    ERR,    ERR,    ERR,    ERR,    ERR,    ERR,
                     17:        SPC,    ERR,    QUO,    IMM,    S+T,    ERR,    ERR,    ERR,
                     18:        LP,     RP,     MUL,    ADD,    COM,    SUB,    S+T,    DIV,
                     19:        D+T,    D+T,    D+T,    D+T,    D+T,    D+T,    D+T,    D+T,
                     20:        D+T,    D+T,    COL,    EOL,    ERR,    EQL,    ERR,    ERR,
                     21:        IND,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,
                     22:        S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,
                     23:        S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,
                     24:        S+T,    S+T,    S+T,    ERR,    ERR,    ERR,    ERR,    S+T,
                     25:        ERR,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,
                     26:        S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,
                     27:        S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,    S+T,
                     28:        S+T,    S+T,    S+T,    LB,     EOL,    RB,     NOT,    S+T
                     29: };  
                     30: 
                     31: /* for local labels: ``[0-9]:'', and references ``[0-9][bh]'' */
                     32: char *ll_format = "*%c%06d";
                     33: int   ll_val[10];
                     34: 
                     35: static struct suffix {
                     36:     int                indx_sx;        /* index register */
                     37:     int                scale_sx;       /* index scaling  */
                     38:     long       disp_sx;        /* displacement   */
                     39:     struct sym_bkt *sym_sx;    /* symbolic displacement */
                     40:     unsigned   flags_sx;       /* see below      */
                     41: } fix [2];
                     42: 
                     43: static struct suffix zero_suffix = {  0  };
                     44: 
                     45: /* flags_sx values */
                     46: #define SX_INDXW       1       /* word-size index specified */
                     47: #define SX_INDXL       2       /* long-size index specified */
                     48: #define SX_DISPW       4       /* word-size displacement specified */
                     49: #define SX_DISPL       010     /* long-size displacement specified */
                     50: #define SX_GOTINDEX    020     /* index register specified */
                     51: #define SX_GOTDISP     040     /* displacement specified */
                     52: #define SX_DISPB       0100    /* word-size displacement specified */
                     53: 
                     54: static struct oper zero_oper  = { T_NULL };
                     55: 
                     56: char *suffix(), *exp(), *term(), *scan_reg_or_immed();
                     57: char * scan_float();
                     58: double atof();
                     59: char * reglist () ;
                     60: 
                     61: /* 
                     62:  * Fetches operand value and register subfields and loads them into
                     63:  * the operand structure. This routine will fetch only one set of value
                     64:  * and register subfields. 
                     65:  * It will move line pointer to first untouched char.
                     66:  */
                     67: char *
                     68: soperand(lptr,opnd)
                     69:        register char *lptr;
                     70:        struct oper *opnd;
                     71: {
                     72:        struct oper   spare_oper;
                     73:        int v;
                     74: 
                     75:        *opnd = zero_oper;
                     76:        spare_oper = zero_oper;
                     77: 
                     78:        if ((v=cinfo[*lptr]) == IMM) {
                     79:                lptr = exp(++lptr,opnd);
                     80:                if (opnd->type_o == T_REG) 
                     81:                        PROG_ERROR(E_REG);
                     82:                opnd->immed_o = opnd->type_o ; /* Save type. */
                     83:                opnd->type_o = T_IMMED;
                     84:        } else if (v == IND) {
                     85:            /* index mode, omitted base */
                     86:            /* expecting LP next        */
                     87:            lptr += 1;
                     88:            skipb(lptr);
                     89:            if (cinfo[*lptr] == LP)
                     90:                goto index_mode;
                     91:            else
                     92:                PROG_ERROR(E_OPERAND);
                     93:        } else { 
                     94:            lptr = exp(lptr,opnd);
                     95:            skipb(lptr);
                     96:            switch (opnd->type_o){
                     97:            case T_REG:
                     98:                switch (cinfo[*lptr]){
                     99:                case COL:       
                    100:                        /* should be a register pair */
                    101:                        lptr = exp( ++lptr, &spare_oper);
                    102:                        if (spare_oper.type_o != T_REG)
                    103:                            PROG_ERROR(E_OPERAND);
                    104:                        if (!ext_instruction_set)
                    105:                            PROG_ERROR( E_OPERAND );
                    106:                        opnd->type_o = T_REGPAIR;
                    107:                        opnd->reg_o = spare_oper.value_o;
                    108:                        break;
                    109:                case IND:
                    110:                        if (!(areg(opnd->value_o)
                    111:                                || pcreg(opnd->value_o)))
                    112:                            PROG_ERROR(E_OPERAND);
                    113:                        lptr += 1;
                    114:                        skipb(lptr);
                    115:                        switch (cinfo[*lptr]){
                    116:                        default:
                    117:                            opnd->type_o = T_DEFER;
                    118:                            break;
                    119:                        case ADD:
                    120:                            opnd->type_o = T_POSTINC;
                    121:                            lptr++;
                    122:                            break;
                    123:                        case SUB:
                    124:                            opnd->type_o = T_PREDEC;
                    125:                            lptr++;
                    126:                            break;
                    127:                        case LP:
                    128:                            /* defer or indexing coming up here */
                    129:                index_mode:
                    130:                            lptr = suffix( lptr, &fix[0] );
                    131:                            if (cinfo[*lptr] != IND){
                    132:                                simplify1( opnd, &fix[0] );
                    133:                            } else {
                    134:                                lptr = suffix( ++lptr, &fix[1] );
                    135:                                simplify2( opnd, &fix[0], &fix[1] );
                    136:                            }
                    137:                            break;
                    138:                        case IND:
                    139:                            lptr = suffix( ++lptr, &fix[1] );
                    140:                            simplify2( opnd, &zero_suffix, 
                    141:                                &fix[1] );
                    142:                            break;
                    143:                        }
                    144:                        if (opnd->type_o == T_INDEX 
                    145:                                && !ext_instruction_set)
                    146:                        if ( (opnd->flags_o &
                    147:                        (O_BSUPRESS|O_INDIRECT|O_WDISP|O_LDISP))
                    148:                        || opnd->scale_o != 1 
                    149:                        || !(opnd->flags_o&O_PREINDEX))
                    150:                                PROG_ERROR( E_OPERAND );
                    151:                        /* flow through */
                    152:                default:
                    153:                        break;
                    154:                }
                    155:                break; 
                    156:            case T_NORMAL:
                    157:                if  (cinfo[*lptr] == COL ){
                    158:                    switch (*++lptr) { 
                    159:                        case 'W':
                    160:                        case 'w': opnd->type_o = T_ABSS;
                    161:                                  lptr++;
                    162:                                  break;
                    163:                        case 'L':
                    164:                        case 'l': opnd->type_o = T_ABSL;
                    165:                                  lptr++;
                    166:                                  break;
                    167:                    }
                    168:                }
                    169:                if (cinfo[*lptr] == IND)
                    170:                    goto index_mode;
                    171:                break; 
                    172:            }
                    173:     }
                    174:     skipb( lptr );
                    175:     if ( cinfo[ *lptr ] == LB ) {
                    176:        /* oh, boy, bitfields */
                    177:        opnd->flags_o |= O_BFLD;
                    178:        spare_oper = zero_oper;
                    179:        lptr = scan_reg_or_immed( lptr+1, &spare_oper);
                    180:        v = spare_oper.value_o;
                    181:        if (spare_oper.type_o == T_REG){
                    182:            opnd->flags_o |= O_BFOREG;
                    183:        } else if ((spare_oper.sym_o && !(spare_oper.sym_o->attr_s&S_DEF)) 
                    184:                || v < 0 || v > 31){
                    185:            PROG_ERROR(E_CONSTANT);
                    186:        }
                    187:        opnd->bfoffset_o = v;
                    188:        skipb( lptr );
                    189:        if ( cinfo[ *lptr ] == COL)
                    190:            lptr ++;
                    191:        else
                    192:            PROG_ERROR(E_OPERAND);
                    193:        spare_oper = zero_oper;
                    194:        lptr = scan_reg_or_immed( lptr, &spare_oper);
                    195:        v = spare_oper.value_o;
                    196:        if (spare_oper.type_o == T_REG){
                    197:            opnd->flags_o |= O_BFWREG;
                    198:        } else if ((spare_oper.sym_o && !(spare_oper.sym_o->attr_s&S_DEF)) 
                    199:                || v < 0 || v > 32){
                    200:            PROG_ERROR(E_CONSTANT);
                    201:        }
                    202:        opnd->bfwidth_o = (v == 32 ? 0 : v);
                    203:        skipb( lptr );
                    204:        if ( cinfo[ *lptr ] == RB )
                    205:            lptr++;
                    206:        else
                    207:            PROG_ERROR(E_OPERAND);
                    208:     }
                    209:     return(lptr);
                    210: } /* end soperand */
                    211: 
                    212: static char * 
                    213: scan_reg_or_immed( lptr, o )
                    214:     register char *lptr;
                    215:     register struct oper *o;
                    216: {
                    217:     skipb( lptr );
                    218:     if (cinfo[*lptr] == IMM) {
                    219:            lptr = exp(++lptr,o);
                    220:            if (o->type_o == T_REG) 
                    221:                    PROG_ERROR(E_REG);
                    222:            if (o->sym_o && !(o->sym_o->attr_s&S_DEF))
                    223:                    PROG_ERROR(E_REG);
                    224:            o->type_o = T_IMMED;
                    225:     } else {
                    226:        lptr = exp( lptr, o );
                    227:        if ( o->type_o != T_REG || o->value_o > D7REG)
                    228:            PROG_ERROR(E_OPERAND);
                    229:     }
                    230:     return lptr;
                    231: }
                    232: 
                    233: static char *
                    234: opt_length( lptr, fp, wflag, lflag, bflag )
                    235:     register char * lptr;
                    236:     struct suffix * fp;
                    237: {
                    238:     char * save = lptr;
                    239:     if (cinfo[ *lptr ] == COL){
                    240:        lptr++;
                    241:        skipb( lptr );
                    242:        switch ( *lptr ){
                    243:        case 'b':
                    244:        case 'B':
                    245:                if (bflag == 0) return save ;
                    246:                fp->flags_sx |= bflag;
                    247:                lptr++;
                    248:                break;
                    249:        case 'l':
                    250:        case 'L':
                    251:                fp->flags_sx |= lflag;
                    252:                lptr++;
                    253:                break;
                    254:        case 'w':
                    255:        case 'W':
                    256:                fp->flags_sx |= wflag;
                    257:                lptr++;
                    258:                break;
                    259:        default: return save; /* : yes, length, no: may be scale */
                    260:        }
                    261:     }
                    262:     return lptr;
                    263: }
                    264: static char *
                    265: opt_scale( lptr, fp )
                    266:     char * lptr;
                    267:     struct suffix * fp;
                    268: {
                    269:     fp->scale_sx = 1;
                    270:     if (cinfo[ *lptr ] == COL){
                    271:        lptr++;
                    272:        skipb( lptr );
                    273:        switch ( *lptr ){
                    274:        case '1':
                    275:        case '2':
                    276:        case '4':
                    277:        case '8':
                    278:                fp->scale_sx = *lptr - '0';
                    279:                lptr++;
                    280:                break;
                    281:        default: PROG_ERROR(E_OPERAND);
                    282:        }
                    283:     }
                    284:     return lptr;
                    285: }
                    286: 
                    287: static char *
                    288: suffix( lptr, fixp )
                    289:     register char * lptr;
                    290:     register struct suffix * fixp;
                    291: {
                    292:     /*
                    293:      * scan for open paran. look for displacement, optional length
                    294:      * specifier, then index register, optional length specifier, 
                    295:      * optional scale specifier.
                    296:      * fill in suffix structure with what we find.
                    297:      */
                    298:     struct oper o;
                    299:     o = zero_oper;
                    300:     *fixp = zero_suffix;
                    301:     skipb( lptr );
                    302:     if (cinfo[ *lptr ] == LP )
                    303:        lptr += 1;
                    304:     else
                    305:        return lptr; /* guess that null suffix might be ok */
                    306:     lptr = exp( lptr , &o );
                    307:     if ( o.type_o == T_NORMAL ){
                    308:        fixp->disp_sx = o.value_o;
                    309:        fixp->sym_sx = o.sym_o;
                    310:        fixp->flags_sx |= SX_GOTDISP;
                    311:        lptr = opt_length( lptr, fixp, SX_DISPW, SX_DISPL, SX_DISPB );
                    312:        skipb( lptr );
                    313:        if (cinfo[ *lptr ] ==  COM)
                    314:            lptr = exp( ++lptr, &o );
                    315:        else
                    316:            goto scan_rp;
                    317:     }
                    318:     /* now we're talking index */
                    319:     if ( o.type_o != T_REG ){
                    320:        PROG_ERROR( E_OPERAND);
                    321:     }
                    322:     fixp->flags_sx |= SX_GOTINDEX;
                    323:     fixp->indx_sx = o.value_o;
                    324:     lptr = opt_length( lptr, fixp, SX_INDXW, SX_INDXL, 0 );
                    325:     lptr = opt_scale( lptr, fixp );
                    326: scan_rp:
                    327:     skipb( lptr );
                    328:     if (cinfo[ *lptr ] == RP)
                    329:        lptr ++;
                    330:     else
                    331:        PROG_ERROR( E_OPERAND);
                    332:     return lptr;
                    333: }
                    334: 
                    335: static
                    336: simplify1( oper, fp )
                    337:     register struct oper * oper;
                    338:     register struct suffix *fp;
                    339: {
                    340:     register bval = oper->value_o;
                    341:     /* we have some form of deferred or indexed addressing here */
                    342:     /* try to make the best of it.                              */
                    343:     /*
                    344:      * examples are:
                    345:      *    a0@(disp)
                    346:      *    a0@(disp,d0:w:2)
                    347:      *    a0@(d0:w:2)
                    348:      *    pc@(disp)
                    349:      *    pc@(disp,d0:w:2)
                    350:      *    pc@(d0:w:2)
                    351:      *      @(d0)
                    352:      *      @(disp,d0)
                    353:      */
                    354:     switch (oper->type_o){
                    355:     case T_REG:
                    356:        if( !(fp->flags_sx&(SX_GOTINDEX|SX_DISPL)) ){
                    357:            /* displacement mode */
                    358:            oper->type_o = T_DISPL;
                    359:            oper->reg_o = bval;
                    360:            oper->value_o = fp->disp_sx;
                    361:            oper->sym_o = fp->sym_sx;
                    362:            if (fp->flags_sx & SX_DISPW)
                    363:                oper->flags_o|= O_WDISP;
                    364:            else if (fp->flags_sx & SX_DISPB) {
                    365:                PROG_ERROR(E_OPERAND);
                    366:                oper->flags_o|= O_WDISP;
                    367:            }
                    368:        } else {
                    369:            /* index mode */
                    370: imode:
                    371:            oper->type_o = T_INDEX;
                    372:            oper->reg_o = bval;
                    373:            oper->disp_o = fp->disp_sx;
                    374:            oper->sym_o = fp->sym_sx;
                    375:            if (fp->flags_sx&SX_GOTINDEX){
                    376:                oper->value_o = fp->indx_sx;
                    377:                oper->scale_o = fp->scale_sx;
                    378:                if (fp->flags_sx&SX_INDXW)
                    379:                    oper->flags_o|= O_WINDEX|O_PREINDEX;
                    380:                else 
                    381:                    oper->flags_o|= O_LINDEX|O_PREINDEX;
                    382:            } else {
                    383:                oper->value_o = 0;
                    384:                oper->scale_o = 0;
                    385:            }
                    386:            if (fp->flags_sx & SX_DISPL)
                    387:                oper->flags_o|= O_LDISP;
                    388:            /* else short form indexing */
                    389:            else if (fp->flags_sx & SX_DISPW)
                    390:                oper->flags_o|= O_WDISP;
                    391:            else if (fp->flags_sx & SX_DISPB)
                    392:                oper->flags_o|= O_BDISP;
                    393:        }
                    394:        return;
                    395:     case T_NULL:
                    396:        /* @(disp,d0)                 */
                    397:        /* @(d0)                      */
                    398:        /* index mode, supressed base */
                    399:        oper->type_o= T_INDEX;
                    400:        oper->flags_o|= O_BSUPRESS;
                    401:        oper->reg_o = A0REG; /* Supress THIS register */
                    402:        oper->disp_o= fp->disp_sx;
                    403:        oper->sym_o= fp->sym_sx;
                    404:        if(fp->flags_sx & SX_DISPL)
                    405:           oper->flags_o |= O_LDISP;
                    406:        else if (fp->flags_sx & SX_DISPW)
                    407:           oper->flags_o |= O_WDISP;
                    408:        else if (fp->flags_sx & SX_DISPB) {
                    409:           PROG_ERROR(E_OPERAND);
                    410:           oper->flags_o |= O_WDISP;
                    411:        }
                    412:     do_index:
                    413:        if (fp->flags_sx & SX_GOTINDEX){
                    414:            oper->value_o = fp->indx_sx;
                    415:            oper->scale_o = fp->scale_sx;
                    416:            if (fp->flags_sx & (SX_INDXW) )
                    417:                oper->flags_o |= O_PREINDEX|O_WINDEX;
                    418:            else
                    419:                oper->flags_o |= O_PREINDEX|O_LINDEX;
                    420:        } else {
                    421:            oper->value_o = 0;
                    422:            oper->scale_o = 0;
                    423:        }
                    424:        return;
                    425:     case T_ABSS:
                    426:        oper->flags_o = O_WDISP;
                    427:        goto normal;
                    428:     case T_ABSL:
                    429:        oper->flags_o = O_LDISP;
                    430:        goto normal;
                    431:     case T_NORMAL:
                    432:        /* disp@                        */
                    433:        /* disp@(d0)                    */
                    434:        /* index mode, supressed base   */
                    435:        oper->flags_o = 0;
                    436:     normal:
                    437:        oper->type_o = T_INDEX;
                    438:        oper->flags_o|= O_BSUPRESS;
                    439:        oper->reg_o = A0REG; /* Supress THIS register */
                    440:        oper->disp_o = oper->value_o;
                    441:        if (fp->flags_sx&SX_GOTDISP)
                    442:            PROG_ERROR(E_OPERAND);
                    443:        goto do_index;
                    444:     default:
                    445:            PROG_ERROR(E_OPERAND);
                    446:     }
                    447: }
                    448: 
                    449: static
                    450: simplify2( oper, fp, dfp )
                    451:     register struct oper * oper;
                    452:              struct suffix *fp;
                    453:     register struct suffix *dfp;
                    454: {
                    455:     /*
                    456:      * we have a memory indirect operand.
                    457:      * examples:
                    458:      * a0@(disp:l,d0:l:4)@(disp:w)
                    459:      *  a0@(disp)@(disp,d0:l:4)
                    460:      *  a0@@
                    461:      *    @(disp,d0)@(disp)
                    462:      *    @(d0)@
                    463:      *    @(disp)@
                    464:      *    @(disp,d0)@
                    465:      *   @(disp)@(d0)
                    466:      */
                    467:     simplify1( oper, fp );
                    468:     if (oper->type_o == T_DISPL){
                    469:        oper->type_o = T_INDEX;
                    470:        oper->disp_o = oper->value_o;
                    471:        oper->value_o = 0;
                    472:     }
                    473:     /* now build on that with second suffix */
                    474:     oper->flags_o |= O_INDIRECT;
                    475:     oper->disp2_o = dfp->disp_sx;
                    476:     oper->sym2_o  = dfp->sym_sx;
                    477:     if (dfp->flags_sx & SX_DISPL)
                    478:        oper->flags_o |= O_LDISP2;
                    479:     else if (dfp->flags_sx & SX_DISPW)
                    480:        oper->flags_o |= O_WDISP2;
                    481:     else if (dfp->flags_sx & SX_DISPB) {
                    482:        PROG_ERROR(E_OPERAND);
                    483:        oper->flags_o |= O_WDISP2;
                    484:     }
                    485:     if (dfp->flags_sx & SX_GOTINDEX){
                    486:        if (oper->flags_o&O_PREINDEX)
                    487:            PROG_ERROR(E_OPERAND);
                    488:        oper->value_o = dfp->indx_sx;
                    489:        oper->flags_o |= O_POSTINDEX;
                    490:        oper->scale_o = dfp->scale_sx;
                    491:        if (dfp->flags_sx&SX_INDXW)
                    492:            oper->flags_o |= O_WINDEX;
                    493:        else
                    494:            oper->flags_o |= O_LINDEX;
                    495:     }
                    496: 
                    497: }
                    498: 
                    499: /* read expression */
                    500: char *
                    501: exp(lptr, arg1)
                    502:     register char *lptr;
                    503:     register struct oper *arg1;
                    504: {
                    505:     struct oper arg2;          /* holds value of right hand term */
                    506:     register int i;
                    507:     static struct oper zero_opr;
                    508:     register char *lptr0 ;
                    509: 
                    510:     lptr0 = lptr ;             /* Save pointer to beginning for 
                    511:                                        use by reglist. */
                    512:        skipb(lptr);            /* Find the operator */
                    513:     i = cinfo[*lptr];
                    514:     if (i==EOL || i==COM){        /* nil operand is zero */
                    515:        arg1->sym_o = NULL;
                    516:         arg1->value_o = 0;
                    517:         return(lptr);
                    518:     }
                    519:     lptr = term( lptr, arg1 );
                    520: 
                    521:     while (1) {
                    522:          arg2 = zero_opr;
                    523:          skipb(lptr);
                    524:          switch (cinfo[*lptr]) {
                    525:            case ADD:   lptr = term( ++lptr, &arg2 );
                    526:                        if (arg1->type_o==T_REG || arg2.type_o==T_REG) 
                    527:                            break;
                    528:                        if (arg1->sym_o && arg2.sym_o) 
                    529:                            if (pass==2) break;
                    530:                        if (arg2.sym_o) 
                    531:                            arg1->sym_o = arg2.sym_o;
                    532:                        arg1->value_o += arg2.value_o;
                    533:                        arg1->flags_o |= arg2.flags_o&O_COMPLEX;
                    534:                        continue;
                    535: 
                    536:            case MUL:   lptr = term(++lptr,&arg2);
                    537:                        if (arg1->type_o==T_REG || arg2.type_o==T_REG) 
                    538:                            break;
                    539:                        if (arg1->sym_o || arg2.sym_o) 
                    540:                            if (pass==2) break;
                    541:                        arg1->value_o *= arg2.value_o;
                    542:                        arg1->flags_o |= arg2.flags_o&O_COMPLEX;
                    543:                        continue;
                    544: 
                    545:            case DIV:   lptr = term( ++lptr, &arg2 );
                    546:                        if (arg1->type_o==T_REG || arg2.type_o==T_REG) 
                    547:                           if (arg1->type_o==T_REG && arg2.type_o==T_REG) 
                    548:                                { /* try move multiple */
                    549:                                lptr = lptr0 ;
                    550:                                return(reglist( lptr, arg1)) ;
                    551:                                }
                    552:                           else break;
                    553:                        if (arg1->sym_o || arg2.sym_o) 
                    554:                            if (pass==2) break;
                    555:                           else if (arg2.value_o == 0) arg2.value_o = 1;
                    556:                        arg1->value_o /= arg2.value_o;
                    557:                        arg1->flags_o |= arg2.flags_o&O_COMPLEX;
                    558:                        continue;
                    559: 
                    560:            case SUB:   lptr = term( ++lptr, &arg2 );
                    561:                        if (arg1->type_o==T_REG || arg2.type_o==T_REG) 
                    562:                           if (arg1->type_o==T_REG && arg2.type_o==T_REG) 
                    563:                                { /* try move multiple */
                    564:                                lptr = lptr0 ;
                    565:                                return(reglist( lptr, arg1)) ;
                    566:                                }
                    567:                           else break;
                    568:                        if (arg2.sym_o){        /* if B is relocatable, */
                    569:                           if (arg1->sym_o){    /* and A is relocatable, */
                    570:                               if ((arg1->sym_o->csect_s == 0) &&
                    571:                                   ( arg2.sym_o->csect_s != 0))
                    572:                                        { /* special case: external - relocatable */
                    573:                                        arg1->flags_o |= O_COMPLEX;     
                    574:                                        }
                    575:                                else
                    576:                                if (arg2.sym_o->csect_s 
                    577:                                        != arg1->sym_o->csect_s
                    578:                               && pass == 2){
                    579:                                   break;  /* break into error */
                    580:                               } else {   /* result is absolute (no offset) */
                    581:                                    arg1->sym_o = NULL; 
                    582:                                    /* but not a simple address for sdi's */
                    583:                                    arg1->flags_o |= O_COMPLEX; 
                    584:                               }
                    585:                           } 
                    586:                            else break;    /* if B rel., and A is not, */
                    587:                                           /* then break into relocation error */
                    588:                        }
                    589:                        arg1->value_o -= arg2.value_o;
                    590:                        continue;
                    591: 
                    592:            default:    return(lptr);
                    593:          }
                    594:        PROG_ERROR(E_RELOCATE);
                    595:        return(lptr);
                    596:     }
                    597: } /* end exp <read expression> */
                    598: 
                    599: /* read term: either symbol, constant, or unary minus */
                    600: char *
                    601: term( lptr, vp )
                    602:        register char *lptr;
                    603:        register struct oper *vp;
                    604: {
                    605:        register struct sym_bkt *sbp;
                    606:        register int base = 10;
                    607:        register long val;
                    608:        register char *p;
                    609:        register int i;
                    610:        char savechar, *t;
                    611:        char token[50];
                    612: 
                    613:        *vp = zero_oper;
                    614:        skipb(lptr);
                    615:        i = cinfo[*lptr];
                    616: 
                    617:        /* here for number */
                    618:        if (i & D){
                    619:                p = lptr;
                    620:                val = 0;
                    621:                if (*lptr == '0'){ 
                    622:                        lptr++;
                    623:                        switch (*lptr ){
                    624:                        case 'x':
                    625:                        case 'X':
                    626:                                lptr++; 
                    627:                                /* hexidecimal number */
                    628:                                while (1){
                    629:                                        if (cinfo[*lptr] & D)
                    630:                                                val = val*16 + *lptr++ - '0';
                    631:                                        else if (*lptr>='A' && *lptr<='F')
                    632:                                                val = val*16 + *lptr++ - 'A' + 10;
                    633:                                        else if (*lptr>='a' && *lptr<='f')
                    634:                                                val = val*16 + *lptr++ - 'a' + 10;
                    635:                                        else break;
                    636:                                }
                    637:                                break;
                    638:                        case 'r':
                    639:                        case 'R':
                    640:                                lptr = scan_float( lptr, vp );
                    641:                                return (lptr);
                    642:                        default:
                    643:                                /* octal number */
                    644:                                while (cinfo[*lptr] & D){
                    645:                                        if (*lptr == '8' || *lptr == '9')
                    646:                                                PROG_ERROR(E_CONSTANT);
                    647:                                        val = val*8 + *lptr++ - '0';
                    648:                                }
                    649:                        }
                    650:                } else {
                    651:                        /* decimal number */
                    652:                        while (cinfo[*lptr] & D)
                    653:                                val = val*10 + *lptr++ - '0';
                    654:                }
                    655:            got_a_number:
                    656:                if (*lptr == '$')
                    657:                        { lptr = p; goto sym; }
                    658:                if (*lptr == 'b' || *lptr == 'f'){
                    659:                        /* local label reference, of form [0-9][bh] */
                    660:                        /* single digits only                       */
                    661:                        if (lptr > p+1 ){
                    662:                            PROG_ERROR(E_SYMLEN);
                    663:                        }
                    664:                        val = ll_val[*p-'0'] + (*lptr++=='f');
                    665:                        if (val < 0 ) PROG_ERROR(E_SYMDEF);
                    666:                        sprintf(token, ll_format, *p, val);
                    667:                        sbp = lookup(token);
                    668:                        goto sym2;
                    669: 
                    670:                }
                    671:                vp->value_o = val;
                    672:                vp->sym_o = NULL;
                    673:                vp->type_o = T_NORMAL;
                    674:                return(lptr);
                    675:        }
                    676: 
                    677:        /* here for symbol name */
                    678:        if (i & S) {
                    679: sym:           t = lptr;
                    680:                while (cinfo[*lptr] & T)
                    681:                        lptr++;
                    682:                savechar = *lptr;
                    683:                *lptr = '\0';     
                    684:                sbp = lookup(t);                /* find its symbol bucket */
                    685:                *lptr = savechar;
                    686: sym2:
                    687:                if (sbp->attr_s & S_DEF)        /* if it's defined, use its value */
                    688:                        vp->value_o = sbp->value_s;
                    689:                else 
                    690:                        vp->value_o = 0;
                    691:                 if (sbp->attr_s & S_REG) {
                    692:                         vp->sym_o = NULL;
                    693:                         vp->type_o = T_REG;
                    694:                } else {
                    695:                        vp->sym_o = ((sbp->attr_s & S_DEF) &&
                    696:                            (sbp->csect_s == C_UNDEF )) ? 0 : sbp;
                    697:                        vp->type_o = T_NORMAL;
                    698:                }
                    699:                return(lptr);
                    700:        }
                    701: 
                    702:        /* check for unary minus */
                    703:        if (i == SUB) {
                    704:                lptr = term(++lptr,vp);
                    705:                if (vp->sym_o) PROG_ERROR(E_RELOCATE);
                    706:                vp->value_o = -(vp->value_o);
                    707:                vp->fval_o = -(vp->fval_o);
                    708:                vp->dval_o = -(vp->dval_o);
                    709:                return(lptr);
                    710:        }
                    711: 
                    712:        /* check for complement */
                    713:        if (i == NOT) {
                    714:                lptr = term(++lptr,vp);
                    715:                if (vp->sym_o) PROG_ERROR(E_RELOCATE);
                    716:                vp->value_o = ~(vp->value_o);
                    717:                return(lptr);
                    718:        }
                    719: 
                    720:        /* here for string */
                    721:        if (i == QUO) {
                    722:                vp->stringval_o = lptr+1;
                    723:                /* scan over the quoted string, being careful of \-stuff */
                    724:                do{
                    725:                        i = *++lptr;
                    726:                        if (i=='\\')
                    727:                        switch (i = *++lptr){
                    728:                        case '"': i = '\\'; /* fake-out loop test by covering up \"*/
                    729:                        }
                    730:                }while (i!='\n' && i!='"');
                    731:                if (i == '\n'){
                    732:                        PROG_ERROR(E_STRING);
                    733:                }
                    734:                *lptr++ = 0;
                    735:                vp->sym_o = NULL;
                    736:                vp->type_o = T_STRING;
                    737:                return(lptr);
                    738:        }
                    739: 
                    740:        /* new, improved kluge -- parens !! */
                    741:        if (i==LP) {
                    742:                lptr = exp(++lptr, vp);
                    743:                skipb(lptr);
                    744:                if ((i=cinfo[*lptr]) == RP) {
                    745:                        lptr++;
                    746:                } else {
                    747:                        PROG_ERROR( E_PAREN );
                    748:                }
                    749:                return( lptr );
                    750:        }
                    751: 
                    752:        PROG_ERROR(E_TERM);
                    753:        return(lptr);
                    754: } /* end term */
                    755: 
                    756: char lowcase( c ) 
                    757:        char c ;
                    758: {
                    759: if (('A' <= c) && (c <= 'Z')) return(c+32) ; else return(c) ;
                    760: }
                    761: 
                    762: char *
                    763: scan_float( lptr, vp )
                    764:     register char * lptr;
                    765:     struct oper *vp;
                    766: {
                    767:     /*
                    768:      * lptr address a string which is a 'd' or an 'f', followed
                    769:      * by a floating-point number. The latter looks like:
                    770:      *     [+-]nan
                    771:      * or  [+-]nan( [0-9a-f]+ )
                    772:      * or  [+-]inf
                    773:      * or  [+-][0-9]+[.[0-9]+][e[+-][0-9]+]
                    774:      * Upper/lower case may be used interchangeably.
                    775:      * For numbers, call atof to do the conversion work.
                    776:      * We do not take great care in syntax checking the number.
                    777:      */
                    778:     int s=0;
                    779:     union{ double d; float f; int x[2]; } fp;
                    780:     unsigned nanno, nanno2;
                    781:     register char *nbegin;
                    782:     char c;
                    783: 
                    784:        lptr++ ;        /* Skip F or f. */
                    785:        nbegin = lptr ;
                    786: again:
                    787:     switch (lowcase( *lptr++)){
                    788:     case '+':  if (s) goto bad_num; s = 1; goto again;
                    789:     case '-':  if (s) goto bad_num; s = -1; goto again;
                    790:     case 'n': /* nan */
                    791:        if (lowcase(*lptr++) != 'a') goto bad_num;
                    792:        if (lowcase(*lptr++) != 'n') goto bad_num;
                    793:        nanno = nanno2 = 0;
                    794:        if (*lptr == '(')
                    795:                { /* nan significand */ 
                    796:                lptr++ ;        /* pass paren */
                    797:                while( isxdigit(c = *lptr++)){
                    798:                if (isdigit(c)) c -= '0';
                    799:                else if (isupper(c)) c -= 'a'-10;
                    800:                else c -= 'A'-10;
                    801:                nanno2 = (nanno2 << 8) | (nanno >> 24);
                    802:                nanno = (nanno<<8) | c;
                    803:                }
                    804:                if (c != ')') goto bad_num;
                    805:                } /* nan significand */
                    806:        if ((nanno | nanno2) == 0) nanno = -1 ; /* avoid zero nan */
                    807:        goto make_indef;
                    808:            
                    809:     case 'i':  /* inf */
                    810:        if (lowcase(*lptr++) != 'n') goto bad_num;
                    811:        if (lowcase(*lptr++) != 'f') goto bad_num;
                    812:         if (strncmp(lptr,"inity",5) == 0) lptr += 5;
                    813:        nanno = nanno2 = 0;
                    814:     make_indef:
                    815:            fp.x[0] = ((s<0)?0xfff00000:0x7ff00000) | nanno2;
                    816:            fp.x[1] = nanno;
                    817:        break;
                    818:     case '0': case '1': case '2': case '3': case '4':
                    819:     case '5': case '6': case '7': case '8': case '9': 
                    820:        /* scan for more digits */
                    821:        while( isdigit( c = *lptr++ ) )
                    822:            continue;
                    823:         if (c != '.' )
                    824:             goto scan_exp;
                    825:         /* FALL THROUGH */
                    826:       case '.':
                    827:         /* scan for more digits */
                    828:         while( isdigit( c = *lptr++ ) )
                    829:             continue;
                    830:       scan_exp:
                    831:        s = 0;
                    832:        switch(lowcase(c)){
                    833:        case '+':
                    834:        case '-':
                    835:            s = 1;
                    836:            /* FALL THROUGH */
                    837:        case 'e':
                    838:            switch ( c= *lptr++ ){
                    839:            case '+':
                    840:            case '-':
                    841:                if (s) goto bad_num;
                    842:                c = *lptr++;
                    843:                /* FALL THROUGH */
                    844:            default:
                    845:                s = 0; /* count chars: 0 is not ok */
                    846:                while( isdigit(c) ){
                    847:                    c = *lptr++;
                    848:                    s++;
                    849:                }
                    850:                if (s == 0) goto bad_num;
                    851:                break;
                    852:            }
                    853:            break;
                    854:        }
                    855:            fp.d = atof( nbegin );
                    856:        lptr--;
                    857:        break;
                    858:     default:
                    859:     bad_num:
                    860:        PROG_ERROR( E_BADCHAR );
                    861:        return lptr;
                    862:     }
                    863:        vp->dval_o = fp.d;
                    864:        vp->value_o = (int) fp.d;
                    865:        vp->type_o = T_DOUBLE;
                    866:     return lptr;
                    867: }
                    868: 
                    869: static void
                    870: printoffset( v, s )
                    871:     struct sym_bkt *s;
                    872: {
                    873:     if (s != NULL){
                    874:        fputs(s->name_s, stdout);
                    875:        if (v)
                    876:            printf("+%d", v);
                    877:     } else {
                    878:        printf("%d", v);
                    879:     }
                    880: }
                    881: 
                    882: static char *rnames[] = {
                    883:     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
                    884:     "a0", "a1", "a2", "a3", "a4", "a5", "a6", 
                    885:     "sp", "pc", "cc", "sr", "usp", "sfc", "dfc", "vbr", 
                    886: };
                    887: 
                    888: static void
                    889: printindex( o )
                    890:     register struct oper *o;
                    891: {
                    892:     printf(",%s:%c", rnames[o->value_o], 
                    893:        o->flags_o&O_WINDEX ? 'w' : 'l');
                    894:     if (o->scale_o != 1) printf(":%d", o->scale_o);
                    895: }
                    896: 
                    897: printop( o )
                    898:     register struct oper *o;
                    899: {
                    900:     switch (o->type_o){
                    901:     case T_REG:                printf("%s",   rnames[o->value_o]); break;
                    902:     case T_DEFER:      printf("%s@",  rnames[o->value_o]); break;
                    903:     case T_POSTINC:    printf("%s@+", rnames[o->value_o]); break;
                    904:     case T_PREDEC:     printf("%s@-", rnames[o->value_o]); break;
                    905:     case T_DISPL:      printf("%s@(", rnames[o->reg_o]);
                    906:                        printoffset(o->value_o, o->sym_o);
                    907:                        putchar(')');
                    908:                        break;
                    909:     case T_INDEX:      printf("%s@(", (o->flags_o&O_BSUPRESS) 
                    910:                                ? "XX" : rnames[o->reg_o]);
                    911:                        printoffset(o->disp_o, o->sym_o);
                    912:                        if (o->flags_o & O_WDISP) fputs(":w", stdout);
                    913:                        else if (o->flags_o & O_LDISP) fputs(":l", stdout);
                    914:                        if (o->flags_o&O_PREINDEX)
                    915:                            printindex( o );
                    916:                        putchar(')');
                    917:                        if (o->flags_o&O_INDIRECT){
                    918:                            fputs("@(", stdout);
                    919:                            printoffset(o->disp2_o, o->sym2_o);
                    920:                            if (o->flags_o&O_POSTINDEX)
                    921:                                printindex( o );
                    922:                            putchar(')');
                    923:                        }
                    924:                        break;
                    925:     case T_ABSS:
                    926:     case T_ABSL:
                    927:                        printoffset(o->value_o, o->sym_o);
                    928:                        fputs( (o->type_o == T_ABSS) ? ":w" : ":l", stdout);
                    929:                        break;
                    930:     case T_IMMED:
                    931:                        putchar('#');
                    932:                        /* FALL THROUGH */
                    933:     case T_NORMAL:
                    934:                        printoffset(o->value_o, o->sym_o);
                    935:                        break;
                    936:     case T_STRING:
                    937:                        printf("\"%s\"", o->stringval_o);
                    938:                        break;
                    939:     case T_REGPAIR:    printf("%s:%s", rnames[o->value_o],rnames[o->reg_o]);
                    940:                        break;
                    941:     case T_FLOAT:      
                    942:     case T_DOUBLE:     printf("0d%g", o->dval_o ); break;
                    943:     default:
                    944:                        printf("UNKNOWN(%d)", o->type_o);
                    945:                        break;
                    946:     }
                    947:     if (o->flags_o&O_BFLD){
                    948:        /* bit field */
                    949:        /* first the offset part */
                    950:        if (o->flags_o&O_BFOREG)
                    951:            printf("[%s:",rnames[o->bfoffset_o]);
                    952:        else
                    953:            printf("[#%d:",o->bfoffset_o);
                    954:        /* then the width part */
                    955:        if (o->flags_o&O_BFWREG)
                    956:            printf("%s]",rnames[o->bfwidth_o]);
                    957:        else
                    958:            printf("#%d]",o->bfwidth_o);
                    959:     }
                    960:     putchar('\n');
                    961: }
                    962: 
                    963: int aregs ;            /* Contains bits for a7..a0. */
                    964: int dregs ;            /* Contains bits for d7..d0. */
                    965: int fregs ;            /* Contains bits for fp7..fp0. */
                    966: int cregs ;            /* Contains bits for fpc..fpi. */
                    967: int otheregs ;         /* Contains 1 for any other regs encountered. */
                    968: 
                    969: storeg( n )
                    970: int n ;
                    971: 
                    972: {
                    973: if ((A0REG <= n) && (n <= A7REG)) aregs |= 1 << (n-A0REG) ;
                    974: else
                    975: if ((D0REG <= n) && (n <= D7REG)) dregs |= 1 << (n-D0REG) ;
                    976: else
                    977: if ((FP0REG <= n) && (n <= FP7REG)) fregs |= 1 << (n-FP0REG) ;
                    978: else
                    979: if ((FPCREG <= n) && (n <= FPIREG)) cregs |= 1 << (FPIREG-n) ;
                    980: else
                    981: otheregs = 1 ;
                    982: }
                    983: 
                    984: storegs( m, n )
                    985: int m, n ;
                    986: 
                    987: {
                    988: int t ;
                    989: 
                    990: if (m > n)
                    991:        {
                    992:        t = m ;
                    993:        m = n ;
                    994:        n = t ;
                    995:        }
                    996: if ((A0REG <= m) && (n <= A7REG)) for (t=m ; t <= n ; ) aregs |= 1 << (t++-A0REG) ;
                    997: else
                    998: if ((D0REG <= m) && (n <= D7REG)) for (t=m ; t<=n ; ) dregs |= 1 << (t++-D0REG) ;
                    999: else
                   1000: if ((FP0REG <= m) && (n <= FP7REG)) for (t=m ; t<=n ; ) fregs |= 1 << (t++-FP0REG) ;
                   1001: else
                   1002: if ((FPCREG <= m) && (n <= FPIREG)) for (t=m ; t<=n ; ) cregs |= 1 << (FPIREG-t++) ;
                   1003: else
                   1004: otheregs = 1 ;
                   1005: }
                   1006: 
                   1007: char * reglist ( lptr, arg1 )
                   1008: 
                   1009:        char *lptr ;
                   1010:        struct oper *arg1 ;
                   1011: 
                   1012: /*     
                   1013:        reglist is called from exp when a register list operand is
                   1014:        suspected.  If it fails, E_RELOCATE occurs.
                   1015: */
                   1016: 
                   1017: {
                   1018: struct oper arg2 ;
                   1019: 
                   1020: aregs = dregs = fregs = cregs = otheregs = 0 ;
                   1021: skipb(lptr) ;
                   1022: lptr = term(lptr, arg1) ;
                   1023: while (arg1->type_o == T_REG)
                   1024:        {
                   1025:        skipb(lptr) ;
                   1026:        switch (cinfo[*lptr])
                   1027:                {
                   1028:                case EOL:
                   1029:                case COM:       /* end of list */
                   1030:                        {
                   1031:                        storeg(arg1->value_o) ;
                   1032:                        if (otheregs) break ;
                   1033:                        if ((aregs|dregs) != 0)
                   1034:                                { /* list of a's and d's */
                   1035:                                if ((fregs|cregs) != 0) break ;
                   1036:                                arg1->type_o = T_REGLIST ;
                   1037:                                arg1->value_o = dregs | (aregs << 8) ; 
                   1038:                                return(lptr) ;
                   1039:                                }
                   1040:                        else
                   1041:                        if (fregs != 0)
                   1042:                                { /* list of fp's */
                   1043:                                if (cregs != 0) break ;
                   1044:                                arg1->type_o = T_FREGLIST ;
                   1045:                                arg1->value_o = fregs ;
                   1046:                                return(lptr) ;
                   1047:                                }
                   1048:                        else 
                   1049:                        if (cregs != 0)
                   1050:                                { /* list of fc's */
                   1051:                                arg1->type_o = T_FCREGLIST ;
                   1052:                                arg1->value_o = cregs ;
                   1053:                                return(lptr) ;
                   1054:                                }
                   1055:                        break ;
                   1056:                        }
                   1057:                case DIV:       /* rn/... */
                   1058:                        {
                   1059:                        storeg(arg1->value_o) ;
                   1060:                        lptr++ ;
                   1061:                        skipb(lptr) ;
                   1062:                        lptr = term(lptr, arg1) ;
                   1063:                        continue ;
                   1064:                        }
                   1065:                case SUB:       /* rn-... */
                   1066:                        {
                   1067:                        lptr = term (++lptr, &arg2) ;
                   1068:                        if (arg2.type_o != T_REG) break ;
                   1069:                        storegs(arg1->value_o,arg2.value_o) ;
                   1070:                        continue ;
                   1071:                        }
                   1072:                }
                   1073:        break ;
                   1074:        }
                   1075: arg1->type_o = T_NULL ; /* Avoid problems later. */
                   1076: PROG_ERROR(E_REGLIST) ;
                   1077: return(lptr) ;
                   1078: }
                   1079: 

unix.superglobalmegacorp.com

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