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