1 /* 2 * Copyright (c) 1982 Regents of the University of California 3 */ 4 #ifndef lint 5 static char sccsid[] = "@(#)asexpr.c 4.4 06/09/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 NEEDSBUF, CNTRL, "need scanner buffer", 430 NL, CNTRL, "new line", 431 SCANEOF, CNTRL, "scanner end of file", 432 BADCHAR, CNTRL, "bad character", 433 SH, CNTRL, "comment, #", 434 435 INT, HUNK, "int", 436 BFINT, HUNK, "local label", 437 BIGNUM, HUNK, "big number", 438 NAME, HUNK, "name", 439 STRING, HUNK, "string", 440 REG, HUNK, "register specifier", 441 442 SIZESPEC, SMALL, "size specifier, [BWLbwl]", 443 SIZEQUOTE, SMALL, "sizequote, [^']", 444 LITOP, SMALL, "litop", 445 446 MP, SMALL, "minus parenthesis, -(", 447 REGOP, SMALL, "register operator, %", 448 449 SP, SMALL, "space", 450 ALPH, SMALL, "alphabetic character, [A-Za-z_]", 451 DIG, SMALL, "digit character, [A-Fa-f0-9]", 452 453 SQ, SMALL, "single quote, '", 454 DQ, SMALL, "double quote, \"", 455 456 LSH, SMALL, "arithmetic left shift, <", 457 RSH, SMALL, "arithmetic right shift, >", 458 XOR, SMALL, "exclusive or, ^", 459 460 PLUS, SMALL, "plus, +", 461 MINUS, SMALL, "minus, -", 462 MUL, SMALL, "multiply, *", 463 DIV, SMALL, "divide, /", 464 SEMI, SMALL, "semi colon, ;", 465 COLON, SMALL, "colon, :", 466 IOR, SMALL, "inclusive or, |", 467 AND, SMALL, "and, &", 468 469 TILDE, SMALL, "one's complement, ~", 470 ORNOT, SMALL, "ornot, !", 471 CM, SMALL, "comma", 472 473 LB, SMALL, "left bracket, [", 474 RB, SMALL, "right bracket, ]", 475 LP, SMALL, "left parenthesis, (", 476 RP, SMALL, "right parentheis, )", 477 478 LASTTOKEN, SMALL, "last token", 479 }; 480 /* 481 * turn a token type into a string 482 */ 483 char *tok_to_name(token) 484 { 485 static int fixed = 0; 486 static char buf[64]; 487 static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"}; 488 int i; 489 char *cp; 490 491 if (!fixed){ 492 for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) 493 tok_name[i] = &NA; 494 for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ 495 tok_name[tok_desc[i].tok_which] = &tok_desc[i]; 496 } 497 fixed = 1; 498 } 499 if (FIRSTTOKEN <= token && token <= LASTTOKEN){ 500 sprintf(buf, "%s %s", tok_name[token]->tok_kind, 501 tok_name[token]->tok_name); 502 return(buf); 503 } else { 504 panic("Unknown token number, %d\n", token); 505 /*NOTREACHED*/ 506 } 507 } 508