1*5823Srrh /* 2*5823Srrh * Copyright (c) 1982 Regents of the University of California 3*5823Srrh */ 4*5823Srrh #ifndef lint 5*5823Srrh static char sccsid[] = "@(#)asexpr.c 4.3 02/14/82"; 6*5823Srrh 7*5823Srrh #endif not lint 8593Sbill #include <stdio.h> 9593Sbill #include "as.h" 10*5823Srrh #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 60*5823Srrh struct exp *combine(op, exp1, exp2) 61*5823Srrh reg struct exp *exp1, *exp2; 62593Sbill { 63*5823Srrh reg e1_type, e2_type; 64*5823Srrh reg back_type; 65*5823Srrh 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 82*5823Srrh switch(exp1->e_number.num_tag){ 83*5823Srrh case TYPB: 84*5823Srrh case TYPW: 85*5823Srrh case TYPL: 86*5823Srrh break; 87*5823Srrh default: 88*5823Srrh yyerror(btype); 89*5823Srrh return(exp1); 90*5823Srrh } 91*5823Srrh switch(exp2->e_number.num_tag){ 92*5823Srrh case TYPB: 93*5823Srrh case TYPW: 94*5823Srrh case TYPL: 95*5823Srrh break; 96*5823Srrh default: 97*5823Srrh yyerror(btype); 98*5823Srrh return(exp1); 99*5823Srrh } 100*5823Srrh 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); 177*5823Srrh 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 207*5823Srrh static inttoktype val; 208*5823Srrh 209*5823Srrh /* 210*5823Srrh * return the value the read head is sitting on 211*5823Srrh */ 212*5823Srrh inttoktype exprparse(inval, backexpr) 213*5823Srrh inttoktype inval; 214593Sbill struct exp **backexpr; 215593Sbill { 216*5823Srrh reg struct exp *lexpr; 217*5823Srrh 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 { 232*5823Srrh reg struct exp *lexpr; 233*5823Srrh 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 { 246*5823Srrh reg struct exp *lexpr; 247*5823Srrh 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; 261*5823Srrh 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; 288*5823Srrh lexpr->e_number = Znumber; 289*5823Srrh lexpr->e_number.num_tag = TYPL; 290593Sbill lexpr = combine(op, lexpr, factor()); 291*5823Srrh } else { 292593Sbill yyerror("Bad expression syntax"); 293593Sbill lexpr = xp++; 294630Shenry lexpr->e_xtype = XABS; 295*5823Srrh lexpr->e_number = Znumber; 296*5823Srrh lexpr->e_number.num_tag = TYPL; 297593Sbill } 298593Sbill return(lexpr); 299593Sbill } 300593Sbill 301593Sbill struct exp *yukkyexpr(val, np) 302593Sbill int val; 303*5823Srrh reg np; 304593Sbill { 305*5823Srrh reg struct exp *locxp; 306*5823Srrh extern int exprisname; /*last factor is a name*/ 307*5823Srrh int off = 0; 308593Sbill 309593Sbill exprisname = 0; 310593Sbill locxp = xp++; 311*5823Srrh locxp->e_number = Znumber; 312*5823Srrh locxp->e_number.num_tag = TYPL; 313*5823Srrh 314*5823Srrh switch(val){ 315*5823Srrh case BFINT: 316*5823Srrh yylval = ((struct exp *)np)->e_xvalue; 317*5823Srrh if (yylval < 0) { 318*5823Srrh yylval = -yylval; 319*5823Srrh yylval--; 320*5823Srrh off = -1; 321*5823Srrh if (lgensym[yylval] == 1) 322*5823Srrh yyerror("Reference to undefined local label %db", yylval); 323*5823Srrh } else { 324*5823Srrh yylval--; 325*5823Srrh genref[yylval] = 1; 326593Sbill } 327*5823Srrh (void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); 328*5823Srrh yylval = np = (int)*lookup(passno == 1); 329*5823Srrh lastnam = (struct symtab *)np; 330*5823Srrh /* FALLTHROUGH */ 331*5823Srrh 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 } 343*5823Srrh break; 344*5823Srrh default: 345*5823Srrh yyerror("Internal Error in yukkyexpr"); 346*5823Srrh /* FALLTHROUGH */ 347*5823Srrh 348*5823Srrh case INSTn: 349*5823Srrh case INST0: 350*5823Srrh case REG: 351630Shenry locxp->e_xtype = XABS; 352630Shenry locxp->e_xvalue = ( (int)np) & 0xFF; 353630Shenry locxp->e_xloc = 0; 354630Shenry locxp->e_xname = NULL; 355*5823Srrh break; 356593Sbill } 357593Sbill 358593Sbill return(locxp); 359593Sbill } 360593Sbill 361593Sbill 362593Sbill #ifdef DEBUG 363593Sbill char *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; 364593Sbill struct Tok_Desc{ 365593Sbill int tok_which; 366593Sbill char *tok_name; 367593Sbill } tok_desc[] = { 368*5823Srrh FIRSTTOKEN, "firsttoken", 369*5823Srrh ISPACE, "ispace", 370*5823Srrh IBYTE, "ibyte", 371*5823Srrh IWORD, "iword", 372*5823Srrh IINT, "iint", 373*5823Srrh ILONG, "ilong", 374*5823Srrh IQUAD, "quad", 375*5823Srrh IOCTA, "octa", 376*5823Srrh IDATA, "idata", 377*5823Srrh IGLOBAL, "iglobal", 378*5823Srrh ISET, "iset", 379*5823Srrh ITEXT, "itext", 380*5823Srrh ICOMM, "icomm", 381*5823Srrh ILCOMM, "ilcomm", 382*5823Srrh IFFLOAT, "iffloat", 383*5823Srrh IDFLOAT, "idfloat", 384*5823Srrh IGFLOAT, "igfloat", 385*5823Srrh IHFLOAT, "ihfloat", 386*5823Srrh IORG, "iorg", 387*5823Srrh IASCII, "iascii", 388*5823Srrh IASCIZ, "iasciz", 389*5823Srrh ILSYM, "ilsym", 390*5823Srrh IFILE, "ifile", 391*5823Srrh ILINENO, "ilineno", 392*5823Srrh IABORT, "iabort", 393*5823Srrh ISTAB, "istab", 394*5823Srrh ISTABSTR, "istabstr", 395*5823Srrh ISTABNONE, "istabnone", 396*5823Srrh ISTABDOT, "istabdot", 397*5823Srrh IJXXX, "ijxxx", 398*5823Srrh IALIGN, "ialign", 399*5823Srrh INST0, "inst0", 400*5823Srrh INSTn, "instn", 401*5823Srrh BFINT, "bfint", 402*5823Srrh PARSEEOF, "parseeof", 403*5823Srrh ILINESKIP, "ilineskip", 404*5823Srrh VOID, "void", 405*5823Srrh SKIP, "skip", 406*5823Srrh INT, "int", 407*5823Srrh BIGNUM, "bignum", 408*5823Srrh NAME, "name", 409*5823Srrh STRING, "string", 410*5823Srrh SIZESPEC, "sizespec", 411*5823Srrh REG, "reg", 412*5823Srrh MUL, "mul", 413*5823Srrh LITOP, "litop", 414*5823Srrh LP, "lp", 415*5823Srrh MP, "mp", 416*5823Srrh NEEDSBUF, "needsbuf", 417*5823Srrh REGOP, "regop", 418*5823Srrh NL, "nl", 419*5823Srrh SCANEOF, "scaneof", 420*5823Srrh BADCHAR, "badchar", 421*5823Srrh SP, "sp", 422*5823Srrh ALPH, "alph", 423*5823Srrh DIG, "dig", 424*5823Srrh SQ, "sq", 425*5823Srrh DQ, "dq", 426*5823Srrh SH, "sh", 427*5823Srrh LSH, "lsh", 428*5823Srrh RSH, "rsh", 429*5823Srrh MINUS, "minus", 430*5823Srrh SIZEQUOTE, "sizequote", 431*5823Srrh XOR, "xor", 432*5823Srrh DIV, "div", 433*5823Srrh SEMI, "semi", 434*5823Srrh COLON, "colon", 435*5823Srrh PLUS, "plus", 436*5823Srrh IOR, "ior", 437*5823Srrh AND, "and", 438*5823Srrh TILDE, "tilde", 439*5823Srrh ORNOT, "ornot", 440*5823Srrh CM, "cm", 441*5823Srrh LB, "lb", 442*5823Srrh RB, "rb", 443*5823Srrh RP, "rp", 444*5823Srrh LASTTOKEN, "lasttoken" 445593Sbill }; 446593Sbill /* 447593Sbill * turn a token type into a string 448593Sbill */ 449593Sbill char *tok_to_name(token) 450593Sbill { 451*5823Srrh static int fixed = 0; 452*5823Srrh 453593Sbill if (!fixed){ 454593Sbill int i; 455593Sbill for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) 456593Sbill tok_name[i] = "NOT ASSIGNED"; 457593Sbill for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ 458593Sbill tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name; 459593Sbill } 460593Sbill fixed = 1; 461593Sbill } 462593Sbill if (FIRSTTOKEN <= token && token <= LASTTOKEN) 463593Sbill return(tok_name[token]); 464593Sbill else 465593Sbill panic("Unknown token number, %d\n", token); 466593Sbill /*NOTREACHED*/ 467593Sbill } 468593Sbill #endif DEBUG 469