15823Srrh /* 2*19822Sdist * Copyright (c) 1982 Regents of the University of California. 3*19822Sdist * All rights reserved. The Berkeley software License Agreement 4*19822Sdist * specifies the terms and conditions for redistribution. 55823Srrh */ 6*19822Sdist 75823Srrh #ifndef lint 8*19822Sdist static char sccsid[] = "@(#)asexpr.c 5.1 (Berkeley) 04/30/85"; 9*19822Sdist #endif not lint 105823Srrh 115823Srrh #endif not lint 12593Sbill #include <stdio.h> 13593Sbill #include "as.h" 145823Srrh #include "asscan.h" 15593Sbill #include "asexpr.h" 16593Sbill 17593Sbill /* 18593Sbill * Tables for combination of operands. 19593Sbill */ 20593Sbill #define XTXRN 5<<1 /* indexes last row/column when right shifted */ 21593Sbill 22593Sbill /* 23593Sbill * table for + 24593Sbill */ 25593Sbill readonly char pltab[6][6] = { 26593Sbill /* UND ABS TXT DAT BSS EXT */ 27593Sbill 28593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 29593Sbill /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN, 30593Sbill /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR, 31593Sbill /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR, 32593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR, 33593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 34593Sbill }; 35593Sbill 36593Sbill /* 37593Sbill * table for - 38593Sbill */ 39593Sbill readonly char mintab[6][6] = { 40593Sbill /* UND ABS TXT DAT BSS EXT */ 41593Sbill 42593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 43593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 44593Sbill /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR, 45593Sbill /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR, 46593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR, 47593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 48593Sbill }; 49593Sbill 50593Sbill /* 51593Sbill * table for other operators 52593Sbill */ 53593Sbill readonly char othtab[6][6] = { 54593Sbill /* UND ABS TXT DAT BSS EXT */ 55593Sbill 56593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 57593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 58593Sbill /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 59593Sbill /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 60593Sbill /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 61593Sbill /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 62593Sbill }; 63593Sbill 645823Srrh struct exp *combine(op, exp1, exp2) 655823Srrh reg struct exp *exp1, *exp2; 66593Sbill { 675823Srrh reg e1_type, e2_type; 685823Srrh reg back_type; 695823Srrh char *btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers"; 70593Sbill 71593Sbill lastnam=0; /* kludge for jxxx instructions */ 72593Sbill 73630Shenry e1_type = exp1->e_xtype&XTYPE; 74630Shenry e2_type = exp2->e_xtype&XTYPE; 75593Sbill 76630Shenry if (exp1->e_xtype==XXTRN+XUNDEF) 77593Sbill e1_type = XTXRN; 78630Shenry if (exp2->e_xtype==XXTRN+XUNDEF) 79593Sbill e2_type = XTXRN; 80593Sbill if (passno==1) 81630Shenry if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type) 82593Sbill e1_type = e2_type = XTXRN; /* error on != loc ctrs */ 83593Sbill e1_type >>= 1; /*dispose of the external (XXTRN) bit*/ 84593Sbill e2_type >>= 1; 85593Sbill 865823Srrh switch(exp1->e_number.num_tag){ 875823Srrh case TYPB: 885823Srrh case TYPW: 895823Srrh case TYPL: 905823Srrh break; 915823Srrh default: 925823Srrh yyerror(btype); 935823Srrh return(exp1); 945823Srrh } 955823Srrh switch(exp2->e_number.num_tag){ 965823Srrh case TYPB: 975823Srrh case TYPW: 985823Srrh case TYPL: 995823Srrh break; 1005823Srrh default: 1015823Srrh yyerror(btype); 1025823Srrh return(exp1); 1035823Srrh } 1045823Srrh switch (op){ 105593Sbill case PLUS: 106630Shenry exp1->e_xvalue += exp2->e_xvalue; 107630Shenry back_type = pltab[e1_type][e2_type]; 108593Sbill break; 109593Sbill case MINUS: 110630Shenry exp1->e_xvalue -= exp2->e_xvalue; 111630Shenry back_type = mintab[e1_type][e2_type]; 112593Sbill break; 113593Sbill case IOR: 114630Shenry exp1->e_xvalue |= exp2->e_xvalue; 115593Sbill goto comm; 116593Sbill case XOR: 117630Shenry exp1->e_xvalue ^= exp2->e_xvalue; 118593Sbill goto comm; 119593Sbill case AND: 120630Shenry exp1->e_xvalue &= exp2->e_xvalue; 121593Sbill goto comm; 122593Sbill case ORNOT: 123630Shenry exp1->e_xvalue |= ~exp2->e_xvalue; 124593Sbill goto comm; 125593Sbill case LSH: 126630Shenry exp1->e_xvalue <<= exp2->e_xvalue; 127593Sbill goto comm; 128593Sbill case RSH: 129630Shenry exp1->e_xvalue >>= exp2->e_xvalue; 130593Sbill goto comm; 131593Sbill case TILDE: 132630Shenry exp1->e_xvalue |= ~ exp2->e_xvalue; 133593Sbill goto comm; 134593Sbill case MUL: 135630Shenry exp1->e_xvalue *= exp2->e_xvalue; 136593Sbill goto comm; 137593Sbill case DIV: 138630Shenry if (exp2->e_xvalue == 0) 139593Sbill yyerror("Divide check"); 140593Sbill else 141630Shenry exp1->e_xvalue /= exp2->e_xvalue; 142593Sbill goto comm; 143593Sbill case REGOP: 144630Shenry if (exp2->e_xvalue == 0) 145593Sbill yyerror("Divide check (modulo)"); 146593Sbill else 147630Shenry exp1->e_xvalue %= exp2->e_xvalue; 148593Sbill goto comm; 149593Sbill 150593Sbill comm: 151630Shenry back_type = othtab[e1_type][e2_type]; 152593Sbill break; 153593Sbill default: 154593Sbill yyerror("Internal error: unknown operator"); 155593Sbill } 156593Sbill 157593Sbill if (e2_type==(XTXRN>>1)) 158630Shenry exp1->e_xname = exp2->e_xname; 159630Shenry exp1->e_xtype = back_type | ( 160630Shenry (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) ); 161630Shenry if (back_type==ERR) 162593Sbill yyerror("Relocation error"); 163593Sbill return(exp1); 164593Sbill } 165593Sbill 166593Sbill buildtokensets() 167593Sbill { 168593Sbill #define clobber(val, set) tokensets[(val)] |= (set) 169593Sbill 170593Sbill clobber(SEMI, LINSTBEGIN); 171593Sbill clobber(NL, LINSTBEGIN); 172593Sbill clobber(INT, LINSTBEGIN); 173593Sbill 174593Sbill clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); 175593Sbill clobber(INSTn, YUKKYEXPRBEG); 176593Sbill clobber(INST0, YUKKYEXPRBEG); 177593Sbill clobber(REG, YUKKYEXPRBEG); 178593Sbill clobber(BFINT, YUKKYEXPRBEG); 179593Sbill 180593Sbill clobber(INT, SAFEEXPRBEG); 1815823Srrh clobber(BIGNUM, SAFEEXPRBEG); 182593Sbill 183593Sbill clobber(PLUS, ADDOPS); 184593Sbill clobber(MINUS, ADDOPS + EBEGOPS); 185593Sbill 186593Sbill clobber(LP, EBEGOPS); 187593Sbill 188593Sbill clobber(IOR, BOOLOPS); 189593Sbill clobber(XOR, BOOLOPS); 190593Sbill clobber(AND, BOOLOPS); 191593Sbill clobber(ORNOT, BOOLOPS); 192593Sbill 193593Sbill clobber(TILDE, MULOPS + EBEGOPS); 194593Sbill clobber(LSH, MULOPS); 195593Sbill clobber(RSH, MULOPS); 196593Sbill clobber(MUL, MULOPS); 197593Sbill clobber(DIV, MULOPS); 198593Sbill clobber(REGOP, MULOPS); /* % */ 199593Sbill 200593Sbill } 201593Sbill 202593Sbill /* 203593Sbill * We keep the current token class in this global variable, so 204593Sbill * the recursive descent expression analyzers can talk amongst 205593Sbill * themselves, and so that we may use the macros shift and shift over 206593Sbill */ 207593Sbill 208593Sbill extern int yylval; /*the value of the lexical value*/ 209593Sbill extern struct exp *xp; /*the next free expression slot*/ 210593Sbill 2115823Srrh static inttoktype val; 2125823Srrh 2135823Srrh /* 2145823Srrh * return the value the read head is sitting on 2155823Srrh */ 2165823Srrh inttoktype exprparse(inval, backexpr) 2175823Srrh inttoktype inval; 218593Sbill struct exp **backexpr; 219593Sbill { 2205823Srrh reg struct exp *lexpr; 2215823Srrh inttoktype op; 222593Sbill 223593Sbill val = inval; 224593Sbill lexpr = boolterm(); 225593Sbill while (INTOKSET(val, ADDOPS)){ 226593Sbill op = val; 227593Sbill shift; 228593Sbill lexpr = combine(op, lexpr, boolterm()); 229593Sbill } 230593Sbill *backexpr = lexpr; 231593Sbill return(val); 232593Sbill } 233593Sbill 234593Sbill struct exp *boolterm() 235593Sbill { 2365823Srrh reg struct exp *lexpr; 2375823Srrh inttoktype op; 238593Sbill 239593Sbill lexpr = term(); 240593Sbill while(INTOKSET(val, BOOLOPS)){ 241593Sbill op = val; 242593Sbill shift; 243593Sbill lexpr = combine(op, lexpr, term()); 244593Sbill } 245593Sbill return(lexpr); 246593Sbill } 247593Sbill 248593Sbill struct exp *term() 249593Sbill { 2505823Srrh reg struct exp *lexpr; 2515823Srrh inttoktype op; 252593Sbill 253593Sbill lexpr = factor(); 254593Sbill while(INTOKSET(val, MULOPS)){ 255593Sbill op = val; 256593Sbill shift; 257593Sbill lexpr = combine(op, lexpr, factor()); 258593Sbill } 259593Sbill return(lexpr); 260593Sbill } 261593Sbill 262593Sbill struct exp *factor() 263593Sbill { 264593Sbill struct exp *lexpr; 2655823Srrh inttoktype op; 266593Sbill extern int droppedLP; /*called exprparse after consuming an LP*/ 267593Sbill 268593Sbill if (val == LP || droppedLP){ 269593Sbill if (droppedLP) 270593Sbill droppedLP = 0; 271593Sbill else 272593Sbill shift; /*the LP*/ 273593Sbill val = exprparse(val, &lexpr); 274593Sbill if (val != RP) 275593Sbill yyerror("right parenthesis expected"); 276593Sbill else 277593Sbill shift; 278593Sbill } else 279593Sbill if (INTOKSET(val, YUKKYEXPRBEG)){ 280593Sbill lexpr = yukkyexpr(val, yylval); 281593Sbill shift; 282593Sbill } 283593Sbill else if (INTOKSET(val, SAFEEXPRBEG)){ 284593Sbill lexpr = (struct exp *)yylval; 285593Sbill shift; 286593Sbill } 287593Sbill else if ( (val == TILDE) || (val == MINUS) ){ 288593Sbill op = val; 289593Sbill shift; 290593Sbill lexpr = xp++; 291630Shenry lexpr->e_xtype = XABS; 2925823Srrh lexpr->e_number = Znumber; 2935823Srrh lexpr->e_number.num_tag = TYPL; 294593Sbill lexpr = combine(op, lexpr, factor()); 2955823Srrh } else { 296593Sbill yyerror("Bad expression syntax"); 297593Sbill lexpr = xp++; 298630Shenry lexpr->e_xtype = XABS; 2995823Srrh lexpr->e_number = Znumber; 3005823Srrh lexpr->e_number.num_tag = TYPL; 301593Sbill } 302593Sbill return(lexpr); 303593Sbill } 304593Sbill 305593Sbill struct exp *yukkyexpr(val, np) 306593Sbill int val; 3075823Srrh reg np; 308593Sbill { 3095823Srrh reg struct exp *locxp; 3105823Srrh extern int exprisname; /*last factor is a name*/ 3115823Srrh int off = 0; 312593Sbill 313593Sbill exprisname = 0; 314593Sbill locxp = xp++; 3155823Srrh locxp->e_number = Znumber; 3165823Srrh locxp->e_number.num_tag = TYPL; 3175823Srrh 3185823Srrh switch(val){ 3195823Srrh case BFINT: 3205823Srrh yylval = ((struct exp *)np)->e_xvalue; 3215823Srrh if (yylval < 0) { 3225823Srrh yylval = -yylval; 3235823Srrh yylval--; 3245823Srrh off = -1; 3255823Srrh if (lgensym[yylval] == 1) 3265823Srrh yyerror("Reference to undefined local label %db", yylval); 3275823Srrh } else { 3285823Srrh yylval--; 3295823Srrh genref[yylval] = 1; 330593Sbill } 3315823Srrh (void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); 3325823Srrh yylval = np = (int)*lookup(passno == 1); 3335823Srrh lastnam = (struct symtab *)np; 3345823Srrh /* FALLTHROUGH */ 3355823Srrh case NAME: 336593Sbill exprisname++; 337630Shenry locxp->e_xtype = ((struct symtab *)np)->s_type; 338630Shenry if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/ 339630Shenry locxp->e_xname = (struct symtab *)np; 340630Shenry locxp->e_xvalue = 0; 341593Sbill if (passno==1) 342630Shenry ((struct symtab *)np)->s_type |= XFORW; 343593Sbill } else { /*otherwise, just get the value*/ 344630Shenry locxp->e_xvalue = ((struct symtab *)np)->s_value; 345630Shenry locxp->e_xname = NULL; 346593Sbill } 3475823Srrh break; 3485823Srrh default: 3495823Srrh yyerror("Internal Error in yukkyexpr"); 3505823Srrh /* FALLTHROUGH */ 3515823Srrh 3525823Srrh case INSTn: 3535823Srrh case INST0: 3545823Srrh case REG: 355630Shenry locxp->e_xtype = XABS; 356630Shenry locxp->e_xvalue = ( (int)np) & 0xFF; 357630Shenry locxp->e_xloc = 0; 358630Shenry locxp->e_xname = NULL; 3595823Srrh break; 360593Sbill } 361593Sbill 362593Sbill return(locxp); 363593Sbill } 364593Sbill 36512944Srrh /* 36612944Srrh * Print definitions for token kinds 36712944Srrh */ 36812944Srrh static char pdirect[] = "directive"; 36912944Srrh static char pinstr[] = "instruction"; 37012944Srrh static char phunk[] = "lexeme"; 37112944Srrh static char psmall[] = "small symbol"; 37212944Srrh static char pcntrl[] = "control token"; 373593Sbill 37412944Srrh #define DIRECT pdirect 37512944Srrh #define INSTR pinstr 37612944Srrh #define HUNK phunk 37712944Srrh #define SMALL psmall 37812944Srrh #define CNTRL pcntrl 37912944Srrh 380593Sbill struct Tok_Desc{ 381593Sbill int tok_which; 38212944Srrh char *tok_kind; 383593Sbill char *tok_name; 384593Sbill }; 38512944Srrh struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; 38612944Srrh 38712944Srrh struct Tok_Desc tok_desc[] = { 38812944Srrh FIRSTTOKEN, DIRECT, "first token", 38912944Srrh 39012944Srrh IBYTE, DIRECT, ".byte", 39112944Srrh IWORD, DIRECT, ".word", 39212944Srrh IINT, DIRECT, ".int", 39312944Srrh ILONG, DIRECT, ".long", 39412944Srrh IQUAD, DIRECT, ".quad", 39512944Srrh IOCTA, DIRECT, ".octa", 39612944Srrh IFFLOAT, DIRECT, ".ffloat", 39712944Srrh IDFLOAT, DIRECT, ".dfloat", 39812944Srrh IGFLOAT, DIRECT, ".gfloat", 39912944Srrh IHFLOAT, DIRECT, ".hfloat", 40012944Srrh IASCII, DIRECT, ".ascii", 40112944Srrh IASCIZ, DIRECT, ".asciz", 40212944Srrh IFILL, DIRECT, ".fill", 40312944Srrh ISPACE, DIRECT, ".space", 40412944Srrh 40512944Srrh IDATA, DIRECT, ".data", 40612944Srrh ITEXT, DIRECT, ".text", 40712944Srrh IGLOBAL, DIRECT, ".global", 40812944Srrh IALIGN, DIRECT, ".align", 40912944Srrh 41012944Srrh ISET, DIRECT, ".set", 41112944Srrh ICOMM, DIRECT, ".comm", 41212944Srrh ILCOMM, DIRECT, ".lcomm", 41312944Srrh IORG, DIRECT, ".org", 41412944Srrh ILSYM, DIRECT, ".lsym", 41512944Srrh 41612944Srrh ISTAB, DIRECT, ".stab", 41712944Srrh ISTABSTR, DIRECT, ".stabstr", 41812944Srrh ISTABNONE, DIRECT, ".stabnone", 41912944Srrh ISTABDOT, DIRECT, ".stabdot", 42012944Srrh 42112944Srrh IFILE, DIRECT, ".file", 42212944Srrh ILINENO, DIRECT, ".lineno", 42312944Srrh IABORT, DIRECT, ".abort", 42412944Srrh 42512944Srrh IJXXX, INSTR, "jump pseudo", 42612944Srrh INST0, INSTR, "0 argument inst", 42712944Srrh INSTn, INSTR, "n argument inst", 42812944Srrh 42912944Srrh PARSEEOF, CNTRL, "parse end of file", 43012944Srrh ILINESKIP, CNTRL, "skip lines", 43112944Srrh VOID, CNTRL, "void", 43212944Srrh SKIP, CNTRL, "skip", 43312944Srrh NL, CNTRL, "new line", 43412944Srrh SCANEOF, CNTRL, "scanner end of file", 43512944Srrh BADCHAR, CNTRL, "bad character", 43612944Srrh SH, CNTRL, "comment, #", 43712944Srrh 43812944Srrh INT, HUNK, "int", 43912944Srrh BFINT, HUNK, "local label", 44012944Srrh BIGNUM, HUNK, "big number", 44112944Srrh NAME, HUNK, "name", 44212944Srrh STRING, HUNK, "string", 44312944Srrh REG, HUNK, "register specifier", 44412944Srrh 44512944Srrh SIZESPEC, SMALL, "size specifier, [BWLbwl]", 44612944Srrh SIZEQUOTE, SMALL, "sizequote, [^']", 44712944Srrh LITOP, SMALL, "litop", 44812944Srrh 44912944Srrh MP, SMALL, "minus parenthesis, -(", 45012944Srrh REGOP, SMALL, "register operator, %", 45112944Srrh 45212944Srrh SP, SMALL, "space", 45312944Srrh ALPH, SMALL, "alphabetic character, [A-Za-z_]", 45412944Srrh DIG, SMALL, "digit character, [A-Fa-f0-9]", 45512944Srrh 45612944Srrh SQ, SMALL, "single quote, '", 45712944Srrh DQ, SMALL, "double quote, \"", 45812944Srrh 45912944Srrh LSH, SMALL, "arithmetic left shift, <", 46012944Srrh RSH, SMALL, "arithmetic right shift, >", 46112944Srrh XOR, SMALL, "exclusive or, ^", 46212944Srrh 46312944Srrh PLUS, SMALL, "plus, +", 46412944Srrh MINUS, SMALL, "minus, -", 46512944Srrh MUL, SMALL, "multiply, *", 46612944Srrh DIV, SMALL, "divide, /", 46712944Srrh SEMI, SMALL, "semi colon, ;", 46812944Srrh COLON, SMALL, "colon, :", 46912944Srrh IOR, SMALL, "inclusive or, |", 47012944Srrh AND, SMALL, "and, &", 47112944Srrh 47212944Srrh TILDE, SMALL, "one's complement, ~", 47312944Srrh ORNOT, SMALL, "ornot, !", 47412944Srrh CM, SMALL, "comma", 47512944Srrh 47612944Srrh LB, SMALL, "left bracket, [", 47712944Srrh RB, SMALL, "right bracket, ]", 47812944Srrh LP, SMALL, "left parenthesis, (", 47912944Srrh RP, SMALL, "right parentheis, )", 48012944Srrh 48112944Srrh LASTTOKEN, SMALL, "last token", 48212944Srrh }; 483593Sbill /* 484593Sbill * turn a token type into a string 485593Sbill */ 486593Sbill char *tok_to_name(token) 487593Sbill { 4885823Srrh static int fixed = 0; 48912944Srrh static char buf[64]; 49012944Srrh static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"}; 49112944Srrh int i; 49212944Srrh char *cp; 4935823Srrh 494593Sbill if (!fixed){ 495593Sbill for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) 49612944Srrh tok_name[i] = &NA; 49712944Srrh for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ 49812944Srrh tok_name[tok_desc[i].tok_which] = &tok_desc[i]; 499593Sbill } 500593Sbill fixed = 1; 501593Sbill } 50212944Srrh if (FIRSTTOKEN <= token && token <= LASTTOKEN){ 50312944Srrh sprintf(buf, "%s %s", tok_name[token]->tok_kind, 50412944Srrh tok_name[token]->tok_name); 50512944Srrh return(buf); 50612944Srrh } else { 507593Sbill panic("Unknown token number, %d\n", token); 50812944Srrh /*NOTREACHED*/ 50912944Srrh } 510593Sbill } 511