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