1 /* Copyright (c) 1980 Regents of the University of California */ 2 static char sccsid[] = "@(#)asexpr.c 4.1 08/13/80"; 3 #include <stdio.h> 4 #include <sys/types.h> 5 #include "as.h" 6 #include "asexpr.h" 7 8 /* 9 * Tables for combination of operands. 10 */ 11 #define XTXRN 5<<1 /* indexes last row/column when right shifted */ 12 13 /* 14 * table for + 15 */ 16 readonly char pltab[6][6] = { 17 /* UND ABS TXT DAT BSS EXT */ 18 19 /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 20 /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN, 21 /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR, 22 /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR, 23 /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR, 24 /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 25 }; 26 27 /* 28 * table for - 29 */ 30 readonly char mintab[6][6] = { 31 /* UND ABS TXT DAT BSS EXT */ 32 33 /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 34 /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 35 /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR, 36 /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR, 37 /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR, 38 /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, 39 }; 40 41 /* 42 * table for other operators 43 */ 44 readonly char othtab[6][6] = { 45 /* UND ABS TXT DAT BSS EXT */ 46 47 /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, 48 /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, 49 /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 50 /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 51 /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 52 /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, 53 }; 54 55 struct exp * 56 combine(op, exp1, exp2) 57 register struct exp *exp1, *exp2; 58 { 59 register e1_type, e2_type; 60 register type; 61 62 lastnam=0; /* kludge for jxxx instructions */ 63 64 e1_type = exp1->xtype&XTYPE; 65 e2_type = exp2->xtype&XTYPE; 66 67 if (exp1->xtype==XXTRN+XUNDEF) 68 e1_type = XTXRN; 69 if (exp2->xtype==XXTRN+XUNDEF) 70 e2_type = XTXRN; 71 if (passno==1) 72 if (exp1->xloc!=exp2->xloc && e1_type==e2_type) 73 e1_type = e2_type = XTXRN; /* error on != loc ctrs */ 74 e1_type >>= 1; /*dispose of the external (XXTRN) bit*/ 75 e2_type >>= 1; 76 77 switch (op) { 78 case PLUS: 79 exp1->xvalue += exp2->xvalue; 80 type = pltab[e1_type][e2_type]; 81 break; 82 case MINUS: 83 exp1->xvalue -= exp2->xvalue; 84 type = mintab[e1_type][e2_type]; 85 break; 86 case IOR: 87 exp1->xvalue |= exp2->xvalue; 88 goto comm; 89 case XOR: 90 exp1->xvalue ^= exp2->xvalue; 91 goto comm; 92 case AND: 93 exp1->xvalue &= exp2->xvalue; 94 goto comm; 95 case ORNOT: 96 exp1->xvalue |= ~exp2->xvalue; 97 goto comm; 98 case LSH: 99 exp1->xvalue <<= exp2->xvalue; 100 goto comm; 101 case RSH: 102 exp1->xvalue >>= exp2->xvalue; 103 goto comm; 104 case TILDE: 105 exp1->xvalue |= ~ exp2->xvalue; 106 goto comm; 107 case MUL: 108 exp1->xvalue *= exp2->xvalue; 109 goto comm; 110 case DIV: 111 if (exp2->xvalue == 0) 112 yyerror("Divide check"); 113 else 114 exp1->xvalue /= exp2->xvalue; 115 goto comm; 116 case REGOP: 117 if (exp2->xvalue == 0) 118 yyerror("Divide check (modulo)"); 119 else 120 exp1->xvalue %= exp2->xvalue; 121 goto comm; 122 123 comm: 124 type = othtab[e1_type][e2_type]; 125 break; 126 default: 127 yyerror("Internal error: unknown operator"); 128 } 129 130 if (e2_type==(XTXRN>>1)) 131 exp1->xname = exp2->xname; 132 exp1->xtype = type | ( 133 (exp1->xtype|exp2->xtype) & (XFORW|XXTRN) ); 134 if (type==ERR) 135 yyerror("Relocation error"); 136 return(exp1); 137 } 138 139 buildtokensets() 140 { 141 #define clobber(val, set) tokensets[(val)] |= (set) 142 143 clobber(SEMI, LINSTBEGIN); 144 clobber(NL, LINSTBEGIN); 145 clobber(INT, LINSTBEGIN); 146 147 clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); 148 clobber(INSTn, YUKKYEXPRBEG); 149 clobber(INST0, YUKKYEXPRBEG); 150 clobber(REG, YUKKYEXPRBEG); 151 clobber(BFINT, YUKKYEXPRBEG); 152 153 clobber(INT, SAFEEXPRBEG); 154 clobber(FLTNUM, SAFEEXPRBEG); 155 156 clobber(PLUS, ADDOPS); 157 clobber(MINUS, ADDOPS + EBEGOPS); 158 159 clobber(LP, EBEGOPS); 160 161 clobber(IOR, BOOLOPS); 162 clobber(XOR, BOOLOPS); 163 clobber(AND, BOOLOPS); 164 clobber(ORNOT, BOOLOPS); 165 166 clobber(TILDE, MULOPS + EBEGOPS); 167 clobber(LSH, MULOPS); 168 clobber(RSH, MULOPS); 169 clobber(MUL, MULOPS); 170 clobber(DIV, MULOPS); 171 clobber(REGOP, MULOPS); /* % */ 172 173 } 174 175 /* 176 * We keep the current token class in this global variable, so 177 * the recursive descent expression analyzers can talk amongst 178 * themselves, and so that we may use the macros shift and shift over 179 */ 180 181 extern int yylval; /*the value of the lexical value*/ 182 extern struct exp *xp; /*the next free expression slot*/ 183 184 static int val; 185 int exprparse(inval, backexpr) /*return the value the read head is sitting on*/ 186 int inval; 187 struct exp **backexpr; 188 { 189 register struct exp *lexpr; 190 int op; 191 192 val = inval; 193 lexpr = boolterm(); 194 while (INTOKSET(val, ADDOPS)){ 195 op = val; 196 shift; 197 lexpr = combine(op, lexpr, boolterm()); 198 } 199 *backexpr = lexpr; 200 return(val); 201 } 202 203 struct exp *boolterm() 204 { 205 register struct exp *lexpr; 206 int op; 207 208 lexpr = term(); 209 while(INTOKSET(val, BOOLOPS)){ 210 op = val; 211 shift; 212 lexpr = combine(op, lexpr, term()); 213 } 214 return(lexpr); 215 } 216 217 struct exp *term() 218 { 219 register struct exp *lexpr; 220 int op; 221 222 lexpr = factor(); 223 while(INTOKSET(val, MULOPS)){ 224 op = val; 225 shift; 226 lexpr = combine(op, lexpr, factor()); 227 } 228 return(lexpr); 229 } 230 231 struct exp *factor() 232 { 233 struct exp *lexpr; 234 int op; 235 extern int droppedLP; /*called exprparse after consuming an LP*/ 236 237 if (val == LP || droppedLP){ 238 if (droppedLP) 239 droppedLP = 0; 240 else 241 shift; /*the LP*/ 242 val = exprparse(val, &lexpr); 243 if (val != RP) 244 yyerror("right parenthesis expected"); 245 else 246 shift; 247 } else 248 if (INTOKSET(val, YUKKYEXPRBEG)){ 249 lexpr = yukkyexpr(val, yylval); 250 shift; 251 } 252 else if (INTOKSET(val, SAFEEXPRBEG)){ 253 lexpr = (struct exp *)yylval; 254 shift; 255 } 256 else if ( (val == TILDE) || (val == MINUS) ){ 257 op = val; 258 shift; 259 lexpr = xp++; 260 lexpr->xtype = XABS; 261 lexpr->xvalue = 0; 262 lexpr = combine(op, lexpr, factor()); 263 } 264 else { 265 yyerror("Bad expression syntax"); 266 lexpr = xp++; 267 lexpr->xtype = XABS; 268 lexpr->xvalue = 0; 269 } 270 return(lexpr); 271 } 272 273 struct exp *yukkyexpr(val, np) 274 int val; 275 register np; 276 { 277 register struct exp *locxp; 278 extern int exprisname; /*last factor is a name*/ 279 280 exprisname = 0; 281 locxp = xp++; 282 if (val == NAME || val == BFINT){ 283 if (val == BFINT) { 284 int off = 0; 285 yylval = ((struct exp *)np)->xvalue; 286 if (yylval < 0) { 287 yylval = -yylval; 288 yylval--; 289 off = -1; 290 if (lgensym[yylval] == 1) 291 yyerror("Reference to undefined local label %db", yylval); 292 } else { 293 yylval--; 294 genref[yylval] = 1; 295 } 296 sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); 297 yylval = np = (int)*lookup(passno == 1); 298 lastnam = (struct symtab *)np; 299 } 300 exprisname++; 301 locxp->xtype = ((struct symtab *)np)->type; 302 if (( ((struct symtab *)np)->type&XTYPE)==XUNDEF) { /*forward*/ 303 locxp->xname = (struct symtab *)np; 304 locxp->xvalue = 0; 305 if (passno==1) 306 ((struct symtab *)np)->type |= XFORW; 307 } else { /*otherwise, just get the value*/ 308 locxp->xvalue = ((struct symtab *)np)->value; 309 locxp->xname = NULL; 310 } 311 } else { /*INSTn or INST0 or REG*/ 312 locxp->xtype = XABS; 313 locxp->xvalue = ( (int)np) & 0xFF; 314 locxp->xloc = 0; 315 locxp->xname = NULL; 316 } 317 318 return(locxp); 319 } 320 321 322 #ifdef DEBUG 323 char *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; 324 struct Tok_Desc{ 325 int tok_which; 326 char *tok_name; 327 } tok_desc[] = { 328 FIRSTTOKEN, "firsttoken", /* 0 */ 329 ISPACE, "ispace", /* 1 */ 330 IBYTE, "ibyte", /* 2 */ 331 IWORD, "iword", /* 3 */ 332 IINT, "iint", /* 4 */ 333 ILONG, "ilong", /* 5 */ 334 IDATA, "idata", /* 6 */ 335 IGLOBAL, "iglobal", /* 7 */ 336 ISET, "iset", /* 8 */ 337 ITEXT, "itext", /* 9 */ 338 ICOMM, "icomm", /* 10 */ 339 ILCOMM, "ilcomm", /* 11 */ 340 IFLOAT, "ifloat", /* 12 */ 341 IDOUBLE, "idouble", /* 13 */ 342 IORG, "iorg", /* 14 */ 343 IASCII, "iascii", /* 15 */ 344 IASCIZ, "iasciz", /* 16 */ 345 ILSYM, "ilsym", /* 17 */ 346 IFILE, "ifile", /* 18 */ 347 ILINENO, "ilineno", /* 19 */ 348 IABORT, "iabort", /* 20 */ 349 ISTAB, "istab", /* 23 */ 350 ISTABSTR, "istabstr", /* 24 */ 351 ISTABNONE, "istabnone", /* 25 */ 352 ISTABDOT, "istabdot", /* 26 */ 353 IJXXX, "ijxxx", /* 27 */ 354 IALIGN, "ialign", /* 28 */ 355 INST0, "inst0", /* 29 */ 356 INSTn, "instn", /* 30 */ 357 BFINT, "bfint", /* 31 */ 358 PARSEEOF, "parseeof", /* 32 */ 359 ILINESKIP, "ilineskip", /* 33 */ 360 VOID, "void", /* 34 */ 361 SKIP, "skip", /* 35 */ 362 INT, "int", /* 36 */ 363 FLTNUM, "fltnum", /* 37 */ 364 NAME, "name", /* 38 */ 365 STRING, "string", /* 39 */ 366 QUAD, "quad", /* 40 */ 367 SIZESPEC, "sizespec", /* 41 */ 368 REG, "reg", /* 42 */ 369 MUL, "mul", /* 43 */ 370 LITOP, "litop", /* 44 */ 371 LP, "lp", /* 45 */ 372 MP, "mp", /* 46 */ 373 NEEDSBUF, "needsbuf", /* 48 */ 374 REGOP, "regop", /* 49 */ 375 NL, "nl", /* 50 */ 376 SCANEOF, "scaneof", /* 51 */ 377 BADCHAR, "badchar", /* 52 */ 378 SP, "sp", /* 53 */ 379 ALPH, "alph", /* 54 */ 380 DIG, "dig", /* 55 */ 381 SQ, "sq", /* 56 */ 382 DQ, "dq", /* 57 */ 383 SH, "sh", /* 58 */ 384 LSH, "lsh", /* 59 */ 385 RSH, "rsh", /* 60 */ 386 MINUS, "minus", /* 61 */ 387 SIZEQUOTE, "sizequote", /* 62 */ 388 XOR, "xor", /* 64 */ 389 DIV, "div", /* 65 */ 390 SEMI, "semi", /* 66 */ 391 COLON, "colon", /* 67 */ 392 PLUS, "plus", /* 68 */ 393 IOR, "ior", /* 69 */ 394 AND, "and", /* 70 */ 395 TILDE, "tilde", /* 71 */ 396 ORNOT, "ornot", /* 72 */ 397 CM, "cm", /* 73 */ 398 LB, "lb", /* 74 */ 399 RB, "rb", /* 75 */ 400 RP, "rp", /* 76 */ 401 LASTTOKEN, "lasttoken" /* 80 */ 402 }; 403 /* 404 * turn a token type into a string 405 */ 406 static int fixed = 0; 407 char *tok_to_name(token) 408 { 409 if (!fixed){ 410 int i; 411 for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) 412 tok_name[i] = "NOT ASSIGNED"; 413 for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ 414 tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name; 415 } 416 fixed = 1; 417 } 418 if (FIRSTTOKEN <= token && token <= LASTTOKEN) 419 return(tok_name[token]); 420 else 421 panic("Unknown token number, %d\n", token); 422 /*NOTREACHED*/ 423 } 424 #endif DEBUG 425