15827Srrh /* 25827Srrh * Copyright (c) 1982 Regents of the University of California 35827Srrh */ 45827Srrh #ifndef lint 5*13274Srrh static char sccsid[] = "@(#)asparse.c 4.11 06/24/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 */ 90*13274Srrh int incasetable; /* set if in a case table */ 91597Sbill 92*13274Srrh 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", 138632Shenry NCPS, 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", 162632Shenry NCPS, 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", 170632Shenry NCPS, 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; 217597Sbill stringp = (struct strdesc *)yylval; 218597Sbill shiftover(STRING); 219597Sbill dotsname = &UDotsname[0]; 220597Sbill movestr(dotsname, stringp->str, 221597Sbill stringp->str_lg >= 32? 32 :stringp->str_lg); 222597Sbill dotsname[stringp->str_lg] = '\0'; 223597Sbill break; 224597Sbill 225597Sbill case ILINENO: 226597Sbill shift; /*over the ILINENO*/ 227597Sbill expr(locxp, val); 228632Shenry lineno = locxp->e_xvalue; 229597Sbill break; 230597Sbill 231597Sbill case ISET: /* .set <name> , <expr> */ 232597Sbill shift; 233597Sbill np = (struct symtab *)yylval; 234597Sbill shiftover(NAME); 235597Sbill shiftover(CM); 236597Sbill expr(locxp, val); 237632Shenry np->s_type &= (XXTRN|XFORW); 238632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 239632Shenry np->s_value = locxp->e_xvalue; 240597Sbill if (passno==1) 241632Shenry np->s_index = locxp->e_xloc; 242632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 243597Sbill yyerror("Illegal set?"); 244597Sbill break; 245597Sbill 246597Sbill case ILSYM: /*.lsym name , expr */ 247597Sbill shift; 248597Sbill np = (struct symtab *)yylval; 249597Sbill shiftover(NAME); 250597Sbill shiftover(CM); 251597Sbill expr(locxp, val); 252597Sbill /* 253597Sbill * Build the unique occurance of the 254597Sbill * symbol. 255597Sbill * The character scanner will have 256597Sbill * already entered it into the symbol 257597Sbill * table, but we should remove it 258597Sbill */ 259597Sbill if (passno == 1){ 260597Sbill stpt = (struct symtab *)symalloc(); 261597Sbill #ifdef FLEXNAMES 262632Shenry stpt->s_name = np->s_name; 263597Sbill #else 264632Shenry movestr(stpt->s_name, np->s_name, NCPS); 265597Sbill #endif 266632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 267597Sbill nforgotten++; 268597Sbill np = stpt; 2695827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) 2705827Srrh yyerror("Illegal second argument to lsym"); 2715827Srrh np->s_value = locxp->e_xvalue; 2725827Srrh np->s_type = XABS; 273632Shenry np->s_tag = ILSYM; 274597Sbill } 275597Sbill break; 276597Sbill 277597Sbill case IGLOBAL: /*.globl <name> */ 278597Sbill shift; 279597Sbill np = (struct symtab *)yylval; 280597Sbill shiftover(NAME); 281632Shenry np->s_type |= XXTRN; 282597Sbill break; 283597Sbill 284597Sbill case IDATA: /*.data [ <expr> ] */ 285597Sbill case ITEXT: /*.text [ <expr> ] */ 286597Sbill seg_type = -val; 287597Sbill shift; 288597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 289597Sbill expr(locxp, val); 290597Sbill seg_type = -seg_type; /*now, it is positive*/ 291597Sbill } 292597Sbill 293597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 294597Sbill seg_number = 0; 295597Sbill seg_type = -seg_type; 296597Sbill } else { 2975827Srrh if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 2985827Srrh || (seg_number = locxp->e_xvalue) >= NLOC) { 299597Sbill yyerror("illegal location counter"); 300597Sbill seg_number = 0; 301597Sbill } 302597Sbill } 303597Sbill if (seg_type == IDATA) 304597Sbill seg_number += NLOC; 305597Sbill flushfield(NBPW/4); 306597Sbill dotp = &usedot[seg_number]; 307597Sbill #ifdef UNIX 308597Sbill if (passno==2) { /* go salt away in pass 2*/ 309597Sbill txtfil = usefile[seg_number]; 310597Sbill relfil = rusefile[seg_number]; 311597Sbill } 312597Sbill #endif UNIX 313597Sbill #ifdef VMS 314597Sbill if (passno==2) { 315597Sbill puchar(vms_obj_ptr,6); /* setpl */ 316597Sbill puchar(vms_obj_ptr,seg_number); /* psect # */ 317632Shenry plong(vms_obj_ptr,dotp->e_xvalue);/* offset */ 318597Sbill puchar(vms_obj_ptr,80); /* setrb */ 319597Sbill if((vms_obj_ptr-sobuf) > 400){ 320597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 321597Sbill vms_obj_ptr=sobuf+1; /*flush buf*/ 322597Sbill } 323597Sbill } 324597Sbill #endif VMS 325597Sbill break; 326597Sbill 327597Sbill /* 328597Sbill * Storage filler directives: 329597Sbill * 330597Sbill * .byte [<exprlist>] 331597Sbill * 332597Sbill * exprlist: empty | exprlist outexpr 333597Sbill * outexpr: <expr> | <expr> : <expr> 334597Sbill */ 335597Sbill case IBYTE: curlen = NBPW/4; goto elist; 3365827Srrh case IWORD: curlen = NBPW/2; goto elist; 3375827Srrh case IINT: curlen = NBPW; goto elist; 338597Sbill case ILONG: curlen = NBPW; goto elist; 339597Sbill 340597Sbill elist: 341597Sbill seg_type = val; 342597Sbill shift; 343597Sbill 344597Sbill /* 345597Sbill * Expression List processing 346597Sbill */ 347597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 348597Sbill do{ 349597Sbill /* 350597Sbill * expression list consists of a list of : 351597Sbill * <expr> 352597Sbill * <expr> : <expr> 353597Sbill * (pack expr2 into expr1 bits 354597Sbill */ 355597Sbill expr(locxp, val); 356597Sbill /* 357597Sbill * now, pointing at the next token 358597Sbill */ 359597Sbill if (val == COLON){ 360597Sbill shiftover(COLON); 361597Sbill expr(pval, val); 3625827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 3635827Srrh yyerror("Width not absolute"); 364632Shenry field_width = locxp->e_xvalue; 365597Sbill locxp = pval; 3665827Srrh if (bitoff + field_width > curlen) 367597Sbill flushfield(curlen); 368597Sbill if (field_width > curlen) 369597Sbill yyerror("Expression crosses field boundary"); 370597Sbill } else { 371597Sbill field_width = curlen; 372597Sbill flushfield(curlen); 373597Sbill } 374597Sbill 3755827Srrh if ((locxp->e_xtype & XTYPE) != XABS) { 376597Sbill if (bitoff) 377597Sbill yyerror("Illegal relocation in field"); 378674Shenry switch(curlen){ 379674Shenry case NBPW/4: reloc_how = TYPB; break; 380674Shenry case NBPW/2: reloc_how = TYPW; break; 381674Shenry case NBPW: reloc_how = TYPL; break; 382674Shenry } 383597Sbill if (passno == 1){ 384674Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 385597Sbill } else { 386674Shenry outrel(locxp, reloc_how); 387597Sbill } 388597Sbill } else { 389*13274Srrh /* 390*13274Srrh * 391*13274Srrh * See if we are doing a case instruction. 392*13274Srrh * If so, then see if the branch distance, 393*13274Srrh * stored as a word, 394*13274Srrh * is going to loose sig bits. 395*13274Srrh */ 396*13274Srrh if (passno == 2 && incasetable){ 397*13274Srrh if ( (locxp->e_xvalue < -32768) 398*13274Srrh ||(locxp->e_xvalue > 32767)){ 399*13274Srrh yyerror("Case will branch too far"); 400*13274Srrh } 401*13274Srrh } 402632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 403597Sbill bitfield |= field_value << bitoff; 404597Sbill bitoff += field_width; 405597Sbill } 406597Sbill xp = explist; 4075827Srrh if (auxval = (val == CM)) 4085827Srrh shift; 409597Sbill } while (auxval); 4105827Srrh } /* there existed an expression at all */ 411597Sbill 412597Sbill flushfield(curlen); 413597Sbill if ( ( curlen == NBPW/4) && bitoff) 414632Shenry dotp->e_xvalue ++; 415597Sbill break; 416597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 417597Sbill 418597Sbill case ISPACE: /* .space <expr> */ 419597Sbill shift; 420597Sbill expr(locxp, val); 4215827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 422597Sbill yyerror("Space size not absolute"); 423632Shenry space_value = locxp->e_xvalue; 424597Sbill ospace: 425597Sbill flushfield(NBPW/4); 426597Sbill #ifdef UNIX 427597Sbill while (space_value > 96){ 428597Sbill outs(strbuf[2].str, 96); 429597Sbill space_value -= 96; 430597Sbill } 431597Sbill outs(strbuf[2].str, space_value); 432597Sbill #endif UNIX 433597Sbill #ifdef VMS 434632Shenry dotp->e_xvalue += space_value; /*bump pc*/ 435597Sbill if (passno==2){ 436597Sbill if(*(strbuf[2].str)==0) { 437597Sbill puchar(vms_obj_ptr,81); /* AUGR */ 438597Sbill pulong(vms_obj_ptr,space_value);/* incr */ 439597Sbill } else yyerror("VMS, encountered non-0 .space"); 440597Sbill if ((vms_obj_ptr-sobuf) > 400) { 441597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 442597Sbill vms_obj_ptr=sobuf+1; /*pur buf*/ 443597Sbill } 444597Sbill } 445597Sbill #endif VMS 446597Sbill break; 447597Sbill 448597Sbill #ifdef UNIX 449647Shenry /* 450647Shenry * .fill rep, size, value 451647Shenry * repeat rep times: fill size bytes with (truncated) value 452647Shenry * size must be between 1 and 8 453647Shenry */ 454647Shenry case IFILL: 455597Sbill shift; 456597Sbill expr(locxp, val); 4575827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 458597Sbill yyerror("Fill repetition count not absolute"); 459647Shenry fill_rep = locxp->e_xvalue; 460597Sbill shiftover(CM); 461597Sbill expr(locxp, val); 4625827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 463647Shenry yyerror("Fill size not absolute"); 464647Shenry fill_size = locxp->e_xvalue; 465647Shenry if (fill_size <= 0 || fill_size > 8) 466647Shenry yyerror("Fill count not in in 1..8"); 467647Shenry shiftover(CM); 468647Shenry expr(locxp, val); 4695827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 4705827Srrh yyerror("Fill value not absolute"); 471597Sbill flushfield(NBPW/4); 472647Shenry if (passno == 1) { 4735827Srrh dotp->e_xvalue += fill_rep * fill_size; 474647Shenry } else { 475647Shenry while(fill_rep-- > 0) 4765827Srrh bwrite((char *)&locxp->e_xvalue, fill_size, txtfil); 477647Shenry } 478597Sbill break; 479597Sbill #endif UNIX 480597Sbill 481597Sbill case IASCII: /* .ascii [ <stringlist> ] */ 482597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 483597Sbill auxval = val; 484597Sbill shift; 485597Sbill 486597Sbill /* 487597Sbill * Code to consume a string list 488597Sbill * 489597Sbill * stringlist: empty | STRING | stringlist STRING 490597Sbill */ 491597Sbill while (val == STRING){ 492597Sbill flushfield(NBPW/4); 493597Sbill if (bitoff) 494632Shenry dotp->e_xvalue++; 495597Sbill stringp = (struct strdesc *)yylval; 496597Sbill #ifdef UNIX 497597Sbill outs(stringp->str, stringp->str_lg); 498597Sbill #endif UNIX 499597Sbill #ifdef VMS 500597Sbill { 5015827Srrh reg int i; 502597Sbill for (i=0; i < stringp->str_lg; i++){ 503632Shenry dotp->e_xvalue += 1; 504597Sbill if (passno==2){ 505597Sbill puchar(vms_obj_ptr,-1); 506597Sbill puchar(vms_obj_ptr,stringp->str[i]); 507597Sbill if (vms_obj_ptr-sobuf > 400) { 508597Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 509597Sbill vms_obj_ptr = sobuf + 1; 510597Sbill } 511597Sbill } 512597Sbill } 513597Sbill } 514597Sbill #endif VMS 515597Sbill shift; /*over the STRING*/ 516597Sbill if (val == CM) /*could be a split string*/ 517597Sbill shift; 518597Sbill } 519597Sbill 520597Sbill if (auxval == IASCIZ){ 521597Sbill flushfield(NBPW/4); 522597Sbill #ifdef UNIX 523597Sbill outb(0); 524597Sbill #endif UNIX 525597Sbill #ifdef VMS 526597Sbill if (passno == 2) { 527597Sbill puchar(vms_obj_ptr,-1); 528597Sbill puchar(vms_obj_ptr,0); 529597Sbill } 530632Shenry dotp->e_xvalue += 1; 531597Sbill #endif VMS 532597Sbill } 533597Sbill break; 534597Sbill 535597Sbill case IORG: /* .org <expr> */ 536597Sbill shift; 537597Sbill expr(locxp, val); 538597Sbill 5395827Srrh if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */ 540597Sbill orgwarn++; 541632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 542597Sbill yyerror("Illegal expression to set origin"); 543632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 544597Sbill if (space_value < 0) 545597Sbill yyerror("Backwards 'org'"); 546597Sbill goto ospace; 547597Sbill break; 548597Sbill 549597Sbill /* 550597Sbill * 551597Sbill * Process stabs. Stabs are created only by the f77 552597Sbill * and the C compiler with the -g flag set. 553597Sbill * We only look at the stab ONCE, during pass 1, and 554597Sbill * virtually remove the stab from the intermediate file 555597Sbill * so it isn't seen during pass2. This makes for some 556597Sbill * hairy processing to handle labels occuring in 557597Sbill * stab entries, but since most expressions in the 558597Sbill * stab are integral we save lots of time in the second 559597Sbill * pass by not looking at the stabs. 560597Sbill * A stab that is tagged floating will be bumped during 561597Sbill * the jxxx resolution phase. A stab tagged fixed will 562597Sbill * not be be bumped. 563597Sbill * 564597Sbill * .stab: Old fashioned stabs 565597Sbill * .stabn: For stabs without names 566597Sbill * .stabs: For stabs with string names 567597Sbill * .stabd: For stabs for line numbers or bracketing, 568597Sbill * without a string name, without 569597Sbill * a final expression. The value of the 570597Sbill * final expression is taken to be the current 571597Sbill * location counter, and is patched by the 2nd pass 572597Sbill * 573674Shenry * .stab{<expr>,}*NCPS,<expr>, <expr>, <expr>, <expr> 574597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 575597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 576597Sbill * .stabd <expr>, <expr>, <expr> # . 577597Sbill */ 578597Sbill case ISTAB: 579597Sbill #ifndef FLEXNAMES 580597Sbill stabname = ".stab"; 581597Sbill if (passno == 2) goto errorfix; 582597Sbill stpt = (struct symtab *)yylval; 583597Sbill /* 584597Sbill * Make a pointer to the .stab slot. 585597Sbill * There is a pointer in the way (stpt), and 586597Sbill * tokptr points to the next token. 587597Sbill */ 588597Sbill stabstart = tokptr; 589597Sbill (char *)stabstart -= sizeof(struct symtab *); 5905827Srrh (char *)stabstart -= sizeof(bytetoktype); 591597Sbill shift; 592674Shenry for (argcnt = 0; argcnt < NCPS; argcnt++){ 593597Sbill expr(locxp, val); 594632Shenry stpt->s_name[argcnt] = locxp->e_xvalue; 595597Sbill xp = explist; 596597Sbill shiftover(CM); 597597Sbill } 598597Sbill goto tailstab; 599597Sbill #else FLEXNAMES 600597Sbill yyerror(".stab directive not supported in; report this compiler bug to system administrator"); 601597Sbill goto errorfix; 602597Sbill #endif FLEXNAMES 603597Sbill 604597Sbill tailstab: 605597Sbill expr(locxp, val); 606632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 6075827Srrh yyerror("Invalid type in %s", stabname); 608597Sbill goto errorfix; 609597Sbill } 610632Shenry stpt->s_ptype = locxp->e_xvalue; 611597Sbill shiftover(CM); 612597Sbill expr(locxp, val); 613632Shenry stpt->s_other = locxp->e_xvalue; 614597Sbill shiftover(CM); 615597Sbill expr(locxp, val); 616632Shenry stpt->s_desc = locxp->e_xvalue; 617597Sbill shiftover(CM); 618597Sbill exprisname = 0; 619597Sbill expr(locxp, val); 620632Shenry p = locxp->e_xname; 621597Sbill if (p == NULL) { /*absolute expr to begin with*/ 622632Shenry stpt->s_value = locxp->e_xvalue; 623632Shenry stpt->s_index = dotp - usedot; 624597Sbill if (exprisname){ 625632Shenry switch(stpt->s_ptype){ 626597Sbill case N_GSYM: 627597Sbill case N_FNAME: 628597Sbill case N_RSYM: 629597Sbill case N_SSYM: 630597Sbill case N_LSYM: 631597Sbill case N_PSYM: 632597Sbill case N_BCOMM: 633597Sbill case N_ECOMM: 634597Sbill case N_LENG: 635632Shenry stpt->s_tag = STABFIXED; 636597Sbill break; 637597Sbill default: 638632Shenry stpt->s_tag = STABFLOATING; 639597Sbill break; 640597Sbill } 641597Sbill } else 642632Shenry stpt->s_tag = STABFIXED; 643597Sbill } 644597Sbill else { /*really have a name*/ 645632Shenry stpt->s_dest = locxp->e_xname; 646632Shenry stpt->s_index = p->s_index; 647632Shenry stpt->s_type = p->s_type | STABFLAG; 648597Sbill /* 649597Sbill * We will assign a more accruate 650597Sbill * guess of locxp's location when 651597Sbill * we sort the symbol table 652597Sbill * The final value of value is 653597Sbill * given by stabfix() 654597Sbill */ 65512591Scsvaf /* 65612591Scsvaf * For exprs of the form (name + value) one needs to remember locxp->e_xvalue 65712591Scsvaf * for use in stabfix. The right place to keep this is in stpt->s_value 65812591Scsvaf * however this gets corrupted at an unknown point. 65912591Scsvaf * As a bandaid hack the value is preserved in s_desc and s_other (a 66012591Scsvaf * short and a char). This destroys these two values and will 66112591Scsvaf * be fixed. May 19 ,1983 Alastair Fyfe 66212591Scsvaf */ 66312591Scsvaf if(locxp->e_xvalue) { 66412591Scsvaf stpt->s_other = (locxp->e_xvalue >> 16); 66512591Scsvaf stpt->s_desc = (locxp->e_xvalue & 0x0000ffff); 66612591Scsvaf stpt->s_tag = STABFLOATING; 66712591Scsvaf } 668597Sbill } 669597Sbill /* 670597Sbill * tokptr now points at one token beyond 671597Sbill * the current token stored in val and yylval, 672597Sbill * which are the next tokens after the end of 673597Sbill * this .stab directive. This next token must 674597Sbill * be either a SEMI or NL, so is of width just 675597Sbill * one. Therefore, to point to the next token 676597Sbill * after the end of this stab, just back up one.. 677597Sbill */ 6785827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 679597Sbill break; /*end of the .stab*/ 680597Sbill 681597Sbill case ISTABDOT: 682597Sbill stabname = ".stabd"; 683597Sbill stpt = (struct symtab *)yylval; 684597Sbill /* 685597Sbill * We clobber everything after the 686597Sbill * .stabd and its pointer... we MUST 687597Sbill * be able to get back to this .stabd 688597Sbill * so that we can resolve its final value 689597Sbill */ 690597Sbill stabstart = tokptr; 691597Sbill shift; /*over the ISTABDOT*/ 692597Sbill if (passno == 1){ 693597Sbill expr(locxp, val); 694632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 695597Sbill yyerror("Invalid type in .stabd"); 696597Sbill goto errorfix; 697597Sbill } 698632Shenry stpt->s_ptype = locxp->e_xvalue; 699597Sbill shiftover(CM); 700597Sbill expr(locxp, val); 701632Shenry stpt->s_other = locxp->e_xvalue; 702597Sbill shiftover(CM); 703597Sbill expr(locxp, val); 704632Shenry stpt->s_desc = locxp->e_xvalue; 705597Sbill /* 706597Sbill * 707597Sbill * Now, clobber everything but the 708597Sbill * .stabd pseudo and the pointer 709597Sbill * to its symbol table entry 710597Sbill * tokptr points to the next token, 711597Sbill * build the skip up to this 712597Sbill */ 7135827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 714597Sbill } 715597Sbill /* 716597Sbill * pass 1: Assign a good guess for its position 717597Sbill * (ensures they are sorted into right place)/ 718597Sbill * pass 2: Fix the actual value 719597Sbill */ 720632Shenry stpt->s_value = dotp->e_xvalue; 721632Shenry stpt->s_index = dotp - usedot; 722632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 723597Sbill break; 724597Sbill 725597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 726597Sbill 727597Sbill case ISTABSTR: stabname = ".stabs"; 728597Sbill shortstab: 729597Sbill auxval = val; 730597Sbill if (passno == 2) goto errorfix; 731597Sbill stpt = (struct symtab *)yylval; 732597Sbill stabstart = tokptr; 7335827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *); 7345827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype); 735597Sbill shift; 736597Sbill if (auxval == ISTABSTR){ 737597Sbill stringp = (struct strdesc *)yylval; 738597Sbill shiftover(STRING); 739597Sbill #ifndef FLEXNAMES 740597Sbill auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg; 741597Sbill #else 742597Sbill stringp->str[stringp->str_lg] = 0; 743597Sbill #endif 744597Sbill shiftover(CM); 745597Sbill } else { 746597Sbill stringp = &(strbuf[2]); 747597Sbill #ifndef FLEXNAMES 748597Sbill auxval = NCPS; 749597Sbill #endif 750597Sbill } 751597Sbill #ifndef FLEXNAMES 752632Shenry movestr(stpt->s_name, stringp->str, auxval); 753597Sbill #else 754632Shenry stpt->s_name = savestr(stringp->str); 755597Sbill #endif 756597Sbill goto tailstab; 757597Sbill break; 758597Sbill 7595827Srrh case ICOMM: /* .comm <name> , <expr> */ 760597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 761597Sbill auxval = val; 762597Sbill shift; 763597Sbill np = (struct symtab *)yylval; 764597Sbill shiftover(NAME); 765597Sbill shiftover(CM); 766597Sbill expr(locxp, val); 767597Sbill 7685827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 769597Sbill yyerror("comm size not absolute"); 7705827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) 771632Shenry #ifdef FLEXNAMES 772632Shenry yyerror("Redefinition of %s", 773632Shenry #else not FLEXNAMES 774632Shenry yyerror("Redefinition of %.*s", 775632Shenry NCPS, 776632Shenry #endif not FLEXNAMES 777632Shenry np->s_name); 778597Sbill if (passno==1) { 779632Shenry np->s_value = locxp->e_xvalue; 780597Sbill if (auxval == ICOMM) 781632Shenry np->s_type |= XXTRN; 782597Sbill else { 783632Shenry np->s_type &= ~XTYPE; 784632Shenry np->s_type |= XBSS; 785597Sbill } 786597Sbill } 787597Sbill break; 788597Sbill 789597Sbill case IALIGN: /* .align <expr> */ 790597Sbill stpt = (struct symtab *)yylval; 791597Sbill shift; 792597Sbill expr(locxp, val); 793597Sbill jalign(locxp, stpt); 794597Sbill break; 795597Sbill 796597Sbill case INST0: /* instructions w/o arguments*/ 797*13274Srrh incasetable = 0; 7985827Srrh insout(yyopcode, (struct arg *)0, 0); 799597Sbill shift; 800597Sbill break; 801597Sbill 802597Sbill case INSTn: /* instructions with arguments*/ 803597Sbill case IJXXX: /* UNIX style jump instructions */ 804597Sbill auxval = val; 805597Sbill /* 806597Sbill * Code to process an argument list 807597Sbill */ 808597Sbill ap = arglist; 809597Sbill xp = explist; 810597Sbill 811597Sbill shift; /* bring in the first token for the arg list*/ 812597Sbill 813597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 814597Sbill /* 815597Sbill * code to process an argument proper 816597Sbill */ 817597Sbill sawindex = sawmul = sawsize = 0; 818597Sbill { 819597Sbill switch(val) { 820597Sbill 821597Sbill default: 822597Sbill disp: 823597Sbill if( !(INTOKSET(val, 824597Sbill EBEGOPS 825597Sbill +YUKKYEXPRBEG 826597Sbill +SAFEEXPRBEG)) ) { 827597Sbill ERROR("expression expected"); 828597Sbill } 829632Shenry expr(ap->a_xp,val); 830597Sbill overdisp: 831597Sbill if ( val == LP || sawsize){ 832597Sbill shiftover(LP); 833597Sbill findreg(regno); 834597Sbill shiftover(RP); 835632Shenry ap->a_atype = ADISP; 836632Shenry ap->a_areg1 = regno; 837597Sbill } else { 838632Shenry ap->a_atype = AEXP; 839632Shenry ap->a_areg1 = 0; 840597Sbill } 841597Sbill goto index; 842597Sbill 843597Sbill case SIZESPEC: 844597Sbill sizespec: 845597Sbill sawsize = yylval; 846597Sbill shift; 847597Sbill goto disp; 848597Sbill 849597Sbill case REG: 850597Sbill case REGOP: 851597Sbill findreg(regno); 852632Shenry ap->a_atype = AREG; 853632Shenry ap->a_areg1 = regno; 854597Sbill break; 855597Sbill 856597Sbill case MUL: 857597Sbill sawmul = 1; 858597Sbill shift; 859597Sbill if (val == LP) goto base; 860597Sbill if (val == LITOP) goto imm; 861597Sbill if (val == SIZESPEC) goto sizespec; 862597Sbill if (INTOKSET(val, 863597Sbill EBEGOPS 864597Sbill +YUKKYEXPRBEG 865597Sbill +SAFEEXPRBEG)) goto disp; 866597Sbill ERROR("expression, '(' or '$' expected"); 867597Sbill break; 868597Sbill 869597Sbill case LP: 870597Sbill base: 871597Sbill shift; /*consume the LP*/ 872597Sbill /* 873597Sbill * hack the ambiguity of 874597Sbill * movl (expr) (rn), ... 875597Sbill * note that (expr) could also 876597Sbill * be (rn) (by special hole in the 877597Sbill * grammar), which we ensure 878597Sbill * means register indirection, instead 879597Sbill * of an expression with value n 880597Sbill */ 881597Sbill if (val != REG && val != REGOP){ 882597Sbill droppedLP = 1; 883632Shenry val = exprparse(val, &(ap->a_xp)); 884597Sbill droppedLP = 0; 885597Sbill goto overdisp; 886597Sbill } 887597Sbill findreg(regno); 888597Sbill shiftover(RP); 889597Sbill if (val == PLUS){ 890597Sbill shift; 891632Shenry ap->a_atype = AINCR; 892597Sbill } else 893632Shenry ap->a_atype = ABASE; 894632Shenry ap->a_areg1 = regno; 895597Sbill goto index; 896597Sbill 897597Sbill case LITOP: 898597Sbill imm: 899597Sbill shift; 900597Sbill expr(locxp, val); 901632Shenry ap->a_atype = AIMM; 902632Shenry ap->a_areg1 = 0; 903632Shenry ap->a_xp = locxp; 904597Sbill goto index; 905597Sbill 906597Sbill case MP: 907597Sbill shift; /* -(reg) */ 908597Sbill findreg(regno); 909597Sbill shiftover(RP); 910632Shenry ap->a_atype = ADECR; 911632Shenry ap->a_areg1 = regno; 912597Sbill index: /*look for [reg] */ 913597Sbill if (val == LB){ 914597Sbill shift; 915597Sbill findreg(regno); 916597Sbill shiftover(RB); 917597Sbill sawindex = 1; 918632Shenry ap->a_areg2 = regno; 919597Sbill } 920597Sbill break; 921597Sbill 922597Sbill } /*end of the switch to process an arg*/ 923597Sbill } /*end of processing an argument*/ 924597Sbill 925597Sbill if (sawmul){ 926597Sbill /* 927597Sbill * Make a concession for *(%r) 928597Sbill * meaning *0(%r) 929597Sbill */ 930632Shenry if (ap->a_atype == ABASE) { 931632Shenry ap->a_atype = ADISP; 932632Shenry xp->e_xtype = XABS; 9335827Srrh xp->e_number = Znumber; 9345827Srrh xp->e_number.num_tag = TYPL; 935632Shenry xp->e_xloc = 0; 936632Shenry ap->a_xp = xp++; 937597Sbill } 938632Shenry ap->a_atype |= ASTAR; 939597Sbill sawmul = 0; 940597Sbill } 941597Sbill if (sawindex){ 942632Shenry ap->a_atype |= AINDX; 943597Sbill sawindex = 0; 944597Sbill } 945632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 946597Sbill if (val != CM) break; 947597Sbill shiftover(CM); 948597Sbill } /*processing all the arguments*/ 949597Sbill 950597Sbill if (argcnt > 6){ 951597Sbill yyerror("More than 6 arguments"); 952597Sbill goto errorfix; 953597Sbill } 954597Sbill 955*13274Srrh /* 956*13274Srrh * See if this is a case instruction, 957*13274Srrh * so we can set up tests on the following 958*13274Srrh * vector of branch displacements 959*13274Srrh */ 960*13274Srrh if (yyopcode.Op_eopcode == CORE){ 961*13274Srrh switch(yyopcode.Op_popcode){ 962*13274Srrh case 0x8f: /* caseb */ 963*13274Srrh case 0xaf: /* casew */ 964*13274Srrh case 0xcf: /* casel */ 965*13274Srrh incasetable++; 966*13274Srrh break; 967*13274Srrh default: 968*13274Srrh incasetable = 0; 969*13274Srrh break; 970*13274Srrh } 971*13274Srrh } 972*13274Srrh 9735827Srrh insout(yyopcode, arglist, 974597Sbill auxval == INSTn ? argcnt : - argcnt); 975597Sbill break; 976597Sbill 9775827Srrh case IQUAD: toconv = TYPQ; goto bignumlist; 9785827Srrh case IOCTA: toconv = TYPO; goto bignumlist; 9795827Srrh 9805827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist; 9815827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist; 9825827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist; 9835827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist; 9845827Srrh bignumlist: 985597Sbill /* 9865827Srrh * eat a list of non 32 bit numbers. 9875827Srrh * IQUAD and IOCTA can, possibly, return 9885827Srrh * INT's, if the numbers are "small". 9895827Srrh * 9905827Srrh * The value of the numbers is coming back 9915827Srrh * as an expression, NOT in yybignum. 992597Sbill */ 9935827Srrh shift; /* over the opener */ 9945827Srrh if ((val == BIGNUM) || (val == INT)){ 995597Sbill do{ 9965827Srrh if ((val != BIGNUM) && (val != INT)){ 9975827Srrh ERROR(ty_float[toconv] 9985827Srrh ? "floating number expected" 9995827Srrh : "integer number expected" ); 1000597Sbill } 10015827Srrh dotp->e_xvalue += ty_nbyte[toconv]; 10025827Srrh if (passno == 2){ 10035827Srrh bignumwrite( 10045827Srrh ((struct exp *)yylval)->e_number, 10055827Srrh toconv); 1006597Sbill } 1007597Sbill xp = explist; 10085827Srrh shift; /* over this number */ 10095827Srrh if (auxval = (val == CM)) 10105827Srrh shift; /* over the comma */ 10115827Srrh } while (auxval); /* as long as there are commas */ 1012597Sbill } 1013597Sbill break; 10145827Srrh /* end of the case for initialized big numbers */ 1015597Sbill } /*end of the switch for looking at each reserved word*/ 1016597Sbill 10175827Srrh continue; 1018597Sbill 1019597Sbill errorfix: 1020597Sbill /* 1021597Sbill * got here by either requesting to skip to the 1022597Sbill * end of this statement, or by erroring out and 1023597Sbill * wanting to apply panic mode recovery 1024597Sbill */ 1025597Sbill while ( (val != NL) 1026597Sbill && (val != SEMI) 1027597Sbill && (val != PARSEEOF) 1028597Sbill ){ 1029597Sbill shift; 1030597Sbill } 1031597Sbill if (val == NL) 1032597Sbill lineno++; 1033597Sbill shift; 1034597Sbill 1035597Sbill } /*end of the loop to read the entire file, line by line*/ 1036597Sbill 1037597Sbill } /*end of yyparse*/ 1038597Sbill 1039597Sbill /* 1040597Sbill * Process a register declaration of the form 1041597Sbill * % <expr> 1042597Sbill * 1043597Sbill * Note: 1044597Sbill * The scanner has already processed funny registers of the form 1045597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 1046597Sbill * preceding zero digit). If there was any space between the % and 1047597Sbill * the digit, the scanner wouldn't have recognized it, so we 1048597Sbill * hack it out here. 1049597Sbill */ 10505827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ 10515827Srrh inttoktype val; /*what the read head is sitting on*/ 1052597Sbill int *regnoback; /*call by return*/ 1053597Sbill { 10545827Srrh reg struct exp *locxp; 10555827Srrh struct exp *loc1xp; 10565827Srrh struct exp **ptrloc1xp = & loc1xp; 1057597Sbill 1058597Sbill expr(locxp, val); /*and leave the current read head with value*/ 1059597Sbill if ( (passno == 2) && 10605827Srrh ( (locxp->e_xtype & XTYPE) != XABS 10615827Srrh || (locxp->e_xvalue < 0) 10625827Srrh || (locxp->e_xvalue >= 16) 1063597Sbill ) 1064597Sbill ){ 1065597Sbill yyerror("Illegal register"); 1066597Sbill return(0); 1067597Sbill } 1068632Shenry *regnoback = locxp->e_xvalue; 1069597Sbill return(val); 1070597Sbill } 107112945Srrh /* 107212945Srrh * Shift over error 107312945Srrh */ 107412945Srrh shiftoerror(token) 107512945Srrh int token; 107612945Srrh { 107712945Srrh char *tok_to_name(); 107812945Srrh yyerror("%s expected", tok_to_name(token)); 107912945Srrh } 1080597Sbill 1081597Sbill /*VARARGS1*/ 1082597Sbill yyerror(s, a1, a2,a3,a4,a5) 1083597Sbill char *s; 1084597Sbill { 1085597Sbill 1086649Shenry #define sink stdout 1087597Sbill 10885827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1089597Sbill fprintf(sink, "Assembler:\n"); 1090597Sbill anyerrs++; 10915827Srrh if (silent) 10925827Srrh return; 1093597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1094597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1095597Sbill fprintf(sink, "\n"); 10965827Srrh #undef sink 1097597Sbill } 1098676Shenry 1099676Shenry /*VARARGS1*/ 1100676Shenry yywarning(s, a1, a2,a3,a4,a5) 1101676Shenry char *s; 1102676Shenry { 1103676Shenry #define sink stdout 11045827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1105676Shenry fprintf(sink, "Assembler:\n"); 11065827Srrh anywarnings++; 11075827Srrh if (silent) 11085827Srrh return; 1109676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1110676Shenry fprintf(sink, s, a1, a2,a3,a4,a5); 1111676Shenry fprintf(sink, "\n"); 11125827Srrh #undef sink 1113676Shenry } 1114