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