1597Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*649Shenry static char sccsid[] = "@(#)asparse.c 4.5 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*/ 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*/ 81597Sbill 82597Sbill xp = explist; 83597Sbill ap = arglist; 84597Sbill 85597Sbill val = yylex(); 86597Sbill 87597Sbill while (val != PARSEEOF){ /* primary loop */ 88597Sbill 89597Sbill while (INTOKSET(val, LINSTBEGIN)){ 90597Sbill if (val == INT) { 91632Shenry int i = ((struct exp *)yylval)->e_xvalue; 92597Sbill shift; 93597Sbill if (val != COLON) 94597Sbill goto nocolon; 95597Sbill if (i < 0 || i > 9) { 96597Sbill yyerror("Local labels are 0-9"); 97597Sbill goto errorfix; 98597Sbill } 99597Sbill sprintf(yytext, "L%d\001%d", i, lgensym[i]); 100597Sbill lgensym[i]++; 101597Sbill genref[i] = 0; 102597Sbill yylval = (int)*lookup(passno == 1); 103597Sbill val = NAME; 104597Sbill np = (struct symtab *)yylval; 105597Sbill goto restlab; 106597Sbill } 107597Sbill if (val == NL){ 108597Sbill lineno++; 109597Sbill shift; 110597Sbill } else 111597Sbill if (val == SEMI) 112597Sbill shift; 113597Sbill else { /*its a name, so we have a label or def */ 114597Sbill if (val != NAME){ 115597Sbill ERROR("Name expected for a label"); 116597Sbill } 117597Sbill np = (struct symtab *)yylval; 118597Sbill shiftover(NAME); 119597Sbill nocolon: 120597Sbill if (val != COLON) { 121632Shenry #ifdef FLEXNAMES 122597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition", 123632Shenry #else not FLEXNAMES 124632Shenry yyerror("\"%.*s\" is not followed by a ':' for a label definition", 125632Shenry NCPS, 126632Shenry #endif not FLEXNAMES 127632Shenry np->s_name); 128597Sbill goto errorfix; 129597Sbill } 130597Sbill restlab: 131597Sbill shift; 132597Sbill flushfield(NBPW/4); 133632Shenry if ((np->s_type&XTYPE)!=XUNDEF) { 134632Shenry if( (np->s_type&XTYPE)!=dotp->e_xtype 135632Shenry || np->s_value!=dotp->e_xvalue 136597Sbill || ( (passno==1) 137632Shenry &&(np->s_index != dotp->e_xloc) 138597Sbill ) 139597Sbill ){ 140597Sbill #ifndef DEBUG 141632Shenry if (np->s_name[0] != 'L') 142597Sbill #endif not DEBUG 143597Sbill { 144597Sbill if (passno == 1) 145632Shenry #ifdef FLEXNAMES 146632Shenry yyerror("%s redefined", 147632Shenry #else not FLEXNAMES 148632Shenry yyerror("%.*s redefined", 149632Shenry NCPS, 150632Shenry #endif not FLEXNAMES 151632Shenry np->s_name); 152597Sbill else 153632Shenry #ifdef FLEXNAMES 154632Shenry yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 155632Shenry #else not FLEXNAMES 156632Shenry yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 157632Shenry NCPS, 158632Shenry #endif not FLEXNAMES 159632Shenry np->s_name, 160632Shenry np->s_value, 161632Shenry dotp->e_xvalue); 162597Sbill } 163597Sbill } 164597Sbill } 165632Shenry np->s_type &= ~(XTYPE|XFORW); 166632Shenry np->s_type |= dotp->e_xtype; 167632Shenry np->s_value = dotp->e_xvalue; 168597Sbill if (passno == 1){ 169632Shenry np->s_index = dotp-usedot; 170632Shenry if (np->s_name[0] == 'L'){ 171597Sbill nlabels++; 172597Sbill } 173632Shenry np->s_tag = LABELID; 174597Sbill } 175597Sbill } /*end of this being a label*/ 176597Sbill } /*end of to consuming all labels, NLs and SEMIS */ 177597Sbill 178597Sbill xp = explist; 179597Sbill ap = arglist; 180597Sbill 181597Sbill /* 182597Sbill * process the INSTRUCTION body 183597Sbill */ 184597Sbill switch(val){ 185597Sbill 186597Sbill default: 187597Sbill ERROR("Unrecognized instruction or directive"); 188597Sbill 189597Sbill case IABORT: 190597Sbill shift; 191597Sbill sawabort(); 192597Sbill /*NOTREACHED*/ 193597Sbill break; 194597Sbill 195597Sbill case PARSEEOF: 196597Sbill tokptr -= sizeof(toktype); 197597Sbill *tokptr++ = VOID; 198597Sbill tokptr[1] = VOID; 199597Sbill tokptr[2] = PARSEEOF; 200597Sbill break; 201597Sbill 202597Sbill case IFILE: 203597Sbill shift; 204597Sbill stringp = (struct strdesc *)yylval; 205597Sbill shiftover(STRING); 206597Sbill dotsname = &UDotsname[0]; 207597Sbill movestr(dotsname, stringp->str, 208597Sbill stringp->str_lg >= 32? 32 :stringp->str_lg); 209597Sbill dotsname[stringp->str_lg] = '\0'; 210597Sbill break; 211597Sbill 212597Sbill case ILINENO: 213597Sbill shift; /*over the ILINENO*/ 214597Sbill expr(locxp, val); 215632Shenry lineno = locxp->e_xvalue; 216597Sbill break; 217597Sbill 218597Sbill case ISET: /* .set <name> , <expr> */ 219597Sbill shift; 220597Sbill np = (struct symtab *)yylval; 221597Sbill shiftover(NAME); 222597Sbill shiftover(CM); 223597Sbill expr(locxp, val); 224632Shenry np->s_type &= (XXTRN|XFORW); 225632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 226632Shenry np->s_value = locxp->e_xvalue; 227597Sbill if (passno==1) 228632Shenry np->s_index = locxp->e_xloc; 229632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 230597Sbill yyerror("Illegal set?"); 231597Sbill break; 232597Sbill 233597Sbill case ILSYM: /*.lsym name , expr */ 234597Sbill shift; 235597Sbill np = (struct symtab *)yylval; 236597Sbill shiftover(NAME); 237597Sbill shiftover(CM); 238597Sbill expr(locxp, val); 239597Sbill /* 240597Sbill * Build the unique occurance of the 241597Sbill * symbol. 242597Sbill * The character scanner will have 243597Sbill * already entered it into the symbol 244597Sbill * table, but we should remove it 245597Sbill */ 246597Sbill if (passno == 1){ 247597Sbill stpt = (struct symtab *)symalloc(); 248597Sbill #ifdef FLEXNAMES 249632Shenry stpt->s_name = np->s_name; 250597Sbill #else 251632Shenry movestr(stpt->s_name, np->s_name, NCPS); 252597Sbill #endif 253632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 254597Sbill nforgotten++; 255597Sbill np = stpt; 256632Shenry if (locxp->e_xtype != XABS) 257597Sbill ("Illegal lsym"); 258632Shenry np->s_value=locxp->e_xvalue; 259632Shenry np->s_type=XABS; 260632Shenry np->s_tag = ILSYM; 261597Sbill } 262597Sbill break; 263597Sbill 264597Sbill case IGLOBAL: /*.globl <name> */ 265597Sbill shift; 266597Sbill np = (struct symtab *)yylval; 267597Sbill shiftover(NAME); 268632Shenry np->s_type |= XXTRN; 269597Sbill break; 270597Sbill 271597Sbill case IDATA: /*.data [ <expr> ] */ 272597Sbill case ITEXT: /*.text [ <expr> ] */ 273597Sbill seg_type = -val; 274597Sbill shift; 275597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 276597Sbill expr(locxp, val); 277597Sbill seg_type = -seg_type; /*now, it is positive*/ 278597Sbill } 279597Sbill 280597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 281597Sbill seg_number = 0; 282597Sbill seg_type = -seg_type; 283597Sbill } else { 284632Shenry if (locxp->e_xtype != XABS || (seg_number=locxp->e_xvalue) >= NLOC) { 285597Sbill yyerror("illegal location counter"); 286597Sbill seg_number = 0; 287597Sbill } 288597Sbill } 289597Sbill if (seg_type == IDATA) 290597Sbill seg_number += NLOC; 291597Sbill flushfield(NBPW/4); 292597Sbill dotp = &usedot[seg_number]; 293597Sbill #ifdef UNIX 294597Sbill if (passno==2) { /* go salt away in pass 2*/ 295597Sbill txtfil = usefile[seg_number]; 296597Sbill relfil = rusefile[seg_number]; 297597Sbill } 298597Sbill #endif UNIX 299597Sbill #ifdef VMS 300597Sbill if (passno==2) { 301597Sbill puchar(vms_obj_ptr,6); /* setpl */ 302597Sbill puchar(vms_obj_ptr,seg_number); /* psect # */ 303632Shenry plong(vms_obj_ptr,dotp->e_xvalue);/* offset */ 304597Sbill puchar(vms_obj_ptr,80); /* setrb */ 305597Sbill if((vms_obj_ptr-sobuf) > 400){ 306597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 307597Sbill vms_obj_ptr=sobuf+1; /*flush buf*/ 308597Sbill } 309597Sbill } 310597Sbill #endif VMS 311597Sbill break; 312597Sbill 313597Sbill /* 314597Sbill * Storage filler directives: 315597Sbill * 316597Sbill * .byte [<exprlist>] 317597Sbill * 318597Sbill * exprlist: empty | exprlist outexpr 319597Sbill * outexpr: <expr> | <expr> : <expr> 320597Sbill */ 321597Sbill case IBYTE: curlen = NBPW/4; goto elist; 322597Sbill 323597Sbill case IINT: 324597Sbill case ILONG: curlen = NBPW; goto elist; 325597Sbill 326597Sbill case IWORD: 327597Sbill curlen = NBPW/2; 328597Sbill elist: 329597Sbill seg_type = val; 330597Sbill shift; 331597Sbill 332597Sbill /* 333597Sbill * Expression List processing 334597Sbill */ 335597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 336597Sbill do{ 337597Sbill /* 338597Sbill * expression list consists of a list of : 339597Sbill * <expr> 340597Sbill * <expr> : <expr> 341597Sbill * (pack expr2 into expr1 bits 342597Sbill */ 343597Sbill expr(locxp, val); 344597Sbill /* 345597Sbill * now, pointing at the next token 346597Sbill */ 347597Sbill if (val == COLON){ 348597Sbill shiftover(COLON); 349597Sbill expr(pval, val); 350632Shenry if (locxp->e_xtype != XABS) 351597Sbill yyerror("Width not absolute"); 352632Shenry field_width = locxp->e_xvalue; 353597Sbill locxp = pval; 354597Sbill if (bitoff + field_width > 355597Sbill curlen) 356597Sbill flushfield(curlen); 357597Sbill if (field_width > curlen) 358597Sbill yyerror("Expression crosses field boundary"); 359597Sbill } else { 360597Sbill field_width = curlen; 361597Sbill flushfield(curlen); 362597Sbill } 363597Sbill 364632Shenry if ((locxp->e_xtype&XTYPE)!=XABS) { 365597Sbill if (bitoff) 366597Sbill yyerror("Illegal relocation in field"); 367597Sbill field_width=LEN1; 368597Sbill if (curlen==NBPW) 369597Sbill field_width = LEN4; 370597Sbill if (curlen==NBPW/2) 371597Sbill field_width = LEN2; 372597Sbill if (passno == 1){ 373632Shenry dotp->e_xvalue += reflen[field_width]; 374597Sbill } else { 375632Shenry outrel(&locxp->e_xvalue, 376597Sbill field_width, 377632Shenry locxp->e_xtype, 378632Shenry locxp->e_xname); 379597Sbill } 380597Sbill } else { 381632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 382597Sbill bitfield |= field_value << bitoff; 383597Sbill bitoff += field_width; 384597Sbill } 385597Sbill if ( auxval = (val == CM)) shift; 386597Sbill xp = explist; 387597Sbill } while (auxval); 388597Sbill } /*existed an expression at all*/ 389597Sbill 390597Sbill flushfield(curlen); 391597Sbill if ( ( curlen == NBPW/4) && bitoff) 392632Shenry dotp->e_xvalue ++; 393597Sbill break; 394597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 395597Sbill 396597Sbill case ISPACE: /* .space <expr> */ 397597Sbill shift; 398597Sbill expr(locxp, val); 399632Shenry if (locxp->e_xtype != XABS) 400597Sbill yyerror("Space size not absolute"); 401632Shenry space_value = locxp->e_xvalue; 402597Sbill ospace: 403597Sbill flushfield(NBPW/4); 404597Sbill #ifdef UNIX 405597Sbill while (space_value > 96){ 406597Sbill outs(strbuf[2].str, 96); 407597Sbill space_value -= 96; 408597Sbill } 409597Sbill outs(strbuf[2].str, space_value); 410597Sbill #endif UNIX 411597Sbill #ifdef VMS 412632Shenry dotp->e_xvalue += space_value; /*bump pc*/ 413597Sbill if (passno==2){ 414597Sbill if(*(strbuf[2].str)==0) { 415597Sbill puchar(vms_obj_ptr,81); /* AUGR */ 416597Sbill pulong(vms_obj_ptr,space_value);/* incr */ 417597Sbill } else yyerror("VMS, encountered non-0 .space"); 418597Sbill if ((vms_obj_ptr-sobuf) > 400) { 419597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 420597Sbill vms_obj_ptr=sobuf+1; /*pur buf*/ 421597Sbill } 422597Sbill } 423597Sbill #endif VMS 424597Sbill break; 425597Sbill 426597Sbill #ifdef UNIX 427647Shenry /* 428647Shenry * .fill rep, size, value 429647Shenry * repeat rep times: fill size bytes with (truncated) value 430647Shenry * size must be between 1 and 8 431647Shenry */ 432647Shenry case IFILL: 433597Sbill shift; 434597Sbill expr(locxp, val); 435632Shenry if (locxp->e_xtype != XABS) 436597Sbill yyerror("Fill repetition count not absolute"); 437647Shenry fill_rep = locxp->e_xvalue; 438597Sbill shiftover(CM); 439597Sbill expr(locxp, val); 440632Shenry if (locxp->e_xtype != XABS) 441647Shenry yyerror("Fill size not absolute"); 442647Shenry fill_size = locxp->e_xvalue; 443647Shenry if (fill_size <= 0 || fill_size > 8) 444647Shenry yyerror("Fill count not in in 1..8"); 445647Shenry shiftover(CM); 446647Shenry expr(locxp, val); 447647Shenry if (passno == 2 && locxp->e_xtype != XABS) 448647Shenry yyerror("Fill value not absolute"); 449597Sbill flushfield(NBPW/4); 450647Shenry if (passno == 1) { 451647Shenry locxp->e_xvalue += fill_rep * fill_size; 452647Shenry } else { 453647Shenry while(fill_rep-- > 0) 454647Shenry bwrite(&locxp->e_xvalue, fill_size, txtfil); 455647Shenry } 456597Sbill break; 457597Sbill #endif UNIX 458597Sbill 459597Sbill case IASCII: /* .ascii [ <stringlist> ] */ 460597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 461597Sbill auxval = val; 462597Sbill shift; 463597Sbill 464597Sbill /* 465597Sbill * Code to consume a string list 466597Sbill * 467597Sbill * stringlist: empty | STRING | stringlist STRING 468597Sbill */ 469597Sbill while (val == STRING){ 470597Sbill flushfield(NBPW/4); 471597Sbill if (bitoff) 472632Shenry dotp->e_xvalue++; 473597Sbill stringp = (struct strdesc *)yylval; 474597Sbill #ifdef UNIX 475597Sbill outs(stringp->str, stringp->str_lg); 476597Sbill #endif UNIX 477597Sbill #ifdef VMS 478597Sbill { 479597Sbill register int i; 480597Sbill for (i=0; i < stringp->str_lg; i++){ 481632Shenry dotp->e_xvalue += 1; 482597Sbill if (passno==2){ 483597Sbill puchar(vms_obj_ptr,-1); 484597Sbill puchar(vms_obj_ptr,stringp->str[i]); 485597Sbill if (vms_obj_ptr-sobuf > 400) { 486597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 487597Sbill vms_obj_ptr = sobuf + 1; 488597Sbill } 489597Sbill } 490597Sbill } 491597Sbill } 492597Sbill #endif VMS 493597Sbill shift; /*over the STRING*/ 494597Sbill if (val == CM) /*could be a split string*/ 495597Sbill shift; 496597Sbill } 497597Sbill 498597Sbill if (auxval == IASCIZ){ 499597Sbill flushfield(NBPW/4); 500597Sbill #ifdef UNIX 501597Sbill outb(0); 502597Sbill #endif UNIX 503597Sbill #ifdef VMS 504597Sbill if (passno == 2) { 505597Sbill puchar(vms_obj_ptr,-1); 506597Sbill puchar(vms_obj_ptr,0); 507597Sbill } 508632Shenry dotp->e_xvalue += 1; 509597Sbill #endif VMS 510597Sbill } 511597Sbill break; 512597Sbill 513597Sbill case IORG: /* .org <expr> */ 514597Sbill shift; 515597Sbill expr(locxp, val); 516597Sbill 517632Shenry if (locxp->e_xtype==XABS) 518597Sbill orgwarn++; 519632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 520597Sbill yyerror("Illegal expression to set origin"); 521632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 522597Sbill if (space_value < 0) 523597Sbill yyerror("Backwards 'org'"); 524597Sbill goto ospace; 525597Sbill break; 526597Sbill 527597Sbill /* 528597Sbill * 529597Sbill * Process stabs. Stabs are created only by the f77 530597Sbill * and the C compiler with the -g flag set. 531597Sbill * We only look at the stab ONCE, during pass 1, and 532597Sbill * virtually remove the stab from the intermediate file 533597Sbill * so it isn't seen during pass2. This makes for some 534597Sbill * hairy processing to handle labels occuring in 535597Sbill * stab entries, but since most expressions in the 536597Sbill * stab are integral we save lots of time in the second 537597Sbill * pass by not looking at the stabs. 538597Sbill * A stab that is tagged floating will be bumped during 539597Sbill * the jxxx resolution phase. A stab tagged fixed will 540597Sbill * not be be bumped. 541597Sbill * 542597Sbill * .stab: Old fashioned stabs 543597Sbill * .stabn: For stabs without names 544597Sbill * .stabs: For stabs with string names 545597Sbill * .stabd: For stabs for line numbers or bracketing, 546597Sbill * without a string name, without 547597Sbill * a final expression. The value of the 548597Sbill * final expression is taken to be the current 549597Sbill * location counter, and is patched by the 2nd pass 550597Sbill * 551597Sbill * .stab{<expr>,}*8,<expr>, <expr>, <expr>, <expr> 552597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 553597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 554597Sbill * .stabd <expr>, <expr>, <expr> # . 555597Sbill */ 556597Sbill case ISTAB: 557597Sbill #ifndef FLEXNAMES 558597Sbill stabname = ".stab"; 559597Sbill if (passno == 2) goto errorfix; 560597Sbill stpt = (struct symtab *)yylval; 561597Sbill /* 562597Sbill * Make a pointer to the .stab slot. 563597Sbill * There is a pointer in the way (stpt), and 564597Sbill * tokptr points to the next token. 565597Sbill */ 566597Sbill stabstart = tokptr; 567597Sbill (char *)stabstart -= sizeof(struct symtab *); 568597Sbill (char *)stabstart -= sizeof(toktype); 569597Sbill shift; 570597Sbill for (argcnt = 0; argcnt < 8; argcnt++){ 571597Sbill expr(locxp, val); 572632Shenry stpt->s_name[argcnt] = locxp->e_xvalue; 573597Sbill xp = explist; 574597Sbill shiftover(CM); 575597Sbill } 576597Sbill goto tailstab; 577597Sbill #else FLEXNAMES 578597Sbill yyerror(".stab directive not supported in; report this compiler bug to system administrator"); 579597Sbill goto errorfix; 580597Sbill #endif FLEXNAMES 581597Sbill 582597Sbill tailstab: 583597Sbill expr(locxp, val); 584632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 585597Sbill yyerror("Invalid type in %s",stabname); 586597Sbill goto errorfix; 587597Sbill } 588632Shenry stpt->s_ptype = locxp->e_xvalue; 589597Sbill shiftover(CM); 590597Sbill expr(locxp, val); 591632Shenry stpt->s_other = locxp->e_xvalue; 592597Sbill shiftover(CM); 593597Sbill expr(locxp, val); 594632Shenry stpt->s_desc = locxp->e_xvalue; 595597Sbill shiftover(CM); 596597Sbill exprisname = 0; 597597Sbill expr(locxp, val); 598632Shenry p = locxp->e_xname; 599597Sbill if (p == NULL) { /*absolute expr to begin with*/ 600632Shenry stpt->s_value = locxp->e_xvalue; 601632Shenry stpt->s_index = dotp - usedot; 602597Sbill if (exprisname){ 603632Shenry switch(stpt->s_ptype){ 604597Sbill case N_GSYM: 605597Sbill case N_FNAME: 606597Sbill case N_RSYM: 607597Sbill case N_SSYM: 608597Sbill case N_LSYM: 609597Sbill case N_PSYM: 610597Sbill case N_BCOMM: 611597Sbill case N_ECOMM: 612597Sbill case N_LENG: 613632Shenry stpt->s_tag = STABFIXED; 614597Sbill break; 615597Sbill default: 616632Shenry stpt->s_tag = STABFLOATING; 617597Sbill break; 618597Sbill } 619597Sbill } else 620632Shenry stpt->s_tag = STABFIXED; 621597Sbill } 622597Sbill else { /*really have a name*/ 623632Shenry stpt->s_dest = locxp->e_xname; 624632Shenry stpt->s_index = p->s_index; 625632Shenry stpt->s_type = p->s_type | STABFLAG; 626597Sbill /* 627597Sbill * We will assign a more accruate 628597Sbill * guess of locxp's location when 629597Sbill * we sort the symbol table 630597Sbill * The final value of value is 631597Sbill * given by stabfix() 632597Sbill */ 633632Shenry stpt->s_tag = STABFLOATING; 634597Sbill } 635597Sbill /* 636597Sbill * tokptr now points at one token beyond 637597Sbill * the current token stored in val and yylval, 638597Sbill * which are the next tokens after the end of 639597Sbill * this .stab directive. This next token must 640597Sbill * be either a SEMI or NL, so is of width just 641597Sbill * one. Therefore, to point to the next token 642597Sbill * after the end of this stab, just back up one.. 643597Sbill */ 644597Sbill buildskip(stabstart, (char *)tokptr - sizeof(toktype)); 645597Sbill break; /*end of the .stab*/ 646597Sbill 647597Sbill case ISTABDOT: 648597Sbill stabname = ".stabd"; 649597Sbill stpt = (struct symtab *)yylval; 650597Sbill /* 651597Sbill * We clobber everything after the 652597Sbill * .stabd and its pointer... we MUST 653597Sbill * be able to get back to this .stabd 654597Sbill * so that we can resolve its final value 655597Sbill */ 656597Sbill stabstart = tokptr; 657597Sbill shift; /*over the ISTABDOT*/ 658597Sbill if (passno == 1){ 659597Sbill expr(locxp, val); 660632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 661597Sbill yyerror("Invalid type in .stabd"); 662597Sbill goto errorfix; 663597Sbill } 664632Shenry stpt->s_ptype = locxp->e_xvalue; 665597Sbill shiftover(CM); 666597Sbill expr(locxp, val); 667632Shenry stpt->s_other = locxp->e_xvalue; 668597Sbill shiftover(CM); 669597Sbill expr(locxp, val); 670632Shenry stpt->s_desc = locxp->e_xvalue; 671597Sbill /* 672597Sbill * 673597Sbill * Now, clobber everything but the 674597Sbill * .stabd pseudo and the pointer 675597Sbill * to its symbol table entry 676597Sbill * tokptr points to the next token, 677597Sbill * build the skip up to this 678597Sbill */ 679597Sbill buildskip(stabstart, (toktype *)tokptr - sizeof(toktype)); 680597Sbill } 681597Sbill /* 682597Sbill * pass 1: Assign a good guess for its position 683597Sbill * (ensures they are sorted into right place)/ 684597Sbill * pass 2: Fix the actual value 685597Sbill */ 686632Shenry stpt->s_value = dotp->e_xvalue; 687632Shenry stpt->s_index = dotp - usedot; 688632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 689597Sbill break; 690597Sbill 691597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 692597Sbill 693597Sbill case ISTABSTR: stabname = ".stabs"; 694597Sbill shortstab: 695597Sbill auxval = val; 696597Sbill if (passno == 2) goto errorfix; 697597Sbill stpt = (struct symtab *)yylval; 698597Sbill stabstart = tokptr; 699597Sbill (char *)stabstart -= sizeof(struct symtab *); 700597Sbill (char *)stabstart -= sizeof(toktype); 701597Sbill shift; 702597Sbill if (auxval == ISTABSTR){ 703597Sbill stringp = (struct strdesc *)yylval; 704597Sbill shiftover(STRING); 705597Sbill #ifndef FLEXNAMES 706597Sbill auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; 707597Sbill #else 708597Sbill stringp->str[stringp->str_lg] = 0; 709597Sbill #endif 710597Sbill shiftover(CM); 711597Sbill } else { 712597Sbill stringp = &(strbuf[2]); 713597Sbill #ifndef FLEXNAMES 714597Sbill auxval = NCPS; 715597Sbill #endif 716597Sbill } 717597Sbill #ifndef FLEXNAMES 718632Shenry movestr(stpt->s_name, stringp->str, auxval); 719597Sbill #else 720632Shenry stpt->s_name = savestr(stringp->str); 721597Sbill #endif 722597Sbill goto tailstab; 723597Sbill break; 724597Sbill 725597Sbill case ICOMM: /* .comm <name> , <expr> */ 726597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 727597Sbill auxval = val; 728597Sbill shift; 729597Sbill np = (struct symtab *)yylval; 730597Sbill shiftover(NAME); 731597Sbill shiftover(CM); 732597Sbill expr(locxp, val); 733597Sbill 734632Shenry if (locxp->e_xtype != XABS) 735597Sbill yyerror("comm size not absolute"); 736632Shenry if (passno==1 && (np->s_type&XTYPE)!=XUNDEF) 737632Shenry #ifdef FLEXNAMES 738632Shenry yyerror("Redefinition of %s", 739632Shenry #else not FLEXNAMES 740632Shenry yyerror("Redefinition of %.*s", 741632Shenry NCPS, 742632Shenry #endif not FLEXNAMES 743632Shenry np->s_name); 744597Sbill if (passno==1) { 745632Shenry np->s_value = locxp->e_xvalue; 746597Sbill if (auxval == ICOMM) 747632Shenry np->s_type |= XXTRN; 748597Sbill else { 749632Shenry np->s_type &= ~XTYPE; 750632Shenry np->s_type |= XBSS; 751597Sbill } 752597Sbill } 753597Sbill break; 754597Sbill 755597Sbill case IALIGN: /* .align <expr> */ 756597Sbill stpt = (struct symtab *)yylval; 757597Sbill shift; 758597Sbill expr(locxp, val); 759597Sbill jalign(locxp, stpt); 760597Sbill break; 761597Sbill 762597Sbill case INST0: /* instructions w/o arguments*/ 763597Sbill insout(yylval, (struct arg *)0, 0); 764597Sbill shift; 765597Sbill break; 766597Sbill 767597Sbill case INSTn: /* instructions with arguments*/ 768597Sbill case IJXXX: /* UNIX style jump instructions */ 769597Sbill auxval = val; 770597Sbill seg_type = yylval; 771597Sbill /* 772597Sbill * Code to process an argument list 773597Sbill */ 774597Sbill ap = arglist; 775597Sbill xp = explist; 776597Sbill 777597Sbill shift; /* bring in the first token for the arg list*/ 778597Sbill 779597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 780597Sbill /* 781597Sbill * code to process an argument proper 782597Sbill */ 783597Sbill sawindex = sawmul = sawsize = 0; 784597Sbill { 785597Sbill switch(val) { 786597Sbill 787597Sbill default: 788597Sbill disp: 789597Sbill if( !(INTOKSET(val, 790597Sbill EBEGOPS 791597Sbill +YUKKYEXPRBEG 792597Sbill +SAFEEXPRBEG)) ) { 793597Sbill ERROR("expression expected"); 794597Sbill } 795632Shenry expr(ap->a_xp,val); 796597Sbill overdisp: 797597Sbill if ( val == LP || sawsize){ 798597Sbill shiftover(LP); 799597Sbill findreg(regno); 800597Sbill shiftover(RP); 801632Shenry ap->a_atype = ADISP; 802632Shenry ap->a_areg1 = regno; 803597Sbill } else { 804632Shenry ap->a_atype = AEXP; 805632Shenry ap->a_areg1 = 0; 806597Sbill } 807597Sbill goto index; 808597Sbill 809597Sbill case SIZESPEC: 810597Sbill sizespec: 811597Sbill sawsize = yylval; 812597Sbill shift; 813597Sbill goto disp; 814597Sbill 815597Sbill case REG: 816597Sbill case REGOP: 817597Sbill findreg(regno); 818632Shenry ap->a_atype = AREG; 819632Shenry ap->a_areg1 = regno; 820597Sbill break; 821597Sbill 822597Sbill case MUL: 823597Sbill sawmul = 1; 824597Sbill shift; 825597Sbill if (val == LP) goto base; 826597Sbill if (val == LITOP) goto imm; 827597Sbill if (val == SIZESPEC) goto sizespec; 828597Sbill if (INTOKSET(val, 829597Sbill EBEGOPS 830597Sbill +YUKKYEXPRBEG 831597Sbill +SAFEEXPRBEG)) goto disp; 832597Sbill ERROR("expression, '(' or '$' expected"); 833597Sbill break; 834597Sbill 835597Sbill case LP: 836597Sbill base: 837597Sbill shift; /*consume the LP*/ 838597Sbill /* 839597Sbill * hack the ambiguity of 840597Sbill * movl (expr) (rn), ... 841597Sbill * note that (expr) could also 842597Sbill * be (rn) (by special hole in the 843597Sbill * grammar), which we ensure 844597Sbill * means register indirection, instead 845597Sbill * of an expression with value n 846597Sbill */ 847597Sbill if (val != REG && val != REGOP){ 848597Sbill droppedLP = 1; 849632Shenry val = exprparse(val, &(ap->a_xp)); 850597Sbill droppedLP = 0; 851597Sbill goto overdisp; 852597Sbill } 853597Sbill findreg(regno); 854597Sbill shiftover(RP); 855597Sbill if (val == PLUS){ 856597Sbill shift; 857632Shenry ap->a_atype = AINCR; 858597Sbill } else 859632Shenry ap->a_atype = ABASE; 860632Shenry ap->a_areg1 = regno; 861597Sbill goto index; 862597Sbill 863597Sbill case LITOP: 864597Sbill imm: 865597Sbill shift; 866597Sbill expr(locxp, val); 867632Shenry ap->a_atype = AIMM; 868632Shenry ap->a_areg1 = 0; 869632Shenry ap->a_xp = locxp; 870597Sbill goto index; 871597Sbill 872597Sbill case MP: 873597Sbill shift; /* -(reg) */ 874597Sbill findreg(regno); 875597Sbill shiftover(RP); 876632Shenry ap->a_atype = ADECR; 877632Shenry ap->a_areg1 = regno; 878597Sbill index: /*look for [reg] */ 879597Sbill if (val == LB){ 880597Sbill shift; 881597Sbill findreg(regno); 882597Sbill shiftover(RB); 883597Sbill sawindex = 1; 884632Shenry ap->a_areg2 = regno; 885597Sbill } 886597Sbill break; 887597Sbill 888597Sbill } /*end of the switch to process an arg*/ 889597Sbill } /*end of processing an argument*/ 890597Sbill 891597Sbill if (sawmul){ 892597Sbill /* 893597Sbill * Make a concession for *(%r) 894597Sbill * meaning *0(%r) 895597Sbill */ 896632Shenry if (ap->a_atype == ABASE) { 897632Shenry ap->a_atype = ADISP; 898632Shenry xp->e_xtype = XABS; 899632Shenry xp->e_xvalue = 0; 900632Shenry xp->e_xloc = 0; 901632Shenry ap->a_xp = xp++; 902597Sbill } 903632Shenry ap->a_atype |= ASTAR; 904597Sbill sawmul = 0; 905597Sbill } 906597Sbill if (sawindex){ 907632Shenry ap->a_atype |= AINDX; 908597Sbill sawindex = 0; 909597Sbill } 910632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 911597Sbill if (val != CM) break; 912597Sbill shiftover(CM); 913597Sbill } /*processing all the arguments*/ 914597Sbill 915597Sbill if (argcnt > 6){ 916597Sbill yyerror("More than 6 arguments"); 917597Sbill goto errorfix; 918597Sbill } 919597Sbill 920597Sbill insout(seg_type, arglist, 921597Sbill auxval == INSTn ? argcnt : - argcnt); 922597Sbill break; 923597Sbill 924597Sbill case IFLOAT: curlen = 4; goto floatlist; 925645Shenry case IQUAD: 926597Sbill case IDOUBLE: 927597Sbill curlen = 8; 928597Sbill floatlist: 929597Sbill /* 930597Sbill * eat a list of floating point numbers 931597Sbill */ 932597Sbill shift; 933597Sbill if (val == FLTNUM){ 934597Sbill /* KLS MOD */ 935597Sbill float flocal; 936597Sbill do{ 937597Sbill if (val == CM) shift; 938597Sbill if (val != FLTNUM) { 939597Sbill ERROR("floating number expected"); 940597Sbill } 941632Shenry dotp->e_xvalue += curlen; 942597Sbill #ifdef UNIX 943597Sbill if (passno == 2) { 944597Sbill if(curlen == 8) 945597Sbill bwrite((char *)&(((union Double *)yylval)->dvalue), 946597Sbill curlen, txtfil); 947597Sbill else { 948597Sbill flocal = ((union Double *)yylval)->dvalue; 949597Sbill bwrite((char *)&flocal, curlen, txtfil); 950597Sbill } 951597Sbill } 952597Sbill #endif UNIX 953597Sbill 954597Sbill #ifdef VMS 955597Sbill if (passno == 2) { 956597Sbill puchar(vms_obj_ptr,-4); 957597Sbill pulong(vms_obj_ptr, 958597Sbill ((struct exp *)yylval) 959597Sbill ->doub_MSW); 960597Sbill if (curlen==8) { 961597Sbill puchar(vms_obj_ptr,-4); 962597Sbill pulong(vms_obj_ptr, 963597Sbill ((struct exp *)yylval) 964597Sbill ->doub_LSW); 965597Sbill } 966597Sbill if((vms_obj_ptr-sobuf) > 400) { 967597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 968597Sbill vms_obj_ptr = sobuf + 1; 969597Sbill } 970597Sbill } 971597Sbill #endif VMS 972597Sbill shift; 973597Sbill xp = explist; 974597Sbill } while (val == CM); 975597Sbill } 976597Sbill break; 977597Sbill } /*end of the switch for looking at each reserved word*/ 978597Sbill 979597Sbill continue; 980597Sbill 981597Sbill errorfix: 982597Sbill /* 983597Sbill * got here by either requesting to skip to the 984597Sbill * end of this statement, or by erroring out and 985597Sbill * wanting to apply panic mode recovery 986597Sbill */ 987597Sbill while ( (val != NL) 988597Sbill && (val != SEMI) 989597Sbill && (val != PARSEEOF) 990597Sbill ){ 991597Sbill shift; 992597Sbill } 993597Sbill if (val == NL) 994597Sbill lineno++; 995597Sbill shift; 996597Sbill 997597Sbill } /*end of the loop to read the entire file, line by line*/ 998597Sbill 999597Sbill } /*end of yyparse*/ 1000597Sbill 1001597Sbill /* 1002597Sbill * Process a register declaration of the form 1003597Sbill * % <expr> 1004597Sbill * 1005597Sbill * Note: 1006597Sbill * The scanner has already processed funny registers of the form 1007597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 1008597Sbill * preceding zero digit). If there was any space between the % and 1009597Sbill * the digit, the scanner wouldn't have recognized it, so we 1010597Sbill * hack it out here. 1011597Sbill */ 1012597Sbill int funnyreg(val, regnoback) /*what the read head will sit on*/ 1013597Sbill int val; /*what the read head is sitting on*/ 1014597Sbill int *regnoback; /*call by return*/ 1015597Sbill { 1016597Sbill register struct exp *locxp; 1017597Sbill struct exp *loc1xp; 1018597Sbill struct exp **ptrloc1xp = & loc1xp; 1019597Sbill 1020597Sbill expr(locxp, val); /*and leave the current read head with value*/ 1021597Sbill if ( (passno == 2) && 1022632Shenry ( locxp->e_xtype & XTYPE != XABS 1023632Shenry || locxp->e_xvalue < 0 1024632Shenry || locxp->e_xvalue >= 16 1025597Sbill ) 1026597Sbill ){ 1027597Sbill yyerror("Illegal register"); 1028597Sbill return(0); 1029597Sbill } 1030632Shenry *regnoback = locxp->e_xvalue; 1031597Sbill return(val); 1032597Sbill } 1033597Sbill 1034597Sbill /*VARARGS1*/ 1035597Sbill yyerror(s, a1, a2,a3,a4,a5) 1036597Sbill char *s; 1037597Sbill { 1038597Sbill 1039*649Shenry #define sink stdout 1040597Sbill 1041597Sbill if (anyerrs == 0 && ! silent) 1042597Sbill fprintf(sink, "Assembler:\n"); 1043597Sbill anyerrs++; 1044597Sbill if (silent) return; 1045597Sbill 1046597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1047597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1048597Sbill fprintf(sink, "\n"); 1049597Sbill } 1050