1593Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*630Shenry static char sccsid[] = "@(#)asexpr.c 4.2 08/15/80"; 3593Sbill #include <stdio.h> 4593Sbill #include "as.h" 5593Sbill #include "asexpr.h" 6593Sbill 7593Sbill /* 8593Sbill * Tables for combination of operands. 9593Sbill */ 10593Sbill #define XTXRN 5<<1 /* indexes last row/column when right shifted */ 11593Sbill 12593Sbill /* 13593Sbill * table for + 14593Sbill */ 15593Sbill readonly char pltab[6][6] = { 16593Sbill /* UND ABS TXT DAT BSS EXT */ 17593Sbill 18593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 19593Sbill /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN, 20593Sbill /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR, 21593Sbill /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR, 22593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR, 23593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 24593Sbill }; 25593Sbill 26593Sbill /* 27593Sbill * table for - 28593Sbill */ 29593Sbill readonly char mintab[6][6] = { 30593Sbill /* UND ABS TXT DAT BSS EXT */ 31593Sbill 32593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 33593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 34593Sbill /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR, 35593Sbill /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR, 36593Sbill /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR, 37593Sbill /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 38593Sbill }; 39593Sbill 40593Sbill /* 41593Sbill * table for other operators 42593Sbill */ 43593Sbill readonly char othtab[6][6] = { 44593Sbill /* UND ABS TXT DAT BSS EXT */ 45593Sbill 46593Sbill /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 47593Sbill /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 48593Sbill /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 49593Sbill /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 50593Sbill /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 51593Sbill /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 52593Sbill }; 53593Sbill 54593Sbill struct exp * 55593Sbill combine(op, exp1, exp2) 56593Sbill register struct exp *exp1, *exp2; 57593Sbill { 58593Sbill register e1_type, e2_type; 59*630Shenry register back_type; 60593Sbill 61593Sbill lastnam=0; /* kludge for jxxx instructions */ 62593Sbill 63*630Shenry e1_type = exp1->e_xtype&XTYPE; 64*630Shenry e2_type = exp2->e_xtype&XTYPE; 65593Sbill 66*630Shenry if (exp1->e_xtype==XXTRN+XUNDEF) 67593Sbill e1_type = XTXRN; 68*630Shenry if (exp2->e_xtype==XXTRN+XUNDEF) 69593Sbill e2_type = XTXRN; 70593Sbill if (passno==1) 71*630Shenry if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type) 72593Sbill e1_type = e2_type = XTXRN; /* error on != loc ctrs */ 73593Sbill e1_type >>= 1; /*dispose of the external (XXTRN) bit*/ 74593Sbill e2_type >>= 1; 75593Sbill 76593Sbill switch (op) { 77593Sbill case PLUS: 78*630Shenry exp1->e_xvalue += exp2->e_xvalue; 79*630Shenry back_type = pltab[e1_type][e2_type]; 80593Sbill break; 81593Sbill case MINUS: 82*630Shenry exp1->e_xvalue -= exp2->e_xvalue; 83*630Shenry back_type = mintab[e1_type][e2_type]; 84593Sbill break; 85593Sbill case IOR: 86*630Shenry exp1->e_xvalue |= exp2->e_xvalue; 87593Sbill goto comm; 88593Sbill case XOR: 89*630Shenry exp1->e_xvalue ^= exp2->e_xvalue; 90593Sbill goto comm; 91593Sbill case AND: 92*630Shenry exp1->e_xvalue &= exp2->e_xvalue; 93593Sbill goto comm; 94593Sbill case ORNOT: 95*630Shenry exp1->e_xvalue |= ~exp2->e_xvalue; 96593Sbill goto comm; 97593Sbill case LSH: 98*630Shenry exp1->e_xvalue <<= exp2->e_xvalue; 99593Sbill goto comm; 100593Sbill case RSH: 101*630Shenry exp1->e_xvalue >>= exp2->e_xvalue; 102593Sbill goto comm; 103593Sbill case TILDE: 104*630Shenry exp1->e_xvalue |= ~ exp2->e_xvalue; 105593Sbill goto comm; 106593Sbill case MUL: 107*630Shenry exp1->e_xvalue *= exp2->e_xvalue; 108593Sbill goto comm; 109593Sbill case DIV: 110*630Shenry if (exp2->e_xvalue == 0) 111593Sbill yyerror("Divide check"); 112593Sbill else 113*630Shenry exp1->e_xvalue /= exp2->e_xvalue; 114593Sbill goto comm; 115593Sbill case REGOP: 116*630Shenry if (exp2->e_xvalue == 0) 117593Sbill yyerror("Divide check (modulo)"); 118593Sbill else 119*630Shenry exp1->e_xvalue %= exp2->e_xvalue; 120593Sbill goto comm; 121593Sbill 122593Sbill comm: 123*630Shenry back_type = othtab[e1_type][e2_type]; 124593Sbill break; 125593Sbill default: 126593Sbill yyerror("Internal error: unknown operator"); 127593Sbill } 128593Sbill 129593Sbill if (e2_type==(XTXRN>>1)) 130*630Shenry exp1->e_xname = exp2->e_xname; 131*630Shenry exp1->e_xtype = back_type | ( 132*630Shenry (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) ); 133*630Shenry if (back_type==ERR) 134593Sbill yyerror("Relocation error"); 135593Sbill return(exp1); 136593Sbill } 137593Sbill 138593Sbill buildtokensets() 139593Sbill { 140593Sbill #define clobber(val, set) tokensets[(val)] |= (set) 141593Sbill 142593Sbill clobber(SEMI, LINSTBEGIN); 143593Sbill clobber(NL, LINSTBEGIN); 144593Sbill clobber(INT, LINSTBEGIN); 145593Sbill 146593Sbill clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); 147593Sbill clobber(INSTn, YUKKYEXPRBEG); 148593Sbill clobber(INST0, YUKKYEXPRBEG); 149593Sbill clobber(REG, YUKKYEXPRBEG); 150593Sbill clobber(BFINT, YUKKYEXPRBEG); 151593Sbill 152593Sbill clobber(INT, SAFEEXPRBEG); 153593Sbill clobber(FLTNUM, SAFEEXPRBEG); 154593Sbill 155593Sbill clobber(PLUS, ADDOPS); 156593Sbill clobber(MINUS, ADDOPS + EBEGOPS); 157593Sbill 158593Sbill clobber(LP, EBEGOPS); 159593Sbill 160593Sbill clobber(IOR, BOOLOPS); 161593Sbill clobber(XOR, BOOLOPS); 162593Sbill clobber(AND, BOOLOPS); 163593Sbill clobber(ORNOT, BOOLOPS); 164593Sbill 165593Sbill clobber(TILDE, MULOPS + EBEGOPS); 166593Sbill clobber(LSH, MULOPS); 167593Sbill clobber(RSH, MULOPS); 168593Sbill clobber(MUL, MULOPS); 169593Sbill clobber(DIV, MULOPS); 170593Sbill clobber(REGOP, MULOPS); /* % */ 171593Sbill 172593Sbill } 173593Sbill 174593Sbill /* 175593Sbill * We keep the current token class in this global variable, so 176593Sbill * the recursive descent expression analyzers can talk amongst 177593Sbill * themselves, and so that we may use the macros shift and shift over 178593Sbill */ 179593Sbill 180593Sbill extern int yylval; /*the value of the lexical value*/ 181593Sbill extern struct exp *xp; /*the next free expression slot*/ 182593Sbill 183593Sbill static int val; 184593Sbill int exprparse(inval, backexpr) /*return the value the read head is sitting on*/ 185593Sbill int inval; 186593Sbill struct exp **backexpr; 187593Sbill { 188593Sbill register struct exp *lexpr; 189593Sbill int op; 190593Sbill 191593Sbill val = inval; 192593Sbill lexpr = boolterm(); 193593Sbill while (INTOKSET(val, ADDOPS)){ 194593Sbill op = val; 195593Sbill shift; 196593Sbill lexpr = combine(op, lexpr, boolterm()); 197593Sbill } 198593Sbill *backexpr = lexpr; 199593Sbill return(val); 200593Sbill } 201593Sbill 202593Sbill struct exp *boolterm() 203593Sbill { 204593Sbill register struct exp *lexpr; 205593Sbill int op; 206593Sbill 207593Sbill lexpr = term(); 208593Sbill while(INTOKSET(val, BOOLOPS)){ 209593Sbill op = val; 210593Sbill shift; 211593Sbill lexpr = combine(op, lexpr, term()); 212593Sbill } 213593Sbill return(lexpr); 214593Sbill } 215593Sbill 216593Sbill struct exp *term() 217593Sbill { 218593Sbill register struct exp *lexpr; 219593Sbill int op; 220593Sbill 221593Sbill lexpr = factor(); 222593Sbill while(INTOKSET(val, MULOPS)){ 223593Sbill op = val; 224593Sbill shift; 225593Sbill lexpr = combine(op, lexpr, factor()); 226593Sbill } 227593Sbill return(lexpr); 228593Sbill } 229593Sbill 230593Sbill struct exp *factor() 231593Sbill { 232593Sbill struct exp *lexpr; 233593Sbill int op; 234593Sbill extern int droppedLP; /*called exprparse after consuming an LP*/ 235593Sbill 236593Sbill if (val == LP || droppedLP){ 237593Sbill if (droppedLP) 238593Sbill droppedLP = 0; 239593Sbill else 240593Sbill shift; /*the LP*/ 241593Sbill val = exprparse(val, &lexpr); 242593Sbill if (val != RP) 243593Sbill yyerror("right parenthesis expected"); 244593Sbill else 245593Sbill shift; 246593Sbill } else 247593Sbill if (INTOKSET(val, YUKKYEXPRBEG)){ 248593Sbill lexpr = yukkyexpr(val, yylval); 249593Sbill shift; 250593Sbill } 251593Sbill else if (INTOKSET(val, SAFEEXPRBEG)){ 252593Sbill lexpr = (struct exp *)yylval; 253593Sbill shift; 254593Sbill } 255593Sbill else if ( (val == TILDE) || (val == MINUS) ){ 256593Sbill op = val; 257593Sbill shift; 258593Sbill lexpr = xp++; 259*630Shenry lexpr->e_xtype = XABS; 260*630Shenry lexpr->e_xvalue = 0; 261593Sbill lexpr = combine(op, lexpr, factor()); 262593Sbill } 263593Sbill else { 264593Sbill yyerror("Bad expression syntax"); 265593Sbill lexpr = xp++; 266*630Shenry lexpr->e_xtype = XABS; 267*630Shenry lexpr->e_xvalue = 0; 268593Sbill } 269593Sbill return(lexpr); 270593Sbill } 271593Sbill 272593Sbill struct exp *yukkyexpr(val, np) 273593Sbill int val; 274593Sbill register np; 275593Sbill { 276593Sbill register struct exp *locxp; 277593Sbill extern int exprisname; /*last factor is a name*/ 278593Sbill 279593Sbill exprisname = 0; 280593Sbill locxp = xp++; 281593Sbill if (val == NAME || val == BFINT){ 282593Sbill if (val == BFINT) { 283593Sbill int off = 0; 284*630Shenry yylval = ((struct exp *)np)->e_xvalue; 285593Sbill if (yylval < 0) { 286593Sbill yylval = -yylval; 287593Sbill yylval--; 288593Sbill off = -1; 289593Sbill if (lgensym[yylval] == 1) 290593Sbill yyerror("Reference to undefined local label %db", yylval); 291593Sbill } else { 292593Sbill yylval--; 293593Sbill genref[yylval] = 1; 294593Sbill } 295593Sbill sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); 296593Sbill yylval = np = (int)*lookup(passno == 1); 297593Sbill lastnam = (struct symtab *)np; 298593Sbill } 299593Sbill exprisname++; 300*630Shenry locxp->e_xtype = ((struct symtab *)np)->s_type; 301*630Shenry if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/ 302*630Shenry locxp->e_xname = (struct symtab *)np; 303*630Shenry locxp->e_xvalue = 0; 304593Sbill if (passno==1) 305*630Shenry ((struct symtab *)np)->s_type |= XFORW; 306593Sbill } else { /*otherwise, just get the value*/ 307*630Shenry locxp->e_xvalue = ((struct symtab *)np)->s_value; 308*630Shenry locxp->e_xname = NULL; 309593Sbill } 310593Sbill } else { /*INSTn or INST0 or REG*/ 311*630Shenry locxp->e_xtype = XABS; 312*630Shenry locxp->e_xvalue = ( (int)np) & 0xFF; 313*630Shenry locxp->e_xloc = 0; 314*630Shenry locxp->e_xname = NULL; 315593Sbill } 316593Sbill 317593Sbill return(locxp); 318593Sbill } 319593Sbill 320593Sbill 321593Sbill #ifdef DEBUG 322593Sbill char *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; 323593Sbill struct Tok_Desc{ 324593Sbill int tok_which; 325593Sbill char *tok_name; 326593Sbill } tok_desc[] = { 327593Sbill FIRSTTOKEN, "firsttoken", /* 0 */ 328593Sbill ISPACE, "ispace", /* 1 */ 329593Sbill IBYTE, "ibyte", /* 2 */ 330593Sbill IWORD, "iword", /* 3 */ 331593Sbill IINT, "iint", /* 4 */ 332593Sbill ILONG, "ilong", /* 5 */ 333593Sbill IDATA, "idata", /* 6 */ 334593Sbill IGLOBAL, "iglobal", /* 7 */ 335593Sbill ISET, "iset", /* 8 */ 336593Sbill ITEXT, "itext", /* 9 */ 337593Sbill ICOMM, "icomm", /* 10 */ 338593Sbill ILCOMM, "ilcomm", /* 11 */ 339593Sbill IFLOAT, "ifloat", /* 12 */ 340593Sbill IDOUBLE, "idouble", /* 13 */ 341593Sbill IORG, "iorg", /* 14 */ 342593Sbill IASCII, "iascii", /* 15 */ 343593Sbill IASCIZ, "iasciz", /* 16 */ 344593Sbill ILSYM, "ilsym", /* 17 */ 345593Sbill IFILE, "ifile", /* 18 */ 346593Sbill ILINENO, "ilineno", /* 19 */ 347593Sbill IABORT, "iabort", /* 20 */ 348593Sbill ISTAB, "istab", /* 23 */ 349593Sbill ISTABSTR, "istabstr", /* 24 */ 350593Sbill ISTABNONE, "istabnone", /* 25 */ 351593Sbill ISTABDOT, "istabdot", /* 26 */ 352593Sbill IJXXX, "ijxxx", /* 27 */ 353593Sbill IALIGN, "ialign", /* 28 */ 354593Sbill INST0, "inst0", /* 29 */ 355593Sbill INSTn, "instn", /* 30 */ 356593Sbill BFINT, "bfint", /* 31 */ 357593Sbill PARSEEOF, "parseeof", /* 32 */ 358593Sbill ILINESKIP, "ilineskip", /* 33 */ 359593Sbill VOID, "void", /* 34 */ 360593Sbill SKIP, "skip", /* 35 */ 361593Sbill INT, "int", /* 36 */ 362593Sbill FLTNUM, "fltnum", /* 37 */ 363593Sbill NAME, "name", /* 38 */ 364593Sbill STRING, "string", /* 39 */ 365593Sbill QUAD, "quad", /* 40 */ 366593Sbill SIZESPEC, "sizespec", /* 41 */ 367593Sbill REG, "reg", /* 42 */ 368593Sbill MUL, "mul", /* 43 */ 369593Sbill LITOP, "litop", /* 44 */ 370593Sbill LP, "lp", /* 45 */ 371593Sbill MP, "mp", /* 46 */ 372593Sbill NEEDSBUF, "needsbuf", /* 48 */ 373593Sbill REGOP, "regop", /* 49 */ 374593Sbill NL, "nl", /* 50 */ 375593Sbill SCANEOF, "scaneof", /* 51 */ 376593Sbill BADCHAR, "badchar", /* 52 */ 377593Sbill SP, "sp", /* 53 */ 378593Sbill ALPH, "alph", /* 54 */ 379593Sbill DIG, "dig", /* 55 */ 380593Sbill SQ, "sq", /* 56 */ 381593Sbill DQ, "dq", /* 57 */ 382593Sbill SH, "sh", /* 58 */ 383593Sbill LSH, "lsh", /* 59 */ 384593Sbill RSH, "rsh", /* 60 */ 385593Sbill MINUS, "minus", /* 61 */ 386593Sbill SIZEQUOTE, "sizequote", /* 62 */ 387593Sbill XOR, "xor", /* 64 */ 388593Sbill DIV, "div", /* 65 */ 389593Sbill SEMI, "semi", /* 66 */ 390593Sbill COLON, "colon", /* 67 */ 391593Sbill PLUS, "plus", /* 68 */ 392593Sbill IOR, "ior", /* 69 */ 393593Sbill AND, "and", /* 70 */ 394593Sbill TILDE, "tilde", /* 71 */ 395593Sbill ORNOT, "ornot", /* 72 */ 396593Sbill CM, "cm", /* 73 */ 397593Sbill LB, "lb", /* 74 */ 398593Sbill RB, "rb", /* 75 */ 399593Sbill RP, "rp", /* 76 */ 400593Sbill LASTTOKEN, "lasttoken" /* 80 */ 401593Sbill }; 402593Sbill /* 403593Sbill * turn a token type into a string 404593Sbill */ 405593Sbill static int fixed = 0; 406593Sbill char *tok_to_name(token) 407593Sbill { 408593Sbill if (!fixed){ 409593Sbill int i; 410593Sbill for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) 411593Sbill tok_name[i] = "NOT ASSIGNED"; 412593Sbill for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ 413593Sbill tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name; 414593Sbill } 415593Sbill fixed = 1; 416593Sbill } 417593Sbill if (FIRSTTOKEN <= token && token <= LASTTOKEN) 418593Sbill return(tok_name[token]); 419593Sbill else 420593Sbill panic("Unknown token number, %d\n", token); 421593Sbill /*NOTREACHED*/ 422593Sbill } 423593Sbill #endif DEBUG 424