15827Srrh /* 25827Srrh * Copyright (c) 1982 Regents of the University of California 35827Srrh */ 45827Srrh #ifndef lint 5*13571Srrh static char sccsid[] = "@(#)asparse.c 4.17 07/01/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 3213459Srrh 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 4713513Srrh static char UDotsname[64]; /*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 7113513Srrh 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 */ 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) { 134597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition", 13513513Srrh FETCHNAME(np)); 136597Sbill goto errorfix; 137597Sbill } 138597Sbill restlab: 139597Sbill shift; 140597Sbill flushfield(NBPW/4); 141632Shenry if ((np->s_type&XTYPE)!=XUNDEF) { 142632Shenry if( (np->s_type&XTYPE)!=dotp->e_xtype 143632Shenry || np->s_value!=dotp->e_xvalue 144597Sbill || ( (passno==1) 145632Shenry &&(np->s_index != dotp->e_xloc) 146597Sbill ) 147597Sbill ){ 148597Sbill #ifndef DEBUG 14913513Srrh if (FETCHNAME(np)[0] != 'L') 150597Sbill #endif not DEBUG 151597Sbill { 152597Sbill if (passno == 1) 153632Shenry yyerror("%s redefined", 15413513Srrh FETCHNAME(np)); 155597Sbill else 156632Shenry yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 15713513Srrh FETCHNAME(np), 158632Shenry np->s_value, 159632Shenry dotp->e_xvalue); 160597Sbill } 161597Sbill } 162597Sbill } 163632Shenry np->s_type &= ~(XTYPE|XFORW); 164632Shenry np->s_type |= dotp->e_xtype; 165632Shenry np->s_value = dotp->e_xvalue; 166597Sbill if (passno == 1){ 167632Shenry np->s_index = dotp-usedot; 16813513Srrh if (FETCHNAME(np)[0] == 'L'){ 169597Sbill nlabels++; 170597Sbill } 171632Shenry np->s_tag = LABELID; 172597Sbill } 173597Sbill } /*end of this being a label*/ 174597Sbill } /*end of to consuming all labels, NLs and SEMIS */ 175597Sbill 176597Sbill xp = explist; 177597Sbill ap = arglist; 178597Sbill 179597Sbill /* 180597Sbill * process the INSTRUCTION body 181597Sbill */ 182597Sbill switch(val){ 183597Sbill 184597Sbill default: 185597Sbill ERROR("Unrecognized instruction or directive"); 186597Sbill 187597Sbill case IABORT: 188597Sbill shift; 189597Sbill sawabort(); 190597Sbill /*NOTREACHED*/ 191597Sbill break; 192597Sbill 193597Sbill case PARSEEOF: 1945827Srrh tokptr -= sizeof(bytetoktype); 195597Sbill *tokptr++ = VOID; 196597Sbill tokptr[1] = VOID; 197597Sbill tokptr[2] = PARSEEOF; 198597Sbill break; 199597Sbill 200597Sbill case IFILE: 201597Sbill shift; 20213513Srrh stringp = (struct strdesc *)yylval; 203597Sbill shiftover(STRING); 204597Sbill dotsname = &UDotsname[0]; 20513513Srrh movestr(dotsname, stringp->sd_string, 20613513Srrh min(stringp->sd_strlen, sizeof(UDotsname))); 207597Sbill break; 208597Sbill 209597Sbill case ILINENO: 210597Sbill shift; /*over the ILINENO*/ 211597Sbill expr(locxp, val); 212632Shenry lineno = locxp->e_xvalue; 213597Sbill break; 214597Sbill 215597Sbill case ISET: /* .set <name> , <expr> */ 216597Sbill shift; 217597Sbill np = (struct symtab *)yylval; 218597Sbill shiftover(NAME); 219597Sbill shiftover(CM); 220597Sbill expr(locxp, val); 221632Shenry np->s_type &= (XXTRN|XFORW); 222632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 223632Shenry np->s_value = locxp->e_xvalue; 224597Sbill if (passno==1) 225632Shenry np->s_index = locxp->e_xloc; 226632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 227597Sbill yyerror("Illegal set?"); 228597Sbill break; 229597Sbill 230597Sbill case ILSYM: /*.lsym name , expr */ 231597Sbill shift; 232597Sbill np = (struct symtab *)yylval; 233597Sbill shiftover(NAME); 234597Sbill shiftover(CM); 235597Sbill expr(locxp, val); 236597Sbill /* 237597Sbill * Build the unique occurance of the 238597Sbill * symbol. 239597Sbill * The character scanner will have 240597Sbill * already entered it into the symbol 241597Sbill * table, but we should remove it 242597Sbill */ 243597Sbill if (passno == 1){ 244597Sbill stpt = (struct symtab *)symalloc(); 245632Shenry stpt->s_name = np->s_name; 246632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 247597Sbill nforgotten++; 248597Sbill np = stpt; 2495827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) 2505827Srrh yyerror("Illegal second argument to lsym"); 2515827Srrh np->s_value = locxp->e_xvalue; 2525827Srrh np->s_type = XABS; 253632Shenry np->s_tag = ILSYM; 254597Sbill } 255597Sbill break; 256597Sbill 257597Sbill case IGLOBAL: /*.globl <name> */ 258597Sbill shift; 259597Sbill np = (struct symtab *)yylval; 260597Sbill shiftover(NAME); 261632Shenry np->s_type |= XXTRN; 262597Sbill break; 263597Sbill 264597Sbill case IDATA: /*.data [ <expr> ] */ 265597Sbill case ITEXT: /*.text [ <expr> ] */ 266597Sbill seg_type = -val; 267597Sbill shift; 268597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 269597Sbill expr(locxp, val); 270597Sbill seg_type = -seg_type; /*now, it is positive*/ 271597Sbill } 272597Sbill 273597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 274597Sbill seg_number = 0; 275597Sbill seg_type = -seg_type; 276597Sbill } else { 2775827Srrh if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 2785827Srrh || (seg_number = locxp->e_xvalue) >= NLOC) { 279597Sbill yyerror("illegal location counter"); 280597Sbill seg_number = 0; 281597Sbill } 282597Sbill } 283597Sbill if (seg_type == IDATA) 284597Sbill seg_number += NLOC; 285597Sbill flushfield(NBPW/4); 286597Sbill dotp = &usedot[seg_number]; 287597Sbill if (passno==2) { /* go salt away in pass 2*/ 288597Sbill txtfil = usefile[seg_number]; 289597Sbill relfil = rusefile[seg_number]; 290597Sbill } 291597Sbill break; 292597Sbill 293597Sbill /* 294597Sbill * Storage filler directives: 295597Sbill * 296597Sbill * .byte [<exprlist>] 297597Sbill * 298597Sbill * exprlist: empty | exprlist outexpr 299597Sbill * outexpr: <expr> | <expr> : <expr> 300597Sbill */ 301597Sbill case IBYTE: curlen = NBPW/4; goto elist; 3025827Srrh case IWORD: curlen = NBPW/2; goto elist; 3035827Srrh case IINT: curlen = NBPW; goto elist; 304597Sbill case ILONG: curlen = NBPW; goto elist; 305597Sbill 306597Sbill elist: 307597Sbill seg_type = val; 308597Sbill shift; 309597Sbill 310597Sbill /* 311597Sbill * Expression List processing 312597Sbill */ 313597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 314597Sbill do{ 315597Sbill /* 316597Sbill * expression list consists of a list of : 317597Sbill * <expr> 318597Sbill * <expr> : <expr> 319597Sbill * (pack expr2 into expr1 bits 320597Sbill */ 321597Sbill expr(locxp, val); 322597Sbill /* 323597Sbill * now, pointing at the next token 324597Sbill */ 325597Sbill if (val == COLON){ 326597Sbill shiftover(COLON); 327597Sbill expr(pval, val); 3285827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 3295827Srrh yyerror("Width not absolute"); 330632Shenry field_width = locxp->e_xvalue; 331597Sbill locxp = pval; 3325827Srrh if (bitoff + field_width > curlen) 333597Sbill flushfield(curlen); 334597Sbill if (field_width > curlen) 335597Sbill yyerror("Expression crosses field boundary"); 336597Sbill } else { 337597Sbill field_width = curlen; 338597Sbill flushfield(curlen); 339597Sbill } 340597Sbill 3415827Srrh if ((locxp->e_xtype & XTYPE) != XABS) { 342597Sbill if (bitoff) 343597Sbill yyerror("Illegal relocation in field"); 344674Shenry switch(curlen){ 345674Shenry case NBPW/4: reloc_how = TYPB; break; 346674Shenry case NBPW/2: reloc_how = TYPW; break; 347674Shenry case NBPW: reloc_how = TYPL; break; 348674Shenry } 349597Sbill if (passno == 1){ 350674Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 351597Sbill } else { 352674Shenry outrel(locxp, reloc_how); 353597Sbill } 354597Sbill } else { 35513274Srrh /* 35613274Srrh * 35713274Srrh * See if we are doing a case instruction. 35813274Srrh * If so, then see if the branch distance, 35913274Srrh * stored as a word, 36013274Srrh * is going to loose sig bits. 36113274Srrh */ 36213274Srrh if (passno == 2 && incasetable){ 36313274Srrh if ( (locxp->e_xvalue < -32768) 36413274Srrh ||(locxp->e_xvalue > 32767)){ 36513274Srrh yyerror("Case will branch too far"); 36613274Srrh } 36713274Srrh } 368632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 369597Sbill bitfield |= field_value << bitoff; 370597Sbill bitoff += field_width; 371597Sbill } 372597Sbill xp = explist; 3735827Srrh if (auxval = (val == CM)) 3745827Srrh shift; 375597Sbill } while (auxval); 3765827Srrh } /* there existed an expression at all */ 377597Sbill 378597Sbill flushfield(curlen); 379597Sbill if ( ( curlen == NBPW/4) && bitoff) 380632Shenry dotp->e_xvalue ++; 381597Sbill break; 382597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 383597Sbill 384597Sbill case ISPACE: /* .space <expr> */ 385597Sbill shift; 386597Sbill expr(locxp, val); 3875827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 388597Sbill yyerror("Space size not absolute"); 389632Shenry space_value = locxp->e_xvalue; 390597Sbill ospace: 391597Sbill flushfield(NBPW/4); 39213446Srrh { 39313446Srrh static char spacebuf[128]; 39413446Srrh while (space_value > sizeof(spacebuf)){ 39513446Srrh outs(spacebuf, sizeof(spacebuf)); 39613446Srrh space_value -= sizeof(spacebuf); 39713446Srrh } 39813446Srrh outs(spacebuf, space_value); 399597Sbill } 400597Sbill break; 401597Sbill 402647Shenry /* 403647Shenry * .fill rep, size, value 404647Shenry * repeat rep times: fill size bytes with (truncated) value 405647Shenry * size must be between 1 and 8 406647Shenry */ 407647Shenry case IFILL: 408597Sbill shift; 409597Sbill expr(locxp, val); 4105827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 411597Sbill yyerror("Fill repetition count not absolute"); 412647Shenry fill_rep = locxp->e_xvalue; 413597Sbill shiftover(CM); 414597Sbill expr(locxp, val); 4155827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 416647Shenry yyerror("Fill size not absolute"); 417647Shenry fill_size = locxp->e_xvalue; 418647Shenry if (fill_size <= 0 || fill_size > 8) 419647Shenry yyerror("Fill count not in in 1..8"); 420647Shenry shiftover(CM); 421647Shenry expr(locxp, val); 4225827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 4235827Srrh yyerror("Fill value not absolute"); 424597Sbill flushfield(NBPW/4); 425647Shenry if (passno == 1) { 4265827Srrh dotp->e_xvalue += fill_rep * fill_size; 427647Shenry } else { 428647Shenry while(fill_rep-- > 0) 4295827Srrh bwrite((char *)&locxp->e_xvalue, fill_size, txtfil); 430647Shenry } 431597Sbill break; 432597Sbill 43313446Srrh case IASCII: /* .ascii [ <stringlist> ] */ 434597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 435597Sbill auxval = val; 436597Sbill shift; 437597Sbill /* 438597Sbill * Code to consume a string list 439597Sbill * 440597Sbill * stringlist: empty | STRING | stringlist STRING 441597Sbill */ 44213446Srrh while (val == STRING){ 44313513Srrh int mystrlen; 444597Sbill flushfield(NBPW/4); 445597Sbill if (bitoff) 44613446Srrh dotp->e_xvalue++; 44713513Srrh stringp = (struct strdesc *)yylval; 44813446Srrh /* 44913513Srrh * utilize the string scanner cheat; 45013513Srrh * the scanner appended a null byte on the string, 45113513Srrh * but didn't charge it to sd_strlen 45213446Srrh */ 45313513Srrh mystrlen = stringp->sd_strlen; 45413513Srrh mystrlen += (auxval == IASCIZ) ? 1 : 0; 45513513Srrh if (passno == 2){ 45613513Srrh if (stringp->sd_place & STR_CORE){ 45713513Srrh outs(stringp->sd_string, mystrlen); 45813513Srrh } else { 45913513Srrh int i, nread; 46013513Srrh fseek(strfile, stringp->sd_stroff, 0); 46113513Srrh for (i = 0; i < mystrlen;/*VOID*/){ 46213513Srrh nread = fread(yytext, 1, 46313513Srrh min(mystrlen - i, 46413513Srrh sizeof(yytext)), strfile); 46513513Srrh outs(yytext, nread); 46613513Srrh i += nread; 46713513Srrh } 46813513Srrh } 46913513Srrh } else { 47013513Srrh dotp->e_xvalue += mystrlen; 47113513Srrh } 472597Sbill shift; /*over the STRING*/ 473597Sbill if (val == CM) /*could be a split string*/ 474597Sbill shift; 475597Sbill } 476597Sbill break; 477597Sbill 478597Sbill case IORG: /* .org <expr> */ 479597Sbill shift; 480597Sbill expr(locxp, val); 481597Sbill 4825827Srrh if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */ 483597Sbill orgwarn++; 484632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 485597Sbill yyerror("Illegal expression to set origin"); 486632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 487597Sbill if (space_value < 0) 488597Sbill yyerror("Backwards 'org'"); 489597Sbill goto ospace; 490597Sbill break; 491597Sbill 492597Sbill /* 493597Sbill * 494597Sbill * Process stabs. Stabs are created only by the f77 495597Sbill * and the C compiler with the -g flag set. 496597Sbill * We only look at the stab ONCE, during pass 1, and 497597Sbill * virtually remove the stab from the intermediate file 498597Sbill * so it isn't seen during pass2. This makes for some 499597Sbill * hairy processing to handle labels occuring in 500597Sbill * stab entries, but since most expressions in the 501597Sbill * stab are integral we save lots of time in the second 502597Sbill * pass by not looking at the stabs. 503597Sbill * A stab that is tagged floating will be bumped during 504597Sbill * the jxxx resolution phase. A stab tagged fixed will 505597Sbill * not be be bumped. 506597Sbill * 507597Sbill * .stab: Old fashioned stabs 508597Sbill * .stabn: For stabs without names 509597Sbill * .stabs: For stabs with string names 510597Sbill * .stabd: For stabs for line numbers or bracketing, 511597Sbill * without a string name, without 512597Sbill * a final expression. The value of the 513597Sbill * final expression is taken to be the current 514597Sbill * location counter, and is patched by the 2nd pass 515597Sbill * 51613459Srrh * .stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr> 517597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 518597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 519597Sbill * .stabd <expr>, <expr>, <expr> # . 520597Sbill */ 521597Sbill case ISTAB: 52213521Srrh yyerror(".stab directive no longer supported"); 523597Sbill goto errorfix; 524597Sbill 525597Sbill tailstab: 526597Sbill expr(locxp, val); 527632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 5285827Srrh yyerror("Invalid type in %s", stabname); 529597Sbill goto errorfix; 530597Sbill } 531632Shenry stpt->s_ptype = locxp->e_xvalue; 532597Sbill shiftover(CM); 533597Sbill expr(locxp, val); 534632Shenry stpt->s_other = locxp->e_xvalue; 535597Sbill shiftover(CM); 536597Sbill expr(locxp, val); 537632Shenry stpt->s_desc = locxp->e_xvalue; 538597Sbill shiftover(CM); 539597Sbill exprisname = 0; 540597Sbill expr(locxp, val); 541632Shenry p = locxp->e_xname; 542597Sbill if (p == NULL) { /*absolute expr to begin with*/ 543632Shenry stpt->s_value = locxp->e_xvalue; 544632Shenry stpt->s_index = dotp - usedot; 545597Sbill if (exprisname){ 546632Shenry switch(stpt->s_ptype){ 547597Sbill case N_GSYM: 548597Sbill case N_FNAME: 549597Sbill case N_RSYM: 550597Sbill case N_SSYM: 551597Sbill case N_LSYM: 552597Sbill case N_PSYM: 553597Sbill case N_BCOMM: 554597Sbill case N_ECOMM: 555597Sbill case N_LENG: 556632Shenry stpt->s_tag = STABFIXED; 557597Sbill break; 558597Sbill default: 559632Shenry stpt->s_tag = STABFLOATING; 560597Sbill break; 561597Sbill } 562597Sbill } else 563632Shenry stpt->s_tag = STABFIXED; 564597Sbill } 565597Sbill else { /*really have a name*/ 566632Shenry stpt->s_dest = locxp->e_xname; 567632Shenry stpt->s_index = p->s_index; 568632Shenry stpt->s_type = p->s_type | STABFLAG; 569597Sbill /* 570597Sbill * We will assign a more accruate 571597Sbill * guess of locxp's location when 572597Sbill * we sort the symbol table 573597Sbill * The final value of value is 574597Sbill * given by stabfix() 575597Sbill */ 57612591Scsvaf /* 57712591Scsvaf * For exprs of the form (name + value) one needs to remember locxp->e_xvalue 57812591Scsvaf * for use in stabfix. The right place to keep this is in stpt->s_value 57912591Scsvaf * however this gets corrupted at an unknown point. 58012591Scsvaf * As a bandaid hack the value is preserved in s_desc and s_other (a 58112591Scsvaf * short and a char). This destroys these two values and will 58212591Scsvaf * be fixed. May 19 ,1983 Alastair Fyfe 58312591Scsvaf */ 58412591Scsvaf if(locxp->e_xvalue) { 58512591Scsvaf stpt->s_other = (locxp->e_xvalue >> 16); 58612591Scsvaf stpt->s_desc = (locxp->e_xvalue & 0x0000ffff); 58712591Scsvaf stpt->s_tag = STABFLOATING; 58812591Scsvaf } 589597Sbill } 590597Sbill /* 591597Sbill * tokptr now points at one token beyond 592597Sbill * the current token stored in val and yylval, 593597Sbill * which are the next tokens after the end of 594597Sbill * this .stab directive. This next token must 595597Sbill * be either a SEMI or NL, so is of width just 596597Sbill * one. Therefore, to point to the next token 597597Sbill * after the end of this stab, just back up one.. 598597Sbill */ 5995827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 600597Sbill break; /*end of the .stab*/ 601597Sbill 602597Sbill case ISTABDOT: 603597Sbill stabname = ".stabd"; 604597Sbill stpt = (struct symtab *)yylval; 605597Sbill /* 606597Sbill * We clobber everything after the 607597Sbill * .stabd and its pointer... we MUST 608597Sbill * be able to get back to this .stabd 609597Sbill * so that we can resolve its final value 610597Sbill */ 611597Sbill stabstart = tokptr; 612597Sbill shift; /*over the ISTABDOT*/ 613597Sbill if (passno == 1){ 614597Sbill expr(locxp, val); 615632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 616597Sbill yyerror("Invalid type in .stabd"); 617597Sbill goto errorfix; 618597Sbill } 619632Shenry stpt->s_ptype = locxp->e_xvalue; 620597Sbill shiftover(CM); 621597Sbill expr(locxp, val); 622632Shenry stpt->s_other = locxp->e_xvalue; 623597Sbill shiftover(CM); 624597Sbill expr(locxp, val); 625632Shenry stpt->s_desc = locxp->e_xvalue; 626597Sbill /* 627597Sbill * 628597Sbill * Now, clobber everything but the 629597Sbill * .stabd pseudo and the pointer 630597Sbill * to its symbol table entry 631597Sbill * tokptr points to the next token, 632597Sbill * build the skip up to this 633597Sbill */ 6345827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 635597Sbill } 636597Sbill /* 637597Sbill * pass 1: Assign a good guess for its position 638597Sbill * (ensures they are sorted into right place)/ 639597Sbill * pass 2: Fix the actual value 640597Sbill */ 641632Shenry stpt->s_value = dotp->e_xvalue; 642632Shenry stpt->s_index = dotp - usedot; 643632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 644597Sbill break; 645597Sbill 646597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 647597Sbill 648597Sbill case ISTABSTR: stabname = ".stabs"; 649597Sbill shortstab: 650597Sbill auxval = val; 651597Sbill if (passno == 2) goto errorfix; 652597Sbill stpt = (struct symtab *)yylval; 653597Sbill stabstart = tokptr; 6545827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *); 6555827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype); 656597Sbill shift; 657597Sbill if (auxval == ISTABSTR){ 65813513Srrh stringp = (struct strdesc *)yylval; 659597Sbill shiftover(STRING); 66013513Srrh stpt->s_name = (char *)stringp; 66113446Srrh /* 66213446Srrh * We want the trailing null included in this string. 66313446Srrh * We utilize the cheat the string scanner used, 66413446Srrh * and merely increment the string length 66513446Srrh */ 66613513Srrh stringp->sd_strlen += 1; 667597Sbill shiftover(CM); 668597Sbill } else { 669*13571Srrh stpt->s_name = (char *)savestr("\0", 0, STR_BOTH); 670597Sbill } 671597Sbill goto tailstab; 672597Sbill break; 673597Sbill 6745827Srrh case ICOMM: /* .comm <name> , <expr> */ 675597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 676597Sbill auxval = val; 677597Sbill shift; 678597Sbill np = (struct symtab *)yylval; 679597Sbill shiftover(NAME); 680597Sbill shiftover(CM); 681597Sbill expr(locxp, val); 682597Sbill 6835827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 684597Sbill yyerror("comm size not absolute"); 6855827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) 68613521Srrh yyerror("Redefinition of %s", FETCHNAME(np)); 687597Sbill if (passno==1) { 688632Shenry np->s_value = locxp->e_xvalue; 689597Sbill if (auxval == ICOMM) 690632Shenry np->s_type |= XXTRN; 691597Sbill else { 692632Shenry np->s_type &= ~XTYPE; 693632Shenry np->s_type |= XBSS; 694597Sbill } 695597Sbill } 696597Sbill break; 697597Sbill 698597Sbill case IALIGN: /* .align <expr> */ 699597Sbill stpt = (struct symtab *)yylval; 700597Sbill shift; 701597Sbill expr(locxp, val); 702597Sbill jalign(locxp, stpt); 703597Sbill break; 704597Sbill 705597Sbill case INST0: /* instructions w/o arguments*/ 70613274Srrh incasetable = 0; 7075827Srrh insout(yyopcode, (struct arg *)0, 0); 708597Sbill shift; 709597Sbill break; 710597Sbill 711597Sbill case INSTn: /* instructions with arguments*/ 712597Sbill case IJXXX: /* UNIX style jump instructions */ 713597Sbill auxval = val; 714597Sbill /* 715597Sbill * Code to process an argument list 716597Sbill */ 717597Sbill ap = arglist; 718597Sbill xp = explist; 719597Sbill 720597Sbill shift; /* bring in the first token for the arg list*/ 721597Sbill 722597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 723597Sbill /* 724597Sbill * code to process an argument proper 725597Sbill */ 726597Sbill sawindex = sawmul = sawsize = 0; 727597Sbill { 728597Sbill switch(val) { 729597Sbill 730597Sbill default: 731597Sbill disp: 732597Sbill if( !(INTOKSET(val, 733597Sbill EBEGOPS 734597Sbill +YUKKYEXPRBEG 735597Sbill +SAFEEXPRBEG)) ) { 736597Sbill ERROR("expression expected"); 737597Sbill } 738632Shenry expr(ap->a_xp,val); 739597Sbill overdisp: 740597Sbill if ( val == LP || sawsize){ 741597Sbill shiftover(LP); 742597Sbill findreg(regno); 743597Sbill shiftover(RP); 744632Shenry ap->a_atype = ADISP; 745632Shenry ap->a_areg1 = regno; 746597Sbill } else { 747632Shenry ap->a_atype = AEXP; 748632Shenry ap->a_areg1 = 0; 749597Sbill } 750597Sbill goto index; 751597Sbill 752597Sbill case SIZESPEC: 753597Sbill sizespec: 754597Sbill sawsize = yylval; 755597Sbill shift; 756597Sbill goto disp; 757597Sbill 758597Sbill case REG: 759597Sbill case REGOP: 760597Sbill findreg(regno); 761632Shenry ap->a_atype = AREG; 762632Shenry ap->a_areg1 = regno; 763597Sbill break; 764597Sbill 765597Sbill case MUL: 766597Sbill sawmul = 1; 767597Sbill shift; 768597Sbill if (val == LP) goto base; 769597Sbill if (val == LITOP) goto imm; 770597Sbill if (val == SIZESPEC) goto sizespec; 771597Sbill if (INTOKSET(val, 772597Sbill EBEGOPS 773597Sbill +YUKKYEXPRBEG 774597Sbill +SAFEEXPRBEG)) goto disp; 775597Sbill ERROR("expression, '(' or '$' expected"); 776597Sbill break; 777597Sbill 778597Sbill case LP: 779597Sbill base: 780597Sbill shift; /*consume the LP*/ 781597Sbill /* 782597Sbill * hack the ambiguity of 783597Sbill * movl (expr) (rn), ... 784597Sbill * note that (expr) could also 785597Sbill * be (rn) (by special hole in the 786597Sbill * grammar), which we ensure 787597Sbill * means register indirection, instead 788597Sbill * of an expression with value n 789597Sbill */ 790597Sbill if (val != REG && val != REGOP){ 791597Sbill droppedLP = 1; 792632Shenry val = exprparse(val, &(ap->a_xp)); 793597Sbill droppedLP = 0; 794597Sbill goto overdisp; 795597Sbill } 796597Sbill findreg(regno); 797597Sbill shiftover(RP); 798597Sbill if (val == PLUS){ 799597Sbill shift; 800632Shenry ap->a_atype = AINCR; 801597Sbill } else 802632Shenry ap->a_atype = ABASE; 803632Shenry ap->a_areg1 = regno; 804597Sbill goto index; 805597Sbill 806597Sbill case LITOP: 807597Sbill imm: 808597Sbill shift; 809597Sbill expr(locxp, val); 810632Shenry ap->a_atype = AIMM; 811632Shenry ap->a_areg1 = 0; 812632Shenry ap->a_xp = locxp; 813597Sbill goto index; 814597Sbill 815597Sbill case MP: 816597Sbill shift; /* -(reg) */ 817597Sbill findreg(regno); 818597Sbill shiftover(RP); 819632Shenry ap->a_atype = ADECR; 820632Shenry ap->a_areg1 = regno; 821597Sbill index: /*look for [reg] */ 822597Sbill if (val == LB){ 823597Sbill shift; 824597Sbill findreg(regno); 825597Sbill shiftover(RB); 826597Sbill sawindex = 1; 827632Shenry ap->a_areg2 = regno; 828597Sbill } 829597Sbill break; 830597Sbill 831597Sbill } /*end of the switch to process an arg*/ 832597Sbill } /*end of processing an argument*/ 833597Sbill 834597Sbill if (sawmul){ 835597Sbill /* 836597Sbill * Make a concession for *(%r) 837597Sbill * meaning *0(%r) 838597Sbill */ 839632Shenry if (ap->a_atype == ABASE) { 840632Shenry ap->a_atype = ADISP; 841632Shenry xp->e_xtype = XABS; 8425827Srrh xp->e_number = Znumber; 8435827Srrh xp->e_number.num_tag = TYPL; 844632Shenry xp->e_xloc = 0; 845632Shenry ap->a_xp = xp++; 846597Sbill } 847632Shenry ap->a_atype |= ASTAR; 848597Sbill sawmul = 0; 849597Sbill } 850597Sbill if (sawindex){ 851632Shenry ap->a_atype |= AINDX; 852597Sbill sawindex = 0; 853597Sbill } 854632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 855597Sbill if (val != CM) break; 856597Sbill shiftover(CM); 857597Sbill } /*processing all the arguments*/ 858597Sbill 859597Sbill if (argcnt > 6){ 860597Sbill yyerror("More than 6 arguments"); 861597Sbill goto errorfix; 862597Sbill } 863597Sbill 86413274Srrh /* 86513274Srrh * See if this is a case instruction, 86613274Srrh * so we can set up tests on the following 86713274Srrh * vector of branch displacements 86813274Srrh */ 86913274Srrh if (yyopcode.Op_eopcode == CORE){ 87013274Srrh switch(yyopcode.Op_popcode){ 87113274Srrh case 0x8f: /* caseb */ 87213274Srrh case 0xaf: /* casew */ 87313274Srrh case 0xcf: /* casel */ 87413274Srrh incasetable++; 87513274Srrh break; 87613274Srrh default: 87713274Srrh incasetable = 0; 87813274Srrh break; 87913274Srrh } 88013274Srrh } 88113274Srrh 8825827Srrh insout(yyopcode, arglist, 883597Sbill auxval == INSTn ? argcnt : - argcnt); 884597Sbill break; 885597Sbill 8865827Srrh case IQUAD: toconv = TYPQ; goto bignumlist; 8875827Srrh case IOCTA: toconv = TYPO; goto bignumlist; 8885827Srrh 8895827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist; 8905827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist; 8915827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist; 8925827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist; 8935827Srrh bignumlist: 894597Sbill /* 8955827Srrh * eat a list of non 32 bit numbers. 8965827Srrh * IQUAD and IOCTA can, possibly, return 8975827Srrh * INT's, if the numbers are "small". 8985827Srrh * 8995827Srrh * The value of the numbers is coming back 9005827Srrh * as an expression, NOT in yybignum. 901597Sbill */ 9025827Srrh shift; /* over the opener */ 9035827Srrh if ((val == BIGNUM) || (val == INT)){ 904597Sbill do{ 9055827Srrh if ((val != BIGNUM) && (val != INT)){ 9065827Srrh ERROR(ty_float[toconv] 9075827Srrh ? "floating number expected" 9085827Srrh : "integer number expected" ); 909597Sbill } 9105827Srrh dotp->e_xvalue += ty_nbyte[toconv]; 9115827Srrh if (passno == 2){ 9125827Srrh bignumwrite( 9135827Srrh ((struct exp *)yylval)->e_number, 9145827Srrh toconv); 915597Sbill } 916597Sbill xp = explist; 9175827Srrh shift; /* over this number */ 9185827Srrh if (auxval = (val == CM)) 9195827Srrh shift; /* over the comma */ 9205827Srrh } while (auxval); /* as long as there are commas */ 921597Sbill } 922597Sbill break; 9235827Srrh /* end of the case for initialized big numbers */ 924597Sbill } /*end of the switch for looking at each reserved word*/ 925597Sbill 9265827Srrh continue; 927597Sbill 928597Sbill errorfix: 929597Sbill /* 930597Sbill * got here by either requesting to skip to the 931597Sbill * end of this statement, or by erroring out and 932597Sbill * wanting to apply panic mode recovery 933597Sbill */ 934597Sbill while ( (val != NL) 935597Sbill && (val != SEMI) 936597Sbill && (val != PARSEEOF) 937597Sbill ){ 938597Sbill shift; 939597Sbill } 940597Sbill if (val == NL) 941597Sbill lineno++; 942597Sbill shift; 943597Sbill 944597Sbill } /*end of the loop to read the entire file, line by line*/ 945597Sbill 946597Sbill } /*end of yyparse*/ 947597Sbill 948597Sbill /* 949597Sbill * Process a register declaration of the form 950597Sbill * % <expr> 951597Sbill * 952597Sbill * Note: 953597Sbill * The scanner has already processed funny registers of the form 954597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 955597Sbill * preceding zero digit). If there was any space between the % and 956597Sbill * the digit, the scanner wouldn't have recognized it, so we 957597Sbill * hack it out here. 958597Sbill */ 9595827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ 9605827Srrh inttoktype val; /*what the read head is sitting on*/ 961597Sbill int *regnoback; /*call by return*/ 962597Sbill { 9635827Srrh reg struct exp *locxp; 9645827Srrh struct exp *loc1xp; 9655827Srrh struct exp **ptrloc1xp = & loc1xp; 966597Sbill 967597Sbill expr(locxp, val); /*and leave the current read head with value*/ 968597Sbill if ( (passno == 2) && 9695827Srrh ( (locxp->e_xtype & XTYPE) != XABS 9705827Srrh || (locxp->e_xvalue < 0) 9715827Srrh || (locxp->e_xvalue >= 16) 972597Sbill ) 973597Sbill ){ 974597Sbill yyerror("Illegal register"); 975597Sbill return(0); 976597Sbill } 977632Shenry *regnoback = locxp->e_xvalue; 978597Sbill return(val); 979597Sbill } 98012945Srrh /* 98112945Srrh * Shift over error 98212945Srrh */ 98312945Srrh shiftoerror(token) 98412945Srrh int token; 98512945Srrh { 98612945Srrh char *tok_to_name(); 98712945Srrh yyerror("%s expected", tok_to_name(token)); 98812945Srrh } 989597Sbill 990597Sbill /*VARARGS1*/ 991597Sbill yyerror(s, a1, a2,a3,a4,a5) 992597Sbill char *s; 993597Sbill { 994597Sbill 995649Shenry #define sink stdout 996597Sbill 9975827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 998597Sbill fprintf(sink, "Assembler:\n"); 999597Sbill anyerrs++; 10005827Srrh if (silent) 10015827Srrh return; 1002597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 1003597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1004597Sbill fprintf(sink, "\n"); 10055827Srrh #undef sink 1006597Sbill } 1007676Shenry 1008676Shenry /*VARARGS1*/ 1009676Shenry yywarning(s, a1, a2,a3,a4,a5) 1010676Shenry char *s; 1011676Shenry { 1012676Shenry #define sink stdout 10135827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1014676Shenry fprintf(sink, "Assembler:\n"); 10155827Srrh anywarnings++; 10165827Srrh if (silent) 10175827Srrh return; 1018676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1019676Shenry fprintf(sink, s, a1, a2,a3,a4,a5); 1020676Shenry fprintf(sink, "\n"); 10215827Srrh #undef sink 1022676Shenry } 1023