1*29831Ssam /* 2*29831Ssam * Copyright (c) 1982 Regents of the University of California 3*29831Ssam */ 4*29831Ssam #ifndef lint 5*29831Ssam static char sccsid[] = "@(#)asexpr.c 4.5 6/30/83"; 6*29831Ssam 7*29831Ssam #endif not lint 8*29831Ssam #include <stdio.h> 9*29831Ssam #include "as.h" 10*29831Ssam #include "asscan.h" 11*29831Ssam #include "asexpr.h" 12*29831Ssam 13*29831Ssam /* 14*29831Ssam * Tables for combination of operands. 15*29831Ssam */ 16*29831Ssam #define XTXRN 5<<1 /* indexes last row/column when right shifted */ 17*29831Ssam 18*29831Ssam /* 19*29831Ssam * table for + 20*29831Ssam */ 21*29831Ssam readonly char pltab[6][6] = { 22*29831Ssam /* UND ABS TXT DAT BSS EXT */ 23*29831Ssam 24*29831Ssam /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 25*29831Ssam /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN, 26*29831Ssam /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR, 27*29831Ssam /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR, 28*29831Ssam /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR, 29*29831Ssam /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 30*29831Ssam }; 31*29831Ssam 32*29831Ssam /* 33*29831Ssam * table for - 34*29831Ssam */ 35*29831Ssam readonly char mintab[6][6] = { 36*29831Ssam /* UND ABS TXT DAT BSS EXT */ 37*29831Ssam 38*29831Ssam /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 39*29831Ssam /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 40*29831Ssam /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR, 41*29831Ssam /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR, 42*29831Ssam /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR, 43*29831Ssam /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 44*29831Ssam }; 45*29831Ssam 46*29831Ssam /* 47*29831Ssam * table for other operators 48*29831Ssam */ 49*29831Ssam readonly char othtab[6][6] = { 50*29831Ssam /* UND ABS TXT DAT BSS EXT */ 51*29831Ssam 52*29831Ssam /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 53*29831Ssam /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 54*29831Ssam /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 55*29831Ssam /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 56*29831Ssam /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 57*29831Ssam /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 58*29831Ssam }; 59*29831Ssam 60*29831Ssam struct exp *combine(op, exp1, exp2) 61*29831Ssam reg struct exp *exp1, *exp2; 62*29831Ssam { 63*29831Ssam reg int e1_type, e2_type; 64*29831Ssam reg int back_type; 65*29831Ssam char *btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers"; 66*29831Ssam 67*29831Ssam lastnam=0; /* kludge for jxxx instructions */ 68*29831Ssam 69*29831Ssam e1_type = exp1->e_xtype&XTYPE; 70*29831Ssam e2_type = exp2->e_xtype&XTYPE; 71*29831Ssam 72*29831Ssam if (exp1->e_xtype==XXTRN+XUNDEF) 73*29831Ssam e1_type = XTXRN; 74*29831Ssam if (exp2->e_xtype==XXTRN+XUNDEF) 75*29831Ssam e2_type = XTXRN; 76*29831Ssam if (passno==1) 77*29831Ssam if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type) 78*29831Ssam e1_type = e2_type = XTXRN; /* error on != loc ctrs */ 79*29831Ssam e1_type >>= 1; /*dispose of the external (XXTRN) bit*/ 80*29831Ssam e2_type >>= 1; 81*29831Ssam 82*29831Ssam switch (op){ 83*29831Ssam case PLUS: 84*29831Ssam exp1->e_xvalue += exp2->e_xvalue; 85*29831Ssam back_type = pltab[e1_type][e2_type]; 86*29831Ssam break; 87*29831Ssam case MINUS: 88*29831Ssam exp1->e_xvalue -= exp2->e_xvalue; 89*29831Ssam back_type = mintab[e1_type][e2_type]; 90*29831Ssam break; 91*29831Ssam case IOR: 92*29831Ssam exp1->e_xvalue |= exp2->e_xvalue; 93*29831Ssam goto comm; 94*29831Ssam case XOR: 95*29831Ssam exp1->e_xvalue ^= exp2->e_xvalue; 96*29831Ssam goto comm; 97*29831Ssam case AND: 98*29831Ssam exp1->e_xvalue &= exp2->e_xvalue; 99*29831Ssam goto comm; 100*29831Ssam case ORNOT: 101*29831Ssam exp1->e_xvalue |= ~exp2->e_xvalue; 102*29831Ssam goto comm; 103*29831Ssam case LSH: 104*29831Ssam exp1->e_xvalue <<= exp2->e_xvalue; 105*29831Ssam goto comm; 106*29831Ssam case RSH: 107*29831Ssam exp1->e_xvalue >>= exp2->e_xvalue; 108*29831Ssam goto comm; 109*29831Ssam case TILDE: 110*29831Ssam exp1->e_xvalue |= ~ exp2->e_xvalue; 111*29831Ssam goto comm; 112*29831Ssam case MUL: 113*29831Ssam exp1->e_xvalue *= exp2->e_xvalue; 114*29831Ssam goto comm; 115*29831Ssam case DIV: 116*29831Ssam if (exp2->e_xvalue == 0) 117*29831Ssam yyerror("Divide check"); 118*29831Ssam else 119*29831Ssam exp1->e_xvalue /= exp2->e_xvalue; 120*29831Ssam goto comm; 121*29831Ssam case REGOP: 122*29831Ssam if (exp2->e_xvalue == 0) 123*29831Ssam yyerror("Divide check (modulo)"); 124*29831Ssam else 125*29831Ssam exp1->e_xvalue %= exp2->e_xvalue; 126*29831Ssam goto comm; 127*29831Ssam 128*29831Ssam comm: 129*29831Ssam back_type = othtab[e1_type][e2_type]; 130*29831Ssam break; 131*29831Ssam default: 132*29831Ssam yyerror("Internal error: unknown operator"); 133*29831Ssam } 134*29831Ssam 135*29831Ssam if (e2_type==(XTXRN>>1)) 136*29831Ssam exp1->e_xname = exp2->e_xname; 137*29831Ssam exp1->e_xtype = back_type | ( 138*29831Ssam (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) ); 139*29831Ssam if (back_type==ERR) 140*29831Ssam yyerror("Relocation error"); 141*29831Ssam return(exp1); 142*29831Ssam } 143*29831Ssam 144*29831Ssam buildtokensets() 145*29831Ssam { 146*29831Ssam #define clobber(val, set) tokensets[(val)] |= (set) 147*29831Ssam 148*29831Ssam clobber(SEMI, LINSTBEGIN); 149*29831Ssam clobber(NL, LINSTBEGIN); 150*29831Ssam clobber(INT, LINSTBEGIN); 151*29831Ssam 152*29831Ssam clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); 153*29831Ssam clobber(INSTn, YUKKYEXPRBEG); 154*29831Ssam clobber(INST0, YUKKYEXPRBEG); 155*29831Ssam clobber(REG, YUKKYEXPRBEG); 156*29831Ssam clobber(BFINT, YUKKYEXPRBEG); 157*29831Ssam 158*29831Ssam clobber(INT, SAFEEXPRBEG); 159*29831Ssam clobber(BIGNUM, SAFEEXPRBEG); 160*29831Ssam 161*29831Ssam clobber(PLUS, ADDOPS); 162*29831Ssam clobber(MINUS, ADDOPS + EBEGOPS); 163*29831Ssam 164*29831Ssam clobber(LP, EBEGOPS); 165*29831Ssam 166*29831Ssam clobber(IOR, BOOLOPS); 167*29831Ssam clobber(XOR, BOOLOPS); 168*29831Ssam clobber(AND, BOOLOPS); 169*29831Ssam clobber(ORNOT, BOOLOPS); 170*29831Ssam 171*29831Ssam clobber(TILDE, MULOPS + EBEGOPS); 172*29831Ssam clobber(LSH, MULOPS); 173*29831Ssam clobber(RSH, MULOPS); 174*29831Ssam clobber(MUL, MULOPS); 175*29831Ssam clobber(DIV, MULOPS); 176*29831Ssam clobber(REGOP, MULOPS); /* % */ 177*29831Ssam 178*29831Ssam } 179*29831Ssam 180*29831Ssam /* 181*29831Ssam * We keep the current token class in this global variable, so 182*29831Ssam * the recursive descent expression analyzers can talk amongst 183*29831Ssam * themselves, and so that we may use the macros shift and shift over 184*29831Ssam */ 185*29831Ssam 186*29831Ssam extern int yylval; /*the value of the lexical value*/ 187*29831Ssam extern struct exp *xp; /*the next free expression slot*/ 188*29831Ssam 189*29831Ssam static inttoktype val; 190*29831Ssam 191*29831Ssam /* 192*29831Ssam * return the value the read head is sitting on 193*29831Ssam */ 194*29831Ssam inttoktype exprparse(inval, backexpr) 195*29831Ssam inttoktype inval; 196*29831Ssam struct exp **backexpr; 197*29831Ssam { 198*29831Ssam reg struct exp *lexpr; 199*29831Ssam inttoktype op; 200*29831Ssam 201*29831Ssam val = inval; 202*29831Ssam lexpr = boolterm(); 203*29831Ssam while (INTOKSET(val, ADDOPS)){ 204*29831Ssam op = val; 205*29831Ssam shift; 206*29831Ssam lexpr = combine(op, lexpr, boolterm()); 207*29831Ssam } 208*29831Ssam *backexpr = lexpr; 209*29831Ssam return(val); 210*29831Ssam } 211*29831Ssam 212*29831Ssam struct exp *boolterm() 213*29831Ssam { 214*29831Ssam reg struct exp *lexpr; 215*29831Ssam inttoktype op; 216*29831Ssam 217*29831Ssam lexpr = term(); 218*29831Ssam while(INTOKSET(val, BOOLOPS)){ 219*29831Ssam op = val; 220*29831Ssam shift; 221*29831Ssam lexpr = combine(op, lexpr, term()); 222*29831Ssam } 223*29831Ssam return(lexpr); 224*29831Ssam } 225*29831Ssam 226*29831Ssam struct exp *term() 227*29831Ssam { 228*29831Ssam reg struct exp *lexpr; 229*29831Ssam inttoktype op; 230*29831Ssam 231*29831Ssam lexpr = factor(); 232*29831Ssam while(INTOKSET(val, MULOPS)){ 233*29831Ssam op = val; 234*29831Ssam shift; 235*29831Ssam lexpr = combine(op, lexpr, factor()); 236*29831Ssam } 237*29831Ssam return(lexpr); 238*29831Ssam } 239*29831Ssam 240*29831Ssam struct exp *factor() 241*29831Ssam { 242*29831Ssam struct exp *lexpr; 243*29831Ssam inttoktype op; 244*29831Ssam extern int droppedLP; /*called exprparse after consuming an LP*/ 245*29831Ssam 246*29831Ssam if (val == LP || droppedLP){ 247*29831Ssam if (droppedLP) 248*29831Ssam droppedLP = 0; 249*29831Ssam else 250*29831Ssam shift; /*the LP*/ 251*29831Ssam val = exprparse(val, &lexpr); 252*29831Ssam if (val != RP) 253*29831Ssam yyerror("right parenthesis expected"); 254*29831Ssam else 255*29831Ssam shift; 256*29831Ssam } else 257*29831Ssam if (INTOKSET(val, YUKKYEXPRBEG)){ 258*29831Ssam lexpr = yukkyexpr(val, yylval); 259*29831Ssam shift; 260*29831Ssam } 261*29831Ssam else if (INTOKSET(val, SAFEEXPRBEG)){ 262*29831Ssam lexpr = (struct exp *)yylval; 263*29831Ssam shift; 264*29831Ssam } 265*29831Ssam else if ( (val == TILDE) || (val == MINUS) ){ 266*29831Ssam op = val; 267*29831Ssam shift; 268*29831Ssam lexpr = xp++; 269*29831Ssam lexpr->e_xtype = XABS; 270*29831Ssam lexpr->e_number = Znumber; 271*29831Ssam lexpr->e_number.num_tag = TYPL; 272*29831Ssam lexpr = combine(op, lexpr, factor()); 273*29831Ssam } else { 274*29831Ssam yyerror("Bad expression syntax"); 275*29831Ssam lexpr = xp++; 276*29831Ssam lexpr->e_xtype = XABS; 277*29831Ssam lexpr->e_number = Znumber; 278*29831Ssam lexpr->e_number.num_tag = TYPL; 279*29831Ssam } 280*29831Ssam return(lexpr); 281*29831Ssam } 282*29831Ssam 283*29831Ssam struct exp *yukkyexpr(val, np) 284*29831Ssam int val; 285*29831Ssam reg int np; 286*29831Ssam { 287*29831Ssam reg struct exp *locxp; 288*29831Ssam extern int exprisname; /*last factor is a name*/ 289*29831Ssam int off = 0; 290*29831Ssam 291*29831Ssam exprisname = 0; 292*29831Ssam locxp = xp++; 293*29831Ssam locxp->e_number = Znumber; 294*29831Ssam locxp->e_number.num_tag = TYPL; 295*29831Ssam 296*29831Ssam switch(val){ 297*29831Ssam case BFINT: 298*29831Ssam yylval = ((struct exp *)np)->e_xvalue; 299*29831Ssam if (yylval < 0) { 300*29831Ssam yylval = -yylval; 301*29831Ssam yylval--; 302*29831Ssam off = -1; 303*29831Ssam if (lgensym[yylval] == 1) 304*29831Ssam yyerror("Reference to undefined local label %db", yylval); 305*29831Ssam } else { 306*29831Ssam yylval--; 307*29831Ssam genref[yylval] = 1; 308*29831Ssam } 309*29831Ssam (void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); 310*29831Ssam yylval = np = (int)*lookup(passno == 1); 311*29831Ssam lastnam = (struct symtab *)np; 312*29831Ssam /* FALLTHROUGH */ 313*29831Ssam case NAME: 314*29831Ssam exprisname++; 315*29831Ssam locxp->e_xtype = ((struct symtab *)np)->s_type; 316*29831Ssam if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/ 317*29831Ssam locxp->e_xname = (struct symtab *)np; 318*29831Ssam locxp->e_xvalue = 0; 319*29831Ssam if (passno==1) 320*29831Ssam ((struct symtab *)np)->s_type |= XFORW; 321*29831Ssam } else { /*otherwise, just get the value*/ 322*29831Ssam locxp->e_xvalue = ((struct symtab *)np)->s_value; 323*29831Ssam locxp->e_xname = NULL; 324*29831Ssam } 325*29831Ssam break; 326*29831Ssam default: 327*29831Ssam yyerror("Internal Error in yukkyexpr"); 328*29831Ssam /* FALLTHROUGH */ 329*29831Ssam 330*29831Ssam case INSTn: 331*29831Ssam case INST0: 332*29831Ssam case REG: 333*29831Ssam locxp->e_xtype = XABS; 334*29831Ssam locxp->e_xvalue = ( (int)np) & 0xFF; 335*29831Ssam locxp->e_xloc = 0; 336*29831Ssam locxp->e_xname = NULL; 337*29831Ssam break; 338*29831Ssam } 339*29831Ssam 340*29831Ssam return(locxp); 341*29831Ssam } 342*29831Ssam 343*29831Ssam /* 344*29831Ssam * Print definitions for token kinds 345*29831Ssam */ 346*29831Ssam static char pdirect[] = "directive"; 347*29831Ssam static char pinstr[] = "instruction"; 348*29831Ssam static char phunk[] = "lexeme"; 349*29831Ssam static char psmall[] = "small symbol"; 350*29831Ssam static char pcntrl[] = "control token"; 351*29831Ssam 352*29831Ssam #define DIRECT pdirect 353*29831Ssam #define INSTR pinstr 354*29831Ssam #define HUNK phunk 355*29831Ssam #define SMALL psmall 356*29831Ssam #define CNTRL pcntrl 357*29831Ssam 358*29831Ssam struct Tok_Desc{ 359*29831Ssam int tok_which; 360*29831Ssam char *tok_kind; 361*29831Ssam char *tok_name; 362*29831Ssam }; 363*29831Ssam struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; 364*29831Ssam 365*29831Ssam struct Tok_Desc tok_desc[] = { 366*29831Ssam FIRSTTOKEN, DIRECT, "first token", 367*29831Ssam 368*29831Ssam IBYTE, DIRECT, ".byte", 369*29831Ssam IWORD, DIRECT, ".word", 370*29831Ssam IINT, DIRECT, ".int", 371*29831Ssam ILONG, DIRECT, ".long", 372*29831Ssam IQUAD, DIRECT, ".quad", 373*29831Ssam IFFLOAT, DIRECT, ".ffloat", 374*29831Ssam IDFLOAT, DIRECT, ".dfloat", 375*29831Ssam IASCII, DIRECT, ".ascii", 376*29831Ssam IASCIZ, DIRECT, ".asciz", 377*29831Ssam IFILL, DIRECT, ".fill", 378*29831Ssam ISPACE, DIRECT, ".space", 379*29831Ssam 380*29831Ssam IDATA, DIRECT, ".data", 381*29831Ssam ITEXT, DIRECT, ".text", 382*29831Ssam IGLOBAL, DIRECT, ".global", 383*29831Ssam IALIGN, DIRECT, ".align", 384*29831Ssam 385*29831Ssam ISET, DIRECT, ".set", 386*29831Ssam ICOMM, DIRECT, ".comm", 387*29831Ssam ILCOMM, DIRECT, ".lcomm", 388*29831Ssam IORG, DIRECT, ".org", 389*29831Ssam ILSYM, DIRECT, ".lsym", 390*29831Ssam 391*29831Ssam ISTAB, DIRECT, ".stab", 392*29831Ssam ISTABSTR, DIRECT, ".stabstr", 393*29831Ssam ISTABNONE, DIRECT, ".stabnone", 394*29831Ssam ISTABDOT, DIRECT, ".stabdot", 395*29831Ssam 396*29831Ssam IFILE, DIRECT, ".file", 397*29831Ssam ILINENO, DIRECT, ".lineno", 398*29831Ssam IABORT, DIRECT, ".abort", 399*29831Ssam 400*29831Ssam IJXXX, INSTR, "jump pseudo", 401*29831Ssam INST0, INSTR, "0 argument inst", 402*29831Ssam INSTn, INSTR, "n argument inst", 403*29831Ssam 404*29831Ssam PARSEEOF, CNTRL, "parse end of file", 405*29831Ssam ILINESKIP, CNTRL, "skip lines", 406*29831Ssam VOID, CNTRL, "void", 407*29831Ssam SKIP, CNTRL, "skip", 408*29831Ssam NL, CNTRL, "new line", 409*29831Ssam SCANEOF, CNTRL, "scanner end of file", 410*29831Ssam BADCHAR, CNTRL, "bad character", 411*29831Ssam SH, CNTRL, "comment, #", 412*29831Ssam 413*29831Ssam INT, HUNK, "int", 414*29831Ssam BFINT, HUNK, "local label", 415*29831Ssam BIGNUM, HUNK, "big number", 416*29831Ssam NAME, HUNK, "name", 417*29831Ssam STRING, HUNK, "string", 418*29831Ssam REG, HUNK, "register specifier", 419*29831Ssam 420*29831Ssam SIZESPEC, SMALL, "size specifier, [BWLbwl]", 421*29831Ssam SIZEQUOTE, SMALL, "sizequote, [^']", 422*29831Ssam LITOP, SMALL, "litop", 423*29831Ssam 424*29831Ssam MP, SMALL, "minus parenthesis, -(", 425*29831Ssam REGOP, SMALL, "register operator, %", 426*29831Ssam 427*29831Ssam SP, SMALL, "space", 428*29831Ssam ALPH, SMALL, "alphabetic character, [A-Za-z_]", 429*29831Ssam DIG, SMALL, "digit character, [A-Fa-f0-9]", 430*29831Ssam 431*29831Ssam SQ, SMALL, "single quote, '", 432*29831Ssam DQ, SMALL, "double quote, \"", 433*29831Ssam 434*29831Ssam LSH, SMALL, "arithmetic left shift, <", 435*29831Ssam RSH, SMALL, "arithmetic right shift, >", 436*29831Ssam XOR, SMALL, "exclusive or, ^", 437*29831Ssam 438*29831Ssam PLUS, SMALL, "plus, +", 439*29831Ssam MINUS, SMALL, "minus, -", 440*29831Ssam MUL, SMALL, "multiply, *", 441*29831Ssam DIV, SMALL, "divide, /", 442*29831Ssam SEMI, SMALL, "semi colon, ;", 443*29831Ssam COLON, SMALL, "colon, :", 444*29831Ssam IOR, SMALL, "inclusive or, |", 445*29831Ssam AND, SMALL, "and, &", 446*29831Ssam 447*29831Ssam TILDE, SMALL, "one's complement, ~", 448*29831Ssam ORNOT, SMALL, "ornot, !", 449*29831Ssam CM, SMALL, "comma", 450*29831Ssam 451*29831Ssam LB, SMALL, "left bracket, [", 452*29831Ssam RB, SMALL, "right bracket, ]", 453*29831Ssam LP, SMALL, "left parenthesis, (", 454*29831Ssam RP, SMALL, "right parentheis, )", 455*29831Ssam 456*29831Ssam LASTTOKEN, SMALL, "last token", 457*29831Ssam }; 458*29831Ssam /* 459*29831Ssam * turn a token type into a string 460*29831Ssam */ 461*29831Ssam char *tok_to_name(token) 462*29831Ssam { 463*29831Ssam static int fixed = 0; 464*29831Ssam static char buf[64]; 465*29831Ssam static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"}; 466*29831Ssam int i; 467*29831Ssam 468*29831Ssam if (!fixed){ 469*29831Ssam for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) 470*29831Ssam tok_name[i] = &NA; 471*29831Ssam for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ 472*29831Ssam tok_name[tok_desc[i].tok_which] = &tok_desc[i]; 473*29831Ssam } 474*29831Ssam fixed = 1; 475*29831Ssam } 476*29831Ssam if (FIRSTTOKEN <= token && token <= LASTTOKEN){ 477*29831Ssam sprintf(buf, "%s %s", tok_name[token]->tok_kind, 478*29831Ssam tok_name[token]->tok_name); 479*29831Ssam return(buf); 480*29831Ssam } else { 481*29831Ssam panic("Unknown token number, %d\n", token); 482*29831Ssam /*NOTREACHED*/ 483*29831Ssam } 484*29831Ssam } 485