15827Srrh /* 25827Srrh * Copyright (c) 1982 Regents of the University of California 35827Srrh */ 45827Srrh #ifndef lint 5*13459Srrh static char sccsid[] = "@(#)asparse.c 4.13 06/30/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 32*13459Srrh char yytext[NCPName+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 7113446Srrh char *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 */ 9013274Srrh int incasetable; /* set if in a case table */ 91597Sbill 9213274Srrh incasetable = 0; 93597Sbill xp = explist; 94597Sbill ap = arglist; 95597Sbill 96597Sbill val = yylex(); 97597Sbill 98597Sbill while (val != PARSEEOF){ /* primary loop */ 99597Sbill 100597Sbill while (INTOKSET(val, LINSTBEGIN)){ 101597Sbill if (val == INT) { 102632Shenry int i = ((struct exp *)yylval)->e_xvalue; 103597Sbill shift; 1045827Srrh if (val != COLON){ 1055827Srrh yyerror("Local label %d is not followed by a ':' for a label definition", 1065827Srrh i); 1075827Srrh goto errorfix; 1085827Srrh } 109597Sbill if (i < 0 || i > 9) { 110597Sbill yyerror("Local labels are 0-9"); 111597Sbill goto errorfix; 112597Sbill } 1135827Srrh (void)sprintf(yytext, "L%d\001%d", i, lgensym[i]); 114597Sbill lgensym[i]++; 115597Sbill genref[i] = 0; 116597Sbill yylval = (int)*lookup(passno == 1); 117597Sbill val = NAME; 118597Sbill np = (struct symtab *)yylval; 119597Sbill goto restlab; 120597Sbill } 121597Sbill if (val == NL){ 122597Sbill lineno++; 123597Sbill shift; 124597Sbill } else 125597Sbill if (val == SEMI) 126597Sbill shift; 127597Sbill else { /*its a name, so we have a label or def */ 128597Sbill if (val != NAME){ 129597Sbill ERROR("Name expected for a label"); 130597Sbill } 131597Sbill np = (struct symtab *)yylval; 132597Sbill shiftover(NAME); 133597Sbill if (val != COLON) { 134632Shenry #ifdef FLEXNAMES 135597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition", 136632Shenry #else not FLEXNAMES 137632Shenry yyerror("\"%.*s\" is not followed by a ':' for a label definition", 138*13459Srrh NCPName, 139632Shenry #endif not FLEXNAMES 140632Shenry np->s_name); 141597Sbill goto errorfix; 142597Sbill } 143597Sbill restlab: 144597Sbill shift; 145597Sbill flushfield(NBPW/4); 146632Shenry if ((np->s_type&XTYPE)!=XUNDEF) { 147632Shenry if( (np->s_type&XTYPE)!=dotp->e_xtype 148632Shenry || np->s_value!=dotp->e_xvalue 149597Sbill || ( (passno==1) 150632Shenry &&(np->s_index != dotp->e_xloc) 151597Sbill ) 152597Sbill ){ 153597Sbill #ifndef DEBUG 154632Shenry if (np->s_name[0] != 'L') 155597Sbill #endif not DEBUG 156597Sbill { 157597Sbill if (passno == 1) 158632Shenry #ifdef FLEXNAMES 159632Shenry yyerror("%s redefined", 160632Shenry #else not FLEXNAMES 161632Shenry yyerror("%.*s redefined", 162*13459Srrh NCPName, 163632Shenry #endif not FLEXNAMES 164632Shenry np->s_name); 165597Sbill else 166632Shenry #ifdef FLEXNAMES 167632Shenry yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 168632Shenry #else not FLEXNAMES 169632Shenry yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 170*13459Srrh NCPName, 171632Shenry #endif not FLEXNAMES 172632Shenry np->s_name, 173632Shenry np->s_value, 174632Shenry dotp->e_xvalue); 175597Sbill } 176597Sbill } 177597Sbill } 178632Shenry np->s_type &= ~(XTYPE|XFORW); 179632Shenry np->s_type |= dotp->e_xtype; 180632Shenry np->s_value = dotp->e_xvalue; 181597Sbill if (passno == 1){ 182632Shenry np->s_index = dotp-usedot; 183632Shenry if (np->s_name[0] == 'L'){ 184597Sbill nlabels++; 185597Sbill } 186632Shenry np->s_tag = LABELID; 187597Sbill } 188597Sbill } /*end of this being a label*/ 189597Sbill } /*end of to consuming all labels, NLs and SEMIS */ 190597Sbill 191597Sbill xp = explist; 192597Sbill ap = arglist; 193597Sbill 194597Sbill /* 195597Sbill * process the INSTRUCTION body 196597Sbill */ 197597Sbill switch(val){ 198597Sbill 199597Sbill default: 200597Sbill ERROR("Unrecognized instruction or directive"); 201597Sbill 202597Sbill case IABORT: 203597Sbill shift; 204597Sbill sawabort(); 205597Sbill /*NOTREACHED*/ 206597Sbill break; 207597Sbill 208597Sbill case PARSEEOF: 2095827Srrh tokptr -= sizeof(bytetoktype); 210597Sbill *tokptr++ = VOID; 211597Sbill tokptr[1] = VOID; 212597Sbill tokptr[2] = PARSEEOF; 213597Sbill break; 214597Sbill 215597Sbill case IFILE: 216597Sbill shift; 21713446Srrh stringp = (char *)yylval; 218597Sbill shiftover(STRING); 219597Sbill dotsname = &UDotsname[0]; 22013446Srrh movestr(dotsname, stringp, min(STRLEN(stringp), sizeof(dotsname))); 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 262*13459Srrh movestr(stpt->s_name, np->s_name, NCPName); 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 { 38713274Srrh /* 38813274Srrh * 38913274Srrh * See if we are doing a case instruction. 39013274Srrh * If so, then see if the branch distance, 39113274Srrh * stored as a word, 39213274Srrh * is going to loose sig bits. 39313274Srrh */ 39413274Srrh if (passno == 2 && incasetable){ 39513274Srrh if ( (locxp->e_xvalue < -32768) 39613274Srrh ||(locxp->e_xvalue > 32767)){ 39713274Srrh yyerror("Case will branch too far"); 39813274Srrh } 39913274Srrh } 400632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 401597Sbill bitfield |= field_value << bitoff; 402597Sbill bitoff += field_width; 403597Sbill } 404597Sbill xp = explist; 4055827Srrh if (auxval = (val == CM)) 4065827Srrh shift; 407597Sbill } while (auxval); 4085827Srrh } /* there existed an expression at all */ 409597Sbill 410597Sbill flushfield(curlen); 411597Sbill if ( ( curlen == NBPW/4) && bitoff) 412632Shenry dotp->e_xvalue ++; 413597Sbill break; 414597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 415597Sbill 416597Sbill case ISPACE: /* .space <expr> */ 417597Sbill shift; 418597Sbill expr(locxp, val); 4195827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 420597Sbill yyerror("Space size not absolute"); 421632Shenry space_value = locxp->e_xvalue; 422597Sbill ospace: 423597Sbill flushfield(NBPW/4); 424597Sbill #ifdef UNIX 42513446Srrh { 42613446Srrh static char spacebuf[128]; 42713446Srrh while (space_value > sizeof(spacebuf)){ 42813446Srrh outs(spacebuf, sizeof(spacebuf)); 42913446Srrh space_value -= sizeof(spacebuf); 43013446Srrh } 43113446Srrh outs(spacebuf, space_value); 432597Sbill } 433597Sbill #endif UNIX 434597Sbill #ifdef VMS 435632Shenry dotp->e_xvalue += space_value; /*bump pc*/ 436597Sbill if (passno==2){ 43713446Srrh puchar(vms_obj_ptr,81); /* AUGR */ 43813446Srrh pulong(vms_obj_ptr,space_value);/* incr */ 439597Sbill if ((vms_obj_ptr-sobuf) > 400) { 440597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 441597Sbill vms_obj_ptr=sobuf+1; /*pur buf*/ 442597Sbill } 443597Sbill } 444597Sbill #endif VMS 445597Sbill break; 446597Sbill 447597Sbill #ifdef UNIX 448647Shenry /* 449647Shenry * .fill rep, size, value 450647Shenry * repeat rep times: fill size bytes with (truncated) value 451647Shenry * size must be between 1 and 8 452647Shenry */ 453647Shenry case IFILL: 454597Sbill shift; 455597Sbill expr(locxp, val); 4565827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 457597Sbill yyerror("Fill repetition count not absolute"); 458647Shenry fill_rep = locxp->e_xvalue; 459597Sbill shiftover(CM); 460597Sbill expr(locxp, val); 4615827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 462647Shenry yyerror("Fill size not absolute"); 463647Shenry fill_size = locxp->e_xvalue; 464647Shenry if (fill_size <= 0 || fill_size > 8) 465647Shenry yyerror("Fill count not in in 1..8"); 466647Shenry shiftover(CM); 467647Shenry expr(locxp, val); 4685827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 4695827Srrh yyerror("Fill value not absolute"); 470597Sbill flushfield(NBPW/4); 471647Shenry if (passno == 1) { 4725827Srrh dotp->e_xvalue += fill_rep * fill_size; 473647Shenry } else { 474647Shenry while(fill_rep-- > 0) 4755827Srrh bwrite((char *)&locxp->e_xvalue, fill_size, txtfil); 476647Shenry } 477597Sbill break; 478597Sbill #endif UNIX 479597Sbill 48013446Srrh case IASCII: /* .ascii [ <stringlist> ] */ 481597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 482597Sbill auxval = val; 483597Sbill shift; 484597Sbill /* 485597Sbill * Code to consume a string list 486597Sbill * 487597Sbill * stringlist: empty | STRING | stringlist STRING 488597Sbill */ 48913446Srrh while (val == STRING){ 490597Sbill flushfield(NBPW/4); 491597Sbill if (bitoff) 49213446Srrh dotp->e_xvalue++; 49313446Srrh stringp = (char *)yylval; 49413446Srrh /* 49513446Srrh * utilize the string scanner cheat, 49613446Srrh * where it appended a null byte on the string, 49713446Srrh * but didn't charge it to STRLEN 49813446Srrh */ 49913446Srrh STRLEN(stringp) += (auxval == IASCIZ) ? 1 : 0; 500597Sbill #ifdef UNIX 50113446Srrh outs(stringp, STRLEN(stringp)); 502597Sbill #endif UNIX 503597Sbill #ifdef VMS 504597Sbill { 5055827Srrh reg int i; 506597Sbill for (i=0; i < stringp->str_lg; i++){ 507632Shenry dotp->e_xvalue += 1; 508597Sbill if (passno==2){ 509597Sbill puchar(vms_obj_ptr,-1); 510597Sbill puchar(vms_obj_ptr,stringp->str[i]); 511597Sbill if (vms_obj_ptr-sobuf > 400) { 512597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 513597Sbill vms_obj_ptr = sobuf + 1; 514597Sbill } 515597Sbill } 516597Sbill } 517597Sbill } 518597Sbill #endif VMS 519597Sbill shift; /*over the STRING*/ 520597Sbill if (val == CM) /*could be a split string*/ 521597Sbill shift; 522597Sbill } 523597Sbill break; 524597Sbill 525597Sbill case IORG: /* .org <expr> */ 526597Sbill shift; 527597Sbill expr(locxp, val); 528597Sbill 5295827Srrh if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */ 530597Sbill orgwarn++; 531632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 532597Sbill yyerror("Illegal expression to set origin"); 533632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 534597Sbill if (space_value < 0) 535597Sbill yyerror("Backwards 'org'"); 536597Sbill goto ospace; 537597Sbill break; 538597Sbill 539597Sbill /* 540597Sbill * 541597Sbill * Process stabs. Stabs are created only by the f77 542597Sbill * and the C compiler with the -g flag set. 543597Sbill * We only look at the stab ONCE, during pass 1, and 544597Sbill * virtually remove the stab from the intermediate file 545597Sbill * so it isn't seen during pass2. This makes for some 546597Sbill * hairy processing to handle labels occuring in 547597Sbill * stab entries, but since most expressions in the 548597Sbill * stab are integral we save lots of time in the second 549597Sbill * pass by not looking at the stabs. 550597Sbill * A stab that is tagged floating will be bumped during 551597Sbill * the jxxx resolution phase. A stab tagged fixed will 552597Sbill * not be be bumped. 553597Sbill * 554597Sbill * .stab: Old fashioned stabs 555597Sbill * .stabn: For stabs without names 556597Sbill * .stabs: For stabs with string names 557597Sbill * .stabd: For stabs for line numbers or bracketing, 558597Sbill * without a string name, without 559597Sbill * a final expression. The value of the 560597Sbill * final expression is taken to be the current 561597Sbill * location counter, and is patched by the 2nd pass 562597Sbill * 563*13459Srrh * .stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr> 564597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 565597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 566597Sbill * .stabd <expr>, <expr>, <expr> # . 567597Sbill */ 568597Sbill case ISTAB: 569597Sbill #ifndef FLEXNAMES 570597Sbill stabname = ".stab"; 571597Sbill if (passno == 2) goto errorfix; 572597Sbill stpt = (struct symtab *)yylval; 573597Sbill /* 574597Sbill * Make a pointer to the .stab slot. 575597Sbill * There is a pointer in the way (stpt), and 576597Sbill * tokptr points to the next token. 577597Sbill */ 578597Sbill stabstart = tokptr; 579597Sbill (char *)stabstart -= sizeof(struct symtab *); 5805827Srrh (char *)stabstart -= sizeof(bytetoktype); 581597Sbill shift; 582*13459Srrh for (argcnt = 0; argcnt < NCPName; argcnt++){ 583597Sbill expr(locxp, val); 584632Shenry stpt->s_name[argcnt] = locxp->e_xvalue; 585597Sbill xp = explist; 586597Sbill shiftover(CM); 587597Sbill } 588597Sbill goto tailstab; 589597Sbill #else FLEXNAMES 590597Sbill yyerror(".stab directive not supported in; report this compiler bug to system administrator"); 591597Sbill goto errorfix; 592597Sbill #endif FLEXNAMES 593597Sbill 594597Sbill tailstab: 595597Sbill expr(locxp, val); 596632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 5975827Srrh yyerror("Invalid type in %s", stabname); 598597Sbill goto errorfix; 599597Sbill } 600632Shenry stpt->s_ptype = locxp->e_xvalue; 601597Sbill shiftover(CM); 602597Sbill expr(locxp, val); 603632Shenry stpt->s_other = locxp->e_xvalue; 604597Sbill shiftover(CM); 605597Sbill expr(locxp, val); 606632Shenry stpt->s_desc = locxp->e_xvalue; 607597Sbill shiftover(CM); 608597Sbill exprisname = 0; 609597Sbill expr(locxp, val); 610632Shenry p = locxp->e_xname; 611597Sbill if (p == NULL) { /*absolute expr to begin with*/ 612632Shenry stpt->s_value = locxp->e_xvalue; 613632Shenry stpt->s_index = dotp - usedot; 614597Sbill if (exprisname){ 615632Shenry switch(stpt->s_ptype){ 616597Sbill case N_GSYM: 617597Sbill case N_FNAME: 618597Sbill case N_RSYM: 619597Sbill case N_SSYM: 620597Sbill case N_LSYM: 621597Sbill case N_PSYM: 622597Sbill case N_BCOMM: 623597Sbill case N_ECOMM: 624597Sbill case N_LENG: 625632Shenry stpt->s_tag = STABFIXED; 626597Sbill break; 627597Sbill default: 628632Shenry stpt->s_tag = STABFLOATING; 629597Sbill break; 630597Sbill } 631597Sbill } else 632632Shenry stpt->s_tag = STABFIXED; 633597Sbill } 634597Sbill else { /*really have a name*/ 635632Shenry stpt->s_dest = locxp->e_xname; 636632Shenry stpt->s_index = p->s_index; 637632Shenry stpt->s_type = p->s_type | STABFLAG; 638597Sbill /* 639597Sbill * We will assign a more accruate 640597Sbill * guess of locxp's location when 641597Sbill * we sort the symbol table 642597Sbill * The final value of value is 643597Sbill * given by stabfix() 644597Sbill */ 64512591Scsvaf /* 64612591Scsvaf * For exprs of the form (name + value) one needs to remember locxp->e_xvalue 64712591Scsvaf * for use in stabfix. The right place to keep this is in stpt->s_value 64812591Scsvaf * however this gets corrupted at an unknown point. 64912591Scsvaf * As a bandaid hack the value is preserved in s_desc and s_other (a 65012591Scsvaf * short and a char). This destroys these two values and will 65112591Scsvaf * be fixed. May 19 ,1983 Alastair Fyfe 65212591Scsvaf */ 65312591Scsvaf if(locxp->e_xvalue) { 65412591Scsvaf stpt->s_other = (locxp->e_xvalue >> 16); 65512591Scsvaf stpt->s_desc = (locxp->e_xvalue & 0x0000ffff); 65612591Scsvaf stpt->s_tag = STABFLOATING; 65712591Scsvaf } 658597Sbill } 659597Sbill /* 660597Sbill * tokptr now points at one token beyond 661597Sbill * the current token stored in val and yylval, 662597Sbill * which are the next tokens after the end of 663597Sbill * this .stab directive. This next token must 664597Sbill * be either a SEMI or NL, so is of width just 665597Sbill * one. Therefore, to point to the next token 666597Sbill * after the end of this stab, just back up one.. 667597Sbill */ 6685827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 669597Sbill break; /*end of the .stab*/ 670597Sbill 671597Sbill case ISTABDOT: 672597Sbill stabname = ".stabd"; 673597Sbill stpt = (struct symtab *)yylval; 674597Sbill /* 675597Sbill * We clobber everything after the 676597Sbill * .stabd and its pointer... we MUST 677597Sbill * be able to get back to this .stabd 678597Sbill * so that we can resolve its final value 679597Sbill */ 680597Sbill stabstart = tokptr; 681597Sbill shift; /*over the ISTABDOT*/ 682597Sbill if (passno == 1){ 683597Sbill expr(locxp, val); 684632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 685597Sbill yyerror("Invalid type in .stabd"); 686597Sbill goto errorfix; 687597Sbill } 688632Shenry stpt->s_ptype = locxp->e_xvalue; 689597Sbill shiftover(CM); 690597Sbill expr(locxp, val); 691632Shenry stpt->s_other = locxp->e_xvalue; 692597Sbill shiftover(CM); 693597Sbill expr(locxp, val); 694632Shenry stpt->s_desc = locxp->e_xvalue; 695597Sbill /* 696597Sbill * 697597Sbill * Now, clobber everything but the 698597Sbill * .stabd pseudo and the pointer 699597Sbill * to its symbol table entry 700597Sbill * tokptr points to the next token, 701597Sbill * build the skip up to this 702597Sbill */ 7035827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 704597Sbill } 705597Sbill /* 706597Sbill * pass 1: Assign a good guess for its position 707597Sbill * (ensures they are sorted into right place)/ 708597Sbill * pass 2: Fix the actual value 709597Sbill */ 710632Shenry stpt->s_value = dotp->e_xvalue; 711632Shenry stpt->s_index = dotp - usedot; 712632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 713597Sbill break; 714597Sbill 715597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 716597Sbill 717597Sbill case ISTABSTR: stabname = ".stabs"; 718597Sbill shortstab: 719597Sbill auxval = val; 720597Sbill if (passno == 2) goto errorfix; 721597Sbill stpt = (struct symtab *)yylval; 722597Sbill stabstart = tokptr; 7235827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *); 7245827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype); 725597Sbill shift; 726597Sbill if (auxval == ISTABSTR){ 72713446Srrh stringp = (char *)yylval; 728597Sbill shiftover(STRING); 729597Sbill #ifndef FLEXNAMES 730*13459Srrh movestr(stpt->s_name, stringp, min(STRLEN(stringp), NCPName)); 731597Sbill #else 73213446Srrh stpt->s_name = stringp; 73313446Srrh /* 73413446Srrh * We want the trailing null included in this string. 73513446Srrh * We utilize the cheat the string scanner used, 73613446Srrh * and merely increment the string length 73713446Srrh */ 73813446Srrh STRLEN(stringp) += 1; 739597Sbill #endif 740597Sbill shiftover(CM); 741597Sbill } else { 742597Sbill #ifndef FLEXNAMES 743*13459Srrh static char nullstr[NCPName]; 744*13459Srrh movestr(stpt->s_name, nullstr, NCPName); 74513446Srrh #else 74613446Srrh static char nullstr[1]; 74713446Srrh stpt->s_name = savestr(nullstr, 1); 748597Sbill #endif 749597Sbill } 750597Sbill goto tailstab; 751597Sbill break; 752597Sbill 7535827Srrh case ICOMM: /* .comm <name> , <expr> */ 754597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 755597Sbill auxval = val; 756597Sbill shift; 757597Sbill np = (struct symtab *)yylval; 758597Sbill shiftover(NAME); 759597Sbill shiftover(CM); 760597Sbill expr(locxp, val); 761597Sbill 7625827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 763597Sbill yyerror("comm size not absolute"); 7645827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) 765632Shenry #ifdef FLEXNAMES 766632Shenry yyerror("Redefinition of %s", 767632Shenry #else not FLEXNAMES 768632Shenry yyerror("Redefinition of %.*s", 769*13459Srrh NCPName, 770632Shenry #endif not FLEXNAMES 771632Shenry np->s_name); 772597Sbill if (passno==1) { 773632Shenry np->s_value = locxp->e_xvalue; 774597Sbill if (auxval == ICOMM) 775632Shenry np->s_type |= XXTRN; 776597Sbill else { 777632Shenry np->s_type &= ~XTYPE; 778632Shenry np->s_type |= XBSS; 779597Sbill } 780597Sbill } 781597Sbill break; 782597Sbill 783597Sbill case IALIGN: /* .align <expr> */ 784597Sbill stpt = (struct symtab *)yylval; 785597Sbill shift; 786597Sbill expr(locxp, val); 787597Sbill jalign(locxp, stpt); 788597Sbill break; 789597Sbill 790597Sbill case INST0: /* instructions w/o arguments*/ 79113274Srrh incasetable = 0; 7925827Srrh insout(yyopcode, (struct arg *)0, 0); 793597Sbill shift; 794597Sbill break; 795597Sbill 796597Sbill case INSTn: /* instructions with arguments*/ 797597Sbill case IJXXX: /* UNIX style jump instructions */ 798597Sbill auxval = val; 799597Sbill /* 800597Sbill * Code to process an argument list 801597Sbill */ 802597Sbill ap = arglist; 803597Sbill xp = explist; 804597Sbill 805597Sbill shift; /* bring in the first token for the arg list*/ 806597Sbill 807597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 808597Sbill /* 809597Sbill * code to process an argument proper 810597Sbill */ 811597Sbill sawindex = sawmul = sawsize = 0; 812597Sbill { 813597Sbill switch(val) { 814597Sbill 815597Sbill default: 816597Sbill disp: 817597Sbill if( !(INTOKSET(val, 818597Sbill EBEGOPS 819597Sbill +YUKKYEXPRBEG 820597Sbill +SAFEEXPRBEG)) ) { 821597Sbill ERROR("expression expected"); 822597Sbill } 823632Shenry expr(ap->a_xp,val); 824597Sbill overdisp: 825597Sbill if ( val == LP || sawsize){ 826597Sbill shiftover(LP); 827597Sbill findreg(regno); 828597Sbill shiftover(RP); 829632Shenry ap->a_atype = ADISP; 830632Shenry ap->a_areg1 = regno; 831597Sbill } else { 832632Shenry ap->a_atype = AEXP; 833632Shenry ap->a_areg1 = 0; 834597Sbill } 835597Sbill goto index; 836597Sbill 837597Sbill case SIZESPEC: 838597Sbill sizespec: 839597Sbill sawsize = yylval; 840597Sbill shift; 841597Sbill goto disp; 842597Sbill 843597Sbill case REG: 844597Sbill case REGOP: 845597Sbill findreg(regno); 846632Shenry ap->a_atype = AREG; 847632Shenry ap->a_areg1 = regno; 848597Sbill break; 849597Sbill 850597Sbill case MUL: 851597Sbill sawmul = 1; 852597Sbill shift; 853597Sbill if (val == LP) goto base; 854597Sbill if (val == LITOP) goto imm; 855597Sbill if (val == SIZESPEC) goto sizespec; 856597Sbill if (INTOKSET(val, 857597Sbill EBEGOPS 858597Sbill +YUKKYEXPRBEG 859597Sbill +SAFEEXPRBEG)) goto disp; 860597Sbill ERROR("expression, '(' or '$' expected"); 861597Sbill break; 862597Sbill 863597Sbill case LP: 864597Sbill base: 865597Sbill shift; /*consume the LP*/ 866597Sbill /* 867597Sbill * hack the ambiguity of 868597Sbill * movl (expr) (rn), ... 869597Sbill * note that (expr) could also 870597Sbill * be (rn) (by special hole in the 871597Sbill * grammar), which we ensure 872597Sbill * means register indirection, instead 873597Sbill * of an expression with value n 874597Sbill */ 875597Sbill if (val != REG && val != REGOP){ 876597Sbill droppedLP = 1; 877632Shenry val = exprparse(val, &(ap->a_xp)); 878597Sbill droppedLP = 0; 879597Sbill goto overdisp; 880597Sbill } 881597Sbill findreg(regno); 882597Sbill shiftover(RP); 883597Sbill if (val == PLUS){ 884597Sbill shift; 885632Shenry ap->a_atype = AINCR; 886597Sbill } else 887632Shenry ap->a_atype = ABASE; 888632Shenry ap->a_areg1 = regno; 889597Sbill goto index; 890597Sbill 891597Sbill case LITOP: 892597Sbill imm: 893597Sbill shift; 894597Sbill expr(locxp, val); 895632Shenry ap->a_atype = AIMM; 896632Shenry ap->a_areg1 = 0; 897632Shenry ap->a_xp = locxp; 898597Sbill goto index; 899597Sbill 900597Sbill case MP: 901597Sbill shift; /* -(reg) */ 902597Sbill findreg(regno); 903597Sbill shiftover(RP); 904632Shenry ap->a_atype = ADECR; 905632Shenry ap->a_areg1 = regno; 906597Sbill index: /*look for [reg] */ 907597Sbill if (val == LB){ 908597Sbill shift; 909597Sbill findreg(regno); 910597Sbill shiftover(RB); 911597Sbill sawindex = 1; 912632Shenry ap->a_areg2 = regno; 913597Sbill } 914597Sbill break; 915597Sbill 916597Sbill } /*end of the switch to process an arg*/ 917597Sbill } /*end of processing an argument*/ 918597Sbill 919597Sbill if (sawmul){ 920597Sbill /* 921597Sbill * Make a concession for *(%r) 922597Sbill * meaning *0(%r) 923597Sbill */ 924632Shenry if (ap->a_atype == ABASE) { 925632Shenry ap->a_atype = ADISP; 926632Shenry xp->e_xtype = XABS; 9275827Srrh xp->e_number = Znumber; 9285827Srrh xp->e_number.num_tag = TYPL; 929632Shenry xp->e_xloc = 0; 930632Shenry ap->a_xp = xp++; 931597Sbill } 932632Shenry ap->a_atype |= ASTAR; 933597Sbill sawmul = 0; 934597Sbill } 935597Sbill if (sawindex){ 936632Shenry ap->a_atype |= AINDX; 937597Sbill sawindex = 0; 938597Sbill } 939632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 940597Sbill if (val != CM) break; 941597Sbill shiftover(CM); 942597Sbill } /*processing all the arguments*/ 943597Sbill 944597Sbill if (argcnt > 6){ 945597Sbill yyerror("More than 6 arguments"); 946597Sbill goto errorfix; 947597Sbill } 948597Sbill 94913274Srrh /* 95013274Srrh * See if this is a case instruction, 95113274Srrh * so we can set up tests on the following 95213274Srrh * vector of branch displacements 95313274Srrh */ 95413274Srrh if (yyopcode.Op_eopcode == CORE){ 95513274Srrh switch(yyopcode.Op_popcode){ 95613274Srrh case 0x8f: /* caseb */ 95713274Srrh case 0xaf: /* casew */ 95813274Srrh case 0xcf: /* casel */ 95913274Srrh incasetable++; 96013274Srrh break; 96113274Srrh default: 96213274Srrh incasetable = 0; 96313274Srrh break; 96413274Srrh } 96513274Srrh } 96613274Srrh 9675827Srrh insout(yyopcode, arglist, 968597Sbill auxval == INSTn ? argcnt : - argcnt); 969597Sbill break; 970597Sbill 9715827Srrh case IQUAD: toconv = TYPQ; goto bignumlist; 9725827Srrh case IOCTA: toconv = TYPO; goto bignumlist; 9735827Srrh 9745827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist; 9755827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist; 9765827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist; 9775827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist; 9785827Srrh bignumlist: 979597Sbill /* 9805827Srrh * eat a list of non 32 bit numbers. 9815827Srrh * IQUAD and IOCTA can, possibly, return 9825827Srrh * INT's, if the numbers are "small". 9835827Srrh * 9845827Srrh * The value of the numbers is coming back 9855827Srrh * as an expression, NOT in yybignum. 986597Sbill */ 9875827Srrh shift; /* over the opener */ 9885827Srrh if ((val == BIGNUM) || (val == INT)){ 989597Sbill do{ 9905827Srrh if ((val != BIGNUM) && (val != INT)){ 9915827Srrh ERROR(ty_float[toconv] 9925827Srrh ? "floating number expected" 9935827Srrh : "integer number expected" ); 994597Sbill } 9955827Srrh dotp->e_xvalue += ty_nbyte[toconv]; 9965827Srrh if (passno == 2){ 9975827Srrh bignumwrite( 9985827Srrh ((struct exp *)yylval)->e_number, 9995827Srrh toconv); 1000597Sbill } 1001597Sbill xp = explist; 10025827Srrh shift; /* over this number */ 10035827Srrh if (auxval = (val == CM)) 10045827Srrh shift; /* over the comma */ 10055827Srrh } while (auxval); /* as long as there are commas */ 1006597Sbill } 1007597Sbill break; 10085827Srrh /* end of the case for initialized big numbers */ 1009597Sbill } /*end of the switch for looking at each reserved word*/ 1010597Sbill 10115827Srrh continue; 1012597Sbill 1013597Sbill errorfix: 1014597Sbill /* 1015597Sbill * got here by either requesting to skip to the 1016597Sbill * end of this statement, or by erroring out and 1017597Sbill * wanting to apply panic mode recovery 1018597Sbill */ 1019597Sbill while ( (val != NL) 1020597Sbill && (val != SEMI) 1021597Sbill && (val != PARSEEOF) 1022597Sbill ){ 1023597Sbill shift; 1024597Sbill } 1025597Sbill if (val == NL) 1026597Sbill lineno++; 1027597Sbill shift; 1028597Sbill 1029597Sbill } /*end of the loop to read the entire file, line by line*/ 1030597Sbill 1031597Sbill } /*end of yyparse*/ 1032597Sbill 1033597Sbill /* 1034597Sbill * Process a register declaration of the form 1035597Sbill * % <expr> 1036597Sbill * 1037597Sbill * Note: 1038597Sbill * The scanner has already processed funny registers of the form 1039597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 1040597Sbill * preceding zero digit). If there was any space between the % and 1041597Sbill * the digit, the scanner wouldn't have recognized it, so we 1042597Sbill * hack it out here. 1043597Sbill */ 10445827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ 10455827Srrh inttoktype val; /*what the read head is sitting on*/ 1046597Sbill int *regnoback; /*call by return*/ 1047597Sbill { 10485827Srrh reg struct exp *locxp; 10495827Srrh struct exp *loc1xp; 10505827Srrh struct exp **ptrloc1xp = & loc1xp; 1051597Sbill 1052597Sbill expr(locxp, val); /*and leave the current read head with value*/ 1053597Sbill if ( (passno == 2) && 10545827Srrh ( (locxp->e_xtype & XTYPE) != XABS 10555827Srrh || (locxp->e_xvalue < 0) 10565827Srrh || (locxp->e_xvalue >= 16) 1057597Sbill ) 1058597Sbill ){ 1059597Sbill yyerror("Illegal register"); 1060597Sbill return(0); 1061597Sbill } 1062632Shenry *regnoback = locxp->e_xvalue; 1063597Sbill return(val); 1064597Sbill } 106512945Srrh /* 106612945Srrh * Shift over error 106712945Srrh */ 106812945Srrh shiftoerror(token) 106912945Srrh int token; 107012945Srrh { 107112945Srrh char *tok_to_name(); 107212945Srrh yyerror("%s expected", tok_to_name(token)); 107312945Srrh } 1074597Sbill 1075597Sbill /*VARARGS1*/ 1076597Sbill yyerror(s, a1, a2,a3,a4,a5) 1077597Sbill char *s; 1078597Sbill { 1079597Sbill 1080649Shenry #define sink stdout 1081597Sbill 10825827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1083597Sbill fprintf(sink, "Assembler:\n"); 1084597Sbill anyerrs++; 10855827Srrh if (silent) 10865827Srrh return; 1087597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1088597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1089597Sbill fprintf(sink, "\n"); 10905827Srrh #undef sink 1091597Sbill } 1092676Shenry 1093676Shenry /*VARARGS1*/ 1094676Shenry yywarning(s, a1, a2,a3,a4,a5) 1095676Shenry char *s; 1096676Shenry { 1097676Shenry #define sink stdout 10985827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1099676Shenry fprintf(sink, "Assembler:\n"); 11005827Srrh anywarnings++; 11015827Srrh if (silent) 11025827Srrh return; 1103676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1104676Shenry fprintf(sink, s, a1, a2,a3,a4,a5); 1105676Shenry fprintf(sink, "\n"); 11065827Srrh #undef sink 1107676Shenry } 1108