15827Srrh /* 25827Srrh * Copyright (c) 1982 Regents of the University of California 35827Srrh */ 45827Srrh #ifndef lint 5*12945Srrh static char sccsid[] = "@(#)asparse.c 4.10 06/09/83"; 65827Srrh #endif not lint 75827Srrh 8597Sbill #include <stdio.h> 9597Sbill #include "as.h" 10597Sbill #include "asscan.h" 11597Sbill #include "assyms.h" 125827Srrh #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*/ 345827Srrh struct Opcode yyopcode; /* lexical value for an opcode */ 355827Srrh 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 495827Srrh yyparse() 50597Sbill { 515827Srrh reg struct exp *locxp; 525827Srrh /* 535827Srrh * loc1xp and ptrloc1xp are used in the 545827Srrh * expression lookahead 555827Srrh */ 565827Srrh struct exp *loc1xp; /*must be non register*/ 575827Srrh struct exp **ptrloc1xp = & loc1xp; 585827Srrh struct exp *pval; /*hacking expr:expr*/ 59597Sbill 605827Srrh reg struct symtab *np; 615827Srrh reg int argcnt; 62597Sbill 635827Srrh reg inttoktype val; /*what yylex gives*/ 645827Srrh reg inttoktype auxval; /*saves val*/ 65597Sbill 665827Srrh reg struct arg *ap; /*first free argument*/ 67597Sbill 685827Srrh reg struct symtab *p; 695827Srrh reg struct symtab *stpt; 70597Sbill 715827Srrh struct strdesc *stringp; /*handles string lists*/ 72597Sbill 735827Srrh int regno; /*handles arguments*/ 745827Srrh int *ptrregno = ®no; 755827Srrh int sawmul; /*saw * */ 765827Srrh int sawindex; /*saw [rn]*/ 775827Srrh int sawsize; 785827Srrh int seg_type; /*the kind of segment: data or text*/ 795827Srrh int seg_number; /*the segment number*/ 805827Srrh int space_value; /*how much .space needs*/ 815827Srrh int fill_rep; /*how many reps for .fill */ 825827Srrh int fill_size; /*how many bytes for .fill */ 83597Sbill 845827Srrh int field_width; /*how wide a field is to be*/ 855827Srrh int field_value; /*the value to stuff in a field*/ 865827Srrh char *stabname; /*name of stab dealing with*/ 875827Srrh ptrall stabstart; /*where the stab starts in the buffer*/ 885827Srrh int reloc_how; /* how to relocate expressions */ 895827Srrh 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; 1025827Srrh if (val != COLON){ 1035827Srrh yyerror("Local label %d is not followed by a ':' for a label definition", 1045827Srrh i); 1055827Srrh goto errorfix; 1065827Srrh } 107597Sbill if (i < 0 || i > 9) { 108597Sbill yyerror("Local labels are 0-9"); 109597Sbill goto errorfix; 110597Sbill } 1115827Srrh (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: 2075827Srrh 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; 2675827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) 2685827Srrh yyerror("Illegal second argument to lsym"); 2695827Srrh np->s_value = locxp->e_xvalue; 2705827Srrh 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 { 2955827Srrh if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 2965827Srrh || (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; 3345827Srrh case IWORD: curlen = NBPW/2; goto elist; 3355827Srrh 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); 3605827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 3615827Srrh yyerror("Width not absolute"); 362632Shenry field_width = locxp->e_xvalue; 363597Sbill locxp = pval; 3645827Srrh 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 3735827Srrh 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; 3925827Srrh if (auxval = (val == CM)) 3935827Srrh shift; 394597Sbill } while (auxval); 3955827Srrh } /* 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); 4065827Srrh 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); 4425827Srrh 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); 4475827Srrh 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); 4545827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 4555827Srrh yyerror("Fill value not absolute"); 456597Sbill flushfield(NBPW/4); 457647Shenry if (passno == 1) { 4585827Srrh dotp->e_xvalue += fill_rep * fill_size; 459647Shenry } else { 460647Shenry while(fill_rep-- > 0) 4615827Srrh 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 { 4865827Srrh 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 5245827Srrh 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 *); 5755827Srrh (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)){ 5925827Srrh 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 */ 64012591Scsvaf /* 64112591Scsvaf * For exprs of the form (name + value) one needs to remember locxp->e_xvalue 64212591Scsvaf * for use in stabfix. The right place to keep this is in stpt->s_value 64312591Scsvaf * however this gets corrupted at an unknown point. 64412591Scsvaf * As a bandaid hack the value is preserved in s_desc and s_other (a 64512591Scsvaf * short and a char). This destroys these two values and will 64612591Scsvaf * be fixed. May 19 ,1983 Alastair Fyfe 64712591Scsvaf */ 64812591Scsvaf if(locxp->e_xvalue) { 64912591Scsvaf stpt->s_other = (locxp->e_xvalue >> 16); 65012591Scsvaf stpt->s_desc = (locxp->e_xvalue & 0x0000ffff); 65112591Scsvaf stpt->s_tag = STABFLOATING; 65212591Scsvaf } 653597Sbill } 654597Sbill /* 655597Sbill * tokptr now points at one token beyond 656597Sbill * the current token stored in val and yylval, 657597Sbill * which are the next tokens after the end of 658597Sbill * this .stab directive. This next token must 659597Sbill * be either a SEMI or NL, so is of width just 660597Sbill * one. Therefore, to point to the next token 661597Sbill * after the end of this stab, just back up one.. 662597Sbill */ 6635827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 664597Sbill break; /*end of the .stab*/ 665597Sbill 666597Sbill case ISTABDOT: 667597Sbill stabname = ".stabd"; 668597Sbill stpt = (struct symtab *)yylval; 669597Sbill /* 670597Sbill * We clobber everything after the 671597Sbill * .stabd and its pointer... we MUST 672597Sbill * be able to get back to this .stabd 673597Sbill * so that we can resolve its final value 674597Sbill */ 675597Sbill stabstart = tokptr; 676597Sbill shift; /*over the ISTABDOT*/ 677597Sbill if (passno == 1){ 678597Sbill expr(locxp, val); 679632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 680597Sbill yyerror("Invalid type in .stabd"); 681597Sbill goto errorfix; 682597Sbill } 683632Shenry stpt->s_ptype = locxp->e_xvalue; 684597Sbill shiftover(CM); 685597Sbill expr(locxp, val); 686632Shenry stpt->s_other = locxp->e_xvalue; 687597Sbill shiftover(CM); 688597Sbill expr(locxp, val); 689632Shenry stpt->s_desc = locxp->e_xvalue; 690597Sbill /* 691597Sbill * 692597Sbill * Now, clobber everything but the 693597Sbill * .stabd pseudo and the pointer 694597Sbill * to its symbol table entry 695597Sbill * tokptr points to the next token, 696597Sbill * build the skip up to this 697597Sbill */ 6985827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 699597Sbill } 700597Sbill /* 701597Sbill * pass 1: Assign a good guess for its position 702597Sbill * (ensures they are sorted into right place)/ 703597Sbill * pass 2: Fix the actual value 704597Sbill */ 705632Shenry stpt->s_value = dotp->e_xvalue; 706632Shenry stpt->s_index = dotp - usedot; 707632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 708597Sbill break; 709597Sbill 710597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 711597Sbill 712597Sbill case ISTABSTR: stabname = ".stabs"; 713597Sbill shortstab: 714597Sbill auxval = val; 715597Sbill if (passno == 2) goto errorfix; 716597Sbill stpt = (struct symtab *)yylval; 717597Sbill stabstart = tokptr; 7185827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *); 7195827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype); 720597Sbill shift; 721597Sbill if (auxval == ISTABSTR){ 722597Sbill stringp = (struct strdesc *)yylval; 723597Sbill shiftover(STRING); 724597Sbill #ifndef FLEXNAMES 725597Sbill auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; 726597Sbill #else 727597Sbill stringp->str[stringp->str_lg] = 0; 728597Sbill #endif 729597Sbill shiftover(CM); 730597Sbill } else { 731597Sbill stringp = &(strbuf[2]); 732597Sbill #ifndef FLEXNAMES 733597Sbill auxval = NCPS; 734597Sbill #endif 735597Sbill } 736597Sbill #ifndef FLEXNAMES 737632Shenry movestr(stpt->s_name, stringp->str, auxval); 738597Sbill #else 739632Shenry stpt->s_name = savestr(stringp->str); 740597Sbill #endif 741597Sbill goto tailstab; 742597Sbill break; 743597Sbill 7445827Srrh case ICOMM: /* .comm <name> , <expr> */ 745597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 746597Sbill auxval = val; 747597Sbill shift; 748597Sbill np = (struct symtab *)yylval; 749597Sbill shiftover(NAME); 750597Sbill shiftover(CM); 751597Sbill expr(locxp, val); 752597Sbill 7535827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 754597Sbill yyerror("comm size not absolute"); 7555827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) 756632Shenry #ifdef FLEXNAMES 757632Shenry yyerror("Redefinition of %s", 758632Shenry #else not FLEXNAMES 759632Shenry yyerror("Redefinition of %.*s", 760632Shenry NCPS, 761632Shenry #endif not FLEXNAMES 762632Shenry np->s_name); 763597Sbill if (passno==1) { 764632Shenry np->s_value = locxp->e_xvalue; 765597Sbill if (auxval == ICOMM) 766632Shenry np->s_type |= XXTRN; 767597Sbill else { 768632Shenry np->s_type &= ~XTYPE; 769632Shenry np->s_type |= XBSS; 770597Sbill } 771597Sbill } 772597Sbill break; 773597Sbill 774597Sbill case IALIGN: /* .align <expr> */ 775597Sbill stpt = (struct symtab *)yylval; 776597Sbill shift; 777597Sbill expr(locxp, val); 778597Sbill jalign(locxp, stpt); 779597Sbill break; 780597Sbill 781597Sbill case INST0: /* instructions w/o arguments*/ 7825827Srrh insout(yyopcode, (struct arg *)0, 0); 783597Sbill shift; 784597Sbill break; 785597Sbill 786597Sbill case INSTn: /* instructions with arguments*/ 787597Sbill case IJXXX: /* UNIX style jump instructions */ 788597Sbill auxval = val; 789597Sbill /* 790597Sbill * Code to process an argument list 791597Sbill */ 792597Sbill ap = arglist; 793597Sbill xp = explist; 794597Sbill 795597Sbill shift; /* bring in the first token for the arg list*/ 796597Sbill 797597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 798597Sbill /* 799597Sbill * code to process an argument proper 800597Sbill */ 801597Sbill sawindex = sawmul = sawsize = 0; 802597Sbill { 803597Sbill switch(val) { 804597Sbill 805597Sbill default: 806597Sbill disp: 807597Sbill if( !(INTOKSET(val, 808597Sbill EBEGOPS 809597Sbill +YUKKYEXPRBEG 810597Sbill +SAFEEXPRBEG)) ) { 811597Sbill ERROR("expression expected"); 812597Sbill } 813632Shenry expr(ap->a_xp,val); 814597Sbill overdisp: 815597Sbill if ( val == LP || sawsize){ 816597Sbill shiftover(LP); 817597Sbill findreg(regno); 818597Sbill shiftover(RP); 819632Shenry ap->a_atype = ADISP; 820632Shenry ap->a_areg1 = regno; 821597Sbill } else { 822632Shenry ap->a_atype = AEXP; 823632Shenry ap->a_areg1 = 0; 824597Sbill } 825597Sbill goto index; 826597Sbill 827597Sbill case SIZESPEC: 828597Sbill sizespec: 829597Sbill sawsize = yylval; 830597Sbill shift; 831597Sbill goto disp; 832597Sbill 833597Sbill case REG: 834597Sbill case REGOP: 835597Sbill findreg(regno); 836632Shenry ap->a_atype = AREG; 837632Shenry ap->a_areg1 = regno; 838597Sbill break; 839597Sbill 840597Sbill case MUL: 841597Sbill sawmul = 1; 842597Sbill shift; 843597Sbill if (val == LP) goto base; 844597Sbill if (val == LITOP) goto imm; 845597Sbill if (val == SIZESPEC) goto sizespec; 846597Sbill if (INTOKSET(val, 847597Sbill EBEGOPS 848597Sbill +YUKKYEXPRBEG 849597Sbill +SAFEEXPRBEG)) goto disp; 850597Sbill ERROR("expression, '(' or '$' expected"); 851597Sbill break; 852597Sbill 853597Sbill case LP: 854597Sbill base: 855597Sbill shift; /*consume the LP*/ 856597Sbill /* 857597Sbill * hack the ambiguity of 858597Sbill * movl (expr) (rn), ... 859597Sbill * note that (expr) could also 860597Sbill * be (rn) (by special hole in the 861597Sbill * grammar), which we ensure 862597Sbill * means register indirection, instead 863597Sbill * of an expression with value n 864597Sbill */ 865597Sbill if (val != REG && val != REGOP){ 866597Sbill droppedLP = 1; 867632Shenry val = exprparse(val, &(ap->a_xp)); 868597Sbill droppedLP = 0; 869597Sbill goto overdisp; 870597Sbill } 871597Sbill findreg(regno); 872597Sbill shiftover(RP); 873597Sbill if (val == PLUS){ 874597Sbill shift; 875632Shenry ap->a_atype = AINCR; 876597Sbill } else 877632Shenry ap->a_atype = ABASE; 878632Shenry ap->a_areg1 = regno; 879597Sbill goto index; 880597Sbill 881597Sbill case LITOP: 882597Sbill imm: 883597Sbill shift; 884597Sbill expr(locxp, val); 885632Shenry ap->a_atype = AIMM; 886632Shenry ap->a_areg1 = 0; 887632Shenry ap->a_xp = locxp; 888597Sbill goto index; 889597Sbill 890597Sbill case MP: 891597Sbill shift; /* -(reg) */ 892597Sbill findreg(regno); 893597Sbill shiftover(RP); 894632Shenry ap->a_atype = ADECR; 895632Shenry ap->a_areg1 = regno; 896597Sbill index: /*look for [reg] */ 897597Sbill if (val == LB){ 898597Sbill shift; 899597Sbill findreg(regno); 900597Sbill shiftover(RB); 901597Sbill sawindex = 1; 902632Shenry ap->a_areg2 = regno; 903597Sbill } 904597Sbill break; 905597Sbill 906597Sbill } /*end of the switch to process an arg*/ 907597Sbill } /*end of processing an argument*/ 908597Sbill 909597Sbill if (sawmul){ 910597Sbill /* 911597Sbill * Make a concession for *(%r) 912597Sbill * meaning *0(%r) 913597Sbill */ 914632Shenry if (ap->a_atype == ABASE) { 915632Shenry ap->a_atype = ADISP; 916632Shenry xp->e_xtype = XABS; 9175827Srrh xp->e_number = Znumber; 9185827Srrh xp->e_number.num_tag = TYPL; 919632Shenry xp->e_xloc = 0; 920632Shenry ap->a_xp = xp++; 921597Sbill } 922632Shenry ap->a_atype |= ASTAR; 923597Sbill sawmul = 0; 924597Sbill } 925597Sbill if (sawindex){ 926632Shenry ap->a_atype |= AINDX; 927597Sbill sawindex = 0; 928597Sbill } 929632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 930597Sbill if (val != CM) break; 931597Sbill shiftover(CM); 932597Sbill } /*processing all the arguments*/ 933597Sbill 934597Sbill if (argcnt > 6){ 935597Sbill yyerror("More than 6 arguments"); 936597Sbill goto errorfix; 937597Sbill } 938597Sbill 9395827Srrh insout(yyopcode, arglist, 940597Sbill auxval == INSTn ? argcnt : - argcnt); 941597Sbill break; 942597Sbill 9435827Srrh case IQUAD: toconv = TYPQ; goto bignumlist; 9445827Srrh case IOCTA: toconv = TYPO; goto bignumlist; 9455827Srrh 9465827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist; 9475827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist; 9485827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist; 9495827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist; 9505827Srrh bignumlist: 951597Sbill /* 9525827Srrh * eat a list of non 32 bit numbers. 9535827Srrh * IQUAD and IOCTA can, possibly, return 9545827Srrh * INT's, if the numbers are "small". 9555827Srrh * 9565827Srrh * The value of the numbers is coming back 9575827Srrh * as an expression, NOT in yybignum. 958597Sbill */ 9595827Srrh shift; /* over the opener */ 9605827Srrh if ((val == BIGNUM) || (val == INT)){ 961597Sbill do{ 9625827Srrh if ((val != BIGNUM) && (val != INT)){ 9635827Srrh ERROR(ty_float[toconv] 9645827Srrh ? "floating number expected" 9655827Srrh : "integer number expected" ); 966597Sbill } 9675827Srrh dotp->e_xvalue += ty_nbyte[toconv]; 9685827Srrh if (passno == 2){ 9695827Srrh bignumwrite( 9705827Srrh ((struct exp *)yylval)->e_number, 9715827Srrh toconv); 972597Sbill } 973597Sbill xp = explist; 9745827Srrh shift; /* over this number */ 9755827Srrh if (auxval = (val == CM)) 9765827Srrh shift; /* over the comma */ 9775827Srrh } while (auxval); /* as long as there are commas */ 978597Sbill } 979597Sbill break; 9805827Srrh /* end of the case for initialized big numbers */ 981597Sbill } /*end of the switch for looking at each reserved word*/ 982597Sbill 9835827Srrh continue; 984597Sbill 985597Sbill errorfix: 986597Sbill /* 987597Sbill * got here by either requesting to skip to the 988597Sbill * end of this statement, or by erroring out and 989597Sbill * wanting to apply panic mode recovery 990597Sbill */ 991597Sbill while ( (val != NL) 992597Sbill && (val != SEMI) 993597Sbill && (val != PARSEEOF) 994597Sbill ){ 995597Sbill shift; 996597Sbill } 997597Sbill if (val == NL) 998597Sbill lineno++; 999597Sbill shift; 1000597Sbill 1001597Sbill } /*end of the loop to read the entire file, line by line*/ 1002597Sbill 1003597Sbill } /*end of yyparse*/ 1004597Sbill 1005597Sbill /* 1006597Sbill * Process a register declaration of the form 1007597Sbill * % <expr> 1008597Sbill * 1009597Sbill * Note: 1010597Sbill * The scanner has already processed funny registers of the form 1011597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 1012597Sbill * preceding zero digit). If there was any space between the % and 1013597Sbill * the digit, the scanner wouldn't have recognized it, so we 1014597Sbill * hack it out here. 1015597Sbill */ 10165827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ 10175827Srrh inttoktype val; /*what the read head is sitting on*/ 1018597Sbill int *regnoback; /*call by return*/ 1019597Sbill { 10205827Srrh reg struct exp *locxp; 10215827Srrh struct exp *loc1xp; 10225827Srrh struct exp **ptrloc1xp = & loc1xp; 1023597Sbill 1024597Sbill expr(locxp, val); /*and leave the current read head with value*/ 1025597Sbill if ( (passno == 2) && 10265827Srrh ( (locxp->e_xtype & XTYPE) != XABS 10275827Srrh || (locxp->e_xvalue < 0) 10285827Srrh || (locxp->e_xvalue >= 16) 1029597Sbill ) 1030597Sbill ){ 1031597Sbill yyerror("Illegal register"); 1032597Sbill return(0); 1033597Sbill } 1034632Shenry *regnoback = locxp->e_xvalue; 1035597Sbill return(val); 1036597Sbill } 1037*12945Srrh /* 1038*12945Srrh * Shift over error 1039*12945Srrh */ 1040*12945Srrh shiftoerror(token) 1041*12945Srrh int token; 1042*12945Srrh { 1043*12945Srrh char *tok_to_name(); 1044*12945Srrh yyerror("%s expected", tok_to_name(token)); 1045*12945Srrh } 1046597Sbill 1047597Sbill /*VARARGS1*/ 1048597Sbill yyerror(s, a1, a2,a3,a4,a5) 1049597Sbill char *s; 1050597Sbill { 1051597Sbill 1052649Shenry #define sink stdout 1053597Sbill 10545827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1055597Sbill fprintf(sink, "Assembler:\n"); 1056597Sbill anyerrs++; 10575827Srrh if (silent) 10585827Srrh return; 1059597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1060597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1061597Sbill fprintf(sink, "\n"); 10625827Srrh #undef sink 1063597Sbill } 1064676Shenry 1065676Shenry /*VARARGS1*/ 1066676Shenry yywarning(s, a1, a2,a3,a4,a5) 1067676Shenry char *s; 1068676Shenry { 1069676Shenry #define sink stdout 10705827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1071676Shenry fprintf(sink, "Assembler:\n"); 10725827Srrh anywarnings++; 10735827Srrh if (silent) 10745827Srrh return; 1075676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1076676Shenry fprintf(sink, s, a1, a2,a3,a4,a5); 1077676Shenry fprintf(sink, "\n"); 10785827Srrh #undef sink 1079676Shenry } 1080