15823Srrh /* 25823Srrh * Copyright (c) 1982 Regents of the University of California 35823Srrh */ 45823Srrh #ifndef lint 5*12944Srrh static char sccsid[] = "@(#)asexpr.c 4.4 06/09/83"; 65823Srrh 75823Srrh #endif not lint 8593Sbill #include <stdio.h> 9593Sbill #include "as.h" 105823Srrh #include "asscan.h" 11593Sbill #include "asexpr.h" 12593Sbill 13593Sbill /* 14593Sbill * Tables for combination of operands. 15593Sbill */ 16593Sbill #define XTXRN 5<<1 /* indexes last row/column when right shifted */ 17593Sbill 18593Sbill /* 19593Sbill * table for + 20593Sbill */ 21593Sbill readonly char pltab[6][6] = { 22593Sbill /* UND ABS TXT DAT BSS EXT */ 23593Sbill 24593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 25593Sbill /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN, 26593Sbill /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR, 27593Sbill /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR, 28593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR, 29593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 30593Sbill }; 31593Sbill 32593Sbill /* 33593Sbill * table for - 34593Sbill */ 35593Sbill readonly char mintab[6][6] = { 36593Sbill /* UND ABS TXT DAT BSS EXT */ 37593Sbill 38593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 39593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 40593Sbill /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR, 41593Sbill /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR, 42593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR, 43593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 44593Sbill }; 45593Sbill 46593Sbill /* 47593Sbill * table for other operators 48593Sbill */ 49593Sbill readonly char othtab[6][6] = { 50593Sbill /* UND ABS TXT DAT BSS EXT */ 51593Sbill 52593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 53593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 54593Sbill /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 55593Sbill /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 56593Sbill /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 57593Sbill /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 58593Sbill }; 59593Sbill 605823Srrh struct exp *combine(op, exp1, exp2) 615823Srrh reg struct exp *exp1, *exp2; 62593Sbill { 635823Srrh reg e1_type, e2_type; 645823Srrh reg back_type; 655823Srrh char *btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers"; 66593Sbill 67593Sbill lastnam=0; /* kludge for jxxx instructions */ 68593Sbill 69630Shenry e1_type = exp1->e_xtype&XTYPE; 70630Shenry e2_type = exp2->e_xtype&XTYPE; 71593Sbill 72630Shenry if (exp1->e_xtype==XXTRN+XUNDEF) 73593Sbill e1_type = XTXRN; 74630Shenry if (exp2->e_xtype==XXTRN+XUNDEF) 75593Sbill e2_type = XTXRN; 76593Sbill if (passno==1) 77630Shenry if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type) 78593Sbill e1_type = e2_type = XTXRN; /* error on != loc ctrs */ 79593Sbill e1_type >>= 1; /*dispose of the external (XXTRN) bit*/ 80593Sbill e2_type >>= 1; 81593Sbill 825823Srrh switch(exp1->e_number.num_tag){ 835823Srrh case TYPB: 845823Srrh case TYPW: 855823Srrh case TYPL: 865823Srrh break; 875823Srrh default: 885823Srrh yyerror(btype); 895823Srrh return(exp1); 905823Srrh } 915823Srrh switch(exp2->e_number.num_tag){ 925823Srrh case TYPB: 935823Srrh case TYPW: 945823Srrh case TYPL: 955823Srrh break; 965823Srrh default: 975823Srrh yyerror(btype); 985823Srrh return(exp1); 995823Srrh } 1005823Srrh switch (op){ 101593Sbill case PLUS: 102630Shenry exp1->e_xvalue += exp2->e_xvalue; 103630Shenry back_type = pltab[e1_type][e2_type]; 104593Sbill break; 105593Sbill case MINUS: 106630Shenry exp1->e_xvalue -= exp2->e_xvalue; 107630Shenry back_type = mintab[e1_type][e2_type]; 108593Sbill break; 109593Sbill case IOR: 110630Shenry exp1->e_xvalue |= exp2->e_xvalue; 111593Sbill goto comm; 112593Sbill case XOR: 113630Shenry exp1->e_xvalue ^= exp2->e_xvalue; 114593Sbill goto comm; 115593Sbill case AND: 116630Shenry exp1->e_xvalue &= exp2->e_xvalue; 117593Sbill goto comm; 118593Sbill case ORNOT: 119630Shenry exp1->e_xvalue |= ~exp2->e_xvalue; 120593Sbill goto comm; 121593Sbill case LSH: 122630Shenry exp1->e_xvalue <<= exp2->e_xvalue; 123593Sbill goto comm; 124593Sbill case RSH: 125630Shenry exp1->e_xvalue >>= exp2->e_xvalue; 126593Sbill goto comm; 127593Sbill case TILDE: 128630Shenry exp1->e_xvalue |= ~ exp2->e_xvalue; 129593Sbill goto comm; 130593Sbill case MUL: 131630Shenry exp1->e_xvalue *= exp2->e_xvalue; 132593Sbill goto comm; 133593Sbill case DIV: 134630Shenry if (exp2->e_xvalue == 0) 135593Sbill yyerror("Divide check"); 136593Sbill else 137630Shenry exp1->e_xvalue /= exp2->e_xvalue; 138593Sbill goto comm; 139593Sbill case REGOP: 140630Shenry if (exp2->e_xvalue == 0) 141593Sbill yyerror("Divide check (modulo)"); 142593Sbill else 143630Shenry exp1->e_xvalue %= exp2->e_xvalue; 144593Sbill goto comm; 145593Sbill 146593Sbill comm: 147630Shenry back_type = othtab[e1_type][e2_type]; 148593Sbill break; 149593Sbill default: 150593Sbill yyerror("Internal error: unknown operator"); 151593Sbill } 152593Sbill 153593Sbill if (e2_type==(XTXRN>>1)) 154630Shenry exp1->e_xname = exp2->e_xname; 155630Shenry exp1->e_xtype = back_type | ( 156630Shenry (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) ); 157630Shenry if (back_type==ERR) 158593Sbill yyerror("Relocation error"); 159593Sbill return(exp1); 160593Sbill } 161593Sbill 162593Sbill buildtokensets() 163593Sbill { 164593Sbill #define clobber(val, set) tokensets[(val)] |= (set) 165593Sbill 166593Sbill clobber(SEMI, LINSTBEGIN); 167593Sbill clobber(NL, LINSTBEGIN); 168593Sbill clobber(INT, LINSTBEGIN); 169593Sbill 170593Sbill clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); 171593Sbill clobber(INSTn, YUKKYEXPRBEG); 172593Sbill clobber(INST0, YUKKYEXPRBEG); 173593Sbill clobber(REG, YUKKYEXPRBEG); 174593Sbill clobber(BFINT, YUKKYEXPRBEG); 175593Sbill 176593Sbill clobber(INT, SAFEEXPRBEG); 1775823Srrh clobber(BIGNUM, SAFEEXPRBEG); 178593Sbill 179593Sbill clobber(PLUS, ADDOPS); 180593Sbill clobber(MINUS, ADDOPS + EBEGOPS); 181593Sbill 182593Sbill clobber(LP, EBEGOPS); 183593Sbill 184593Sbill clobber(IOR, BOOLOPS); 185593Sbill clobber(XOR, BOOLOPS); 186593Sbill clobber(AND, BOOLOPS); 187593Sbill clobber(ORNOT, BOOLOPS); 188593Sbill 189593Sbill clobber(TILDE, MULOPS + EBEGOPS); 190593Sbill clobber(LSH, MULOPS); 191593Sbill clobber(RSH, MULOPS); 192593Sbill clobber(MUL, MULOPS); 193593Sbill clobber(DIV, MULOPS); 194593Sbill clobber(REGOP, MULOPS); /* % */ 195593Sbill 196593Sbill } 197593Sbill 198593Sbill /* 199593Sbill * We keep the current token class in this global variable, so 200593Sbill * the recursive descent expression analyzers can talk amongst 201593Sbill * themselves, and so that we may use the macros shift and shift over 202593Sbill */ 203593Sbill 204593Sbill extern int yylval; /*the value of the lexical value*/ 205593Sbill extern struct exp *xp; /*the next free expression slot*/ 206593Sbill 2075823Srrh static inttoktype val; 2085823Srrh 2095823Srrh /* 2105823Srrh * return the value the read head is sitting on 2115823Srrh */ 2125823Srrh inttoktype exprparse(inval, backexpr) 2135823Srrh inttoktype inval; 214593Sbill struct exp **backexpr; 215593Sbill { 2165823Srrh reg struct exp *lexpr; 2175823Srrh inttoktype op; 218593Sbill 219593Sbill val = inval; 220593Sbill lexpr = boolterm(); 221593Sbill while (INTOKSET(val, ADDOPS)){ 222593Sbill op = val; 223593Sbill shift; 224593Sbill lexpr = combine(op, lexpr, boolterm()); 225593Sbill } 226593Sbill *backexpr = lexpr; 227593Sbill return(val); 228593Sbill } 229593Sbill 230593Sbill struct exp *boolterm() 231593Sbill { 2325823Srrh reg struct exp *lexpr; 2335823Srrh inttoktype op; 234593Sbill 235593Sbill lexpr = term(); 236593Sbill while(INTOKSET(val, BOOLOPS)){ 237593Sbill op = val; 238593Sbill shift; 239593Sbill lexpr = combine(op, lexpr, term()); 240593Sbill } 241593Sbill return(lexpr); 242593Sbill } 243593Sbill 244593Sbill struct exp *term() 245593Sbill { 2465823Srrh reg struct exp *lexpr; 2475823Srrh inttoktype op; 248593Sbill 249593Sbill lexpr = factor(); 250593Sbill while(INTOKSET(val, MULOPS)){ 251593Sbill op = val; 252593Sbill shift; 253593Sbill lexpr = combine(op, lexpr, factor()); 254593Sbill } 255593Sbill return(lexpr); 256593Sbill } 257593Sbill 258593Sbill struct exp *factor() 259593Sbill { 260593Sbill struct exp *lexpr; 2615823Srrh inttoktype op; 262593Sbill extern int droppedLP; /*called exprparse after consuming an LP*/ 263593Sbill 264593Sbill if (val == LP || droppedLP){ 265593Sbill if (droppedLP) 266593Sbill droppedLP = 0; 267593Sbill else 268593Sbill shift; /*the LP*/ 269593Sbill val = exprparse(val, &lexpr); 270593Sbill if (val != RP) 271593Sbill yyerror("right parenthesis expected"); 272593Sbill else 273593Sbill shift; 274593Sbill } else 275593Sbill if (INTOKSET(val, YUKKYEXPRBEG)){ 276593Sbill lexpr = yukkyexpr(val, yylval); 277593Sbill shift; 278593Sbill } 279593Sbill else if (INTOKSET(val, SAFEEXPRBEG)){ 280593Sbill lexpr = (struct exp *)yylval; 281593Sbill shift; 282593Sbill } 283593Sbill else if ( (val == TILDE) || (val == MINUS) ){ 284593Sbill op = val; 285593Sbill shift; 286593Sbill lexpr = xp++; 287630Shenry lexpr->e_xtype = XABS; 2885823Srrh lexpr->e_number = Znumber; 2895823Srrh lexpr->e_number.num_tag = TYPL; 290593Sbill lexpr = combine(op, lexpr, factor()); 2915823Srrh } else { 292593Sbill yyerror("Bad expression syntax"); 293593Sbill lexpr = xp++; 294630Shenry lexpr->e_xtype = XABS; 2955823Srrh lexpr->e_number = Znumber; 2965823Srrh lexpr->e_number.num_tag = TYPL; 297593Sbill } 298593Sbill return(lexpr); 299593Sbill } 300593Sbill 301593Sbill struct exp *yukkyexpr(val, np) 302593Sbill int val; 3035823Srrh reg np; 304593Sbill { 3055823Srrh reg struct exp *locxp; 3065823Srrh extern int exprisname; /*last factor is a name*/ 3075823Srrh int off = 0; 308593Sbill 309593Sbill exprisname = 0; 310593Sbill locxp = xp++; 3115823Srrh locxp->e_number = Znumber; 3125823Srrh locxp->e_number.num_tag = TYPL; 3135823Srrh 3145823Srrh switch(val){ 3155823Srrh case BFINT: 3165823Srrh yylval = ((struct exp *)np)->e_xvalue; 3175823Srrh if (yylval < 0) { 3185823Srrh yylval = -yylval; 3195823Srrh yylval--; 3205823Srrh off = -1; 3215823Srrh if (lgensym[yylval] == 1) 3225823Srrh yyerror("Reference to undefined local label %db", yylval); 3235823Srrh } else { 3245823Srrh yylval--; 3255823Srrh genref[yylval] = 1; 326593Sbill } 3275823Srrh (void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); 3285823Srrh yylval = np = (int)*lookup(passno == 1); 3295823Srrh lastnam = (struct symtab *)np; 3305823Srrh /* FALLTHROUGH */ 3315823Srrh case NAME: 332593Sbill exprisname++; 333630Shenry locxp->e_xtype = ((struct symtab *)np)->s_type; 334630Shenry if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/ 335630Shenry locxp->e_xname = (struct symtab *)np; 336630Shenry locxp->e_xvalue = 0; 337593Sbill if (passno==1) 338630Shenry ((struct symtab *)np)->s_type |= XFORW; 339593Sbill } else { /*otherwise, just get the value*/ 340630Shenry locxp->e_xvalue = ((struct symtab *)np)->s_value; 341630Shenry locxp->e_xname = NULL; 342593Sbill } 3435823Srrh break; 3445823Srrh default: 3455823Srrh yyerror("Internal Error in yukkyexpr"); 3465823Srrh /* FALLTHROUGH */ 3475823Srrh 3485823Srrh case INSTn: 3495823Srrh case INST0: 3505823Srrh case REG: 351630Shenry locxp->e_xtype = XABS; 352630Shenry locxp->e_xvalue = ( (int)np) & 0xFF; 353630Shenry locxp->e_xloc = 0; 354630Shenry locxp->e_xname = NULL; 3555823Srrh break; 356593Sbill } 357593Sbill 358593Sbill return(locxp); 359593Sbill } 360593Sbill 361*12944Srrh /* 362*12944Srrh * Print definitions for token kinds 363*12944Srrh */ 364*12944Srrh static char pdirect[] = "directive"; 365*12944Srrh static char pinstr[] = "instruction"; 366*12944Srrh static char phunk[] = "lexeme"; 367*12944Srrh static char psmall[] = "small symbol"; 368*12944Srrh static char pcntrl[] = "control token"; 369593Sbill 370*12944Srrh #define DIRECT pdirect 371*12944Srrh #define INSTR pinstr 372*12944Srrh #define HUNK phunk 373*12944Srrh #define SMALL psmall 374*12944Srrh #define CNTRL pcntrl 375*12944Srrh 376593Sbill struct Tok_Desc{ 377593Sbill int tok_which; 378*12944Srrh char *tok_kind; 379593Sbill char *tok_name; 380593Sbill }; 381*12944Srrh struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; 382*12944Srrh 383*12944Srrh struct Tok_Desc tok_desc[] = { 384*12944Srrh FIRSTTOKEN, DIRECT, "first token", 385*12944Srrh 386*12944Srrh IBYTE, DIRECT, ".byte", 387*12944Srrh IWORD, DIRECT, ".word", 388*12944Srrh IINT, DIRECT, ".int", 389*12944Srrh ILONG, DIRECT, ".long", 390*12944Srrh IQUAD, DIRECT, ".quad", 391*12944Srrh IOCTA, DIRECT, ".octa", 392*12944Srrh IFFLOAT, DIRECT, ".ffloat", 393*12944Srrh IDFLOAT, DIRECT, ".dfloat", 394*12944Srrh IGFLOAT, DIRECT, ".gfloat", 395*12944Srrh IHFLOAT, DIRECT, ".hfloat", 396*12944Srrh IASCII, DIRECT, ".ascii", 397*12944Srrh IASCIZ, DIRECT, ".asciz", 398*12944Srrh IFILL, DIRECT, ".fill", 399*12944Srrh ISPACE, DIRECT, ".space", 400*12944Srrh 401*12944Srrh IDATA, DIRECT, ".data", 402*12944Srrh ITEXT, DIRECT, ".text", 403*12944Srrh IGLOBAL, DIRECT, ".global", 404*12944Srrh IALIGN, DIRECT, ".align", 405*12944Srrh 406*12944Srrh ISET, DIRECT, ".set", 407*12944Srrh ICOMM, DIRECT, ".comm", 408*12944Srrh ILCOMM, DIRECT, ".lcomm", 409*12944Srrh IORG, DIRECT, ".org", 410*12944Srrh ILSYM, DIRECT, ".lsym", 411*12944Srrh 412*12944Srrh ISTAB, DIRECT, ".stab", 413*12944Srrh ISTABSTR, DIRECT, ".stabstr", 414*12944Srrh ISTABNONE, DIRECT, ".stabnone", 415*12944Srrh ISTABDOT, DIRECT, ".stabdot", 416*12944Srrh 417*12944Srrh IFILE, DIRECT, ".file", 418*12944Srrh ILINENO, DIRECT, ".lineno", 419*12944Srrh IABORT, DIRECT, ".abort", 420*12944Srrh 421*12944Srrh IJXXX, INSTR, "jump pseudo", 422*12944Srrh INST0, INSTR, "0 argument inst", 423*12944Srrh INSTn, INSTR, "n argument inst", 424*12944Srrh 425*12944Srrh PARSEEOF, CNTRL, "parse end of file", 426*12944Srrh ILINESKIP, CNTRL, "skip lines", 427*12944Srrh VOID, CNTRL, "void", 428*12944Srrh SKIP, CNTRL, "skip", 429*12944Srrh NEEDSBUF, CNTRL, "need scanner buffer", 430*12944Srrh NL, CNTRL, "new line", 431*12944Srrh SCANEOF, CNTRL, "scanner end of file", 432*12944Srrh BADCHAR, CNTRL, "bad character", 433*12944Srrh SH, CNTRL, "comment, #", 434*12944Srrh 435*12944Srrh INT, HUNK, "int", 436*12944Srrh BFINT, HUNK, "local label", 437*12944Srrh BIGNUM, HUNK, "big number", 438*12944Srrh NAME, HUNK, "name", 439*12944Srrh STRING, HUNK, "string", 440*12944Srrh REG, HUNK, "register specifier", 441*12944Srrh 442*12944Srrh SIZESPEC, SMALL, "size specifier, [BWLbwl]", 443*12944Srrh SIZEQUOTE, SMALL, "sizequote, [^']", 444*12944Srrh LITOP, SMALL, "litop", 445*12944Srrh 446*12944Srrh MP, SMALL, "minus parenthesis, -(", 447*12944Srrh REGOP, SMALL, "register operator, %", 448*12944Srrh 449*12944Srrh SP, SMALL, "space", 450*12944Srrh ALPH, SMALL, "alphabetic character, [A-Za-z_]", 451*12944Srrh DIG, SMALL, "digit character, [A-Fa-f0-9]", 452*12944Srrh 453*12944Srrh SQ, SMALL, "single quote, '", 454*12944Srrh DQ, SMALL, "double quote, \"", 455*12944Srrh 456*12944Srrh LSH, SMALL, "arithmetic left shift, <", 457*12944Srrh RSH, SMALL, "arithmetic right shift, >", 458*12944Srrh XOR, SMALL, "exclusive or, ^", 459*12944Srrh 460*12944Srrh PLUS, SMALL, "plus, +", 461*12944Srrh MINUS, SMALL, "minus, -", 462*12944Srrh MUL, SMALL, "multiply, *", 463*12944Srrh DIV, SMALL, "divide, /", 464*12944Srrh SEMI, SMALL, "semi colon, ;", 465*12944Srrh COLON, SMALL, "colon, :", 466*12944Srrh IOR, SMALL, "inclusive or, |", 467*12944Srrh AND, SMALL, "and, &", 468*12944Srrh 469*12944Srrh TILDE, SMALL, "one's complement, ~", 470*12944Srrh ORNOT, SMALL, "ornot, !", 471*12944Srrh CM, SMALL, "comma", 472*12944Srrh 473*12944Srrh LB, SMALL, "left bracket, [", 474*12944Srrh RB, SMALL, "right bracket, ]", 475*12944Srrh LP, SMALL, "left parenthesis, (", 476*12944Srrh RP, SMALL, "right parentheis, )", 477*12944Srrh 478*12944Srrh LASTTOKEN, SMALL, "last token", 479*12944Srrh }; 480593Sbill /* 481593Sbill * turn a token type into a string 482593Sbill */ 483593Sbill char *tok_to_name(token) 484593Sbill { 4855823Srrh static int fixed = 0; 486*12944Srrh static char buf[64]; 487*12944Srrh static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"}; 488*12944Srrh int i; 489*12944Srrh char *cp; 4905823Srrh 491593Sbill if (!fixed){ 492593Sbill for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) 493*12944Srrh tok_name[i] = &NA; 494*12944Srrh for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ 495*12944Srrh tok_name[tok_desc[i].tok_which] = &tok_desc[i]; 496593Sbill } 497593Sbill fixed = 1; 498593Sbill } 499*12944Srrh if (FIRSTTOKEN <= token && token <= LASTTOKEN){ 500*12944Srrh sprintf(buf, "%s %s", tok_name[token]->tok_kind, 501*12944Srrh tok_name[token]->tok_name); 502*12944Srrh return(buf); 503*12944Srrh } else { 504593Sbill panic("Unknown token number, %d\n", token); 505*12944Srrh /*NOTREACHED*/ 506*12944Srrh } 507593Sbill } 508