Annotation of coherent/b/bin/as/asm.y, revision 1.1.1.1

1.1       root        1: %{
                      2: #include <asm.h>
                      3: /*
                      4:  * count macro parms.
                      5:  */
                      6: static 
                      7: parmCt()
                      8: {
                      9:        if(NULL == trueMac) {
                     10:                yyerror(".parmct not in macro");
                     11:                /* \fB.parmct\fR returns the number of
                     12:                 * parameters in the current macro. */
                     13:                return(0);
                     14:        }
                     15:        else
                     16:                return(countList(trueMac->parms));
                     17: }
                     18: 
                     19: /*
                     20:  * Verify that 2 symbols have the same segment.
                     21:  */
                     22: static void
                     23: ckseg(s1, s2)
                     24: sym *s1, *s2;
                     25: {
                     26:        if(s1->sg != s2->sg)
                     27:                yyerror("Arithmetic between addresses on different segments");
                     28:                /* You may only add or subtract addresses if they
                     29:                 * are in the same segment. */
                     30: }
                     31: 
                     32: /*
                     33:  * Create Immediate exps.
                     34:  */
                     35: static expr *
                     36: setImm(val, symRef)
                     37: long val;
                     38: sym  *symRef;
                     39: {
                     40:        register expr *oper;
                     41:        register short w;
                     42: 
                     43:        oper = xalloc();
                     44:        oper->mode = T_IMM;
                     45:        if (NULL != (oper->ref = symRef))
                     46:                oper->ref = symRef->ref;
                     47:        w = oper->exp = val;
                     48:        if(w == val)
                     49:                oper->size = 2;
                     50:        else
                     51:                oper->size = 4;
                     52:        return(oper);
                     53: }
                     54: 
                     55: /*
                     56:  * Set up for most addressing modes.
                     57:  */
                     58: static expr *
                     59: qbild(val, mode, r1, r2, scale, symRef)
                     60: long val;
                     61: int mode;
                     62: psym *r1, *r2;
                     63: long scale;
                     64: sym *symRef;
                     65: {
                     66:        register expr *oper;
                     67:        char i;
                     68: 
                     69:        if (NULL != r1 && T_R != mode) {
                     70:                switch((int)r1->size) {
                     71:                case 2:
                     72:                        lflags |= A_SHORT;
                     73:                        if (!scale)
                     74:                                break;
                     75:                case 1:
                     76:                        regerror(r1);
                     77:                        break;
                     78:                case 4:
                     79:                        lflags |= A_LONG;
                     80:                        break;
                     81:                }
                     82: 
                     83:                if (ORD_REG != r1->flag)        /* cant ind via ctl regs */
                     84:                        regerror(r1);
                     85: 
                     86:                if (NULL != r2) {
                     87:                        if (ORD_REG != r2->flag)
                     88:                                regerror(r2);
                     89:                        if (r1->size != r2->size)
                     90:                                yyerror("Mixed length addressing registers");
                     91:                /* Addressing registers must both be the same length. */
                     92:                }
                     93:        }
                     94:        else if ((T_R == mode) && (r1->flag == ORD_REG)) {
                     95:                switch ((int)r1->size) {
                     96:                case 4:
                     97:                        lflags |= O_LONG;
                     98:                        break;
                     99:                case 2:
                    100:                        lflags |= O_SHORT;
                    101:                }
                    102:        }
                    103: 
                    104:        oper = xalloc();
                    105:        oper->exp  = val;
                    106:        oper->r1 = r1;
                    107:        oper->r2 = r2;
                    108:        oper->mode = mode;
                    109: 
                    110:        i = scale;
                    111:        if (i != scale)
                    112:                i = 3;  /* set a bad scale */
                    113: 
                    114:        switch (i) {
                    115:        case 0:
                    116:        case 1: /* for generated code */
                    117:                oper->scale = 0; break;
                    118:        case 2:
                    119:                oper->scale = 1; break;
                    120:        case 4:
                    121:                oper->scale = 2; break;
                    122:        case 8:
                    123:                oper->scale = 3; break;
                    124:        default:
                    125:                yyerror("Bad scale");
                    126:                /* Address scale must be 0, 1, 2, 4, or 8. */
                    127:        }
                    128: 
                    129:        if (NULL != (oper->ref = symRef))
                    130:                oper->ref = symRef->ref;
                    131:        return(oper);
                    132: }
                    133: 
                    134: /*
                    135:  * Floating point register expr.
                    136:  */
                    137: static expr *
                    138: fbild(regno)
                    139: long regno;
                    140: {
                    141:        register expr *oper;
                    142: 
                    143:        if (regno < 0 || regno > 7) {
                    144:                regno &= 7;
                    145:                yyerror("Invalid floating point register number"); /**/
                    146:        }
                    147: 
                    148:        oper = xalloc();
                    149:        oper->exp = regno;
                    150:        oper->mode = T_FP;
                    151:        return (oper);
                    152: }
                    153:        
                    154: /*
                    155:  * Report register error.
                    156:  */
                    157: regerror(rg)
                    158: psym *rg;
                    159: {
                    160:        yyerror("%s is an improper register in this context", rg->name); /**/
                    161: }
                    162: 
                    163: /*
                    164:  * Concatinate strings.
                    165:  */
                    166: static char *
                    167: concat(s1, s2)
                    168: char *s1, *s2;
                    169: {
                    170:        long l;
                    171:        unsigned short u;
                    172:        char *res;
                    173: 
                    174:        u = l = (long)strlen(s1) + (long)strlen(s2) + 1;
                    175:        if(u != l) {
                    176:                yyerror("Length %ld string range exceeded", l);
                    177:                /* Strings may not exceed 32 kilobytes. */
                    178:                return(galloc(1));
                    179:        }
                    180:        res = galloc(u);
                    181:        sprintf(res, "%s%s", s1, s2);
                    182:        return(res);
                    183: }
                    184: 
                    185: /*
                    186:  * Substring.
                    187:  * Assumes that all strings are created from unsigned lengths.
                    188:  */
                    189: static char *
                    190: substr(s, from, len)
                    191: char *s;
                    192: long from, len;
                    193: {
                    194:        register char *p, *res;
                    195:        unsigned short l;
                    196: 
                    197:        l = strlen(s);
                    198:        s += from;
                    199:        from = l - from;        /* from now len to end */
                    200: 
                    201:        if(len > from)
                    202:                len = from;     /* since strlen fit unsigned len must */
                    203:        if(len < 0)
                    204:                len = 0;
                    205: 
                    206:        for(p = res = galloc((unsigned)(len + 1)); len--; )
                    207:                *p++ = *s++;
                    208:        return(res);
                    209: }
                    210: 
                    211: /*
                    212:  * String search.
                    213:  */
                    214: static
                    215: stringSearch(s1, s2)
                    216: char *s1, *s2;
                    217: {
                    218:        char *p;
                    219: 
                    220:        if(NULL == (p = strstr(s1, s2)))
                    221:                return(-1);
                    222:        return(p - s1);
                    223: }
                    224: 
                    225: /*
                    226:  * Do long comparisons.
                    227:  * < > <= >= != ==  compare operator
                    228:  * 1 2  5  6  3  4  t
                    229:  */
                    230: static
                    231: compare(t, v)
                    232: int t;
                    233: long v;
                    234: {
                    235:        return(((v < 0) ? t : (v > 0) ? (t >> 1) : (t >> 2)) & 1);
                    236: }
                    237: 
                    238: /*
                    239:  * Do double comparisons.
                    240:  * < > <= >= != ==  compare operator
                    241:  * 1 2  5  6  3  4  t
                    242:  */
                    243: static
                    244: fcompare(t, v)
                    245: int t;
                    246: double v;
                    247: {
                    248:        return(((v < 0.0) ? t : (v > 0.0) ? (t >> 1) : (t >> 2)) & 1);
                    249: }
                    250: 
                    251: static void
                    252: unmatched(c)
                    253: {
                    254:        yyerror("Unmatched '%c'", c);
                    255:        /* A delimeter, [, (, ), or ] is unmatched in this command. */
                    256: }
                    257: 
                    258: %}
                    259: %union {
                    260:        long    val;    /* numeric value */
                    261:        double  dbl;
                    262:        sym     *s;     /* name size loc bitd bitl flag */
                    263:        opc     *o;     /* opcode kind */
                    264:        expr    *e;     /* mode loc size exp bitd bitl chain next */
                    265:        char    *t;     /* token */
                    266:        parm    *p;     /* parm  */
                    267:        data    *d;     /* data item */
                    268:        }
                    269: %token PC              /* The PC reg */
                    270: %token <val> NUMBER    /* a number */
                    271: %token <dbl> FNUM      /* floating point number */
                    272: %token <val> COMPARISON        /* =  < > <= >= !=*/
                    273: %token <o> OP          /* a 386 opcode */
                    274: %token <o> DATA                /* dc.w etc */
                    275: %token <o> CMD         /* an assembler command or macro call */
                    276: %token <o> DCMD                /* a command with string parms */
                    277: %token <o> ICMD                /* an assembler command taking a numexp parm */
                    278: %token <o> NCMD                /* an assembler command without parms */
                    279: %token <o> ECMD                /* an assembler command with a name and an expr */
                    280: %token <o> ECMDX       /* an assembler command with a name and a datalist */
                    281: %token <s> IDENTIFIER  /* a symbol */
                    282: %token <s> REG         /* A register */
                    283: 
                    284: %token DEFINED         /* the word .defined */
                    285: %token SIZEOF          /* the word .sizeof */
                    286: %token SEGMENT         /* the word .segment */
                    287: %token LOCATION                /* the word .location */
                    288: %token PLUS            /* + */
                    289: %token MINUS           /* - */
                    290: %token TIMES           /* * */
                    291: %token DIVIDE          /* / */
                    292: %token REM             /* % */
                    293: %token LSHIFT          /* << */
                    294: %token RSHIFT          /* >> */
                    295: %token AND             /* & */
                    296: %token OR              /* | */
                    297: %token XOR             /* ^ */
                    298: %token COMMA           /* , */
                    299: %token LPAREN          /* [ reversed with () */
                    300: %token RPAREN          /* ] */
                    301: %token LBRACK          /* ( */
                    302: %token RBRACK          /* ) */
                    303: %token AT              /* @ */
                    304: %token D_SIGN          /* $ */
                    305: %token NOT             /* ~ */
                    306: %token BANG            /* ! */
                    307: %token COLON           /* : */
                    308: %token PARMCT          /* .parmct */
                    309: %token TOSTRING                /* .string */
                    310: %token TONUMBER                /* .number */
                    311: %token TOFLOAT         /* .float */
                    312: %token FSTACK          /* %st */
                    313: %token NL              /* \n */
                    314: 
                    315: %token <t> TOKEN       /* a token in an assembler command or macro call */
                    316: %type <p> label parm plist
                    317: %type  <t> string
                    318: 
                    319: %right COMMA           /* low presidence to hi */
                    320: %right COLON
                    321: %right AT P_SIGN
                    322: %left  OR
                    323: %left  XOR
                    324: %left  AND
                    325: %left  COMPARISON
                    326: %left  LSHIFT RSHIFT
                    327: %left  PLUS MINUS
                    328: %left  TIMES DIVIDE REM
                    329: %right DEFINED SIZEOF SEGMENT LOCATION NOT LEN BANG
                    330: %right TOKEN
                    331: %left  LPAREN LBRACK TOSTRING TONUMBER TOFLOAT
                    332: %right NL
                    333: 
                    334: %type <dbl> dblexp
                    335: %type <val> numexp
                    336: /* addressing modes */
                    337: %type <e> operand oper escoper
                    338: 
                    339: %type <s> addexp
                    340: 
                    341: /* for dc.? */
                    342: %type <d> item itemlist
                    343: %%
                    344: 
                    345: /* oper types */
                    346: /*
                    347:  * label opcode operand comment NL
                    348:  * label and comment eaten by lexer.
                    349:  */ 
                    350: file   : line | file line;
                    351: 
                    352: line   : label CMD plist NL { /* assembler command with parms */
                    353:                docmd($1, $2, $3); }
                    354:        | label DCMD plist NL { /* a command with string parms */
                    355:                docmd($1, $2, $3); }
                    356:        | label ECMD parm COMMA item NL { /* command with a name & an expr */
                    357:                ecmd($1, $2, $3, $5); }
                    358:         /* command with a name & a datalist */
                    359:        | label ECMDX parm COMMA itemlist NL {
                    360:                ecmd($1, $2, $3, $5); }
                    361:        | label ECMD NL {
                    362:                ecmd($1, $2, NULL, NULL); }
                    363:        | label NCMD NL {       /* assembler command takes no parms */
                    364:                docmd($1, $2, (parm *)NULL); }
                    365:        | label ICMD item NL { /* assembler command with data parm */
                    366:                ncmd($1, $2, $3); }
                    367:        | label DATA itemlist NL { /* data list */
                    368:                dcmd($1, $2, $3); }
                    369:        | label OP operand NL { /* opcode operands */
                    370:                buildind($1, $2, $3); }
                    371:        | label OP OP NL {      /* built by rep instr */
                    372:                buildind($1, $2, NULL);
                    373:                buildind(NULL, $3, NULL ); }
                    374:        | label NL {    /* label alone on line */
                    375:                buildlab($1); }
                    376:        | error NL {    /* syntax error */
                    377:                if (bcnt > 0)
                    378:                        unmatched('[');
                    379:                if (bcnt < 0)
                    380:                        unmatched(']');
                    381:                if (pcnt > 0)
                    382:                        unmatched('(');
                    383:                if (pcnt < 0)
                    384:                        unmatched(')');
                    385:                yyerrok; };
                    386: 
                    387: itemlist : item COMMA itemlist {
                    388:                $$ = $1;
                    389:                $$->next = $3; }
                    390:        | item {
                    391:                $$ = $1; }
                    392:        | {
                    393:                $$ = NULL; };
                    394: 
                    395: item   : addexp {
                    396:                $$ = gitem('y');
                    397:                $$->d.y  = $1; }
                    398:        | dblexp {
                    399:                $$ = gitem('d');
                    400:                $$->d.d = $1; }
                    401:        | numexp {
                    402:                $$ = gitem('l');
                    403:                $$->d.l = $1; }
                    404:        | string {
                    405:                $$ = gitem('s');
                    406:                $$->d.s = $1; }
                    407:        | numexp P_SIGN item {
                    408:                $$ = $3;
                    409:                $$->count = $1; };
                    410: 
                    411: plist  : parm {                /* start parm list */
                    412:                $$ = $1; }
                    413:        | parm COMMA plist {    /* chain parm list */
                    414:                $$ = $1;
                    415:                $$->next = $3; }
                    416:        | {
                    417:                $$ = NULL; };
                    418: 
                    419: parm   : TOKEN {               /* start a parm */
                    420:                $$ = (parm *)gcpy($1, offset(parm, str)); };
                    421: 
                    422: label  : { 
                    423:                $$ = NULL; }
                    424:        | TOKEN {
                    425:                $$ = (parm *)gcpy($1, offset(parm, str)); };
                    426: 
                    427: /* operand may be stuff separated by commas */
                    428: operand : escoper COMMA operand {
                    429:                $$ = $1;
                    430:                $$->next = $3; }
                    431:        | escoper {
                    432:                $$ = $1; }
                    433:        | TIMES escoper {
                    434:                lflags |= A_INDIR;
                    435:                $$ = $2; }
                    436:        | {
                    437:                $$ = NULL; };
                    438: 
                    439: escoper : oper {
                    440:        $$->sg = -1;
                    441:        $$ = $1; }
                    442:        | REG COLON oper {
                    443:                $$ = $3;
                    444:                if ($1->flag != SEG_REG)
                    445:                        regerror($1);
                    446:                $$->sg = $1->loc; };
                    447: 
                    448: /* operands are one of these */
                    449: oper : REG {
                    450:                $$ = qbild(0L, T_R, $1, NULL, 0L, NULL); }
                    451: 
                    452:      | FSTACK {
                    453:                $$ = fbild(0L); }
                    454: 
                    455:      | FSTACK LBRACK numexp RBRACK {
                    456:                $$ = fbild($3); }
                    457: 
                    458:      | LBRACK REG RBRACK {
                    459:                $$ = qbild(0L, T_RI, $2, NULL, 0L, NULL); }
                    460: 
                    461:      | LBRACK REG COMMA numexp RBRACK {
                    462:                $$ = qbild(0L, T_RIS, $2, NULL, $4, NULL); }
                    463: 
                    464:      | LBRACK COMMA REG COMMA numexp RBRACK {
                    465:                $$ = qbild(0L, T_RIS, $3, NULL, $5, NULL); }
                    466: 
                    467:      | LBRACK REG COMMA REG RBRACK {
                    468:                $$ = qbild(0L, T_RIX, $2, $4, 0L, NULL); }
                    469: 
                    470:      | LBRACK REG COMMA REG COMMA numexp RBRACK {
                    471:                $$ = qbild(0L, T_RIXS, $2, $4, $6, NULL); }
                    472: 
                    473:      | numexp LBRACK REG RBRACK {
                    474:                $$ = qbild($1, T_RID, $3, NULL, 0L, NULL); }
                    475: 
                    476:      | numexp LBRACK REG COMMA numexp RBRACK {
                    477:                $$ = qbild($1, T_RIDS, $3, NULL, $5, NULL); }
                    478: 
                    479:      | numexp LBRACK COMMA REG COMMA numexp RBRACK {
                    480:                $$ = qbild($1, T_RIDS, $4, NULL, $6, NULL); }
                    481: 
                    482:      | numexp LBRACK REG COMMA REG RBRACK {
                    483:                $$ = qbild($1, T_RIXD, $3, $5, 0L, NULL); }
                    484: 
                    485:      | numexp LBRACK REG COMMA REG COMMA numexp RBRACK {
                    486:                $$ = qbild($1, T_RIXDS, $3, $5, $7, NULL); }
                    487: 
                    488:      | addexp LBRACK REG RBRACK {
                    489:                $$ = qbild($1->loc, T_RID, $3, NULL, 0L, $1); }
                    490: 
                    491:      | addexp LBRACK REG COMMA numexp RBRACK {
                    492:                $$ = qbild($1->loc, T_RIDS, $3, NULL, $5, $1); }
                    493: 
                    494:      | addexp LBRACK COMMA REG COMMA numexp RBRACK {
                    495:                $$ = qbild($1->loc, T_RIDS, $4, NULL, $6, $1); }
                    496: 
                    497:      | addexp LBRACK REG COMMA REG RBRACK {
                    498:                $$ = qbild($1->loc, T_RIXD, $3, $5, 0L, $1); }
                    499: 
                    500:      | addexp LBRACK REG COMMA REG COMMA numexp RBRACK {
                    501:                $$ = qbild($1->loc, T_RIXDS, $3, $5, $7, $1); }
                    502: 
                    503:      | addexp {
                    504:                $$ = qbild($1->loc, T_D, NULL, NULL, 0L, $1); }
                    505: 
                    506:      | numexp {
                    507:                $$ = qbild($1, T_D, NULL, NULL, 0L, NULL); }
                    508: 
                    509:      | D_SIGN numexp {
                    510:                $$ = setImm($2, (sym *)NULL); }
                    511: 
                    512:      | D_SIGN addexp {
                    513:                $$ = setImm($2->loc, $2); };
                    514: 
                    515: 
                    516: /* Various expressions */
                    517: 
                    518: addexp : IDENTIFIER  { $$ = $1; }
                    519:        | LPAREN addexp RPAREN { $$=$2; }
                    520:        | addexp PLUS numexp { $$ = copySym($1); $$->loc += $3; }
                    521:        | addexp MINUS numexp { $$ = copySym($1); $$->loc -= $3; }
                    522:        | numexp PLUS addexp { $$ = copySym($3); $$->loc += $1; };
                    523: 
                    524: /* numeric expressions done here */
                    525: numexp : NUMBER {
                    526:                $$ = $1; }
                    527:        | LPAREN numexp RPAREN {
                    528:                $$ = $2; }
                    529:        | addexp MINUS addexp {
                    530:                ckseg($1, $3); $$ = $1->loc - $3->loc; }
                    531:        | addexp COMPARISON addexp {
                    532:                ckseg($1, $3); $$ = compare((int)$2, $1->loc - $3->loc); }
                    533:        | numexp COMPARISON numexp {
                    534:                $$ = compare((int)$2, $1 - $3); }
                    535:        | string COMPARISON string {
                    536:                $$ = compare((int)$2, (long)strcmp($1, $3)); }
                    537:        | dblexp COMPARISON dblexp {
                    538:                $$ = fcompare((int)$2, $1 - $3); }
                    539: 
                    540:        | SIZEOF addexp {
                    541:                $$ = $2->size; }
                    542: 
                    543:        | LOCATION addexp {
                    544:                $$ = $2->loc; }
                    545: 
                    546:        | SEGMENT addexp {
                    547:                $$ = $2->sg + 1; }
                    548: 
                    549:        | DEFINED IDENTIFIER {
                    550:                $$ = $2->statement && (statement >= $2->statement); }
                    551:        | DEFINED NUMBER {
                    552:                $$ = 1; }
                    553:        | PARMCT {
                    554:                $$ = parmCt(); }
                    555: 
                    556:        | numexp PLUS numexp {
                    557:                $$ = $1 + $3; }
                    558:        | numexp MINUS numexp {
                    559:                $$ = $1 - $3; }
                    560:        | numexp TIMES numexp {
                    561:                $$ = $1 * $3; }
                    562:        | numexp DIVIDE numexp {
                    563:                $$ = $1 / $3; }
                    564:        | numexp REM numexp {
                    565:                $$ = $1 % $3; }
                    566: 
                    567:        | numexp LSHIFT numexp {
                    568:                $$ = $1 << $3; }
                    569:        | numexp RSHIFT numexp {
                    570:                $$ = $1 >> $3; }
                    571: 
                    572: 
                    573:        | numexp AND numexp {
                    574:                $$ = $1 & $3; }
                    575:        | numexp OR numexp {
                    576:                $$ = $1 | $3; }
                    577:        | numexp XOR numexp {
                    578:                $$ = $1 ^ $3; }
                    579:        | MINUS numexp %prec TIMES {
                    580:                $$ = - $2; }
                    581:        | BANG numexp {
                    582:                $$ = !$2; }
                    583:        | NOT numexp {
                    584:                $$ = ~$2; }
                    585: 
                    586:        | string LBRACK numexp RBRACK {
                    587:                $$ = ($3 > strlen($1)) ? 0 : $1[(short)$3]; }
                    588:        | string AT string {
                    589:                $$ = stringSearch($1, $3); }
                    590:        | TONUMBER string {
                    591:                $$ = atol($2); }
                    592:        | TONUMBER dblexp {
                    593:                $$ = $2; };
                    594: 
                    595: string : TOKEN {
                    596:                $$ = gcpy($1, 0); }
                    597:        | LPAREN string RPAREN {
                    598:                $$ = $2; }
                    599:        | string PLUS string {
                    600:                $$ = concat($1, $3); }
                    601:        | string LPAREN numexp COMMA numexp RPAREN {
                    602:                $$ = substr($1, $3, $5); }
                    603:        | string LPAREN numexp RPAREN {
                    604:                $$ = substr($1, $3, strlen($1) - $3); }
                    605:        | TOSTRING numexp {
                    606:                $$ = galloc(12);
                    607:                sprintf($$, "%ld", $2); }
                    608:        | TOSTRING dblexp {
                    609:                $$ = galloc(20);
                    610:                sprintf($$, "%g", $2); };
                    611: 
                    612: /* floating point done here */
                    613: dblexp : FNUM {
                    614:                $$ = $1; }
                    615:        | LPAREN dblexp RPAREN {
                    616:                $$ = $2; }
                    617:        | dblexp PLUS dblexp {
                    618:                $$ = $1 + $3; }
                    619:        | dblexp MINUS dblexp {
                    620:                $$ = $1 - $3; }
                    621:        | dblexp TIMES dblexp {
                    622:                $$ = $1 * $3; }
                    623:        | dblexp DIVIDE dblexp {
                    624:                $$ = $1 / $3; }
                    625:        | MINUS dblexp %prec TIMES {
                    626:                $$ = - $2; }
                    627:        | TOFLOAT string {
                    628:                $$ = strtod($2, (char **)NULL); }
                    629:        | TOFLOAT numexp {
                    630:                $$ = $2; };
                    631: 

unix.superglobalmegacorp.com

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