1597Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*645Shenry static char sccsid[] = "@(#)asparse.c 4.3 08/16/80"; 3597Sbill #include <stdio.h> 4597Sbill #include "as.h" 5597Sbill #include "asexpr.h" 6597Sbill #include "asscan.h" 7597Sbill #include "assyms.h" 8597Sbill 9597Sbill int lgensym[10]; 10597Sbill char genref[10]; 11597Sbill 12597Sbill long bitfield; 13597Sbill int bitoff; 14597Sbill int curlen; /* current length of literals */ 15597Sbill 16597Sbill /* 17597Sbill * The following three variables are communication between various 18597Sbill * modules to special case a number of things. They are properly 19597Sbill * categorized as hacks. 20597Sbill */ 21597Sbill extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/ 22597Sbill int exprisname; /*last factor in an expression was a name*/ 23597Sbill int droppedLP; /*one is analyzing an expression beginning with*/ 24597Sbill /*a left parenthesis, which has already been*/ 25597Sbill /*shifted. (Used to parse (<expr>)(rn)*/ 26597Sbill 27597Sbill char yytext[NCPS+2]; /*the lexical image*/ 28597Sbill int yylval; /*the lexical value; sloppy typing*/ 29597Sbill /* 30597Sbill * Expression and argument managers 31597Sbill */ 32597Sbill struct exp *xp; /*next free expression slot, used by expr.c*/ 33597Sbill struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/ 34597Sbill struct arg arglist[NARG]; /*building up operands in instructions*/ 35597Sbill /* 36597Sbill * Sets to accelerate token discrimination 37597Sbill */ 38597Sbill char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1]; 39597Sbill 40597Sbill static char UDotsname[32]; /*name of the assembly source*/ 41597Sbill 42597Sbill int yyparse() 43597Sbill { 44597Sbill register struct exp *locxp; 45597Sbill /* 46597Sbill * loc1xp and ptrloc1xp are used in the 47597Sbill * expression lookahead 48597Sbill */ 49597Sbill struct exp *loc1xp; /*must be non register*/ 50597Sbill struct exp **ptrloc1xp = & loc1xp; 51597Sbill struct exp *pval; /*hacking expr:expr*/ 52597Sbill 53597Sbill register struct symtab *np; 54597Sbill register int argcnt; 55597Sbill 56597Sbill register int val; /*what yylex gives*/ 57597Sbill register int auxval; /*saves val*/ 58597Sbill 59597Sbill register struct arg *ap; /*first free argument*/ 60597Sbill 61597Sbill struct symtab *p; 62597Sbill register struct symtab *stpt; 63597Sbill 64597Sbill struct strdesc *stringp; /*handles string lists*/ 65597Sbill 66597Sbill int regno; /*handles arguments*/ 67597Sbill int *ptrregno = ®no; 68597Sbill int sawmul; /*saw * */ 69597Sbill int sawindex; /*saw [rn]*/ 70597Sbill int sawsize; 71597Sbill int seg_type; /*the kind of segment: data or text*/ 72597Sbill int seg_number; /*the segment number*/ 73597Sbill int space_value; /*how much .space needs*/ 74597Sbill 75597Sbill int field_width; /*how wide a field is to be*/ 76597Sbill int field_value; /*the value to stuff in a field*/ 77597Sbill char *stabname; /*name of stab dealing with*/ 78597Sbill ptrall stabstart; /*where the stab starts in the buffer*/ 79597Sbill 80597Sbill xp = explist; 81597Sbill ap = arglist; 82597Sbill 83597Sbill val = yylex(); 84597Sbill 85597Sbill while (val != PARSEEOF){ /* primary loop */ 86597Sbill 87597Sbill while (INTOKSET(val, LINSTBEGIN)){ 88597Sbill if (val == INT) { 89632Shenry int i = ((struct exp *)yylval)->e_xvalue; 90597Sbill shift; 91597Sbill if (val != COLON) 92597Sbill goto nocolon; 93597Sbill if (i < 0 || i > 9) { 94597Sbill yyerror("Local labels are 0-9"); 95597Sbill goto errorfix; 96597Sbill } 97597Sbill sprintf(yytext, "L%d\001%d", i, lgensym[i]); 98597Sbill lgensym[i]++; 99597Sbill genref[i] = 0; 100597Sbill yylval = (int)*lookup(passno == 1); 101597Sbill val = NAME; 102597Sbill np = (struct symtab *)yylval; 103597Sbill goto restlab; 104597Sbill } 105597Sbill if (val == NL){ 106597Sbill lineno++; 107597Sbill shift; 108597Sbill } else 109597Sbill if (val == SEMI) 110597Sbill shift; 111597Sbill else { /*its a name, so we have a label or def */ 112597Sbill if (val != NAME){ 113597Sbill ERROR("Name expected for a label"); 114597Sbill } 115597Sbill np = (struct symtab *)yylval; 116597Sbill shiftover(NAME); 117597Sbill nocolon: 118597Sbill if (val != COLON) { 119632Shenry #ifdef FLEXNAMES 120597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition", 121632Shenry #else not FLEXNAMES 122632Shenry yyerror("\"%.*s\" is not followed by a ':' for a label definition", 123632Shenry NCPS, 124632Shenry #endif not FLEXNAMES 125632Shenry np->s_name); 126597Sbill goto errorfix; 127597Sbill } 128597Sbill restlab: 129597Sbill shift; 130597Sbill flushfield(NBPW/4); 131632Shenry if ((np->s_type&XTYPE)!=XUNDEF) { 132632Shenry if( (np->s_type&XTYPE)!=dotp->e_xtype 133632Shenry || np->s_value!=dotp->e_xvalue 134597Sbill || ( (passno==1) 135632Shenry &&(np->s_index != dotp->e_xloc) 136597Sbill ) 137597Sbill ){ 138597Sbill #ifndef DEBUG 139632Shenry if (np->s_name[0] != 'L') 140597Sbill #endif not DEBUG 141597Sbill { 142597Sbill if (passno == 1) 143632Shenry #ifdef FLEXNAMES 144632Shenry yyerror("%s redefined", 145632Shenry #else not FLEXNAMES 146632Shenry yyerror("%.*s redefined", 147632Shenry NCPS, 148632Shenry #endif not FLEXNAMES 149632Shenry np->s_name); 150597Sbill else 151632Shenry #ifdef FLEXNAMES 152632Shenry yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 153632Shenry #else not FLEXNAMES 154632Shenry yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 155632Shenry NCPS, 156632Shenry #endif not FLEXNAMES 157632Shenry np->s_name, 158632Shenry np->s_value, 159632Shenry dotp->e_xvalue); 160597Sbill } 161597Sbill } 162597Sbill } 163632Shenry np->s_type &= ~(XTYPE|XFORW); 164632Shenry np->s_type |= dotp->e_xtype; 165632Shenry np->s_value = dotp->e_xvalue; 166597Sbill if (passno == 1){ 167632Shenry np->s_index = dotp-usedot; 168632Shenry if (np->s_name[0] == 'L'){ 169597Sbill nlabels++; 170597Sbill } 171632Shenry np->s_tag = LABELID; 172597Sbill } 173597Sbill } /*end of this being a label*/ 174597Sbill } /*end of to consuming all labels, NLs and SEMIS */ 175597Sbill 176597Sbill xp = explist; 177597Sbill ap = arglist; 178597Sbill 179597Sbill /* 180597Sbill * process the INSTRUCTION body 181597Sbill */ 182597Sbill switch(val){ 183597Sbill 184597Sbill default: 185597Sbill ERROR("Unrecognized instruction or directive"); 186597Sbill 187597Sbill case IABORT: 188597Sbill shift; 189597Sbill sawabort(); 190597Sbill /*NOTREACHED*/ 191597Sbill break; 192597Sbill 193597Sbill case PARSEEOF: 194597Sbill tokptr -= sizeof(toktype); 195597Sbill *tokptr++ = VOID; 196597Sbill tokptr[1] = VOID; 197597Sbill tokptr[2] = PARSEEOF; 198597Sbill break; 199597Sbill 200597Sbill case IFILE: 201597Sbill shift; 202597Sbill stringp = (struct strdesc *)yylval; 203597Sbill shiftover(STRING); 204597Sbill dotsname = &UDotsname[0]; 205597Sbill movestr(dotsname, stringp->str, 206597Sbill stringp->str_lg >= 32? 32 :stringp->str_lg); 207597Sbill dotsname[stringp->str_lg] = '\0'; 208597Sbill break; 209597Sbill 210597Sbill case ILINENO: 211597Sbill shift; /*over the ILINENO*/ 212597Sbill expr(locxp, val); 213632Shenry lineno = locxp->e_xvalue; 214597Sbill break; 215597Sbill 216597Sbill case ISET: /* .set <name> , <expr> */ 217597Sbill shift; 218597Sbill np = (struct symtab *)yylval; 219597Sbill shiftover(NAME); 220597Sbill shiftover(CM); 221597Sbill expr(locxp, val); 222632Shenry np->s_type &= (XXTRN|XFORW); 223632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 224632Shenry np->s_value = locxp->e_xvalue; 225597Sbill if (passno==1) 226632Shenry np->s_index = locxp->e_xloc; 227632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 228597Sbill yyerror("Illegal set?"); 229597Sbill break; 230597Sbill 231597Sbill case ILSYM: /*.lsym name , expr */ 232597Sbill shift; 233597Sbill np = (struct symtab *)yylval; 234597Sbill shiftover(NAME); 235597Sbill shiftover(CM); 236597Sbill expr(locxp, val); 237597Sbill /* 238597Sbill * Build the unique occurance of the 239597Sbill * symbol. 240597Sbill * The character scanner will have 241597Sbill * already entered it into the symbol 242597Sbill * table, but we should remove it 243597Sbill */ 244597Sbill if (passno == 1){ 245597Sbill stpt = (struct symtab *)symalloc(); 246597Sbill #ifdef FLEXNAMES 247632Shenry stpt->s_name = np->s_name; 248597Sbill #else 249632Shenry movestr(stpt->s_name, np->s_name, NCPS); 250597Sbill #endif 251632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 252597Sbill nforgotten++; 253597Sbill np = stpt; 254632Shenry if (locxp->e_xtype != XABS) 255597Sbill ("Illegal lsym"); 256632Shenry np->s_value=locxp->e_xvalue; 257632Shenry np->s_type=XABS; 258632Shenry np->s_tag = ILSYM; 259597Sbill } 260597Sbill break; 261597Sbill 262597Sbill case IGLOBAL: /*.globl <name> */ 263597Sbill shift; 264597Sbill np = (struct symtab *)yylval; 265597Sbill shiftover(NAME); 266632Shenry np->s_type |= XXTRN; 267597Sbill break; 268597Sbill 269597Sbill case IDATA: /*.data [ <expr> ] */ 270597Sbill case ITEXT: /*.text [ <expr> ] */ 271597Sbill seg_type = -val; 272597Sbill shift; 273597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 274597Sbill expr(locxp, val); 275597Sbill seg_type = -seg_type; /*now, it is positive*/ 276597Sbill } 277597Sbill 278597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 279597Sbill seg_number = 0; 280597Sbill seg_type = -seg_type; 281597Sbill } else { 282632Shenry if (locxp->e_xtype != XABS || (seg_number=locxp->e_xvalue) >= NLOC) { 283597Sbill yyerror("illegal location counter"); 284597Sbill seg_number = 0; 285597Sbill } 286597Sbill } 287597Sbill if (seg_type == IDATA) 288597Sbill seg_number += NLOC; 289597Sbill flushfield(NBPW/4); 290597Sbill dotp = &usedot[seg_number]; 291597Sbill #ifdef UNIX 292597Sbill if (passno==2) { /* go salt away in pass 2*/ 293597Sbill txtfil = usefile[seg_number]; 294597Sbill relfil = rusefile[seg_number]; 295597Sbill } 296597Sbill #endif UNIX 297597Sbill #ifdef VMS 298597Sbill if (passno==2) { 299597Sbill puchar(vms_obj_ptr,6); /* setpl */ 300597Sbill puchar(vms_obj_ptr,seg_number); /* psect # */ 301632Shenry plong(vms_obj_ptr,dotp->e_xvalue);/* offset */ 302597Sbill puchar(vms_obj_ptr,80); /* setrb */ 303597Sbill if((vms_obj_ptr-sobuf) > 400){ 304597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 305597Sbill vms_obj_ptr=sobuf+1; /*flush buf*/ 306597Sbill } 307597Sbill } 308597Sbill #endif VMS 309597Sbill break; 310597Sbill 311597Sbill /* 312597Sbill * Storage filler directives: 313597Sbill * 314597Sbill * .byte [<exprlist>] 315597Sbill * 316597Sbill * exprlist: empty | exprlist outexpr 317597Sbill * outexpr: <expr> | <expr> : <expr> 318597Sbill */ 319597Sbill case IBYTE: curlen = NBPW/4; goto elist; 320597Sbill 321597Sbill case IINT: 322597Sbill case ILONG: curlen = NBPW; goto elist; 323597Sbill 324597Sbill case IWORD: 325597Sbill curlen = NBPW/2; 326597Sbill elist: 327597Sbill seg_type = val; 328597Sbill shift; 329597Sbill 330597Sbill /* 331597Sbill * Expression List processing 332597Sbill */ 333597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 334597Sbill do{ 335597Sbill /* 336597Sbill * expression list consists of a list of : 337597Sbill * <expr> 338597Sbill * <expr> : <expr> 339597Sbill * (pack expr2 into expr1 bits 340597Sbill */ 341597Sbill expr(locxp, val); 342597Sbill /* 343597Sbill * now, pointing at the next token 344597Sbill */ 345597Sbill if (val == COLON){ 346597Sbill shiftover(COLON); 347597Sbill expr(pval, val); 348632Shenry if (locxp->e_xtype != XABS) 349597Sbill yyerror("Width not absolute"); 350632Shenry field_width = locxp->e_xvalue; 351597Sbill locxp = pval; 352597Sbill if (bitoff + field_width > 353597Sbill curlen) 354597Sbill flushfield(curlen); 355597Sbill if (field_width > curlen) 356597Sbill yyerror("Expression crosses field boundary"); 357597Sbill } else { 358597Sbill field_width = curlen; 359597Sbill flushfield(curlen); 360597Sbill } 361597Sbill 362632Shenry if ((locxp->e_xtype&XTYPE)!=XABS) { 363597Sbill if (bitoff) 364597Sbill yyerror("Illegal relocation in field"); 365597Sbill field_width=LEN1; 366597Sbill if (curlen==NBPW) 367597Sbill field_width = LEN4; 368597Sbill if (curlen==NBPW/2) 369597Sbill field_width = LEN2; 370597Sbill if (passno == 1){ 371632Shenry dotp->e_xvalue += reflen[field_width]; 372597Sbill } else { 373632Shenry outrel(&locxp->e_xvalue, 374597Sbill field_width, 375632Shenry locxp->e_xtype, 376632Shenry locxp->e_xname); 377597Sbill } 378597Sbill } else { 379632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 380597Sbill bitfield |= field_value << bitoff; 381597Sbill bitoff += field_width; 382597Sbill } 383597Sbill if ( auxval = (val == CM)) shift; 384597Sbill xp = explist; 385597Sbill } while (auxval); 386597Sbill } /*existed an expression at all*/ 387597Sbill 388597Sbill flushfield(curlen); 389597Sbill if ( ( curlen == NBPW/4) && bitoff) 390632Shenry dotp->e_xvalue ++; 391597Sbill break; 392597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 393597Sbill 394597Sbill case ISPACE: /* .space <expr> */ 395597Sbill shift; 396597Sbill expr(locxp, val); 397632Shenry if (locxp->e_xtype != XABS) 398597Sbill yyerror("Space size not absolute"); 399632Shenry space_value = locxp->e_xvalue; 400597Sbill ospace: 401597Sbill flushfield(NBPW/4); 402597Sbill #ifdef UNIX 403597Sbill while (space_value > 96){ 404597Sbill outs(strbuf[2].str, 96); 405597Sbill space_value -= 96; 406597Sbill } 407597Sbill outs(strbuf[2].str, space_value); 408597Sbill #endif UNIX 409597Sbill #ifdef VMS 410632Shenry dotp->e_xvalue += space_value; /*bump pc*/ 411597Sbill if (passno==2){ 412597Sbill if(*(strbuf[2].str)==0) { 413597Sbill puchar(vms_obj_ptr,81); /* AUGR */ 414597Sbill pulong(vms_obj_ptr,space_value);/* incr */ 415597Sbill } else yyerror("VMS, encountered non-0 .space"); 416597Sbill if ((vms_obj_ptr-sobuf) > 400) { 417597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 418597Sbill vms_obj_ptr=sobuf+1; /*pur buf*/ 419597Sbill } 420597Sbill } 421597Sbill #endif VMS 422597Sbill break; 423597Sbill 424597Sbill #ifdef UNIX 425597Sbill case IFILL: /* .fill count, value */ 426597Sbill /* fill count bytes with value */ 427597Sbill shift; 428597Sbill expr(locxp, val); 429632Shenry if (locxp->e_xtype != XABS) 430597Sbill yyerror("Fill repetition count not absolute"); 431632Shenry space_value = locxp->e_xvalue; 432597Sbill shiftover(CM); 433597Sbill expr(locxp, val); 434632Shenry if (locxp->e_xtype != XABS) 435597Sbill yyerror("Fill value not absolute"); 436597Sbill flushfield(NBPW/4); 437597Sbill while(space_value-- > 0) 438632Shenry outb(locxp->e_xvalue & 0xFF); 439597Sbill break; 440597Sbill #endif UNIX 441597Sbill 442597Sbill case IASCII: /* .ascii [ <stringlist> ] */ 443597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 444597Sbill auxval = val; 445597Sbill shift; 446597Sbill 447597Sbill /* 448597Sbill * Code to consume a string list 449597Sbill * 450597Sbill * stringlist: empty | STRING | stringlist STRING 451597Sbill */ 452597Sbill while (val == STRING){ 453597Sbill flushfield(NBPW/4); 454597Sbill if (bitoff) 455632Shenry dotp->e_xvalue++; 456597Sbill stringp = (struct strdesc *)yylval; 457597Sbill #ifdef UNIX 458597Sbill outs(stringp->str, stringp->str_lg); 459597Sbill #endif UNIX 460597Sbill #ifdef VMS 461597Sbill { 462597Sbill register int i; 463597Sbill for (i=0; i < stringp->str_lg; i++){ 464632Shenry dotp->e_xvalue += 1; 465597Sbill if (passno==2){ 466597Sbill puchar(vms_obj_ptr,-1); 467597Sbill puchar(vms_obj_ptr,stringp->str[i]); 468597Sbill if (vms_obj_ptr-sobuf > 400) { 469597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 470597Sbill vms_obj_ptr = sobuf + 1; 471597Sbill } 472597Sbill } 473597Sbill } 474597Sbill } 475597Sbill #endif VMS 476597Sbill shift; /*over the STRING*/ 477597Sbill if (val == CM) /*could be a split string*/ 478597Sbill shift; 479597Sbill } 480597Sbill 481597Sbill if (auxval == IASCIZ){ 482597Sbill flushfield(NBPW/4); 483597Sbill #ifdef UNIX 484597Sbill outb(0); 485597Sbill #endif UNIX 486597Sbill #ifdef VMS 487597Sbill if (passno == 2) { 488597Sbill puchar(vms_obj_ptr,-1); 489597Sbill puchar(vms_obj_ptr,0); 490597Sbill } 491632Shenry dotp->e_xvalue += 1; 492597Sbill #endif VMS 493597Sbill } 494597Sbill break; 495597Sbill 496597Sbill case IORG: /* .org <expr> */ 497597Sbill shift; 498597Sbill expr(locxp, val); 499597Sbill 500632Shenry if (locxp->e_xtype==XABS) 501597Sbill orgwarn++; 502632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 503597Sbill yyerror("Illegal expression to set origin"); 504632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 505597Sbill if (space_value < 0) 506597Sbill yyerror("Backwards 'org'"); 507597Sbill goto ospace; 508597Sbill break; 509597Sbill 510597Sbill /* 511597Sbill * 512597Sbill * Process stabs. Stabs are created only by the f77 513597Sbill * and the C compiler with the -g flag set. 514597Sbill * We only look at the stab ONCE, during pass 1, and 515597Sbill * virtually remove the stab from the intermediate file 516597Sbill * so it isn't seen during pass2. This makes for some 517597Sbill * hairy processing to handle labels occuring in 518597Sbill * stab entries, but since most expressions in the 519597Sbill * stab are integral we save lots of time in the second 520597Sbill * pass by not looking at the stabs. 521597Sbill * A stab that is tagged floating will be bumped during 522597Sbill * the jxxx resolution phase. A stab tagged fixed will 523597Sbill * not be be bumped. 524597Sbill * 525597Sbill * .stab: Old fashioned stabs 526597Sbill * .stabn: For stabs without names 527597Sbill * .stabs: For stabs with string names 528597Sbill * .stabd: For stabs for line numbers or bracketing, 529597Sbill * without a string name, without 530597Sbill * a final expression. The value of the 531597Sbill * final expression is taken to be the current 532597Sbill * location counter, and is patched by the 2nd pass 533597Sbill * 534597Sbill * .stab{<expr>,}*8,<expr>, <expr>, <expr>, <expr> 535597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 536597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 537597Sbill * .stabd <expr>, <expr>, <expr> # . 538597Sbill */ 539597Sbill case ISTAB: 540597Sbill #ifndef FLEXNAMES 541597Sbill stabname = ".stab"; 542597Sbill if (passno == 2) goto errorfix; 543597Sbill stpt = (struct symtab *)yylval; 544597Sbill /* 545597Sbill * Make a pointer to the .stab slot. 546597Sbill * There is a pointer in the way (stpt), and 547597Sbill * tokptr points to the next token. 548597Sbill */ 549597Sbill stabstart = tokptr; 550597Sbill (char *)stabstart -= sizeof(struct symtab *); 551597Sbill (char *)stabstart -= sizeof(toktype); 552597Sbill shift; 553597Sbill for (argcnt = 0; argcnt < 8; argcnt++){ 554597Sbill expr(locxp, val); 555632Shenry stpt->s_name[argcnt] = locxp->e_xvalue; 556597Sbill xp = explist; 557597Sbill shiftover(CM); 558597Sbill } 559597Sbill goto tailstab; 560597Sbill #else FLEXNAMES 561597Sbill yyerror(".stab directive not supported in; report this compiler bug to system administrator"); 562597Sbill goto errorfix; 563597Sbill #endif FLEXNAMES 564597Sbill 565597Sbill tailstab: 566597Sbill expr(locxp, val); 567632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 568597Sbill yyerror("Invalid type in %s",stabname); 569597Sbill goto errorfix; 570597Sbill } 571632Shenry stpt->s_ptype = locxp->e_xvalue; 572597Sbill shiftover(CM); 573597Sbill expr(locxp, val); 574632Shenry stpt->s_other = locxp->e_xvalue; 575597Sbill shiftover(CM); 576597Sbill expr(locxp, val); 577632Shenry stpt->s_desc = locxp->e_xvalue; 578597Sbill shiftover(CM); 579597Sbill exprisname = 0; 580597Sbill expr(locxp, val); 581632Shenry p = locxp->e_xname; 582597Sbill if (p == NULL) { /*absolute expr to begin with*/ 583632Shenry stpt->s_value = locxp->e_xvalue; 584632Shenry stpt->s_index = dotp - usedot; 585597Sbill if (exprisname){ 586632Shenry switch(stpt->s_ptype){ 587597Sbill case N_GSYM: 588597Sbill case N_FNAME: 589597Sbill case N_RSYM: 590597Sbill case N_SSYM: 591597Sbill case N_LSYM: 592597Sbill case N_PSYM: 593597Sbill case N_BCOMM: 594597Sbill case N_ECOMM: 595597Sbill case N_LENG: 596632Shenry stpt->s_tag = STABFIXED; 597597Sbill break; 598597Sbill default: 599632Shenry stpt->s_tag = STABFLOATING; 600597Sbill break; 601597Sbill } 602597Sbill } else 603632Shenry stpt->s_tag = STABFIXED; 604597Sbill } 605597Sbill else { /*really have a name*/ 606632Shenry stpt->s_dest = locxp->e_xname; 607632Shenry stpt->s_index = p->s_index; 608632Shenry stpt->s_type = p->s_type | STABFLAG; 609597Sbill /* 610597Sbill * We will assign a more accruate 611597Sbill * guess of locxp's location when 612597Sbill * we sort the symbol table 613597Sbill * The final value of value is 614597Sbill * given by stabfix() 615597Sbill */ 616632Shenry stpt->s_tag = STABFLOATING; 617597Sbill } 618597Sbill /* 619597Sbill * tokptr now points at one token beyond 620597Sbill * the current token stored in val and yylval, 621597Sbill * which are the next tokens after the end of 622597Sbill * this .stab directive. This next token must 623597Sbill * be either a SEMI or NL, so is of width just 624597Sbill * one. Therefore, to point to the next token 625597Sbill * after the end of this stab, just back up one.. 626597Sbill */ 627597Sbill buildskip(stabstart, (char *)tokptr - sizeof(toktype)); 628597Sbill break; /*end of the .stab*/ 629597Sbill 630597Sbill case ISTABDOT: 631597Sbill stabname = ".stabd"; 632597Sbill stpt = (struct symtab *)yylval; 633597Sbill /* 634597Sbill * We clobber everything after the 635597Sbill * .stabd and its pointer... we MUST 636597Sbill * be able to get back to this .stabd 637597Sbill * so that we can resolve its final value 638597Sbill */ 639597Sbill stabstart = tokptr; 640597Sbill shift; /*over the ISTABDOT*/ 641597Sbill if (passno == 1){ 642597Sbill expr(locxp, val); 643632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 644597Sbill yyerror("Invalid type in .stabd"); 645597Sbill goto errorfix; 646597Sbill } 647632Shenry stpt->s_ptype = locxp->e_xvalue; 648597Sbill shiftover(CM); 649597Sbill expr(locxp, val); 650632Shenry stpt->s_other = locxp->e_xvalue; 651597Sbill shiftover(CM); 652597Sbill expr(locxp, val); 653632Shenry stpt->s_desc = locxp->e_xvalue; 654597Sbill /* 655597Sbill * 656597Sbill * Now, clobber everything but the 657597Sbill * .stabd pseudo and the pointer 658597Sbill * to its symbol table entry 659597Sbill * tokptr points to the next token, 660597Sbill * build the skip up to this 661597Sbill */ 662597Sbill buildskip(stabstart, (toktype *)tokptr - sizeof(toktype)); 663597Sbill } 664597Sbill /* 665597Sbill * pass 1: Assign a good guess for its position 666597Sbill * (ensures they are sorted into right place)/ 667597Sbill * pass 2: Fix the actual value 668597Sbill */ 669632Shenry stpt->s_value = dotp->e_xvalue; 670632Shenry stpt->s_index = dotp - usedot; 671632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 672597Sbill break; 673597Sbill 674597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 675597Sbill 676597Sbill case ISTABSTR: stabname = ".stabs"; 677597Sbill shortstab: 678597Sbill auxval = val; 679597Sbill if (passno == 2) goto errorfix; 680597Sbill stpt = (struct symtab *)yylval; 681597Sbill stabstart = tokptr; 682597Sbill (char *)stabstart -= sizeof(struct symtab *); 683597Sbill (char *)stabstart -= sizeof(toktype); 684597Sbill shift; 685597Sbill if (auxval == ISTABSTR){ 686597Sbill stringp = (struct strdesc *)yylval; 687597Sbill shiftover(STRING); 688597Sbill #ifndef FLEXNAMES 689597Sbill auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; 690597Sbill #else 691597Sbill stringp->str[stringp->str_lg] = 0; 692597Sbill #endif 693597Sbill shiftover(CM); 694597Sbill } else { 695597Sbill stringp = &(strbuf[2]); 696597Sbill #ifndef FLEXNAMES 697597Sbill auxval = NCPS; 698597Sbill #endif 699597Sbill } 700597Sbill #ifndef FLEXNAMES 701632Shenry movestr(stpt->s_name, stringp->str, auxval); 702597Sbill #else 703632Shenry stpt->s_name = savestr(stringp->str); 704597Sbill #endif 705597Sbill goto tailstab; 706597Sbill break; 707597Sbill 708597Sbill case ICOMM: /* .comm <name> , <expr> */ 709597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 710597Sbill auxval = val; 711597Sbill shift; 712597Sbill np = (struct symtab *)yylval; 713597Sbill shiftover(NAME); 714597Sbill shiftover(CM); 715597Sbill expr(locxp, val); 716597Sbill 717632Shenry if (locxp->e_xtype != XABS) 718597Sbill yyerror("comm size not absolute"); 719632Shenry if (passno==1 && (np->s_type&XTYPE)!=XUNDEF) 720632Shenry #ifdef FLEXNAMES 721632Shenry yyerror("Redefinition of %s", 722632Shenry #else not FLEXNAMES 723632Shenry yyerror("Redefinition of %.*s", 724632Shenry NCPS, 725632Shenry #endif not FLEXNAMES 726632Shenry np->s_name); 727597Sbill if (passno==1) { 728632Shenry np->s_value = locxp->e_xvalue; 729597Sbill if (auxval == ICOMM) 730632Shenry np->s_type |= XXTRN; 731597Sbill else { 732632Shenry np->s_type &= ~XTYPE; 733632Shenry np->s_type |= XBSS; 734597Sbill } 735597Sbill } 736597Sbill break; 737597Sbill 738597Sbill case IALIGN: /* .align <expr> */ 739597Sbill stpt = (struct symtab *)yylval; 740597Sbill shift; 741597Sbill expr(locxp, val); 742597Sbill jalign(locxp, stpt); 743597Sbill break; 744597Sbill 745597Sbill case INST0: /* instructions w/o arguments*/ 746597Sbill insout(yylval, (struct arg *)0, 0); 747597Sbill shift; 748597Sbill break; 749597Sbill 750597Sbill case INSTn: /* instructions with arguments*/ 751597Sbill case IJXXX: /* UNIX style jump instructions */ 752597Sbill auxval = val; 753597Sbill seg_type = yylval; 754597Sbill /* 755597Sbill * Code to process an argument list 756597Sbill */ 757597Sbill ap = arglist; 758597Sbill xp = explist; 759597Sbill 760597Sbill shift; /* bring in the first token for the arg list*/ 761597Sbill 762597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 763597Sbill /* 764597Sbill * code to process an argument proper 765597Sbill */ 766597Sbill sawindex = sawmul = sawsize = 0; 767597Sbill { 768597Sbill switch(val) { 769597Sbill 770597Sbill default: 771597Sbill disp: 772597Sbill if( !(INTOKSET(val, 773597Sbill EBEGOPS 774597Sbill +YUKKYEXPRBEG 775597Sbill +SAFEEXPRBEG)) ) { 776597Sbill ERROR("expression expected"); 777597Sbill } 778632Shenry expr(ap->a_xp,val); 779597Sbill overdisp: 780597Sbill if ( val == LP || sawsize){ 781597Sbill shiftover(LP); 782597Sbill findreg(regno); 783597Sbill shiftover(RP); 784632Shenry ap->a_atype = ADISP; 785632Shenry ap->a_areg1 = regno; 786597Sbill } else { 787632Shenry ap->a_atype = AEXP; 788632Shenry ap->a_areg1 = 0; 789597Sbill } 790597Sbill goto index; 791597Sbill 792597Sbill case SIZESPEC: 793597Sbill sizespec: 794597Sbill sawsize = yylval; 795597Sbill shift; 796597Sbill goto disp; 797597Sbill 798597Sbill case REG: 799597Sbill case REGOP: 800597Sbill findreg(regno); 801632Shenry ap->a_atype = AREG; 802632Shenry ap->a_areg1 = regno; 803597Sbill break; 804597Sbill 805597Sbill case MUL: 806597Sbill sawmul = 1; 807597Sbill shift; 808597Sbill if (val == LP) goto base; 809597Sbill if (val == LITOP) goto imm; 810597Sbill if (val == SIZESPEC) goto sizespec; 811597Sbill if (INTOKSET(val, 812597Sbill EBEGOPS 813597Sbill +YUKKYEXPRBEG 814597Sbill +SAFEEXPRBEG)) goto disp; 815597Sbill ERROR("expression, '(' or '$' expected"); 816597Sbill break; 817597Sbill 818597Sbill case LP: 819597Sbill base: 820597Sbill shift; /*consume the LP*/ 821597Sbill /* 822597Sbill * hack the ambiguity of 823597Sbill * movl (expr) (rn), ... 824597Sbill * note that (expr) could also 825597Sbill * be (rn) (by special hole in the 826597Sbill * grammar), which we ensure 827597Sbill * means register indirection, instead 828597Sbill * of an expression with value n 829597Sbill */ 830597Sbill if (val != REG && val != REGOP){ 831597Sbill droppedLP = 1; 832632Shenry val = exprparse(val, &(ap->a_xp)); 833597Sbill droppedLP = 0; 834597Sbill goto overdisp; 835597Sbill } 836597Sbill findreg(regno); 837597Sbill shiftover(RP); 838597Sbill if (val == PLUS){ 839597Sbill shift; 840632Shenry ap->a_atype = AINCR; 841597Sbill } else 842632Shenry ap->a_atype = ABASE; 843632Shenry ap->a_areg1 = regno; 844597Sbill goto index; 845597Sbill 846597Sbill case LITOP: 847597Sbill imm: 848597Sbill shift; 849597Sbill expr(locxp, val); 850632Shenry ap->a_atype = AIMM; 851632Shenry ap->a_areg1 = 0; 852632Shenry ap->a_xp = locxp; 853597Sbill goto index; 854597Sbill 855597Sbill case MP: 856597Sbill shift; /* -(reg) */ 857597Sbill findreg(regno); 858597Sbill shiftover(RP); 859632Shenry ap->a_atype = ADECR; 860632Shenry ap->a_areg1 = regno; 861597Sbill index: /*look for [reg] */ 862597Sbill if (val == LB){ 863597Sbill shift; 864597Sbill findreg(regno); 865597Sbill shiftover(RB); 866597Sbill sawindex = 1; 867632Shenry ap->a_areg2 = regno; 868597Sbill } 869597Sbill break; 870597Sbill 871597Sbill } /*end of the switch to process an arg*/ 872597Sbill } /*end of processing an argument*/ 873597Sbill 874597Sbill if (sawmul){ 875597Sbill /* 876597Sbill * Make a concession for *(%r) 877597Sbill * meaning *0(%r) 878597Sbill */ 879632Shenry if (ap->a_atype == ABASE) { 880632Shenry ap->a_atype = ADISP; 881632Shenry xp->e_xtype = XABS; 882632Shenry xp->e_xvalue = 0; 883632Shenry xp->e_xloc = 0; 884632Shenry ap->a_xp = xp++; 885597Sbill } 886632Shenry ap->a_atype |= ASTAR; 887597Sbill sawmul = 0; 888597Sbill } 889597Sbill if (sawindex){ 890632Shenry ap->a_atype |= AINDX; 891597Sbill sawindex = 0; 892597Sbill } 893632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 894597Sbill if (val != CM) break; 895597Sbill shiftover(CM); 896597Sbill } /*processing all the arguments*/ 897597Sbill 898597Sbill if (argcnt > 6){ 899597Sbill yyerror("More than 6 arguments"); 900597Sbill goto errorfix; 901597Sbill } 902597Sbill 903597Sbill insout(seg_type, arglist, 904597Sbill auxval == INSTn ? argcnt : - argcnt); 905597Sbill break; 906597Sbill 907597Sbill case IFLOAT: curlen = 4; goto floatlist; 908*645Shenry case IQUAD: 909597Sbill case IDOUBLE: 910597Sbill curlen = 8; 911597Sbill floatlist: 912597Sbill /* 913597Sbill * eat a list of floating point numbers 914597Sbill */ 915597Sbill shift; 916597Sbill if (val == FLTNUM){ 917597Sbill /* KLS MOD */ 918597Sbill float flocal; 919597Sbill do{ 920597Sbill if (val == CM) shift; 921597Sbill if (val != FLTNUM) { 922597Sbill ERROR("floating number expected"); 923597Sbill } 924632Shenry dotp->e_xvalue += curlen; 925597Sbill #ifdef UNIX 926597Sbill if (passno == 2) { 927597Sbill if(curlen == 8) 928597Sbill bwrite((char *)&(((union Double *)yylval)->dvalue), 929597Sbill curlen, txtfil); 930597Sbill else { 931597Sbill flocal = ((union Double *)yylval)->dvalue; 932597Sbill bwrite((char *)&flocal, curlen, txtfil); 933597Sbill } 934597Sbill } 935597Sbill #endif UNIX 936597Sbill 937597Sbill #ifdef VMS 938597Sbill if (passno == 2) { 939597Sbill puchar(vms_obj_ptr,-4); 940597Sbill pulong(vms_obj_ptr, 941597Sbill ((struct exp *)yylval) 942597Sbill ->doub_MSW); 943597Sbill if (curlen==8) { 944597Sbill puchar(vms_obj_ptr,-4); 945597Sbill pulong(vms_obj_ptr, 946597Sbill ((struct exp *)yylval) 947597Sbill ->doub_LSW); 948597Sbill } 949597Sbill if((vms_obj_ptr-sobuf) > 400) { 950597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 951597Sbill vms_obj_ptr = sobuf + 1; 952597Sbill } 953597Sbill } 954597Sbill #endif VMS 955597Sbill shift; 956597Sbill xp = explist; 957597Sbill } while (val == CM); 958597Sbill } 959597Sbill break; 960597Sbill } /*end of the switch for looking at each reserved word*/ 961597Sbill 962597Sbill continue; 963597Sbill 964597Sbill errorfix: 965597Sbill /* 966597Sbill * got here by either requesting to skip to the 967597Sbill * end of this statement, or by erroring out and 968597Sbill * wanting to apply panic mode recovery 969597Sbill */ 970597Sbill while ( (val != NL) 971597Sbill && (val != SEMI) 972597Sbill && (val != PARSEEOF) 973597Sbill ){ 974597Sbill shift; 975597Sbill } 976597Sbill if (val == NL) 977597Sbill lineno++; 978597Sbill shift; 979597Sbill 980597Sbill } /*end of the loop to read the entire file, line by line*/ 981597Sbill 982597Sbill } /*end of yyparse*/ 983597Sbill 984597Sbill /* 985597Sbill * Process a register declaration of the form 986597Sbill * % <expr> 987597Sbill * 988597Sbill * Note: 989597Sbill * The scanner has already processed funny registers of the form 990597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 991597Sbill * preceding zero digit). If there was any space between the % and 992597Sbill * the digit, the scanner wouldn't have recognized it, so we 993597Sbill * hack it out here. 994597Sbill */ 995597Sbill int funnyreg(val, regnoback) /*what the read head will sit on*/ 996597Sbill int val; /*what the read head is sitting on*/ 997597Sbill int *regnoback; /*call by return*/ 998597Sbill { 999597Sbill register struct exp *locxp; 1000597Sbill struct exp *loc1xp; 1001597Sbill struct exp **ptrloc1xp = & loc1xp; 1002597Sbill 1003597Sbill expr(locxp, val); /*and leave the current read head with value*/ 1004597Sbill if ( (passno == 2) && 1005632Shenry ( locxp->e_xtype & XTYPE != XABS 1006632Shenry || locxp->e_xvalue < 0 1007632Shenry || locxp->e_xvalue >= 16 1008597Sbill ) 1009597Sbill ){ 1010597Sbill yyerror("Illegal register"); 1011597Sbill return(0); 1012597Sbill } 1013632Shenry *regnoback = locxp->e_xvalue; 1014597Sbill return(val); 1015597Sbill } 1016597Sbill 1017597Sbill /*VARARGS1*/ 1018597Sbill yyerror(s, a1, a2,a3,a4,a5) 1019597Sbill char *s; 1020597Sbill { 1021597Sbill FILE *sink; 1022597Sbill 1023597Sbill #ifdef DEBUG 1024597Sbill sink = stdout; 1025597Sbill #else not DEBUG 1026597Sbill sink = stderr; 1027597Sbill #endif DEBUG 1028597Sbill 1029597Sbill if (anyerrs == 0 && ! silent) 1030597Sbill fprintf(sink, "Assembler:\n"); 1031597Sbill anyerrs++; 1032597Sbill if (silent) return; 1033597Sbill 1034597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1035597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1036597Sbill fprintf(sink, "\n"); 1037597Sbill } 1038