1 /* Copyright (c) 1980 Regents of the University of California */ 2 static char sccsid[] = "@(#)asparse.c 4.7 08/20/80"; 3 #include <stdio.h> 4 #include "as.h" 5 #include "asexpr.h" 6 #include "asscan.h" 7 #include "assyms.h" 8 9 int lgensym[10]; 10 char genref[10]; 11 12 long bitfield; 13 int bitoff; 14 int curlen; /* current length of literals */ 15 16 /* 17 * The following three variables are communication between various 18 * modules to special case a number of things. They are properly 19 * categorized as hacks. 20 */ 21 extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/ 22 int exprisname; /*last factor in an expression was a name*/ 23 int droppedLP; /*one is analyzing an expression beginning with*/ 24 /*a left parenthesis, which has already been*/ 25 /*shifted. (Used to parse (<expr>)(rn)*/ 26 27 char yytext[NCPS+2]; /*the lexical image*/ 28 int yylval; /*the lexical value; sloppy typing*/ 29 /* 30 * Expression and argument managers 31 */ 32 struct exp *xp; /*next free expression slot, used by expr.c*/ 33 struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/ 34 struct arg arglist[NARG]; /*building up operands in instructions*/ 35 /* 36 * Sets to accelerate token discrimination 37 */ 38 char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1]; 39 40 static char UDotsname[32]; /*name of the assembly source*/ 41 42 int yyparse() 43 { 44 register struct exp *locxp; 45 /* 46 * loc1xp and ptrloc1xp are used in the 47 * expression lookahead 48 */ 49 struct exp *loc1xp; /*must be non register*/ 50 struct exp **ptrloc1xp = & loc1xp; 51 struct exp *pval; /*hacking expr:expr*/ 52 53 register struct symtab *np; 54 register int argcnt; 55 56 register int val; /*what yylex gives*/ 57 register int auxval; /*saves val*/ 58 59 register struct arg *ap; /*first free argument*/ 60 61 struct symtab *p; 62 register struct symtab *stpt; 63 64 struct strdesc *stringp; /*handles string lists*/ 65 66 int regno; /*handles arguments*/ 67 int *ptrregno = ®no; 68 int sawmul; /*saw * */ 69 int sawindex; /*saw [rn]*/ 70 int sawsize; 71 int seg_type; /*the kind of segment: data or text*/ 72 int seg_number; /*the segment number*/ 73 int space_value; /*how much .space needs*/ 74 int fill_rep; /*how many reps for .fill */ 75 int fill_size; /*how many bytes for .fill */ 76 77 int field_width; /*how wide a field is to be*/ 78 int field_value; /*the value to stuff in a field*/ 79 char *stabname; /*name of stab dealing with*/ 80 ptrall stabstart; /*where the stab starts in the buffer*/ 81 int reloc_how; /* how to relocate expressions */ 82 83 xp = explist; 84 ap = arglist; 85 86 val = yylex(); 87 88 while (val != PARSEEOF){ /* primary loop */ 89 90 while (INTOKSET(val, LINSTBEGIN)){ 91 if (val == INT) { 92 int i = ((struct exp *)yylval)->e_xvalue; 93 shift; 94 if (val != COLON) 95 goto nocolon; 96 if (i < 0 || i > 9) { 97 yyerror("Local labels are 0-9"); 98 goto errorfix; 99 } 100 sprintf(yytext, "L%d\001%d", i, lgensym[i]); 101 lgensym[i]++; 102 genref[i] = 0; 103 yylval = (int)*lookup(passno == 1); 104 val = NAME; 105 np = (struct symtab *)yylval; 106 goto restlab; 107 } 108 if (val == NL){ 109 lineno++; 110 shift; 111 } else 112 if (val == SEMI) 113 shift; 114 else { /*its a name, so we have a label or def */ 115 if (val != NAME){ 116 ERROR("Name expected for a label"); 117 } 118 np = (struct symtab *)yylval; 119 shiftover(NAME); 120 nocolon: 121 if (val != COLON) { 122 #ifdef FLEXNAMES 123 yyerror("\"%s\" is not followed by a ':' for a label definition", 124 #else not FLEXNAMES 125 yyerror("\"%.*s\" is not followed by a ':' for a label definition", 126 NCPS, 127 #endif not FLEXNAMES 128 np->s_name); 129 goto errorfix; 130 } 131 restlab: 132 shift; 133 flushfield(NBPW/4); 134 if ((np->s_type&XTYPE)!=XUNDEF) { 135 if( (np->s_type&XTYPE)!=dotp->e_xtype 136 || np->s_value!=dotp->e_xvalue 137 || ( (passno==1) 138 &&(np->s_index != dotp->e_xloc) 139 ) 140 ){ 141 #ifndef DEBUG 142 if (np->s_name[0] != 'L') 143 #endif not DEBUG 144 { 145 if (passno == 1) 146 #ifdef FLEXNAMES 147 yyerror("%s redefined", 148 #else not FLEXNAMES 149 yyerror("%.*s redefined", 150 NCPS, 151 #endif not FLEXNAMES 152 np->s_name); 153 else 154 #ifdef FLEXNAMES 155 yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 156 #else not FLEXNAMES 157 yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 158 NCPS, 159 #endif not FLEXNAMES 160 np->s_name, 161 np->s_value, 162 dotp->e_xvalue); 163 } 164 } 165 } 166 np->s_type &= ~(XTYPE|XFORW); 167 np->s_type |= dotp->e_xtype; 168 np->s_value = dotp->e_xvalue; 169 if (passno == 1){ 170 np->s_index = dotp-usedot; 171 if (np->s_name[0] == 'L'){ 172 nlabels++; 173 } 174 np->s_tag = LABELID; 175 } 176 } /*end of this being a label*/ 177 } /*end of to consuming all labels, NLs and SEMIS */ 178 179 xp = explist; 180 ap = arglist; 181 182 /* 183 * process the INSTRUCTION body 184 */ 185 switch(val){ 186 187 default: 188 ERROR("Unrecognized instruction or directive"); 189 190 case IABORT: 191 shift; 192 sawabort(); 193 /*NOTREACHED*/ 194 break; 195 196 case PARSEEOF: 197 tokptr -= sizeof(toktype); 198 *tokptr++ = VOID; 199 tokptr[1] = VOID; 200 tokptr[2] = PARSEEOF; 201 break; 202 203 case IFILE: 204 shift; 205 stringp = (struct strdesc *)yylval; 206 shiftover(STRING); 207 dotsname = &UDotsname[0]; 208 movestr(dotsname, stringp->str, 209 stringp->str_lg >= 32? 32 :stringp->str_lg); 210 dotsname[stringp->str_lg] = '\0'; 211 break; 212 213 case ILINENO: 214 shift; /*over the ILINENO*/ 215 expr(locxp, val); 216 lineno = locxp->e_xvalue; 217 break; 218 219 case ISET: /* .set <name> , <expr> */ 220 shift; 221 np = (struct symtab *)yylval; 222 shiftover(NAME); 223 shiftover(CM); 224 expr(locxp, val); 225 np->s_type &= (XXTRN|XFORW); 226 np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 227 np->s_value = locxp->e_xvalue; 228 if (passno==1) 229 np->s_index = locxp->e_xloc; 230 if ((locxp->e_xtype&XTYPE) == XUNDEF) 231 yyerror("Illegal set?"); 232 break; 233 234 case ILSYM: /*.lsym name , expr */ 235 shift; 236 np = (struct symtab *)yylval; 237 shiftover(NAME); 238 shiftover(CM); 239 expr(locxp, val); 240 /* 241 * Build the unique occurance of the 242 * symbol. 243 * The character scanner will have 244 * already entered it into the symbol 245 * table, but we should remove it 246 */ 247 if (passno == 1){ 248 stpt = (struct symtab *)symalloc(); 249 #ifdef FLEXNAMES 250 stpt->s_name = np->s_name; 251 #else 252 movestr(stpt->s_name, np->s_name, NCPS); 253 #endif 254 np->s_tag = OBSOLETE; /*invalidate original */ 255 nforgotten++; 256 np = stpt; 257 if (locxp->e_xtype != XABS) 258 ("Illegal lsym"); 259 np->s_value=locxp->e_xvalue; 260 np->s_type=XABS; 261 np->s_tag = ILSYM; 262 } 263 break; 264 265 case IGLOBAL: /*.globl <name> */ 266 shift; 267 np = (struct symtab *)yylval; 268 shiftover(NAME); 269 np->s_type |= XXTRN; 270 break; 271 272 case IDATA: /*.data [ <expr> ] */ 273 case ITEXT: /*.text [ <expr> ] */ 274 seg_type = -val; 275 shift; 276 if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 277 expr(locxp, val); 278 seg_type = -seg_type; /*now, it is positive*/ 279 } 280 281 if (seg_type < 0) { /*there wasn't an associated expr*/ 282 seg_number = 0; 283 seg_type = -seg_type; 284 } else { 285 if (locxp->e_xtype != XABS || (seg_number=locxp->e_xvalue) >= NLOC) { 286 yyerror("illegal location counter"); 287 seg_number = 0; 288 } 289 } 290 if (seg_type == IDATA) 291 seg_number += NLOC; 292 flushfield(NBPW/4); 293 dotp = &usedot[seg_number]; 294 #ifdef UNIX 295 if (passno==2) { /* go salt away in pass 2*/ 296 txtfil = usefile[seg_number]; 297 relfil = rusefile[seg_number]; 298 } 299 #endif UNIX 300 #ifdef VMS 301 if (passno==2) { 302 puchar(vms_obj_ptr,6); /* setpl */ 303 puchar(vms_obj_ptr,seg_number); /* psect # */ 304 plong(vms_obj_ptr,dotp->e_xvalue);/* offset */ 305 puchar(vms_obj_ptr,80); /* setrb */ 306 if((vms_obj_ptr-sobuf) > 400){ 307 write(objfil,sobuf,vms_obj_ptr-sobuf); 308 vms_obj_ptr=sobuf+1; /*flush buf*/ 309 } 310 } 311 #endif VMS 312 break; 313 314 /* 315 * Storage filler directives: 316 * 317 * .byte [<exprlist>] 318 * 319 * exprlist: empty | exprlist outexpr 320 * outexpr: <expr> | <expr> : <expr> 321 */ 322 case IBYTE: curlen = NBPW/4; goto elist; 323 324 case IINT: 325 case ILONG: curlen = NBPW; goto elist; 326 327 case IWORD: 328 curlen = NBPW/2; 329 elist: 330 seg_type = val; 331 shift; 332 333 /* 334 * Expression List processing 335 */ 336 if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 337 do{ 338 /* 339 * expression list consists of a list of : 340 * <expr> 341 * <expr> : <expr> 342 * (pack expr2 into expr1 bits 343 */ 344 expr(locxp, val); 345 /* 346 * now, pointing at the next token 347 */ 348 if (val == COLON){ 349 shiftover(COLON); 350 expr(pval, val); 351 if (locxp->e_xtype != XABS) 352 yyerror("Width not absolute"); 353 field_width = locxp->e_xvalue; 354 locxp = pval; 355 if (bitoff + field_width > 356 curlen) 357 flushfield(curlen); 358 if (field_width > curlen) 359 yyerror("Expression crosses field boundary"); 360 } else { 361 field_width = curlen; 362 flushfield(curlen); 363 } 364 365 if ((locxp->e_xtype&XTYPE)!=XABS) { 366 if (bitoff) 367 yyerror("Illegal relocation in field"); 368 switch(curlen){ 369 case NBPW/4: reloc_how = TYPB; break; 370 case NBPW/2: reloc_how = TYPW; break; 371 case NBPW: reloc_how = TYPL; break; 372 } 373 if (passno == 1){ 374 dotp->e_xvalue += ty_nbyte[reloc_how]; 375 } else { 376 outrel(locxp, reloc_how); 377 } 378 } else { 379 field_value = locxp->e_xvalue & ( (1L << field_width)-1); 380 bitfield |= field_value << bitoff; 381 bitoff += field_width; 382 } 383 if ( auxval = (val == CM)) shift; 384 xp = explist; 385 } while (auxval); 386 } /*existed an expression at all*/ 387 388 flushfield(curlen); 389 if ( ( curlen == NBPW/4) && bitoff) 390 dotp->e_xvalue ++; 391 break; 392 /*end of case IBYTE, IWORD, ILONG, IINT*/ 393 394 case ISPACE: /* .space <expr> */ 395 shift; 396 expr(locxp, val); 397 if (locxp->e_xtype != XABS) 398 yyerror("Space size not absolute"); 399 space_value = locxp->e_xvalue; 400 ospace: 401 flushfield(NBPW/4); 402 #ifdef UNIX 403 while (space_value > 96){ 404 outs(strbuf[2].str, 96); 405 space_value -= 96; 406 } 407 outs(strbuf[2].str, space_value); 408 #endif UNIX 409 #ifdef VMS 410 dotp->e_xvalue += space_value; /*bump pc*/ 411 if (passno==2){ 412 if(*(strbuf[2].str)==0) { 413 puchar(vms_obj_ptr,81); /* AUGR */ 414 pulong(vms_obj_ptr,space_value);/* incr */ 415 } else yyerror("VMS, encountered non-0 .space"); 416 if ((vms_obj_ptr-sobuf) > 400) { 417 write(objfil,sobuf,vms_obj_ptr-sobuf); 418 vms_obj_ptr=sobuf+1; /*pur buf*/ 419 } 420 } 421 #endif VMS 422 break; 423 424 #ifdef UNIX 425 /* 426 * .fill rep, size, value 427 * repeat rep times: fill size bytes with (truncated) value 428 * size must be between 1 and 8 429 */ 430 case IFILL: 431 shift; 432 expr(locxp, val); 433 if (locxp->e_xtype != XABS) 434 yyerror("Fill repetition count not absolute"); 435 fill_rep = locxp->e_xvalue; 436 shiftover(CM); 437 expr(locxp, val); 438 if (locxp->e_xtype != XABS) 439 yyerror("Fill size not absolute"); 440 fill_size = locxp->e_xvalue; 441 if (fill_size <= 0 || fill_size > 8) 442 yyerror("Fill count not in in 1..8"); 443 shiftover(CM); 444 expr(locxp, val); 445 if (passno == 2 && locxp->e_xtype != XABS) 446 yyerror("Fill value not absolute"); 447 flushfield(NBPW/4); 448 if (passno == 1) { 449 locxp->e_xvalue += fill_rep * fill_size; 450 } else { 451 while(fill_rep-- > 0) 452 bwrite(&locxp->e_xvalue, fill_size, txtfil); 453 } 454 break; 455 #endif UNIX 456 457 case IASCII: /* .ascii [ <stringlist> ] */ 458 case IASCIZ: /* .asciz [ <stringlist> ] */ 459 auxval = val; 460 shift; 461 462 /* 463 * Code to consume a string list 464 * 465 * stringlist: empty | STRING | stringlist STRING 466 */ 467 while (val == STRING){ 468 flushfield(NBPW/4); 469 if (bitoff) 470 dotp->e_xvalue++; 471 stringp = (struct strdesc *)yylval; 472 #ifdef UNIX 473 outs(stringp->str, stringp->str_lg); 474 #endif UNIX 475 #ifdef VMS 476 { 477 register int i; 478 for (i=0; i < stringp->str_lg; i++){ 479 dotp->e_xvalue += 1; 480 if (passno==2){ 481 puchar(vms_obj_ptr,-1); 482 puchar(vms_obj_ptr,stringp->str[i]); 483 if (vms_obj_ptr-sobuf > 400) { 484 write(objfil,sobuf,vms_obj_ptr-sobuf); 485 vms_obj_ptr = sobuf + 1; 486 } 487 } 488 } 489 } 490 #endif VMS 491 shift; /*over the STRING*/ 492 if (val == CM) /*could be a split string*/ 493 shift; 494 } 495 496 if (auxval == IASCIZ){ 497 flushfield(NBPW/4); 498 #ifdef UNIX 499 outb(0); 500 #endif UNIX 501 #ifdef VMS 502 if (passno == 2) { 503 puchar(vms_obj_ptr,-1); 504 puchar(vms_obj_ptr,0); 505 } 506 dotp->e_xvalue += 1; 507 #endif VMS 508 } 509 break; 510 511 case IORG: /* .org <expr> */ 512 shift; 513 expr(locxp, val); 514 515 if (locxp->e_xtype==XABS) 516 orgwarn++; 517 else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 518 yyerror("Illegal expression to set origin"); 519 space_value = locxp->e_xvalue - dotp->e_xvalue; 520 if (space_value < 0) 521 yyerror("Backwards 'org'"); 522 goto ospace; 523 break; 524 525 /* 526 * 527 * Process stabs. Stabs are created only by the f77 528 * and the C compiler with the -g flag set. 529 * We only look at the stab ONCE, during pass 1, and 530 * virtually remove the stab from the intermediate file 531 * so it isn't seen during pass2. This makes for some 532 * hairy processing to handle labels occuring in 533 * stab entries, but since most expressions in the 534 * stab are integral we save lots of time in the second 535 * pass by not looking at the stabs. 536 * A stab that is tagged floating will be bumped during 537 * the jxxx resolution phase. A stab tagged fixed will 538 * not be be bumped. 539 * 540 * .stab: Old fashioned stabs 541 * .stabn: For stabs without names 542 * .stabs: For stabs with string names 543 * .stabd: For stabs for line numbers or bracketing, 544 * without a string name, without 545 * a final expression. The value of the 546 * final expression is taken to be the current 547 * location counter, and is patched by the 2nd pass 548 * 549 * .stab{<expr>,}*NCPS,<expr>, <expr>, <expr>, <expr> 550 * .stabn <expr>, <expr>, <expr>, <expr> 551 * .stabs STRING, <expr>, <expr>, <expr>, <expr> 552 * .stabd <expr>, <expr>, <expr> # . 553 */ 554 case ISTAB: 555 #ifndef FLEXNAMES 556 stabname = ".stab"; 557 if (passno == 2) goto errorfix; 558 stpt = (struct symtab *)yylval; 559 /* 560 * Make a pointer to the .stab slot. 561 * There is a pointer in the way (stpt), and 562 * tokptr points to the next token. 563 */ 564 stabstart = tokptr; 565 (char *)stabstart -= sizeof(struct symtab *); 566 (char *)stabstart -= sizeof(toktype); 567 shift; 568 for (argcnt = 0; argcnt < NCPS; argcnt++){ 569 expr(locxp, val); 570 stpt->s_name[argcnt] = locxp->e_xvalue; 571 xp = explist; 572 shiftover(CM); 573 } 574 goto tailstab; 575 #else FLEXNAMES 576 yyerror(".stab directive not supported in; report this compiler bug to system administrator"); 577 goto errorfix; 578 #endif FLEXNAMES 579 580 tailstab: 581 expr(locxp, val); 582 if (! (locxp->e_xvalue & STABTYPS)){ 583 yyerror("Invalid type in %s",stabname); 584 goto errorfix; 585 } 586 stpt->s_ptype = locxp->e_xvalue; 587 shiftover(CM); 588 expr(locxp, val); 589 stpt->s_other = locxp->e_xvalue; 590 shiftover(CM); 591 expr(locxp, val); 592 stpt->s_desc = locxp->e_xvalue; 593 shiftover(CM); 594 exprisname = 0; 595 expr(locxp, val); 596 p = locxp->e_xname; 597 if (p == NULL) { /*absolute expr to begin with*/ 598 stpt->s_value = locxp->e_xvalue; 599 stpt->s_index = dotp - usedot; 600 if (exprisname){ 601 switch(stpt->s_ptype){ 602 case N_GSYM: 603 case N_FNAME: 604 case N_RSYM: 605 case N_SSYM: 606 case N_LSYM: 607 case N_PSYM: 608 case N_BCOMM: 609 case N_ECOMM: 610 case N_LENG: 611 stpt->s_tag = STABFIXED; 612 break; 613 default: 614 stpt->s_tag = STABFLOATING; 615 break; 616 } 617 } else 618 stpt->s_tag = STABFIXED; 619 } 620 else { /*really have a name*/ 621 stpt->s_dest = locxp->e_xname; 622 stpt->s_index = p->s_index; 623 stpt->s_type = p->s_type | STABFLAG; 624 /* 625 * We will assign a more accruate 626 * guess of locxp's location when 627 * we sort the symbol table 628 * The final value of value is 629 * given by stabfix() 630 */ 631 stpt->s_tag = STABFLOATING; 632 } 633 /* 634 * tokptr now points at one token beyond 635 * the current token stored in val and yylval, 636 * which are the next tokens after the end of 637 * this .stab directive. This next token must 638 * be either a SEMI or NL, so is of width just 639 * one. Therefore, to point to the next token 640 * after the end of this stab, just back up one.. 641 */ 642 buildskip(stabstart, (char *)tokptr - sizeof(toktype)); 643 break; /*end of the .stab*/ 644 645 case ISTABDOT: 646 stabname = ".stabd"; 647 stpt = (struct symtab *)yylval; 648 /* 649 * We clobber everything after the 650 * .stabd and its pointer... we MUST 651 * be able to get back to this .stabd 652 * so that we can resolve its final value 653 */ 654 stabstart = tokptr; 655 shift; /*over the ISTABDOT*/ 656 if (passno == 1){ 657 expr(locxp, val); 658 if (! (locxp->e_xvalue & STABTYPS)){ 659 yyerror("Invalid type in .stabd"); 660 goto errorfix; 661 } 662 stpt->s_ptype = locxp->e_xvalue; 663 shiftover(CM); 664 expr(locxp, val); 665 stpt->s_other = locxp->e_xvalue; 666 shiftover(CM); 667 expr(locxp, val); 668 stpt->s_desc = locxp->e_xvalue; 669 /* 670 * 671 * Now, clobber everything but the 672 * .stabd pseudo and the pointer 673 * to its symbol table entry 674 * tokptr points to the next token, 675 * build the skip up to this 676 */ 677 buildskip(stabstart, (toktype *)tokptr - sizeof(toktype)); 678 } 679 /* 680 * pass 1: Assign a good guess for its position 681 * (ensures they are sorted into right place)/ 682 * pass 2: Fix the actual value 683 */ 684 stpt->s_value = dotp->e_xvalue; 685 stpt->s_index = dotp - usedot; 686 stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 687 break; 688 689 case ISTABNONE: stabname = ".stabn"; goto shortstab; 690 691 case ISTABSTR: stabname = ".stabs"; 692 shortstab: 693 auxval = val; 694 if (passno == 2) goto errorfix; 695 stpt = (struct symtab *)yylval; 696 stabstart = tokptr; 697 (char *)stabstart -= sizeof(struct symtab *); 698 (char *)stabstart -= sizeof(toktype); 699 shift; 700 if (auxval == ISTABSTR){ 701 stringp = (struct strdesc *)yylval; 702 shiftover(STRING); 703 #ifndef FLEXNAMES 704 auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; 705 #else 706 stringp->str[stringp->str_lg] = 0; 707 #endif 708 shiftover(CM); 709 } else { 710 stringp = &(strbuf[2]); 711 #ifndef FLEXNAMES 712 auxval = NCPS; 713 #endif 714 } 715 #ifndef FLEXNAMES 716 movestr(stpt->s_name, stringp->str, auxval); 717 #else 718 stpt->s_name = savestr(stringp->str); 719 #endif 720 goto tailstab; 721 break; 722 723 case ICOMM: /* .comm <name> , <expr> */ 724 case ILCOMM: /* .lcomm <name> , <expr> */ 725 auxval = val; 726 shift; 727 np = (struct symtab *)yylval; 728 shiftover(NAME); 729 shiftover(CM); 730 expr(locxp, val); 731 732 if (locxp->e_xtype != XABS) 733 yyerror("comm size not absolute"); 734 if (passno==1 && (np->s_type&XTYPE)!=XUNDEF) 735 #ifdef FLEXNAMES 736 yyerror("Redefinition of %s", 737 #else not FLEXNAMES 738 yyerror("Redefinition of %.*s", 739 NCPS, 740 #endif not FLEXNAMES 741 np->s_name); 742 if (passno==1) { 743 np->s_value = locxp->e_xvalue; 744 if (auxval == ICOMM) 745 np->s_type |= XXTRN; 746 else { 747 np->s_type &= ~XTYPE; 748 np->s_type |= XBSS; 749 } 750 } 751 break; 752 753 case IALIGN: /* .align <expr> */ 754 stpt = (struct symtab *)yylval; 755 shift; 756 expr(locxp, val); 757 jalign(locxp, stpt); 758 break; 759 760 case INST0: /* instructions w/o arguments*/ 761 insout(yylval, (struct arg *)0, 0); 762 shift; 763 break; 764 765 case INSTn: /* instructions with arguments*/ 766 case IJXXX: /* UNIX style jump instructions */ 767 auxval = val; 768 seg_type = yylval; 769 /* 770 * Code to process an argument list 771 */ 772 ap = arglist; 773 xp = explist; 774 775 shift; /* bring in the first token for the arg list*/ 776 777 for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 778 /* 779 * code to process an argument proper 780 */ 781 sawindex = sawmul = sawsize = 0; 782 { 783 switch(val) { 784 785 default: 786 disp: 787 if( !(INTOKSET(val, 788 EBEGOPS 789 +YUKKYEXPRBEG 790 +SAFEEXPRBEG)) ) { 791 ERROR("expression expected"); 792 } 793 expr(ap->a_xp,val); 794 overdisp: 795 if ( val == LP || sawsize){ 796 shiftover(LP); 797 findreg(regno); 798 shiftover(RP); 799 ap->a_atype = ADISP; 800 ap->a_areg1 = regno; 801 } else { 802 ap->a_atype = AEXP; 803 ap->a_areg1 = 0; 804 } 805 goto index; 806 807 case SIZESPEC: 808 sizespec: 809 sawsize = yylval; 810 shift; 811 goto disp; 812 813 case REG: 814 case REGOP: 815 findreg(regno); 816 ap->a_atype = AREG; 817 ap->a_areg1 = regno; 818 break; 819 820 case MUL: 821 sawmul = 1; 822 shift; 823 if (val == LP) goto base; 824 if (val == LITOP) goto imm; 825 if (val == SIZESPEC) goto sizespec; 826 if (INTOKSET(val, 827 EBEGOPS 828 +YUKKYEXPRBEG 829 +SAFEEXPRBEG)) goto disp; 830 ERROR("expression, '(' or '$' expected"); 831 break; 832 833 case LP: 834 base: 835 shift; /*consume the LP*/ 836 /* 837 * hack the ambiguity of 838 * movl (expr) (rn), ... 839 * note that (expr) could also 840 * be (rn) (by special hole in the 841 * grammar), which we ensure 842 * means register indirection, instead 843 * of an expression with value n 844 */ 845 if (val != REG && val != REGOP){ 846 droppedLP = 1; 847 val = exprparse(val, &(ap->a_xp)); 848 droppedLP = 0; 849 goto overdisp; 850 } 851 findreg(regno); 852 shiftover(RP); 853 if (val == PLUS){ 854 shift; 855 ap->a_atype = AINCR; 856 } else 857 ap->a_atype = ABASE; 858 ap->a_areg1 = regno; 859 goto index; 860 861 case LITOP: 862 imm: 863 shift; 864 expr(locxp, val); 865 ap->a_atype = AIMM; 866 ap->a_areg1 = 0; 867 ap->a_xp = locxp; 868 goto index; 869 870 case MP: 871 shift; /* -(reg) */ 872 findreg(regno); 873 shiftover(RP); 874 ap->a_atype = ADECR; 875 ap->a_areg1 = regno; 876 index: /*look for [reg] */ 877 if (val == LB){ 878 shift; 879 findreg(regno); 880 shiftover(RB); 881 sawindex = 1; 882 ap->a_areg2 = regno; 883 } 884 break; 885 886 } /*end of the switch to process an arg*/ 887 } /*end of processing an argument*/ 888 889 if (sawmul){ 890 /* 891 * Make a concession for *(%r) 892 * meaning *0(%r) 893 */ 894 if (ap->a_atype == ABASE) { 895 ap->a_atype = ADISP; 896 xp->e_xtype = XABS; 897 xp->e_xvalue = 0; 898 xp->e_xloc = 0; 899 ap->a_xp = xp++; 900 } 901 ap->a_atype |= ASTAR; 902 sawmul = 0; 903 } 904 if (sawindex){ 905 ap->a_atype |= AINDX; 906 sawindex = 0; 907 } 908 ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 909 if (val != CM) break; 910 shiftover(CM); 911 } /*processing all the arguments*/ 912 913 if (argcnt > 6){ 914 yyerror("More than 6 arguments"); 915 goto errorfix; 916 } 917 918 insout(seg_type, arglist, 919 auxval == INSTn ? argcnt : - argcnt); 920 break; 921 922 case IFLOAT: curlen = 4; goto floatlist; 923 case IQUAD: 924 case IDOUBLE: 925 curlen = 8; 926 floatlist: 927 /* 928 * eat a list of floating point numbers 929 */ 930 shift; 931 if (val == FLTNUM){ 932 /* KLS MOD */ 933 float flocal; 934 do{ 935 if (val == CM) shift; 936 if (val != FLTNUM) { 937 ERROR("floating number expected"); 938 } 939 dotp->e_xvalue += curlen; 940 #ifdef UNIX 941 if (passno == 2) { 942 if(curlen == 8) 943 bwrite((char *)&(((union Double *)yylval)->dvalue), 944 curlen, txtfil); 945 else { 946 flocal = ((union Double *)yylval)->dvalue; 947 bwrite((char *)&flocal, curlen, txtfil); 948 } 949 } 950 #endif UNIX 951 952 #ifdef VMS 953 if (passno == 2) { 954 puchar(vms_obj_ptr,-4); 955 pulong(vms_obj_ptr, 956 ((struct exp *)yylval) 957 ->doub_MSW); 958 if (curlen==8) { 959 puchar(vms_obj_ptr,-4); 960 pulong(vms_obj_ptr, 961 ((struct exp *)yylval) 962 ->doub_LSW); 963 } 964 if((vms_obj_ptr-sobuf) > 400) { 965 write(objfil,sobuf,vms_obj_ptr-sobuf); 966 vms_obj_ptr = sobuf + 1; 967 } 968 } 969 #endif VMS 970 shift; 971 xp = explist; 972 } while (val == CM); 973 } 974 break; 975 } /*end of the switch for looking at each reserved word*/ 976 977 continue; 978 979 errorfix: 980 /* 981 * got here by either requesting to skip to the 982 * end of this statement, or by erroring out and 983 * wanting to apply panic mode recovery 984 */ 985 while ( (val != NL) 986 && (val != SEMI) 987 && (val != PARSEEOF) 988 ){ 989 shift; 990 } 991 if (val == NL) 992 lineno++; 993 shift; 994 995 } /*end of the loop to read the entire file, line by line*/ 996 997 } /*end of yyparse*/ 998 999 /* 1000 * Process a register declaration of the form 1001 * % <expr> 1002 * 1003 * Note: 1004 * The scanner has already processed funny registers of the form 1005 * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 1006 * preceding zero digit). If there was any space between the % and 1007 * the digit, the scanner wouldn't have recognized it, so we 1008 * hack it out here. 1009 */ 1010 int funnyreg(val, regnoback) /*what the read head will sit on*/ 1011 int val; /*what the read head is sitting on*/ 1012 int *regnoback; /*call by return*/ 1013 { 1014 register struct exp *locxp; 1015 struct exp *loc1xp; 1016 struct exp **ptrloc1xp = & loc1xp; 1017 1018 expr(locxp, val); /*and leave the current read head with value*/ 1019 if ( (passno == 2) && 1020 ( locxp->e_xtype & XTYPE != XABS 1021 || locxp->e_xvalue < 0 1022 || locxp->e_xvalue >= 16 1023 ) 1024 ){ 1025 yyerror("Illegal register"); 1026 return(0); 1027 } 1028 *regnoback = locxp->e_xvalue; 1029 return(val); 1030 } 1031 1032 /*VARARGS1*/ 1033 yyerror(s, a1, a2,a3,a4,a5) 1034 char *s; 1035 { 1036 1037 #define sink stdout 1038 1039 if (anyerrs == 0 && ! silent) 1040 fprintf(sink, "Assembler:\n"); 1041 anyerrs++; 1042 if (silent) return; 1043 1044 fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1045 fprintf(sink, s, a1, a2,a3,a4,a5); 1046 fprintf(sink, "\n"); 1047 } 1048 1049 /*VARARGS1*/ 1050 yywarning(s, a1, a2,a3,a4,a5) 1051 char *s; 1052 { 1053 1054 #define sink stdout 1055 1056 if (anyerrs == 0 && ! silent) 1057 fprintf(sink, "Assembler:\n"); 1058 if (silent) return; 1059 1060 fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1061 fprintf(sink, s, a1, a2,a3,a4,a5); 1062 fprintf(sink, "\n"); 1063 } 1064