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