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