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