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