1*5827Srrh /* 2*5827Srrh * Copyright (c) 1982 Regents of the University of California 3*5827Srrh */ 4*5827Srrh #ifndef lint 5*5827Srrh static char sccsid[] = "@(#)asparse.c 4.8 02/14/82"; 6*5827Srrh #endif not lint 7*5827Srrh 8597Sbill #include <stdio.h> 9597Sbill #include "as.h" 10597Sbill #include "asscan.h" 11597Sbill #include "assyms.h" 12*5827Srrh #include "asexpr.h" 13597Sbill 14597Sbill int lgensym[10]; 15597Sbill char genref[10]; 16597Sbill 17597Sbill long bitfield; 18597Sbill int bitoff; 19597Sbill int curlen; /* current length of literals */ 20597Sbill 21597Sbill /* 22597Sbill * The following three variables are communication between various 23597Sbill * modules to special case a number of things. They are properly 24597Sbill * categorized as hacks. 25597Sbill */ 26597Sbill extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/ 27597Sbill int exprisname; /*last factor in an expression was a name*/ 28597Sbill int droppedLP; /*one is analyzing an expression beginning with*/ 29597Sbill /*a left parenthesis, which has already been*/ 30597Sbill /*shifted. (Used to parse (<expr>)(rn)*/ 31597Sbill 32597Sbill char yytext[NCPS+2]; /*the lexical image*/ 33597Sbill int yylval; /*the lexical value; sloppy typing*/ 34*5827Srrh struct Opcode yyopcode; /* lexical value for an opcode */ 35*5827Srrh Bignum yybignum; /* lexical value for a big number */ 36597Sbill /* 37597Sbill * Expression and argument managers 38597Sbill */ 39597Sbill struct exp *xp; /*next free expression slot, used by expr.c*/ 40597Sbill struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/ 41597Sbill struct arg arglist[NARG]; /*building up operands in instructions*/ 42597Sbill /* 43597Sbill * Sets to accelerate token discrimination 44597Sbill */ 45597Sbill char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1]; 46597Sbill 47597Sbill static char UDotsname[32]; /*name of the assembly source*/ 48597Sbill 49*5827Srrh yyparse() 50597Sbill { 51*5827Srrh reg struct exp *locxp; 52*5827Srrh /* 53*5827Srrh * loc1xp and ptrloc1xp are used in the 54*5827Srrh * expression lookahead 55*5827Srrh */ 56*5827Srrh struct exp *loc1xp; /*must be non register*/ 57*5827Srrh struct exp **ptrloc1xp = & loc1xp; 58*5827Srrh struct exp *pval; /*hacking expr:expr*/ 59597Sbill 60*5827Srrh reg struct symtab *np; 61*5827Srrh reg int argcnt; 62597Sbill 63*5827Srrh reg inttoktype val; /*what yylex gives*/ 64*5827Srrh reg inttoktype auxval; /*saves val*/ 65597Sbill 66*5827Srrh reg struct arg *ap; /*first free argument*/ 67597Sbill 68*5827Srrh reg struct symtab *p; 69*5827Srrh reg struct symtab *stpt; 70597Sbill 71*5827Srrh struct strdesc *stringp; /*handles string lists*/ 72597Sbill 73*5827Srrh int regno; /*handles arguments*/ 74*5827Srrh int *ptrregno = ®no; 75*5827Srrh int sawmul; /*saw * */ 76*5827Srrh int sawindex; /*saw [rn]*/ 77*5827Srrh int sawsize; 78*5827Srrh int seg_type; /*the kind of segment: data or text*/ 79*5827Srrh int seg_number; /*the segment number*/ 80*5827Srrh int space_value; /*how much .space needs*/ 81*5827Srrh int fill_rep; /*how many reps for .fill */ 82*5827Srrh int fill_size; /*how many bytes for .fill */ 83597Sbill 84*5827Srrh int field_width; /*how wide a field is to be*/ 85*5827Srrh int field_value; /*the value to stuff in a field*/ 86*5827Srrh char *stabname; /*name of stab dealing with*/ 87*5827Srrh ptrall stabstart; /*where the stab starts in the buffer*/ 88*5827Srrh int reloc_how; /* how to relocate expressions */ 89*5827Srrh int toconv; /* how to convert bignums */ 90597Sbill 91597Sbill xp = explist; 92597Sbill ap = arglist; 93597Sbill 94597Sbill val = yylex(); 95597Sbill 96597Sbill while (val != PARSEEOF){ /* primary loop */ 97597Sbill 98597Sbill while (INTOKSET(val, LINSTBEGIN)){ 99597Sbill if (val == INT) { 100632Shenry int i = ((struct exp *)yylval)->e_xvalue; 101597Sbill shift; 102*5827Srrh if (val != COLON){ 103*5827Srrh yyerror("Local label %d is not followed by a ':' for a label definition", 104*5827Srrh i); 105*5827Srrh goto errorfix; 106*5827Srrh } 107597Sbill if (i < 0 || i > 9) { 108597Sbill yyerror("Local labels are 0-9"); 109597Sbill goto errorfix; 110597Sbill } 111*5827Srrh (void)sprintf(yytext, "L%d\001%d", i, lgensym[i]); 112597Sbill lgensym[i]++; 113597Sbill genref[i] = 0; 114597Sbill yylval = (int)*lookup(passno == 1); 115597Sbill val = NAME; 116597Sbill np = (struct symtab *)yylval; 117597Sbill goto restlab; 118597Sbill } 119597Sbill if (val == NL){ 120597Sbill lineno++; 121597Sbill shift; 122597Sbill } else 123597Sbill if (val == SEMI) 124597Sbill shift; 125597Sbill else { /*its a name, so we have a label or def */ 126597Sbill if (val != NAME){ 127597Sbill ERROR("Name expected for a label"); 128597Sbill } 129597Sbill np = (struct symtab *)yylval; 130597Sbill shiftover(NAME); 131597Sbill if (val != COLON) { 132632Shenry #ifdef FLEXNAMES 133597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition", 134632Shenry #else not FLEXNAMES 135632Shenry yyerror("\"%.*s\" is not followed by a ':' for a label definition", 136632Shenry NCPS, 137632Shenry #endif not FLEXNAMES 138632Shenry np->s_name); 139597Sbill goto errorfix; 140597Sbill } 141597Sbill restlab: 142597Sbill shift; 143597Sbill flushfield(NBPW/4); 144632Shenry if ((np->s_type&XTYPE)!=XUNDEF) { 145632Shenry if( (np->s_type&XTYPE)!=dotp->e_xtype 146632Shenry || np->s_value!=dotp->e_xvalue 147597Sbill || ( (passno==1) 148632Shenry &&(np->s_index != dotp->e_xloc) 149597Sbill ) 150597Sbill ){ 151597Sbill #ifndef DEBUG 152632Shenry if (np->s_name[0] != 'L') 153597Sbill #endif not DEBUG 154597Sbill { 155597Sbill if (passno == 1) 156632Shenry #ifdef FLEXNAMES 157632Shenry yyerror("%s redefined", 158632Shenry #else not FLEXNAMES 159632Shenry yyerror("%.*s redefined", 160632Shenry NCPS, 161632Shenry #endif not FLEXNAMES 162632Shenry np->s_name); 163597Sbill else 164632Shenry #ifdef FLEXNAMES 165632Shenry yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 166632Shenry #else not FLEXNAMES 167632Shenry yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 168632Shenry NCPS, 169632Shenry #endif not FLEXNAMES 170632Shenry np->s_name, 171632Shenry np->s_value, 172632Shenry dotp->e_xvalue); 173597Sbill } 174597Sbill } 175597Sbill } 176632Shenry np->s_type &= ~(XTYPE|XFORW); 177632Shenry np->s_type |= dotp->e_xtype; 178632Shenry np->s_value = dotp->e_xvalue; 179597Sbill if (passno == 1){ 180632Shenry np->s_index = dotp-usedot; 181632Shenry if (np->s_name[0] == 'L'){ 182597Sbill nlabels++; 183597Sbill } 184632Shenry np->s_tag = LABELID; 185597Sbill } 186597Sbill } /*end of this being a label*/ 187597Sbill } /*end of to consuming all labels, NLs and SEMIS */ 188597Sbill 189597Sbill xp = explist; 190597Sbill ap = arglist; 191597Sbill 192597Sbill /* 193597Sbill * process the INSTRUCTION body 194597Sbill */ 195597Sbill switch(val){ 196597Sbill 197597Sbill default: 198597Sbill ERROR("Unrecognized instruction or directive"); 199597Sbill 200597Sbill case IABORT: 201597Sbill shift; 202597Sbill sawabort(); 203597Sbill /*NOTREACHED*/ 204597Sbill break; 205597Sbill 206597Sbill case PARSEEOF: 207*5827Srrh tokptr -= sizeof(bytetoktype); 208597Sbill *tokptr++ = VOID; 209597Sbill tokptr[1] = VOID; 210597Sbill tokptr[2] = PARSEEOF; 211597Sbill break; 212597Sbill 213597Sbill case IFILE: 214597Sbill shift; 215597Sbill stringp = (struct strdesc *)yylval; 216597Sbill shiftover(STRING); 217597Sbill dotsname = &UDotsname[0]; 218597Sbill movestr(dotsname, stringp->str, 219597Sbill stringp->str_lg >= 32? 32 :stringp->str_lg); 220597Sbill dotsname[stringp->str_lg] = '\0'; 221597Sbill break; 222597Sbill 223597Sbill case ILINENO: 224597Sbill shift; /*over the ILINENO*/ 225597Sbill expr(locxp, val); 226632Shenry lineno = locxp->e_xvalue; 227597Sbill break; 228597Sbill 229597Sbill case ISET: /* .set <name> , <expr> */ 230597Sbill shift; 231597Sbill np = (struct symtab *)yylval; 232597Sbill shiftover(NAME); 233597Sbill shiftover(CM); 234597Sbill expr(locxp, val); 235632Shenry np->s_type &= (XXTRN|XFORW); 236632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 237632Shenry np->s_value = locxp->e_xvalue; 238597Sbill if (passno==1) 239632Shenry np->s_index = locxp->e_xloc; 240632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 241597Sbill yyerror("Illegal set?"); 242597Sbill break; 243597Sbill 244597Sbill case ILSYM: /*.lsym name , expr */ 245597Sbill shift; 246597Sbill np = (struct symtab *)yylval; 247597Sbill shiftover(NAME); 248597Sbill shiftover(CM); 249597Sbill expr(locxp, val); 250597Sbill /* 251597Sbill * Build the unique occurance of the 252597Sbill * symbol. 253597Sbill * The character scanner will have 254597Sbill * already entered it into the symbol 255597Sbill * table, but we should remove it 256597Sbill */ 257597Sbill if (passno == 1){ 258597Sbill stpt = (struct symtab *)symalloc(); 259597Sbill #ifdef FLEXNAMES 260632Shenry stpt->s_name = np->s_name; 261597Sbill #else 262632Shenry movestr(stpt->s_name, np->s_name, NCPS); 263597Sbill #endif 264632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 265597Sbill nforgotten++; 266597Sbill np = stpt; 267*5827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) 268*5827Srrh yyerror("Illegal second argument to lsym"); 269*5827Srrh np->s_value = locxp->e_xvalue; 270*5827Srrh np->s_type = XABS; 271632Shenry np->s_tag = ILSYM; 272597Sbill } 273597Sbill break; 274597Sbill 275597Sbill case IGLOBAL: /*.globl <name> */ 276597Sbill shift; 277597Sbill np = (struct symtab *)yylval; 278597Sbill shiftover(NAME); 279632Shenry np->s_type |= XXTRN; 280597Sbill break; 281597Sbill 282597Sbill case IDATA: /*.data [ <expr> ] */ 283597Sbill case ITEXT: /*.text [ <expr> ] */ 284597Sbill seg_type = -val; 285597Sbill shift; 286597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 287597Sbill expr(locxp, val); 288597Sbill seg_type = -seg_type; /*now, it is positive*/ 289597Sbill } 290597Sbill 291597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 292597Sbill seg_number = 0; 293597Sbill seg_type = -seg_type; 294597Sbill } else { 295*5827Srrh if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 296*5827Srrh || (seg_number = locxp->e_xvalue) >= NLOC) { 297597Sbill yyerror("illegal location counter"); 298597Sbill seg_number = 0; 299597Sbill } 300597Sbill } 301597Sbill if (seg_type == IDATA) 302597Sbill seg_number += NLOC; 303597Sbill flushfield(NBPW/4); 304597Sbill dotp = &usedot[seg_number]; 305597Sbill #ifdef UNIX 306597Sbill if (passno==2) { /* go salt away in pass 2*/ 307597Sbill txtfil = usefile[seg_number]; 308597Sbill relfil = rusefile[seg_number]; 309597Sbill } 310597Sbill #endif UNIX 311597Sbill #ifdef VMS 312597Sbill if (passno==2) { 313597Sbill puchar(vms_obj_ptr,6); /* setpl */ 314597Sbill puchar(vms_obj_ptr,seg_number); /* psect # */ 315632Shenry plong(vms_obj_ptr,dotp->e_xvalue);/* offset */ 316597Sbill puchar(vms_obj_ptr,80); /* setrb */ 317597Sbill if((vms_obj_ptr-sobuf) > 400){ 318597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 319597Sbill vms_obj_ptr=sobuf+1; /*flush buf*/ 320597Sbill } 321597Sbill } 322597Sbill #endif VMS 323597Sbill break; 324597Sbill 325597Sbill /* 326597Sbill * Storage filler directives: 327597Sbill * 328597Sbill * .byte [<exprlist>] 329597Sbill * 330597Sbill * exprlist: empty | exprlist outexpr 331597Sbill * outexpr: <expr> | <expr> : <expr> 332597Sbill */ 333597Sbill case IBYTE: curlen = NBPW/4; goto elist; 334*5827Srrh case IWORD: curlen = NBPW/2; goto elist; 335*5827Srrh case IINT: curlen = NBPW; goto elist; 336597Sbill case ILONG: curlen = NBPW; goto elist; 337597Sbill 338597Sbill elist: 339597Sbill seg_type = val; 340597Sbill shift; 341597Sbill 342597Sbill /* 343597Sbill * Expression List processing 344597Sbill */ 345597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 346597Sbill do{ 347597Sbill /* 348597Sbill * expression list consists of a list of : 349597Sbill * <expr> 350597Sbill * <expr> : <expr> 351597Sbill * (pack expr2 into expr1 bits 352597Sbill */ 353597Sbill expr(locxp, val); 354597Sbill /* 355597Sbill * now, pointing at the next token 356597Sbill */ 357597Sbill if (val == COLON){ 358597Sbill shiftover(COLON); 359597Sbill expr(pval, val); 360*5827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 361*5827Srrh yyerror("Width not absolute"); 362632Shenry field_width = locxp->e_xvalue; 363597Sbill locxp = pval; 364*5827Srrh if (bitoff + field_width > curlen) 365597Sbill flushfield(curlen); 366597Sbill if (field_width > curlen) 367597Sbill yyerror("Expression crosses field boundary"); 368597Sbill } else { 369597Sbill field_width = curlen; 370597Sbill flushfield(curlen); 371597Sbill } 372597Sbill 373*5827Srrh if ((locxp->e_xtype & XTYPE) != XABS) { 374597Sbill if (bitoff) 375597Sbill yyerror("Illegal relocation in field"); 376674Shenry switch(curlen){ 377674Shenry case NBPW/4: reloc_how = TYPB; break; 378674Shenry case NBPW/2: reloc_how = TYPW; break; 379674Shenry case NBPW: reloc_how = TYPL; break; 380674Shenry } 381597Sbill if (passno == 1){ 382674Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 383597Sbill } else { 384674Shenry outrel(locxp, reloc_how); 385597Sbill } 386597Sbill } else { 387632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 388597Sbill bitfield |= field_value << bitoff; 389597Sbill bitoff += field_width; 390597Sbill } 391597Sbill xp = explist; 392*5827Srrh if (auxval = (val == CM)) 393*5827Srrh shift; 394597Sbill } while (auxval); 395*5827Srrh } /* there existed an expression at all */ 396597Sbill 397597Sbill flushfield(curlen); 398597Sbill if ( ( curlen == NBPW/4) && bitoff) 399632Shenry dotp->e_xvalue ++; 400597Sbill break; 401597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 402597Sbill 403597Sbill case ISPACE: /* .space <expr> */ 404597Sbill shift; 405597Sbill expr(locxp, val); 406*5827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 407597Sbill yyerror("Space size not absolute"); 408632Shenry space_value = locxp->e_xvalue; 409597Sbill ospace: 410597Sbill flushfield(NBPW/4); 411597Sbill #ifdef UNIX 412597Sbill while (space_value > 96){ 413597Sbill outs(strbuf[2].str, 96); 414597Sbill space_value -= 96; 415597Sbill } 416597Sbill outs(strbuf[2].str, space_value); 417597Sbill #endif UNIX 418597Sbill #ifdef VMS 419632Shenry dotp->e_xvalue += space_value; /*bump pc*/ 420597Sbill if (passno==2){ 421597Sbill if(*(strbuf[2].str)==0) { 422597Sbill puchar(vms_obj_ptr,81); /* AUGR */ 423597Sbill pulong(vms_obj_ptr,space_value);/* incr */ 424597Sbill } else yyerror("VMS, encountered non-0 .space"); 425597Sbill if ((vms_obj_ptr-sobuf) > 400) { 426597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 427597Sbill vms_obj_ptr=sobuf+1; /*pur buf*/ 428597Sbill } 429597Sbill } 430597Sbill #endif VMS 431597Sbill break; 432597Sbill 433597Sbill #ifdef UNIX 434647Shenry /* 435647Shenry * .fill rep, size, value 436647Shenry * repeat rep times: fill size bytes with (truncated) value 437647Shenry * size must be between 1 and 8 438647Shenry */ 439647Shenry case IFILL: 440597Sbill shift; 441597Sbill expr(locxp, val); 442*5827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 443597Sbill yyerror("Fill repetition count not absolute"); 444647Shenry fill_rep = locxp->e_xvalue; 445597Sbill shiftover(CM); 446597Sbill expr(locxp, val); 447*5827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 448647Shenry yyerror("Fill size not absolute"); 449647Shenry fill_size = locxp->e_xvalue; 450647Shenry if (fill_size <= 0 || fill_size > 8) 451647Shenry yyerror("Fill count not in in 1..8"); 452647Shenry shiftover(CM); 453647Shenry expr(locxp, val); 454*5827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 455*5827Srrh yyerror("Fill value not absolute"); 456597Sbill flushfield(NBPW/4); 457647Shenry if (passno == 1) { 458*5827Srrh dotp->e_xvalue += fill_rep * fill_size; 459647Shenry } else { 460647Shenry while(fill_rep-- > 0) 461*5827Srrh bwrite((char *)&locxp->e_xvalue, fill_size, txtfil); 462647Shenry } 463597Sbill break; 464597Sbill #endif UNIX 465597Sbill 466597Sbill case IASCII: /* .ascii [ <stringlist> ] */ 467597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 468597Sbill auxval = val; 469597Sbill shift; 470597Sbill 471597Sbill /* 472597Sbill * Code to consume a string list 473597Sbill * 474597Sbill * stringlist: empty | STRING | stringlist STRING 475597Sbill */ 476597Sbill while (val == STRING){ 477597Sbill flushfield(NBPW/4); 478597Sbill if (bitoff) 479632Shenry dotp->e_xvalue++; 480597Sbill stringp = (struct strdesc *)yylval; 481597Sbill #ifdef UNIX 482597Sbill outs(stringp->str, stringp->str_lg); 483597Sbill #endif UNIX 484597Sbill #ifdef VMS 485597Sbill { 486*5827Srrh reg int i; 487597Sbill for (i=0; i < stringp->str_lg; i++){ 488632Shenry dotp->e_xvalue += 1; 489597Sbill if (passno==2){ 490597Sbill puchar(vms_obj_ptr,-1); 491597Sbill puchar(vms_obj_ptr,stringp->str[i]); 492597Sbill if (vms_obj_ptr-sobuf > 400) { 493597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 494597Sbill vms_obj_ptr = sobuf + 1; 495597Sbill } 496597Sbill } 497597Sbill } 498597Sbill } 499597Sbill #endif VMS 500597Sbill shift; /*over the STRING*/ 501597Sbill if (val == CM) /*could be a split string*/ 502597Sbill shift; 503597Sbill } 504597Sbill 505597Sbill if (auxval == IASCIZ){ 506597Sbill flushfield(NBPW/4); 507597Sbill #ifdef UNIX 508597Sbill outb(0); 509597Sbill #endif UNIX 510597Sbill #ifdef VMS 511597Sbill if (passno == 2) { 512597Sbill puchar(vms_obj_ptr,-1); 513597Sbill puchar(vms_obj_ptr,0); 514597Sbill } 515632Shenry dotp->e_xvalue += 1; 516597Sbill #endif VMS 517597Sbill } 518597Sbill break; 519597Sbill 520597Sbill case IORG: /* .org <expr> */ 521597Sbill shift; 522597Sbill expr(locxp, val); 523597Sbill 524*5827Srrh if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */ 525597Sbill orgwarn++; 526632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 527597Sbill yyerror("Illegal expression to set origin"); 528632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 529597Sbill if (space_value < 0) 530597Sbill yyerror("Backwards 'org'"); 531597Sbill goto ospace; 532597Sbill break; 533597Sbill 534597Sbill /* 535597Sbill * 536597Sbill * Process stabs. Stabs are created only by the f77 537597Sbill * and the C compiler with the -g flag set. 538597Sbill * We only look at the stab ONCE, during pass 1, and 539597Sbill * virtually remove the stab from the intermediate file 540597Sbill * so it isn't seen during pass2. This makes for some 541597Sbill * hairy processing to handle labels occuring in 542597Sbill * stab entries, but since most expressions in the 543597Sbill * stab are integral we save lots of time in the second 544597Sbill * pass by not looking at the stabs. 545597Sbill * A stab that is tagged floating will be bumped during 546597Sbill * the jxxx resolution phase. A stab tagged fixed will 547597Sbill * not be be bumped. 548597Sbill * 549597Sbill * .stab: Old fashioned stabs 550597Sbill * .stabn: For stabs without names 551597Sbill * .stabs: For stabs with string names 552597Sbill * .stabd: For stabs for line numbers or bracketing, 553597Sbill * without a string name, without 554597Sbill * a final expression. The value of the 555597Sbill * final expression is taken to be the current 556597Sbill * location counter, and is patched by the 2nd pass 557597Sbill * 558674Shenry * .stab{<expr>,}*NCPS,<expr>, <expr>, <expr>, <expr> 559597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 560597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 561597Sbill * .stabd <expr>, <expr>, <expr> # . 562597Sbill */ 563597Sbill case ISTAB: 564597Sbill #ifndef FLEXNAMES 565597Sbill stabname = ".stab"; 566597Sbill if (passno == 2) goto errorfix; 567597Sbill stpt = (struct symtab *)yylval; 568597Sbill /* 569597Sbill * Make a pointer to the .stab slot. 570597Sbill * There is a pointer in the way (stpt), and 571597Sbill * tokptr points to the next token. 572597Sbill */ 573597Sbill stabstart = tokptr; 574597Sbill (char *)stabstart -= sizeof(struct symtab *); 575*5827Srrh (char *)stabstart -= sizeof(bytetoktype); 576597Sbill shift; 577674Shenry for (argcnt = 0; argcnt < NCPS; argcnt++){ 578597Sbill expr(locxp, val); 579632Shenry stpt->s_name[argcnt] = locxp->e_xvalue; 580597Sbill xp = explist; 581597Sbill shiftover(CM); 582597Sbill } 583597Sbill goto tailstab; 584597Sbill #else FLEXNAMES 585597Sbill yyerror(".stab directive not supported in; report this compiler bug to system administrator"); 586597Sbill goto errorfix; 587597Sbill #endif FLEXNAMES 588597Sbill 589597Sbill tailstab: 590597Sbill expr(locxp, val); 591632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 592*5827Srrh yyerror("Invalid type in %s", stabname); 593597Sbill goto errorfix; 594597Sbill } 595632Shenry stpt->s_ptype = locxp->e_xvalue; 596597Sbill shiftover(CM); 597597Sbill expr(locxp, val); 598632Shenry stpt->s_other = locxp->e_xvalue; 599597Sbill shiftover(CM); 600597Sbill expr(locxp, val); 601632Shenry stpt->s_desc = locxp->e_xvalue; 602597Sbill shiftover(CM); 603597Sbill exprisname = 0; 604597Sbill expr(locxp, val); 605632Shenry p = locxp->e_xname; 606597Sbill if (p == NULL) { /*absolute expr to begin with*/ 607632Shenry stpt->s_value = locxp->e_xvalue; 608632Shenry stpt->s_index = dotp - usedot; 609597Sbill if (exprisname){ 610632Shenry switch(stpt->s_ptype){ 611597Sbill case N_GSYM: 612597Sbill case N_FNAME: 613597Sbill case N_RSYM: 614597Sbill case N_SSYM: 615597Sbill case N_LSYM: 616597Sbill case N_PSYM: 617597Sbill case N_BCOMM: 618597Sbill case N_ECOMM: 619597Sbill case N_LENG: 620632Shenry stpt->s_tag = STABFIXED; 621597Sbill break; 622597Sbill default: 623632Shenry stpt->s_tag = STABFLOATING; 624597Sbill break; 625597Sbill } 626597Sbill } else 627632Shenry stpt->s_tag = STABFIXED; 628597Sbill } 629597Sbill else { /*really have a name*/ 630632Shenry stpt->s_dest = locxp->e_xname; 631632Shenry stpt->s_index = p->s_index; 632632Shenry stpt->s_type = p->s_type | STABFLAG; 633597Sbill /* 634597Sbill * We will assign a more accruate 635597Sbill * guess of locxp's location when 636597Sbill * we sort the symbol table 637597Sbill * The final value of value is 638597Sbill * given by stabfix() 639597Sbill */ 640632Shenry stpt->s_tag = STABFLOATING; 641597Sbill } 642597Sbill /* 643597Sbill * tokptr now points at one token beyond 644597Sbill * the current token stored in val and yylval, 645597Sbill * which are the next tokens after the end of 646597Sbill * this .stab directive. This next token must 647597Sbill * be either a SEMI or NL, so is of width just 648597Sbill * one. Therefore, to point to the next token 649597Sbill * after the end of this stab, just back up one.. 650597Sbill */ 651*5827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 652597Sbill break; /*end of the .stab*/ 653597Sbill 654597Sbill case ISTABDOT: 655597Sbill stabname = ".stabd"; 656597Sbill stpt = (struct symtab *)yylval; 657597Sbill /* 658597Sbill * We clobber everything after the 659597Sbill * .stabd and its pointer... we MUST 660597Sbill * be able to get back to this .stabd 661597Sbill * so that we can resolve its final value 662597Sbill */ 663597Sbill stabstart = tokptr; 664597Sbill shift; /*over the ISTABDOT*/ 665597Sbill if (passno == 1){ 666597Sbill expr(locxp, val); 667632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 668597Sbill yyerror("Invalid type in .stabd"); 669597Sbill goto errorfix; 670597Sbill } 671632Shenry stpt->s_ptype = locxp->e_xvalue; 672597Sbill shiftover(CM); 673597Sbill expr(locxp, val); 674632Shenry stpt->s_other = locxp->e_xvalue; 675597Sbill shiftover(CM); 676597Sbill expr(locxp, val); 677632Shenry stpt->s_desc = locxp->e_xvalue; 678597Sbill /* 679597Sbill * 680597Sbill * Now, clobber everything but the 681597Sbill * .stabd pseudo and the pointer 682597Sbill * to its symbol table entry 683597Sbill * tokptr points to the next token, 684597Sbill * build the skip up to this 685597Sbill */ 686*5827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 687597Sbill } 688597Sbill /* 689597Sbill * pass 1: Assign a good guess for its position 690597Sbill * (ensures they are sorted into right place)/ 691597Sbill * pass 2: Fix the actual value 692597Sbill */ 693632Shenry stpt->s_value = dotp->e_xvalue; 694632Shenry stpt->s_index = dotp - usedot; 695632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 696597Sbill break; 697597Sbill 698597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 699597Sbill 700597Sbill case ISTABSTR: stabname = ".stabs"; 701597Sbill shortstab: 702597Sbill auxval = val; 703597Sbill if (passno == 2) goto errorfix; 704597Sbill stpt = (struct symtab *)yylval; 705597Sbill stabstart = tokptr; 706*5827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *); 707*5827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype); 708597Sbill shift; 709597Sbill if (auxval == ISTABSTR){ 710597Sbill stringp = (struct strdesc *)yylval; 711597Sbill shiftover(STRING); 712597Sbill #ifndef FLEXNAMES 713597Sbill auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; 714597Sbill #else 715597Sbill stringp->str[stringp->str_lg] = 0; 716597Sbill #endif 717597Sbill shiftover(CM); 718597Sbill } else { 719597Sbill stringp = &(strbuf[2]); 720597Sbill #ifndef FLEXNAMES 721597Sbill auxval = NCPS; 722597Sbill #endif 723597Sbill } 724597Sbill #ifndef FLEXNAMES 725632Shenry movestr(stpt->s_name, stringp->str, auxval); 726597Sbill #else 727632Shenry stpt->s_name = savestr(stringp->str); 728597Sbill #endif 729597Sbill goto tailstab; 730597Sbill break; 731597Sbill 732*5827Srrh case ICOMM: /* .comm <name> , <expr> */ 733597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 734597Sbill auxval = val; 735597Sbill shift; 736597Sbill np = (struct symtab *)yylval; 737597Sbill shiftover(NAME); 738597Sbill shiftover(CM); 739597Sbill expr(locxp, val); 740597Sbill 741*5827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 742597Sbill yyerror("comm size not absolute"); 743*5827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) 744632Shenry #ifdef FLEXNAMES 745632Shenry yyerror("Redefinition of %s", 746632Shenry #else not FLEXNAMES 747632Shenry yyerror("Redefinition of %.*s", 748632Shenry NCPS, 749632Shenry #endif not FLEXNAMES 750632Shenry np->s_name); 751597Sbill if (passno==1) { 752632Shenry np->s_value = locxp->e_xvalue; 753597Sbill if (auxval == ICOMM) 754632Shenry np->s_type |= XXTRN; 755597Sbill else { 756632Shenry np->s_type &= ~XTYPE; 757632Shenry np->s_type |= XBSS; 758597Sbill } 759597Sbill } 760597Sbill break; 761597Sbill 762597Sbill case IALIGN: /* .align <expr> */ 763597Sbill stpt = (struct symtab *)yylval; 764597Sbill shift; 765597Sbill expr(locxp, val); 766597Sbill jalign(locxp, stpt); 767597Sbill break; 768597Sbill 769597Sbill case INST0: /* instructions w/o arguments*/ 770*5827Srrh insout(yyopcode, (struct arg *)0, 0); 771597Sbill shift; 772597Sbill break; 773597Sbill 774597Sbill case INSTn: /* instructions with arguments*/ 775597Sbill case IJXXX: /* UNIX style jump instructions */ 776597Sbill auxval = val; 777597Sbill /* 778597Sbill * Code to process an argument list 779597Sbill */ 780597Sbill ap = arglist; 781597Sbill xp = explist; 782597Sbill 783597Sbill shift; /* bring in the first token for the arg list*/ 784597Sbill 785597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 786597Sbill /* 787597Sbill * code to process an argument proper 788597Sbill */ 789597Sbill sawindex = sawmul = sawsize = 0; 790597Sbill { 791597Sbill switch(val) { 792597Sbill 793597Sbill default: 794597Sbill disp: 795597Sbill if( !(INTOKSET(val, 796597Sbill EBEGOPS 797597Sbill +YUKKYEXPRBEG 798597Sbill +SAFEEXPRBEG)) ) { 799597Sbill ERROR("expression expected"); 800597Sbill } 801632Shenry expr(ap->a_xp,val); 802597Sbill overdisp: 803597Sbill if ( val == LP || sawsize){ 804597Sbill shiftover(LP); 805597Sbill findreg(regno); 806597Sbill shiftover(RP); 807632Shenry ap->a_atype = ADISP; 808632Shenry ap->a_areg1 = regno; 809597Sbill } else { 810632Shenry ap->a_atype = AEXP; 811632Shenry ap->a_areg1 = 0; 812597Sbill } 813597Sbill goto index; 814597Sbill 815597Sbill case SIZESPEC: 816597Sbill sizespec: 817597Sbill sawsize = yylval; 818597Sbill shift; 819597Sbill goto disp; 820597Sbill 821597Sbill case REG: 822597Sbill case REGOP: 823597Sbill findreg(regno); 824632Shenry ap->a_atype = AREG; 825632Shenry ap->a_areg1 = regno; 826597Sbill break; 827597Sbill 828597Sbill case MUL: 829597Sbill sawmul = 1; 830597Sbill shift; 831597Sbill if (val == LP) goto base; 832597Sbill if (val == LITOP) goto imm; 833597Sbill if (val == SIZESPEC) goto sizespec; 834597Sbill if (INTOKSET(val, 835597Sbill EBEGOPS 836597Sbill +YUKKYEXPRBEG 837597Sbill +SAFEEXPRBEG)) goto disp; 838597Sbill ERROR("expression, '(' or '$' expected"); 839597Sbill break; 840597Sbill 841597Sbill case LP: 842597Sbill base: 843597Sbill shift; /*consume the LP*/ 844597Sbill /* 845597Sbill * hack the ambiguity of 846597Sbill * movl (expr) (rn), ... 847597Sbill * note that (expr) could also 848597Sbill * be (rn) (by special hole in the 849597Sbill * grammar), which we ensure 850597Sbill * means register indirection, instead 851597Sbill * of an expression with value n 852597Sbill */ 853597Sbill if (val != REG && val != REGOP){ 854597Sbill droppedLP = 1; 855632Shenry val = exprparse(val, &(ap->a_xp)); 856597Sbill droppedLP = 0; 857597Sbill goto overdisp; 858597Sbill } 859597Sbill findreg(regno); 860597Sbill shiftover(RP); 861597Sbill if (val == PLUS){ 862597Sbill shift; 863632Shenry ap->a_atype = AINCR; 864597Sbill } else 865632Shenry ap->a_atype = ABASE; 866632Shenry ap->a_areg1 = regno; 867597Sbill goto index; 868597Sbill 869597Sbill case LITOP: 870597Sbill imm: 871597Sbill shift; 872597Sbill expr(locxp, val); 873632Shenry ap->a_atype = AIMM; 874632Shenry ap->a_areg1 = 0; 875632Shenry ap->a_xp = locxp; 876597Sbill goto index; 877597Sbill 878597Sbill case MP: 879597Sbill shift; /* -(reg) */ 880597Sbill findreg(regno); 881597Sbill shiftover(RP); 882632Shenry ap->a_atype = ADECR; 883632Shenry ap->a_areg1 = regno; 884597Sbill index: /*look for [reg] */ 885597Sbill if (val == LB){ 886597Sbill shift; 887597Sbill findreg(regno); 888597Sbill shiftover(RB); 889597Sbill sawindex = 1; 890632Shenry ap->a_areg2 = regno; 891597Sbill } 892597Sbill break; 893597Sbill 894597Sbill } /*end of the switch to process an arg*/ 895597Sbill } /*end of processing an argument*/ 896597Sbill 897597Sbill if (sawmul){ 898597Sbill /* 899597Sbill * Make a concession for *(%r) 900597Sbill * meaning *0(%r) 901597Sbill */ 902632Shenry if (ap->a_atype == ABASE) { 903632Shenry ap->a_atype = ADISP; 904632Shenry xp->e_xtype = XABS; 905*5827Srrh xp->e_number = Znumber; 906*5827Srrh xp->e_number.num_tag = TYPL; 907632Shenry xp->e_xloc = 0; 908632Shenry ap->a_xp = xp++; 909597Sbill } 910632Shenry ap->a_atype |= ASTAR; 911597Sbill sawmul = 0; 912597Sbill } 913597Sbill if (sawindex){ 914632Shenry ap->a_atype |= AINDX; 915597Sbill sawindex = 0; 916597Sbill } 917632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 918597Sbill if (val != CM) break; 919597Sbill shiftover(CM); 920597Sbill } /*processing all the arguments*/ 921597Sbill 922597Sbill if (argcnt > 6){ 923597Sbill yyerror("More than 6 arguments"); 924597Sbill goto errorfix; 925597Sbill } 926597Sbill 927*5827Srrh insout(yyopcode, arglist, 928597Sbill auxval == INSTn ? argcnt : - argcnt); 929597Sbill break; 930597Sbill 931*5827Srrh case IQUAD: toconv = TYPQ; goto bignumlist; 932*5827Srrh case IOCTA: toconv = TYPO; goto bignumlist; 933*5827Srrh 934*5827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist; 935*5827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist; 936*5827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist; 937*5827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist; 938*5827Srrh bignumlist: 939597Sbill /* 940*5827Srrh * eat a list of non 32 bit numbers. 941*5827Srrh * IQUAD and IOCTA can, possibly, return 942*5827Srrh * INT's, if the numbers are "small". 943*5827Srrh * 944*5827Srrh * The value of the numbers is coming back 945*5827Srrh * as an expression, NOT in yybignum. 946597Sbill */ 947*5827Srrh shift; /* over the opener */ 948*5827Srrh if ((val == BIGNUM) || (val == INT)){ 949597Sbill do{ 950*5827Srrh if ((val != BIGNUM) && (val != INT)){ 951*5827Srrh ERROR(ty_float[toconv] 952*5827Srrh ? "floating number expected" 953*5827Srrh : "integer number expected" ); 954597Sbill } 955*5827Srrh dotp->e_xvalue += ty_nbyte[toconv]; 956*5827Srrh if (passno == 2){ 957*5827Srrh bignumwrite( 958*5827Srrh ((struct exp *)yylval)->e_number, 959*5827Srrh toconv); 960597Sbill } 961597Sbill xp = explist; 962*5827Srrh shift; /* over this number */ 963*5827Srrh if (auxval = (val == CM)) 964*5827Srrh shift; /* over the comma */ 965*5827Srrh } while (auxval); /* as long as there are commas */ 966597Sbill } 967597Sbill break; 968*5827Srrh /* end of the case for initialized big numbers */ 969597Sbill } /*end of the switch for looking at each reserved word*/ 970597Sbill 971*5827Srrh continue; 972597Sbill 973597Sbill errorfix: 974597Sbill /* 975597Sbill * got here by either requesting to skip to the 976597Sbill * end of this statement, or by erroring out and 977597Sbill * wanting to apply panic mode recovery 978597Sbill */ 979597Sbill while ( (val != NL) 980597Sbill && (val != SEMI) 981597Sbill && (val != PARSEEOF) 982597Sbill ){ 983597Sbill shift; 984597Sbill } 985597Sbill if (val == NL) 986597Sbill lineno++; 987597Sbill shift; 988597Sbill 989597Sbill } /*end of the loop to read the entire file, line by line*/ 990597Sbill 991597Sbill } /*end of yyparse*/ 992597Sbill 993597Sbill /* 994597Sbill * Process a register declaration of the form 995597Sbill * % <expr> 996597Sbill * 997597Sbill * Note: 998597Sbill * The scanner has already processed funny registers of the form 999597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 1000597Sbill * preceding zero digit). If there was any space between the % and 1001597Sbill * the digit, the scanner wouldn't have recognized it, so we 1002597Sbill * hack it out here. 1003597Sbill */ 1004*5827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ 1005*5827Srrh inttoktype val; /*what the read head is sitting on*/ 1006597Sbill int *regnoback; /*call by return*/ 1007597Sbill { 1008*5827Srrh reg struct exp *locxp; 1009*5827Srrh struct exp *loc1xp; 1010*5827Srrh struct exp **ptrloc1xp = & loc1xp; 1011597Sbill 1012597Sbill expr(locxp, val); /*and leave the current read head with value*/ 1013597Sbill if ( (passno == 2) && 1014*5827Srrh ( (locxp->e_xtype & XTYPE) != XABS 1015*5827Srrh || (locxp->e_xvalue < 0) 1016*5827Srrh || (locxp->e_xvalue >= 16) 1017597Sbill ) 1018597Sbill ){ 1019597Sbill yyerror("Illegal register"); 1020597Sbill return(0); 1021597Sbill } 1022632Shenry *regnoback = locxp->e_xvalue; 1023597Sbill return(val); 1024597Sbill } 1025597Sbill 1026597Sbill /*VARARGS1*/ 1027597Sbill yyerror(s, a1, a2,a3,a4,a5) 1028597Sbill char *s; 1029597Sbill { 1030597Sbill 1031649Shenry #define sink stdout 1032597Sbill 1033*5827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1034597Sbill fprintf(sink, "Assembler:\n"); 1035597Sbill anyerrs++; 1036*5827Srrh if (silent) 1037*5827Srrh return; 1038597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1039597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1040597Sbill fprintf(sink, "\n"); 1041*5827Srrh #undef sink 1042597Sbill } 1043676Shenry 1044676Shenry /*VARARGS1*/ 1045676Shenry yywarning(s, a1, a2,a3,a4,a5) 1046676Shenry char *s; 1047676Shenry { 1048676Shenry #define sink stdout 1049*5827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1050676Shenry fprintf(sink, "Assembler:\n"); 1051*5827Srrh anywarnings++; 1052*5827Srrh if (silent) 1053*5827Srrh return; 1054676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1055676Shenry fprintf(sink, s, a1, a2,a3,a4,a5); 1056676Shenry fprintf(sink, "\n"); 1057*5827Srrh #undef sink 1058676Shenry } 1059