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