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