1597Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*674Shenry static char sccsid[] = "@(#)asparse.c 4.6 08/20/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*/ 74647Shenry int fill_rep; /*how many reps for .fill */ 75647Shenry int fill_size; /*how many bytes for .fill */ 76597Sbill 77597Sbill int field_width; /*how wide a field is to be*/ 78597Sbill int field_value; /*the value to stuff in a field*/ 79597Sbill char *stabname; /*name of stab dealing with*/ 80597Sbill ptrall stabstart; /*where the stab starts in the buffer*/ 81*674Shenry int reloc_how; /* how to relocate expressions */ 82597Sbill 83597Sbill xp = explist; 84597Sbill ap = arglist; 85597Sbill 86597Sbill val = yylex(); 87597Sbill 88597Sbill while (val != PARSEEOF){ /* primary loop */ 89597Sbill 90597Sbill while (INTOKSET(val, LINSTBEGIN)){ 91597Sbill if (val == INT) { 92632Shenry int i = ((struct exp *)yylval)->e_xvalue; 93597Sbill shift; 94597Sbill if (val != COLON) 95597Sbill goto nocolon; 96597Sbill if (i < 0 || i > 9) { 97597Sbill yyerror("Local labels are 0-9"); 98597Sbill goto errorfix; 99597Sbill } 100597Sbill sprintf(yytext, "L%d\001%d", i, lgensym[i]); 101597Sbill lgensym[i]++; 102597Sbill genref[i] = 0; 103597Sbill yylval = (int)*lookup(passno == 1); 104597Sbill val = NAME; 105597Sbill np = (struct symtab *)yylval; 106597Sbill goto restlab; 107597Sbill } 108597Sbill if (val == NL){ 109597Sbill lineno++; 110597Sbill shift; 111597Sbill } else 112597Sbill if (val == SEMI) 113597Sbill shift; 114597Sbill else { /*its a name, so we have a label or def */ 115597Sbill if (val != NAME){ 116597Sbill ERROR("Name expected for a label"); 117597Sbill } 118597Sbill np = (struct symtab *)yylval; 119597Sbill shiftover(NAME); 120597Sbill nocolon: 121597Sbill if (val != COLON) { 122632Shenry #ifdef FLEXNAMES 123597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition", 124632Shenry #else not FLEXNAMES 125632Shenry yyerror("\"%.*s\" is not followed by a ':' for a label definition", 126632Shenry NCPS, 127632Shenry #endif not FLEXNAMES 128632Shenry np->s_name); 129597Sbill goto errorfix; 130597Sbill } 131597Sbill restlab: 132597Sbill shift; 133597Sbill flushfield(NBPW/4); 134632Shenry if ((np->s_type&XTYPE)!=XUNDEF) { 135632Shenry if( (np->s_type&XTYPE)!=dotp->e_xtype 136632Shenry || np->s_value!=dotp->e_xvalue 137597Sbill || ( (passno==1) 138632Shenry &&(np->s_index != dotp->e_xloc) 139597Sbill ) 140597Sbill ){ 141597Sbill #ifndef DEBUG 142632Shenry if (np->s_name[0] != 'L') 143597Sbill #endif not DEBUG 144597Sbill { 145597Sbill if (passno == 1) 146632Shenry #ifdef FLEXNAMES 147632Shenry yyerror("%s redefined", 148632Shenry #else not FLEXNAMES 149632Shenry yyerror("%.*s redefined", 150632Shenry NCPS, 151632Shenry #endif not FLEXNAMES 152632Shenry np->s_name); 153597Sbill else 154632Shenry #ifdef FLEXNAMES 155632Shenry yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 156632Shenry #else not FLEXNAMES 157632Shenry yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 158632Shenry NCPS, 159632Shenry #endif not FLEXNAMES 160632Shenry np->s_name, 161632Shenry np->s_value, 162632Shenry dotp->e_xvalue); 163597Sbill } 164597Sbill } 165597Sbill } 166632Shenry np->s_type &= ~(XTYPE|XFORW); 167632Shenry np->s_type |= dotp->e_xtype; 168632Shenry np->s_value = dotp->e_xvalue; 169597Sbill if (passno == 1){ 170632Shenry np->s_index = dotp-usedot; 171632Shenry if (np->s_name[0] == 'L'){ 172597Sbill nlabels++; 173597Sbill } 174632Shenry np->s_tag = LABELID; 175597Sbill } 176597Sbill } /*end of this being a label*/ 177597Sbill } /*end of to consuming all labels, NLs and SEMIS */ 178597Sbill 179597Sbill xp = explist; 180597Sbill ap = arglist; 181597Sbill 182597Sbill /* 183597Sbill * process the INSTRUCTION body 184597Sbill */ 185597Sbill switch(val){ 186597Sbill 187597Sbill default: 188597Sbill ERROR("Unrecognized instruction or directive"); 189597Sbill 190597Sbill case IABORT: 191597Sbill shift; 192597Sbill sawabort(); 193597Sbill /*NOTREACHED*/ 194597Sbill break; 195597Sbill 196597Sbill case PARSEEOF: 197597Sbill tokptr -= sizeof(toktype); 198597Sbill *tokptr++ = VOID; 199597Sbill tokptr[1] = VOID; 200597Sbill tokptr[2] = PARSEEOF; 201597Sbill break; 202597Sbill 203597Sbill case IFILE: 204597Sbill shift; 205597Sbill stringp = (struct strdesc *)yylval; 206597Sbill shiftover(STRING); 207597Sbill dotsname = &UDotsname[0]; 208597Sbill movestr(dotsname, stringp->str, 209597Sbill stringp->str_lg >= 32? 32 :stringp->str_lg); 210597Sbill dotsname[stringp->str_lg] = '\0'; 211597Sbill break; 212597Sbill 213597Sbill case ILINENO: 214597Sbill shift; /*over the ILINENO*/ 215597Sbill expr(locxp, val); 216632Shenry lineno = locxp->e_xvalue; 217597Sbill break; 218597Sbill 219597Sbill case ISET: /* .set <name> , <expr> */ 220597Sbill shift; 221597Sbill np = (struct symtab *)yylval; 222597Sbill shiftover(NAME); 223597Sbill shiftover(CM); 224597Sbill expr(locxp, val); 225632Shenry np->s_type &= (XXTRN|XFORW); 226632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 227632Shenry np->s_value = locxp->e_xvalue; 228597Sbill if (passno==1) 229632Shenry np->s_index = locxp->e_xloc; 230632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 231597Sbill yyerror("Illegal set?"); 232597Sbill break; 233597Sbill 234597Sbill case ILSYM: /*.lsym name , expr */ 235597Sbill shift; 236597Sbill np = (struct symtab *)yylval; 237597Sbill shiftover(NAME); 238597Sbill shiftover(CM); 239597Sbill expr(locxp, val); 240597Sbill /* 241597Sbill * Build the unique occurance of the 242597Sbill * symbol. 243597Sbill * The character scanner will have 244597Sbill * already entered it into the symbol 245597Sbill * table, but we should remove it 246597Sbill */ 247597Sbill if (passno == 1){ 248597Sbill stpt = (struct symtab *)symalloc(); 249597Sbill #ifdef FLEXNAMES 250632Shenry stpt->s_name = np->s_name; 251597Sbill #else 252632Shenry movestr(stpt->s_name, np->s_name, NCPS); 253597Sbill #endif 254632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 255597Sbill nforgotten++; 256597Sbill np = stpt; 257632Shenry if (locxp->e_xtype != XABS) 258597Sbill ("Illegal lsym"); 259632Shenry np->s_value=locxp->e_xvalue; 260632Shenry np->s_type=XABS; 261632Shenry np->s_tag = ILSYM; 262597Sbill } 263597Sbill break; 264597Sbill 265597Sbill case IGLOBAL: /*.globl <name> */ 266597Sbill shift; 267597Sbill np = (struct symtab *)yylval; 268597Sbill shiftover(NAME); 269632Shenry np->s_type |= XXTRN; 270597Sbill break; 271597Sbill 272597Sbill case IDATA: /*.data [ <expr> ] */ 273597Sbill case ITEXT: /*.text [ <expr> ] */ 274597Sbill seg_type = -val; 275597Sbill shift; 276597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 277597Sbill expr(locxp, val); 278597Sbill seg_type = -seg_type; /*now, it is positive*/ 279597Sbill } 280597Sbill 281597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 282597Sbill seg_number = 0; 283597Sbill seg_type = -seg_type; 284597Sbill } else { 285632Shenry if (locxp->e_xtype != XABS || (seg_number=locxp->e_xvalue) >= NLOC) { 286597Sbill yyerror("illegal location counter"); 287597Sbill seg_number = 0; 288597Sbill } 289597Sbill } 290597Sbill if (seg_type == IDATA) 291597Sbill seg_number += NLOC; 292597Sbill flushfield(NBPW/4); 293597Sbill dotp = &usedot[seg_number]; 294597Sbill #ifdef UNIX 295597Sbill if (passno==2) { /* go salt away in pass 2*/ 296597Sbill txtfil = usefile[seg_number]; 297597Sbill relfil = rusefile[seg_number]; 298597Sbill } 299597Sbill #endif UNIX 300597Sbill #ifdef VMS 301597Sbill if (passno==2) { 302597Sbill puchar(vms_obj_ptr,6); /* setpl */ 303597Sbill puchar(vms_obj_ptr,seg_number); /* psect # */ 304632Shenry plong(vms_obj_ptr,dotp->e_xvalue);/* offset */ 305597Sbill puchar(vms_obj_ptr,80); /* setrb */ 306597Sbill if((vms_obj_ptr-sobuf) > 400){ 307597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 308597Sbill vms_obj_ptr=sobuf+1; /*flush buf*/ 309597Sbill } 310597Sbill } 311597Sbill #endif VMS 312597Sbill break; 313597Sbill 314597Sbill /* 315597Sbill * Storage filler directives: 316597Sbill * 317597Sbill * .byte [<exprlist>] 318597Sbill * 319597Sbill * exprlist: empty | exprlist outexpr 320597Sbill * outexpr: <expr> | <expr> : <expr> 321597Sbill */ 322597Sbill case IBYTE: curlen = NBPW/4; goto elist; 323597Sbill 324597Sbill case IINT: 325597Sbill case ILONG: curlen = NBPW; goto elist; 326597Sbill 327597Sbill case IWORD: 328597Sbill curlen = NBPW/2; 329597Sbill elist: 330597Sbill seg_type = val; 331597Sbill shift; 332597Sbill 333597Sbill /* 334597Sbill * Expression List processing 335597Sbill */ 336597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 337597Sbill do{ 338597Sbill /* 339597Sbill * expression list consists of a list of : 340597Sbill * <expr> 341597Sbill * <expr> : <expr> 342597Sbill * (pack expr2 into expr1 bits 343597Sbill */ 344597Sbill expr(locxp, val); 345597Sbill /* 346597Sbill * now, pointing at the next token 347597Sbill */ 348597Sbill if (val == COLON){ 349597Sbill shiftover(COLON); 350597Sbill expr(pval, val); 351632Shenry if (locxp->e_xtype != XABS) 352597Sbill yyerror("Width not absolute"); 353632Shenry field_width = locxp->e_xvalue; 354597Sbill locxp = pval; 355597Sbill if (bitoff + field_width > 356597Sbill curlen) 357597Sbill flushfield(curlen); 358597Sbill if (field_width > curlen) 359597Sbill yyerror("Expression crosses field boundary"); 360597Sbill } else { 361597Sbill field_width = curlen; 362597Sbill flushfield(curlen); 363597Sbill } 364597Sbill 365632Shenry if ((locxp->e_xtype&XTYPE)!=XABS) { 366597Sbill if (bitoff) 367597Sbill yyerror("Illegal relocation in field"); 368*674Shenry switch(curlen){ 369*674Shenry case NBPW/4: reloc_how = TYPB; break; 370*674Shenry case NBPW/2: reloc_how = TYPW; break; 371*674Shenry case NBPW: reloc_how = TYPL; break; 372*674Shenry } 373597Sbill if (passno == 1){ 374*674Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 375597Sbill } else { 376*674Shenry outrel(locxp, reloc_how); 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 425647Shenry /* 426647Shenry * .fill rep, size, value 427647Shenry * repeat rep times: fill size bytes with (truncated) value 428647Shenry * size must be between 1 and 8 429647Shenry */ 430647Shenry case IFILL: 431597Sbill shift; 432597Sbill expr(locxp, val); 433632Shenry if (locxp->e_xtype != XABS) 434597Sbill yyerror("Fill repetition count not absolute"); 435647Shenry fill_rep = locxp->e_xvalue; 436597Sbill shiftover(CM); 437597Sbill expr(locxp, val); 438632Shenry if (locxp->e_xtype != XABS) 439647Shenry yyerror("Fill size not absolute"); 440647Shenry fill_size = locxp->e_xvalue; 441647Shenry if (fill_size <= 0 || fill_size > 8) 442647Shenry yyerror("Fill count not in in 1..8"); 443647Shenry shiftover(CM); 444647Shenry expr(locxp, val); 445647Shenry if (passno == 2 && locxp->e_xtype != XABS) 446647Shenry yyerror("Fill value not absolute"); 447597Sbill flushfield(NBPW/4); 448647Shenry if (passno == 1) { 449647Shenry locxp->e_xvalue += fill_rep * fill_size; 450647Shenry } else { 451647Shenry while(fill_rep-- > 0) 452647Shenry bwrite(&locxp->e_xvalue, fill_size, txtfil); 453647Shenry } 454597Sbill break; 455597Sbill #endif UNIX 456597Sbill 457597Sbill case IASCII: /* .ascii [ <stringlist> ] */ 458597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 459597Sbill auxval = val; 460597Sbill shift; 461597Sbill 462597Sbill /* 463597Sbill * Code to consume a string list 464597Sbill * 465597Sbill * stringlist: empty | STRING | stringlist STRING 466597Sbill */ 467597Sbill while (val == STRING){ 468597Sbill flushfield(NBPW/4); 469597Sbill if (bitoff) 470632Shenry dotp->e_xvalue++; 471597Sbill stringp = (struct strdesc *)yylval; 472597Sbill #ifdef UNIX 473597Sbill outs(stringp->str, stringp->str_lg); 474597Sbill #endif UNIX 475597Sbill #ifdef VMS 476597Sbill { 477597Sbill register int i; 478597Sbill for (i=0; i < stringp->str_lg; i++){ 479632Shenry dotp->e_xvalue += 1; 480597Sbill if (passno==2){ 481597Sbill puchar(vms_obj_ptr,-1); 482597Sbill puchar(vms_obj_ptr,stringp->str[i]); 483597Sbill if (vms_obj_ptr-sobuf > 400) { 484597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 485597Sbill vms_obj_ptr = sobuf + 1; 486597Sbill } 487597Sbill } 488597Sbill } 489597Sbill } 490597Sbill #endif VMS 491597Sbill shift; /*over the STRING*/ 492597Sbill if (val == CM) /*could be a split string*/ 493597Sbill shift; 494597Sbill } 495597Sbill 496597Sbill if (auxval == IASCIZ){ 497597Sbill flushfield(NBPW/4); 498597Sbill #ifdef UNIX 499597Sbill outb(0); 500597Sbill #endif UNIX 501597Sbill #ifdef VMS 502597Sbill if (passno == 2) { 503597Sbill puchar(vms_obj_ptr,-1); 504597Sbill puchar(vms_obj_ptr,0); 505597Sbill } 506632Shenry dotp->e_xvalue += 1; 507597Sbill #endif VMS 508597Sbill } 509597Sbill break; 510597Sbill 511597Sbill case IORG: /* .org <expr> */ 512597Sbill shift; 513597Sbill expr(locxp, val); 514597Sbill 515632Shenry if (locxp->e_xtype==XABS) 516597Sbill orgwarn++; 517632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 518597Sbill yyerror("Illegal expression to set origin"); 519632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 520597Sbill if (space_value < 0) 521597Sbill yyerror("Backwards 'org'"); 522597Sbill goto ospace; 523597Sbill break; 524597Sbill 525597Sbill /* 526597Sbill * 527597Sbill * Process stabs. Stabs are created only by the f77 528597Sbill * and the C compiler with the -g flag set. 529597Sbill * We only look at the stab ONCE, during pass 1, and 530597Sbill * virtually remove the stab from the intermediate file 531597Sbill * so it isn't seen during pass2. This makes for some 532597Sbill * hairy processing to handle labels occuring in 533597Sbill * stab entries, but since most expressions in the 534597Sbill * stab are integral we save lots of time in the second 535597Sbill * pass by not looking at the stabs. 536597Sbill * A stab that is tagged floating will be bumped during 537597Sbill * the jxxx resolution phase. A stab tagged fixed will 538597Sbill * not be be bumped. 539597Sbill * 540597Sbill * .stab: Old fashioned stabs 541597Sbill * .stabn: For stabs without names 542597Sbill * .stabs: For stabs with string names 543597Sbill * .stabd: For stabs for line numbers or bracketing, 544597Sbill * without a string name, without 545597Sbill * a final expression. The value of the 546597Sbill * final expression is taken to be the current 547597Sbill * location counter, and is patched by the 2nd pass 548597Sbill * 549*674Shenry * .stab{<expr>,}*NCPS,<expr>, <expr>, <expr>, <expr> 550597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 551597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 552597Sbill * .stabd <expr>, <expr>, <expr> # . 553597Sbill */ 554597Sbill case ISTAB: 555597Sbill #ifndef FLEXNAMES 556597Sbill stabname = ".stab"; 557597Sbill if (passno == 2) goto errorfix; 558597Sbill stpt = (struct symtab *)yylval; 559597Sbill /* 560597Sbill * Make a pointer to the .stab slot. 561597Sbill * There is a pointer in the way (stpt), and 562597Sbill * tokptr points to the next token. 563597Sbill */ 564597Sbill stabstart = tokptr; 565597Sbill (char *)stabstart -= sizeof(struct symtab *); 566597Sbill (char *)stabstart -= sizeof(toktype); 567597Sbill shift; 568*674Shenry for (argcnt = 0; argcnt < NCPS; argcnt++){ 569597Sbill expr(locxp, val); 570632Shenry stpt->s_name[argcnt] = locxp->e_xvalue; 571597Sbill xp = explist; 572597Sbill shiftover(CM); 573597Sbill } 574597Sbill goto tailstab; 575597Sbill #else FLEXNAMES 576597Sbill yyerror(".stab directive not supported in; report this compiler bug to system administrator"); 577597Sbill goto errorfix; 578597Sbill #endif FLEXNAMES 579597Sbill 580597Sbill tailstab: 581597Sbill expr(locxp, val); 582632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 583597Sbill yyerror("Invalid type in %s",stabname); 584597Sbill goto errorfix; 585597Sbill } 586632Shenry stpt->s_ptype = locxp->e_xvalue; 587597Sbill shiftover(CM); 588597Sbill expr(locxp, val); 589632Shenry stpt->s_other = locxp->e_xvalue; 590597Sbill shiftover(CM); 591597Sbill expr(locxp, val); 592632Shenry stpt->s_desc = locxp->e_xvalue; 593597Sbill shiftover(CM); 594597Sbill exprisname = 0; 595597Sbill expr(locxp, val); 596632Shenry p = locxp->e_xname; 597597Sbill if (p == NULL) { /*absolute expr to begin with*/ 598632Shenry stpt->s_value = locxp->e_xvalue; 599632Shenry stpt->s_index = dotp - usedot; 600597Sbill if (exprisname){ 601632Shenry switch(stpt->s_ptype){ 602597Sbill case N_GSYM: 603597Sbill case N_FNAME: 604597Sbill case N_RSYM: 605597Sbill case N_SSYM: 606597Sbill case N_LSYM: 607597Sbill case N_PSYM: 608597Sbill case N_BCOMM: 609597Sbill case N_ECOMM: 610597Sbill case N_LENG: 611632Shenry stpt->s_tag = STABFIXED; 612597Sbill break; 613597Sbill default: 614632Shenry stpt->s_tag = STABFLOATING; 615597Sbill break; 616597Sbill } 617597Sbill } else 618632Shenry stpt->s_tag = STABFIXED; 619597Sbill } 620597Sbill else { /*really have a name*/ 621632Shenry stpt->s_dest = locxp->e_xname; 622632Shenry stpt->s_index = p->s_index; 623632Shenry stpt->s_type = p->s_type | STABFLAG; 624597Sbill /* 625597Sbill * We will assign a more accruate 626597Sbill * guess of locxp's location when 627597Sbill * we sort the symbol table 628597Sbill * The final value of value is 629597Sbill * given by stabfix() 630597Sbill */ 631632Shenry stpt->s_tag = STABFLOATING; 632597Sbill } 633597Sbill /* 634597Sbill * tokptr now points at one token beyond 635597Sbill * the current token stored in val and yylval, 636597Sbill * which are the next tokens after the end of 637597Sbill * this .stab directive. This next token must 638597Sbill * be either a SEMI or NL, so is of width just 639597Sbill * one. Therefore, to point to the next token 640597Sbill * after the end of this stab, just back up one.. 641597Sbill */ 642597Sbill buildskip(stabstart, (char *)tokptr - sizeof(toktype)); 643597Sbill break; /*end of the .stab*/ 644597Sbill 645597Sbill case ISTABDOT: 646597Sbill stabname = ".stabd"; 647597Sbill stpt = (struct symtab *)yylval; 648597Sbill /* 649597Sbill * We clobber everything after the 650597Sbill * .stabd and its pointer... we MUST 651597Sbill * be able to get back to this .stabd 652597Sbill * so that we can resolve its final value 653597Sbill */ 654597Sbill stabstart = tokptr; 655597Sbill shift; /*over the ISTABDOT*/ 656597Sbill if (passno == 1){ 657597Sbill expr(locxp, val); 658632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 659597Sbill yyerror("Invalid type in .stabd"); 660597Sbill goto errorfix; 661597Sbill } 662632Shenry stpt->s_ptype = locxp->e_xvalue; 663597Sbill shiftover(CM); 664597Sbill expr(locxp, val); 665632Shenry stpt->s_other = locxp->e_xvalue; 666597Sbill shiftover(CM); 667597Sbill expr(locxp, val); 668632Shenry stpt->s_desc = locxp->e_xvalue; 669597Sbill /* 670597Sbill * 671597Sbill * Now, clobber everything but the 672597Sbill * .stabd pseudo and the pointer 673597Sbill * to its symbol table entry 674597Sbill * tokptr points to the next token, 675597Sbill * build the skip up to this 676597Sbill */ 677597Sbill buildskip(stabstart, (toktype *)tokptr - sizeof(toktype)); 678597Sbill } 679597Sbill /* 680597Sbill * pass 1: Assign a good guess for its position 681597Sbill * (ensures they are sorted into right place)/ 682597Sbill * pass 2: Fix the actual value 683597Sbill */ 684632Shenry stpt->s_value = dotp->e_xvalue; 685632Shenry stpt->s_index = dotp - usedot; 686632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 687597Sbill break; 688597Sbill 689597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 690597Sbill 691597Sbill case ISTABSTR: stabname = ".stabs"; 692597Sbill shortstab: 693597Sbill auxval = val; 694597Sbill if (passno == 2) goto errorfix; 695597Sbill stpt = (struct symtab *)yylval; 696597Sbill stabstart = tokptr; 697597Sbill (char *)stabstart -= sizeof(struct symtab *); 698597Sbill (char *)stabstart -= sizeof(toktype); 699597Sbill shift; 700597Sbill if (auxval == ISTABSTR){ 701597Sbill stringp = (struct strdesc *)yylval; 702597Sbill shiftover(STRING); 703597Sbill #ifndef FLEXNAMES 704597Sbill auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; 705597Sbill #else 706597Sbill stringp->str[stringp->str_lg] = 0; 707597Sbill #endif 708597Sbill shiftover(CM); 709597Sbill } else { 710597Sbill stringp = &(strbuf[2]); 711597Sbill #ifndef FLEXNAMES 712597Sbill auxval = NCPS; 713597Sbill #endif 714597Sbill } 715597Sbill #ifndef FLEXNAMES 716632Shenry movestr(stpt->s_name, stringp->str, auxval); 717597Sbill #else 718632Shenry stpt->s_name = savestr(stringp->str); 719597Sbill #endif 720597Sbill goto tailstab; 721597Sbill break; 722597Sbill 723597Sbill case ICOMM: /* .comm <name> , <expr> */ 724597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 725597Sbill auxval = val; 726597Sbill shift; 727597Sbill np = (struct symtab *)yylval; 728597Sbill shiftover(NAME); 729597Sbill shiftover(CM); 730597Sbill expr(locxp, val); 731597Sbill 732632Shenry if (locxp->e_xtype != XABS) 733597Sbill yyerror("comm size not absolute"); 734632Shenry if (passno==1 && (np->s_type&XTYPE)!=XUNDEF) 735632Shenry #ifdef FLEXNAMES 736632Shenry yyerror("Redefinition of %s", 737632Shenry #else not FLEXNAMES 738632Shenry yyerror("Redefinition of %.*s", 739632Shenry NCPS, 740632Shenry #endif not FLEXNAMES 741632Shenry np->s_name); 742597Sbill if (passno==1) { 743632Shenry np->s_value = locxp->e_xvalue; 744597Sbill if (auxval == ICOMM) 745632Shenry np->s_type |= XXTRN; 746597Sbill else { 747632Shenry np->s_type &= ~XTYPE; 748632Shenry np->s_type |= XBSS; 749597Sbill } 750597Sbill } 751597Sbill break; 752597Sbill 753597Sbill case IALIGN: /* .align <expr> */ 754597Sbill stpt = (struct symtab *)yylval; 755597Sbill shift; 756597Sbill expr(locxp, val); 757597Sbill jalign(locxp, stpt); 758597Sbill break; 759597Sbill 760597Sbill case INST0: /* instructions w/o arguments*/ 761597Sbill insout(yylval, (struct arg *)0, 0); 762597Sbill shift; 763597Sbill break; 764597Sbill 765597Sbill case INSTn: /* instructions with arguments*/ 766597Sbill case IJXXX: /* UNIX style jump instructions */ 767597Sbill auxval = val; 768597Sbill seg_type = yylval; 769597Sbill /* 770597Sbill * Code to process an argument list 771597Sbill */ 772597Sbill ap = arglist; 773597Sbill xp = explist; 774597Sbill 775597Sbill shift; /* bring in the first token for the arg list*/ 776597Sbill 777597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 778597Sbill /* 779597Sbill * code to process an argument proper 780597Sbill */ 781597Sbill sawindex = sawmul = sawsize = 0; 782597Sbill { 783597Sbill switch(val) { 784597Sbill 785597Sbill default: 786597Sbill disp: 787597Sbill if( !(INTOKSET(val, 788597Sbill EBEGOPS 789597Sbill +YUKKYEXPRBEG 790597Sbill +SAFEEXPRBEG)) ) { 791597Sbill ERROR("expression expected"); 792597Sbill } 793632Shenry expr(ap->a_xp,val); 794597Sbill overdisp: 795597Sbill if ( val == LP || sawsize){ 796597Sbill shiftover(LP); 797597Sbill findreg(regno); 798597Sbill shiftover(RP); 799632Shenry ap->a_atype = ADISP; 800632Shenry ap->a_areg1 = regno; 801597Sbill } else { 802632Shenry ap->a_atype = AEXP; 803632Shenry ap->a_areg1 = 0; 804597Sbill } 805597Sbill goto index; 806597Sbill 807597Sbill case SIZESPEC: 808597Sbill sizespec: 809597Sbill sawsize = yylval; 810597Sbill shift; 811597Sbill goto disp; 812597Sbill 813597Sbill case REG: 814597Sbill case REGOP: 815597Sbill findreg(regno); 816632Shenry ap->a_atype = AREG; 817632Shenry ap->a_areg1 = regno; 818597Sbill break; 819597Sbill 820597Sbill case MUL: 821597Sbill sawmul = 1; 822597Sbill shift; 823597Sbill if (val == LP) goto base; 824597Sbill if (val == LITOP) goto imm; 825597Sbill if (val == SIZESPEC) goto sizespec; 826597Sbill if (INTOKSET(val, 827597Sbill EBEGOPS 828597Sbill +YUKKYEXPRBEG 829597Sbill +SAFEEXPRBEG)) goto disp; 830597Sbill ERROR("expression, '(' or '$' expected"); 831597Sbill break; 832597Sbill 833597Sbill case LP: 834597Sbill base: 835597Sbill shift; /*consume the LP*/ 836597Sbill /* 837597Sbill * hack the ambiguity of 838597Sbill * movl (expr) (rn), ... 839597Sbill * note that (expr) could also 840597Sbill * be (rn) (by special hole in the 841597Sbill * grammar), which we ensure 842597Sbill * means register indirection, instead 843597Sbill * of an expression with value n 844597Sbill */ 845597Sbill if (val != REG && val != REGOP){ 846597Sbill droppedLP = 1; 847632Shenry val = exprparse(val, &(ap->a_xp)); 848597Sbill droppedLP = 0; 849597Sbill goto overdisp; 850597Sbill } 851597Sbill findreg(regno); 852597Sbill shiftover(RP); 853597Sbill if (val == PLUS){ 854597Sbill shift; 855632Shenry ap->a_atype = AINCR; 856597Sbill } else 857632Shenry ap->a_atype = ABASE; 858632Shenry ap->a_areg1 = regno; 859597Sbill goto index; 860597Sbill 861597Sbill case LITOP: 862597Sbill imm: 863597Sbill shift; 864597Sbill expr(locxp, val); 865632Shenry ap->a_atype = AIMM; 866632Shenry ap->a_areg1 = 0; 867632Shenry ap->a_xp = locxp; 868597Sbill goto index; 869597Sbill 870597Sbill case MP: 871597Sbill shift; /* -(reg) */ 872597Sbill findreg(regno); 873597Sbill shiftover(RP); 874632Shenry ap->a_atype = ADECR; 875632Shenry ap->a_areg1 = regno; 876597Sbill index: /*look for [reg] */ 877597Sbill if (val == LB){ 878597Sbill shift; 879597Sbill findreg(regno); 880597Sbill shiftover(RB); 881597Sbill sawindex = 1; 882632Shenry ap->a_areg2 = regno; 883597Sbill } 884597Sbill break; 885597Sbill 886597Sbill } /*end of the switch to process an arg*/ 887597Sbill } /*end of processing an argument*/ 888597Sbill 889597Sbill if (sawmul){ 890597Sbill /* 891597Sbill * Make a concession for *(%r) 892597Sbill * meaning *0(%r) 893597Sbill */ 894632Shenry if (ap->a_atype == ABASE) { 895632Shenry ap->a_atype = ADISP; 896632Shenry xp->e_xtype = XABS; 897632Shenry xp->e_xvalue = 0; 898632Shenry xp->e_xloc = 0; 899632Shenry ap->a_xp = xp++; 900597Sbill } 901632Shenry ap->a_atype |= ASTAR; 902597Sbill sawmul = 0; 903597Sbill } 904597Sbill if (sawindex){ 905632Shenry ap->a_atype |= AINDX; 906597Sbill sawindex = 0; 907597Sbill } 908632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 909597Sbill if (val != CM) break; 910597Sbill shiftover(CM); 911597Sbill } /*processing all the arguments*/ 912597Sbill 913597Sbill if (argcnt > 6){ 914597Sbill yyerror("More than 6 arguments"); 915597Sbill goto errorfix; 916597Sbill } 917597Sbill 918597Sbill insout(seg_type, arglist, 919597Sbill auxval == INSTn ? argcnt : - argcnt); 920597Sbill break; 921597Sbill 922597Sbill case IFLOAT: curlen = 4; goto floatlist; 923645Shenry case IQUAD: 924597Sbill case IDOUBLE: 925597Sbill curlen = 8; 926597Sbill floatlist: 927597Sbill /* 928597Sbill * eat a list of floating point numbers 929597Sbill */ 930597Sbill shift; 931597Sbill if (val == FLTNUM){ 932597Sbill /* KLS MOD */ 933597Sbill float flocal; 934597Sbill do{ 935597Sbill if (val == CM) shift; 936597Sbill if (val != FLTNUM) { 937597Sbill ERROR("floating number expected"); 938597Sbill } 939632Shenry dotp->e_xvalue += curlen; 940597Sbill #ifdef UNIX 941597Sbill if (passno == 2) { 942597Sbill if(curlen == 8) 943597Sbill bwrite((char *)&(((union Double *)yylval)->dvalue), 944597Sbill curlen, txtfil); 945597Sbill else { 946597Sbill flocal = ((union Double *)yylval)->dvalue; 947597Sbill bwrite((char *)&flocal, curlen, txtfil); 948597Sbill } 949597Sbill } 950597Sbill #endif UNIX 951597Sbill 952597Sbill #ifdef VMS 953597Sbill if (passno == 2) { 954597Sbill puchar(vms_obj_ptr,-4); 955597Sbill pulong(vms_obj_ptr, 956597Sbill ((struct exp *)yylval) 957597Sbill ->doub_MSW); 958597Sbill if (curlen==8) { 959597Sbill puchar(vms_obj_ptr,-4); 960597Sbill pulong(vms_obj_ptr, 961597Sbill ((struct exp *)yylval) 962597Sbill ->doub_LSW); 963597Sbill } 964597Sbill if((vms_obj_ptr-sobuf) > 400) { 965597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 966597Sbill vms_obj_ptr = sobuf + 1; 967597Sbill } 968597Sbill } 969597Sbill #endif VMS 970597Sbill shift; 971597Sbill xp = explist; 972597Sbill } while (val == CM); 973597Sbill } 974597Sbill break; 975597Sbill } /*end of the switch for looking at each reserved word*/ 976597Sbill 977597Sbill continue; 978597Sbill 979597Sbill errorfix: 980597Sbill /* 981597Sbill * got here by either requesting to skip to the 982597Sbill * end of this statement, or by erroring out and 983597Sbill * wanting to apply panic mode recovery 984597Sbill */ 985597Sbill while ( (val != NL) 986597Sbill && (val != SEMI) 987597Sbill && (val != PARSEEOF) 988597Sbill ){ 989597Sbill shift; 990597Sbill } 991597Sbill if (val == NL) 992597Sbill lineno++; 993597Sbill shift; 994597Sbill 995597Sbill } /*end of the loop to read the entire file, line by line*/ 996597Sbill 997597Sbill } /*end of yyparse*/ 998597Sbill 999597Sbill /* 1000597Sbill * Process a register declaration of the form 1001597Sbill * % <expr> 1002597Sbill * 1003597Sbill * Note: 1004597Sbill * The scanner has already processed funny registers of the form 1005597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 1006597Sbill * preceding zero digit). If there was any space between the % and 1007597Sbill * the digit, the scanner wouldn't have recognized it, so we 1008597Sbill * hack it out here. 1009597Sbill */ 1010597Sbill int funnyreg(val, regnoback) /*what the read head will sit on*/ 1011597Sbill int val; /*what the read head is sitting on*/ 1012597Sbill int *regnoback; /*call by return*/ 1013597Sbill { 1014597Sbill register struct exp *locxp; 1015597Sbill struct exp *loc1xp; 1016597Sbill struct exp **ptrloc1xp = & loc1xp; 1017597Sbill 1018597Sbill expr(locxp, val); /*and leave the current read head with value*/ 1019597Sbill if ( (passno == 2) && 1020632Shenry ( locxp->e_xtype & XTYPE != XABS 1021632Shenry || locxp->e_xvalue < 0 1022632Shenry || locxp->e_xvalue >= 16 1023597Sbill ) 1024597Sbill ){ 1025597Sbill yyerror("Illegal register"); 1026597Sbill return(0); 1027597Sbill } 1028632Shenry *regnoback = locxp->e_xvalue; 1029597Sbill return(val); 1030597Sbill } 1031597Sbill 1032597Sbill /*VARARGS1*/ 1033597Sbill yyerror(s, a1, a2,a3,a4,a5) 1034597Sbill char *s; 1035597Sbill { 1036597Sbill 1037649Shenry #define sink stdout 1038597Sbill 1039597Sbill if (anyerrs == 0 && ! silent) 1040597Sbill fprintf(sink, "Assembler:\n"); 1041597Sbill anyerrs++; 1042597Sbill if (silent) return; 1043597Sbill 1044597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1045597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1046597Sbill fprintf(sink, "\n"); 1047597Sbill } 1048