15827Srrh /* 25827Srrh * Copyright (c) 1982 Regents of the University of California 35827Srrh */ 45827Srrh #ifndef lint 5*16570Srrh static char sccsid[] = "@(#)asparse.c 4.19 06/06/84"; 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) { 14215235Sralph if ( (np->s_type&XTYPE) != dotp->e_xtype 14315235Sralph || np->s_value != dotp->e_xvalue 14415235Sralph || ( passno == 1 14515235Sralph && np->s_index != dotp->e_xloc) ) { 14615235Sralph if (passno == 1) 14715235Sralph yyerror("%s redefined", 14813513Srrh FETCHNAME(np)); 14915235Sralph else 15015235Sralph yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 15113513Srrh FETCHNAME(np), 152632Shenry np->s_value, 153632Shenry dotp->e_xvalue); 154597Sbill } 155597Sbill } 156632Shenry np->s_type &= ~(XTYPE|XFORW); 157632Shenry np->s_type |= dotp->e_xtype; 158632Shenry np->s_value = dotp->e_xvalue; 159597Sbill if (passno == 1){ 160632Shenry np->s_index = dotp-usedot; 16113513Srrh if (FETCHNAME(np)[0] == 'L'){ 162597Sbill nlabels++; 163597Sbill } 164632Shenry np->s_tag = LABELID; 165597Sbill } 166597Sbill } /*end of this being a label*/ 16715235Sralph } /*end of consuming all labels, NLs and SEMIS */ 168597Sbill 169597Sbill xp = explist; 170597Sbill ap = arglist; 171597Sbill 172597Sbill /* 173597Sbill * process the INSTRUCTION body 174597Sbill */ 175597Sbill switch(val){ 176597Sbill 177597Sbill default: 178597Sbill ERROR("Unrecognized instruction or directive"); 179597Sbill 180597Sbill case IABORT: 181597Sbill shift; 182597Sbill sawabort(); 183597Sbill /*NOTREACHED*/ 184597Sbill break; 185597Sbill 186597Sbill case PARSEEOF: 1875827Srrh tokptr -= sizeof(bytetoktype); 188597Sbill *tokptr++ = VOID; 189597Sbill tokptr[1] = VOID; 190597Sbill tokptr[2] = PARSEEOF; 191597Sbill break; 192597Sbill 193597Sbill case IFILE: 194597Sbill shift; 19513513Srrh stringp = (struct strdesc *)yylval; 196597Sbill shiftover(STRING); 197597Sbill dotsname = &UDotsname[0]; 19813513Srrh movestr(dotsname, stringp->sd_string, 19913513Srrh min(stringp->sd_strlen, sizeof(UDotsname))); 200597Sbill break; 201597Sbill 202597Sbill case ILINENO: 203597Sbill shift; /*over the ILINENO*/ 204597Sbill expr(locxp, val); 205632Shenry lineno = locxp->e_xvalue; 206597Sbill break; 207597Sbill 208597Sbill case ISET: /* .set <name> , <expr> */ 209597Sbill shift; 210597Sbill np = (struct symtab *)yylval; 211597Sbill shiftover(NAME); 212597Sbill shiftover(CM); 213597Sbill expr(locxp, val); 214632Shenry np->s_type &= (XXTRN|XFORW); 215632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 216632Shenry np->s_value = locxp->e_xvalue; 217597Sbill if (passno==1) 218632Shenry np->s_index = locxp->e_xloc; 219632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 220597Sbill yyerror("Illegal set?"); 221597Sbill break; 222597Sbill 223597Sbill case ILSYM: /*.lsym name , expr */ 224597Sbill shift; 225597Sbill np = (struct symtab *)yylval; 226597Sbill shiftover(NAME); 227597Sbill shiftover(CM); 228597Sbill expr(locxp, val); 229597Sbill /* 230597Sbill * Build the unique occurance of the 231597Sbill * symbol. 232597Sbill * The character scanner will have 233597Sbill * already entered it into the symbol 234597Sbill * table, but we should remove it 235597Sbill */ 236597Sbill if (passno == 1){ 237597Sbill stpt = (struct symtab *)symalloc(); 238632Shenry stpt->s_name = np->s_name; 239632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 240597Sbill nforgotten++; 241597Sbill np = stpt; 2425827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) 2435827Srrh yyerror("Illegal second argument to lsym"); 2445827Srrh np->s_value = locxp->e_xvalue; 2455827Srrh np->s_type = XABS; 246632Shenry np->s_tag = ILSYM; 247597Sbill } 248597Sbill break; 249597Sbill 250597Sbill case IGLOBAL: /*.globl <name> */ 251597Sbill shift; 252597Sbill np = (struct symtab *)yylval; 253597Sbill shiftover(NAME); 254632Shenry np->s_type |= XXTRN; 255597Sbill break; 256597Sbill 257597Sbill case IDATA: /*.data [ <expr> ] */ 258597Sbill case ITEXT: /*.text [ <expr> ] */ 259597Sbill seg_type = -val; 260597Sbill shift; 261597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 262597Sbill expr(locxp, val); 263597Sbill seg_type = -seg_type; /*now, it is positive*/ 264597Sbill } 265597Sbill 266597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 267597Sbill seg_number = 0; 268597Sbill seg_type = -seg_type; 269597Sbill } else { 2705827Srrh if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 2715827Srrh || (seg_number = locxp->e_xvalue) >= NLOC) { 272597Sbill yyerror("illegal location counter"); 273597Sbill seg_number = 0; 274597Sbill } 275597Sbill } 276597Sbill if (seg_type == IDATA) 277597Sbill seg_number += NLOC; 278597Sbill flushfield(NBPW/4); 279597Sbill dotp = &usedot[seg_number]; 280597Sbill if (passno==2) { /* go salt away in pass 2*/ 281597Sbill txtfil = usefile[seg_number]; 282597Sbill relfil = rusefile[seg_number]; 283597Sbill } 284597Sbill break; 285597Sbill 286597Sbill /* 287597Sbill * Storage filler directives: 288597Sbill * 289597Sbill * .byte [<exprlist>] 290597Sbill * 291597Sbill * exprlist: empty | exprlist outexpr 292597Sbill * outexpr: <expr> | <expr> : <expr> 293597Sbill */ 294597Sbill case IBYTE: curlen = NBPW/4; goto elist; 2955827Srrh case IWORD: curlen = NBPW/2; goto elist; 2965827Srrh case IINT: curlen = NBPW; goto elist; 297597Sbill case ILONG: curlen = NBPW; goto elist; 298597Sbill 299597Sbill elist: 300597Sbill seg_type = val; 301597Sbill shift; 302597Sbill 303597Sbill /* 304597Sbill * Expression List processing 305597Sbill */ 306597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 307597Sbill do{ 308597Sbill /* 309597Sbill * expression list consists of a list of : 310597Sbill * <expr> 311597Sbill * <expr> : <expr> 312597Sbill * (pack expr2 into expr1 bits 313597Sbill */ 314597Sbill expr(locxp, val); 315597Sbill /* 316597Sbill * now, pointing at the next token 317597Sbill */ 318597Sbill if (val == COLON){ 319597Sbill shiftover(COLON); 320597Sbill expr(pval, val); 3215827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 3225827Srrh yyerror("Width not absolute"); 323632Shenry field_width = locxp->e_xvalue; 324597Sbill locxp = pval; 3255827Srrh if (bitoff + field_width > curlen) 326597Sbill flushfield(curlen); 327597Sbill if (field_width > curlen) 328597Sbill yyerror("Expression crosses field boundary"); 329597Sbill } else { 330597Sbill field_width = curlen; 331597Sbill flushfield(curlen); 332597Sbill } 333597Sbill 3345827Srrh if ((locxp->e_xtype & XTYPE) != XABS) { 335597Sbill if (bitoff) 336597Sbill yyerror("Illegal relocation in field"); 337674Shenry switch(curlen){ 338674Shenry case NBPW/4: reloc_how = TYPB; break; 339674Shenry case NBPW/2: reloc_how = TYPW; break; 340674Shenry case NBPW: reloc_how = TYPL; break; 341674Shenry } 342597Sbill if (passno == 1){ 343674Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 344597Sbill } else { 345674Shenry outrel(locxp, reloc_how); 346597Sbill } 347597Sbill } else { 34813274Srrh /* 34913274Srrh * 35013274Srrh * See if we are doing a case instruction. 35113274Srrh * If so, then see if the branch distance, 35213274Srrh * stored as a word, 35313274Srrh * is going to loose sig bits. 35413274Srrh */ 35513274Srrh if (passno == 2 && incasetable){ 35613274Srrh if ( (locxp->e_xvalue < -32768) 35713274Srrh ||(locxp->e_xvalue > 32767)){ 35813274Srrh yyerror("Case will branch too far"); 35913274Srrh } 36013274Srrh } 361632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 362597Sbill bitfield |= field_value << bitoff; 363597Sbill bitoff += field_width; 364597Sbill } 365597Sbill xp = explist; 3665827Srrh if (auxval = (val == CM)) 3675827Srrh shift; 368597Sbill } while (auxval); 3695827Srrh } /* there existed an expression at all */ 370597Sbill 371597Sbill flushfield(curlen); 372597Sbill if ( ( curlen == NBPW/4) && bitoff) 373632Shenry dotp->e_xvalue ++; 374597Sbill break; 375597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 376597Sbill 377597Sbill case ISPACE: /* .space <expr> */ 378597Sbill shift; 379597Sbill expr(locxp, val); 3805827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 381597Sbill yyerror("Space size not absolute"); 382632Shenry space_value = locxp->e_xvalue; 383597Sbill ospace: 384597Sbill flushfield(NBPW/4); 38513446Srrh { 38613446Srrh static char spacebuf[128]; 38713446Srrh while (space_value > sizeof(spacebuf)){ 38813446Srrh outs(spacebuf, sizeof(spacebuf)); 38913446Srrh space_value -= sizeof(spacebuf); 39013446Srrh } 39113446Srrh outs(spacebuf, space_value); 392597Sbill } 393597Sbill break; 394597Sbill 395647Shenry /* 396647Shenry * .fill rep, size, value 397647Shenry * repeat rep times: fill size bytes with (truncated) value 398647Shenry * size must be between 1 and 8 399647Shenry */ 400647Shenry case IFILL: 401597Sbill shift; 402597Sbill expr(locxp, val); 4035827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 404597Sbill yyerror("Fill repetition count not absolute"); 405647Shenry fill_rep = locxp->e_xvalue; 406597Sbill shiftover(CM); 407597Sbill expr(locxp, val); 4085827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 409647Shenry yyerror("Fill size not absolute"); 410647Shenry fill_size = locxp->e_xvalue; 411647Shenry if (fill_size <= 0 || fill_size > 8) 412647Shenry yyerror("Fill count not in in 1..8"); 413647Shenry shiftover(CM); 414647Shenry expr(locxp, val); 4155827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 4165827Srrh yyerror("Fill value not absolute"); 417597Sbill flushfield(NBPW/4); 418*16570Srrh dotp->e_xvalue += fill_rep * fill_size; 419*16570Srrh if (passno == 2) { 420647Shenry while(fill_rep-- > 0) 4215827Srrh bwrite((char *)&locxp->e_xvalue, fill_size, txtfil); 422647Shenry } 423597Sbill break; 424597Sbill 42513446Srrh case IASCII: /* .ascii [ <stringlist> ] */ 426597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 427597Sbill auxval = val; 428597Sbill shift; 429597Sbill /* 430597Sbill * Code to consume a string list 431597Sbill * 432597Sbill * stringlist: empty | STRING | stringlist STRING 433597Sbill */ 43413446Srrh while (val == STRING){ 43513513Srrh int mystrlen; 436597Sbill flushfield(NBPW/4); 437597Sbill if (bitoff) 43813446Srrh dotp->e_xvalue++; 43913513Srrh stringp = (struct strdesc *)yylval; 44013446Srrh /* 44113513Srrh * utilize the string scanner cheat; 44213513Srrh * the scanner appended a null byte on the string, 44313513Srrh * but didn't charge it to sd_strlen 44413446Srrh */ 44513513Srrh mystrlen = stringp->sd_strlen; 44613513Srrh mystrlen += (auxval == IASCIZ) ? 1 : 0; 44713513Srrh if (passno == 2){ 44813513Srrh if (stringp->sd_place & STR_CORE){ 44913513Srrh outs(stringp->sd_string, mystrlen); 45013513Srrh } else { 45113513Srrh int i, nread; 45213513Srrh fseek(strfile, stringp->sd_stroff, 0); 45313513Srrh for (i = 0; i < mystrlen;/*VOID*/){ 45413513Srrh nread = fread(yytext, 1, 45513513Srrh min(mystrlen - i, 45613513Srrh sizeof(yytext)), strfile); 45713513Srrh outs(yytext, nread); 45813513Srrh i += nread; 45913513Srrh } 46013513Srrh } 46113513Srrh } else { 46213513Srrh dotp->e_xvalue += mystrlen; 46313513Srrh } 464597Sbill shift; /*over the STRING*/ 465597Sbill if (val == CM) /*could be a split string*/ 466597Sbill shift; 467597Sbill } 468597Sbill break; 469597Sbill 470597Sbill case IORG: /* .org <expr> */ 471597Sbill shift; 472597Sbill expr(locxp, val); 473597Sbill 4745827Srrh if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */ 475597Sbill orgwarn++; 476632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 477597Sbill yyerror("Illegal expression to set origin"); 478632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 479597Sbill if (space_value < 0) 480597Sbill yyerror("Backwards 'org'"); 481597Sbill goto ospace; 482597Sbill break; 483597Sbill 484597Sbill /* 485597Sbill * 486597Sbill * Process stabs. Stabs are created only by the f77 487597Sbill * and the C compiler with the -g flag set. 488597Sbill * We only look at the stab ONCE, during pass 1, and 489597Sbill * virtually remove the stab from the intermediate file 490597Sbill * so it isn't seen during pass2. This makes for some 491597Sbill * hairy processing to handle labels occuring in 492597Sbill * stab entries, but since most expressions in the 493597Sbill * stab are integral we save lots of time in the second 494597Sbill * pass by not looking at the stabs. 495597Sbill * A stab that is tagged floating will be bumped during 496597Sbill * the jxxx resolution phase. A stab tagged fixed will 497597Sbill * not be be bumped. 498597Sbill * 499597Sbill * .stab: Old fashioned stabs 500597Sbill * .stabn: For stabs without names 501597Sbill * .stabs: For stabs with string names 502597Sbill * .stabd: For stabs for line numbers or bracketing, 503597Sbill * without a string name, without 504597Sbill * a final expression. The value of the 505597Sbill * final expression is taken to be the current 506597Sbill * location counter, and is patched by the 2nd pass 507597Sbill * 50813459Srrh * .stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr> 509597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 510597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 511597Sbill * .stabd <expr>, <expr>, <expr> # . 512597Sbill */ 513597Sbill case ISTAB: 51413521Srrh yyerror(".stab directive no longer supported"); 515597Sbill goto errorfix; 516597Sbill 517597Sbill tailstab: 518597Sbill expr(locxp, val); 519632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 5205827Srrh yyerror("Invalid type in %s", stabname); 521597Sbill goto errorfix; 522597Sbill } 523632Shenry stpt->s_ptype = locxp->e_xvalue; 524597Sbill shiftover(CM); 525597Sbill expr(locxp, val); 526632Shenry stpt->s_other = locxp->e_xvalue; 527597Sbill shiftover(CM); 528597Sbill expr(locxp, val); 529632Shenry stpt->s_desc = locxp->e_xvalue; 530597Sbill shiftover(CM); 531597Sbill exprisname = 0; 532597Sbill expr(locxp, val); 533632Shenry p = locxp->e_xname; 534597Sbill if (p == NULL) { /*absolute expr to begin with*/ 535632Shenry stpt->s_value = locxp->e_xvalue; 536632Shenry stpt->s_index = dotp - usedot; 537597Sbill if (exprisname){ 538632Shenry switch(stpt->s_ptype){ 539597Sbill case N_GSYM: 540597Sbill case N_FNAME: 541597Sbill case N_RSYM: 542597Sbill case N_SSYM: 543597Sbill case N_LSYM: 544597Sbill case N_PSYM: 545597Sbill case N_BCOMM: 546597Sbill case N_ECOMM: 547597Sbill case N_LENG: 548632Shenry stpt->s_tag = STABFIXED; 549597Sbill break; 550597Sbill default: 551632Shenry stpt->s_tag = STABFLOATING; 552597Sbill break; 553597Sbill } 554597Sbill } else 555632Shenry stpt->s_tag = STABFIXED; 556597Sbill } 557597Sbill else { /*really have a name*/ 558632Shenry stpt->s_dest = locxp->e_xname; 559632Shenry stpt->s_index = p->s_index; 560632Shenry stpt->s_type = p->s_type | STABFLAG; 561597Sbill /* 562597Sbill * We will assign a more accruate 563597Sbill * guess of locxp's location when 564597Sbill * we sort the symbol table 565597Sbill * The final value of value is 566597Sbill * given by stabfix() 567597Sbill */ 56812591Scsvaf /* 56912591Scsvaf * For exprs of the form (name + value) one needs to remember locxp->e_xvalue 57012591Scsvaf * for use in stabfix. The right place to keep this is in stpt->s_value 57112591Scsvaf * however this gets corrupted at an unknown point. 57212591Scsvaf * As a bandaid hack the value is preserved in s_desc and s_other (a 57312591Scsvaf * short and a char). This destroys these two values and will 57412591Scsvaf * be fixed. May 19 ,1983 Alastair Fyfe 57512591Scsvaf */ 57612591Scsvaf if(locxp->e_xvalue) { 57712591Scsvaf stpt->s_other = (locxp->e_xvalue >> 16); 57812591Scsvaf stpt->s_desc = (locxp->e_xvalue & 0x0000ffff); 57912591Scsvaf stpt->s_tag = STABFLOATING; 58012591Scsvaf } 581597Sbill } 582597Sbill /* 583597Sbill * tokptr now points at one token beyond 584597Sbill * the current token stored in val and yylval, 585597Sbill * which are the next tokens after the end of 586597Sbill * this .stab directive. This next token must 587597Sbill * be either a SEMI or NL, so is of width just 588597Sbill * one. Therefore, to point to the next token 589597Sbill * after the end of this stab, just back up one.. 590597Sbill */ 5915827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 592597Sbill break; /*end of the .stab*/ 593597Sbill 594597Sbill case ISTABDOT: 595597Sbill stabname = ".stabd"; 596597Sbill stpt = (struct symtab *)yylval; 597597Sbill /* 598597Sbill * We clobber everything after the 599597Sbill * .stabd and its pointer... we MUST 600597Sbill * be able to get back to this .stabd 601597Sbill * so that we can resolve its final value 602597Sbill */ 603597Sbill stabstart = tokptr; 604597Sbill shift; /*over the ISTABDOT*/ 605597Sbill if (passno == 1){ 606597Sbill expr(locxp, val); 607632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 608597Sbill yyerror("Invalid type in .stabd"); 609597Sbill goto errorfix; 610597Sbill } 611632Shenry stpt->s_ptype = locxp->e_xvalue; 612597Sbill shiftover(CM); 613597Sbill expr(locxp, val); 614632Shenry stpt->s_other = locxp->e_xvalue; 615597Sbill shiftover(CM); 616597Sbill expr(locxp, val); 617632Shenry stpt->s_desc = locxp->e_xvalue; 618597Sbill /* 619597Sbill * 620597Sbill * Now, clobber everything but the 621597Sbill * .stabd pseudo and the pointer 622597Sbill * to its symbol table entry 623597Sbill * tokptr points to the next token, 624597Sbill * build the skip up to this 625597Sbill */ 6265827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 627597Sbill } 628597Sbill /* 629597Sbill * pass 1: Assign a good guess for its position 630597Sbill * (ensures they are sorted into right place)/ 631597Sbill * pass 2: Fix the actual value 632597Sbill */ 633632Shenry stpt->s_value = dotp->e_xvalue; 634632Shenry stpt->s_index = dotp - usedot; 635632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 636597Sbill break; 637597Sbill 638597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 639597Sbill 640597Sbill case ISTABSTR: stabname = ".stabs"; 641597Sbill shortstab: 642597Sbill auxval = val; 643597Sbill if (passno == 2) goto errorfix; 644597Sbill stpt = (struct symtab *)yylval; 645597Sbill stabstart = tokptr; 6465827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *); 6475827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype); 648597Sbill shift; 649597Sbill if (auxval == ISTABSTR){ 65013513Srrh stringp = (struct strdesc *)yylval; 651597Sbill shiftover(STRING); 65213513Srrh stpt->s_name = (char *)stringp; 65313446Srrh /* 65413446Srrh * We want the trailing null included in this string. 65513446Srrh * We utilize the cheat the string scanner used, 65613446Srrh * and merely increment the string length 65713446Srrh */ 65813513Srrh stringp->sd_strlen += 1; 659597Sbill shiftover(CM); 660597Sbill } else { 66113571Srrh stpt->s_name = (char *)savestr("\0", 0, STR_BOTH); 662597Sbill } 663597Sbill goto tailstab; 664597Sbill break; 665597Sbill 6665827Srrh case ICOMM: /* .comm <name> , <expr> */ 667597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 668597Sbill auxval = val; 669597Sbill shift; 670597Sbill np = (struct symtab *)yylval; 671597Sbill shiftover(NAME); 672597Sbill shiftover(CM); 673597Sbill expr(locxp, val); 674597Sbill 6755827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 676597Sbill yyerror("comm size not absolute"); 6775827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) 67813521Srrh yyerror("Redefinition of %s", FETCHNAME(np)); 679597Sbill if (passno==1) { 680632Shenry np->s_value = locxp->e_xvalue; 681597Sbill if (auxval == ICOMM) 682632Shenry np->s_type |= XXTRN; 683597Sbill else { 684632Shenry np->s_type &= ~XTYPE; 685632Shenry np->s_type |= XBSS; 686597Sbill } 687597Sbill } 688597Sbill break; 689597Sbill 690597Sbill case IALIGN: /* .align <expr> */ 691597Sbill stpt = (struct symtab *)yylval; 692597Sbill shift; 693597Sbill expr(locxp, val); 694597Sbill jalign(locxp, stpt); 695597Sbill break; 696597Sbill 697597Sbill case INST0: /* instructions w/o arguments*/ 69813274Srrh incasetable = 0; 6995827Srrh insout(yyopcode, (struct arg *)0, 0); 700597Sbill shift; 701597Sbill break; 702597Sbill 703597Sbill case INSTn: /* instructions with arguments*/ 704597Sbill case IJXXX: /* UNIX style jump instructions */ 705597Sbill auxval = val; 706597Sbill /* 707597Sbill * Code to process an argument list 708597Sbill */ 709597Sbill ap = arglist; 710597Sbill xp = explist; 711597Sbill 712597Sbill shift; /* bring in the first token for the arg list*/ 713597Sbill 714597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 715597Sbill /* 716597Sbill * code to process an argument proper 717597Sbill */ 718597Sbill sawindex = sawmul = sawsize = 0; 719597Sbill { 720597Sbill switch(val) { 721597Sbill 722597Sbill default: 723597Sbill disp: 724597Sbill if( !(INTOKSET(val, 725597Sbill EBEGOPS 726597Sbill +YUKKYEXPRBEG 727597Sbill +SAFEEXPRBEG)) ) { 728597Sbill ERROR("expression expected"); 729597Sbill } 730632Shenry expr(ap->a_xp,val); 731597Sbill overdisp: 732597Sbill if ( val == LP || sawsize){ 733597Sbill shiftover(LP); 734597Sbill findreg(regno); 735597Sbill shiftover(RP); 736632Shenry ap->a_atype = ADISP; 737632Shenry ap->a_areg1 = regno; 738597Sbill } else { 739632Shenry ap->a_atype = AEXP; 740632Shenry ap->a_areg1 = 0; 741597Sbill } 742597Sbill goto index; 743597Sbill 744597Sbill case SIZESPEC: 745597Sbill sizespec: 746597Sbill sawsize = yylval; 747597Sbill shift; 748597Sbill goto disp; 749597Sbill 750597Sbill case REG: 751597Sbill case REGOP: 752597Sbill findreg(regno); 753632Shenry ap->a_atype = AREG; 754632Shenry ap->a_areg1 = regno; 755597Sbill break; 756597Sbill 757597Sbill case MUL: 758597Sbill sawmul = 1; 759597Sbill shift; 760597Sbill if (val == LP) goto base; 761597Sbill if (val == LITOP) goto imm; 762597Sbill if (val == SIZESPEC) goto sizespec; 763597Sbill if (INTOKSET(val, 764597Sbill EBEGOPS 765597Sbill +YUKKYEXPRBEG 766597Sbill +SAFEEXPRBEG)) goto disp; 767597Sbill ERROR("expression, '(' or '$' expected"); 768597Sbill break; 769597Sbill 770597Sbill case LP: 771597Sbill base: 772597Sbill shift; /*consume the LP*/ 773597Sbill /* 774597Sbill * hack the ambiguity of 775597Sbill * movl (expr) (rn), ... 776597Sbill * note that (expr) could also 777597Sbill * be (rn) (by special hole in the 778597Sbill * grammar), which we ensure 779597Sbill * means register indirection, instead 780597Sbill * of an expression with value n 781597Sbill */ 782597Sbill if (val != REG && val != REGOP){ 783597Sbill droppedLP = 1; 784632Shenry val = exprparse(val, &(ap->a_xp)); 785597Sbill droppedLP = 0; 786597Sbill goto overdisp; 787597Sbill } 788597Sbill findreg(regno); 789597Sbill shiftover(RP); 790597Sbill if (val == PLUS){ 791597Sbill shift; 792632Shenry ap->a_atype = AINCR; 793597Sbill } else 794632Shenry ap->a_atype = ABASE; 795632Shenry ap->a_areg1 = regno; 796597Sbill goto index; 797597Sbill 798597Sbill case LITOP: 799597Sbill imm: 800597Sbill shift; 801597Sbill expr(locxp, val); 802632Shenry ap->a_atype = AIMM; 803632Shenry ap->a_areg1 = 0; 804632Shenry ap->a_xp = locxp; 805597Sbill goto index; 806597Sbill 807597Sbill case MP: 808597Sbill shift; /* -(reg) */ 809597Sbill findreg(regno); 810597Sbill shiftover(RP); 811632Shenry ap->a_atype = ADECR; 812632Shenry ap->a_areg1 = regno; 813597Sbill index: /*look for [reg] */ 814597Sbill if (val == LB){ 815597Sbill shift; 816597Sbill findreg(regno); 817597Sbill shiftover(RB); 818597Sbill sawindex = 1; 819632Shenry ap->a_areg2 = regno; 820597Sbill } 821597Sbill break; 822597Sbill 823597Sbill } /*end of the switch to process an arg*/ 824597Sbill } /*end of processing an argument*/ 825597Sbill 826597Sbill if (sawmul){ 827597Sbill /* 828597Sbill * Make a concession for *(%r) 829597Sbill * meaning *0(%r) 830597Sbill */ 831632Shenry if (ap->a_atype == ABASE) { 832632Shenry ap->a_atype = ADISP; 833632Shenry xp->e_xtype = XABS; 8345827Srrh xp->e_number = Znumber; 8355827Srrh xp->e_number.num_tag = TYPL; 836632Shenry xp->e_xloc = 0; 837632Shenry ap->a_xp = xp++; 838597Sbill } 839632Shenry ap->a_atype |= ASTAR; 840597Sbill sawmul = 0; 841597Sbill } 842597Sbill if (sawindex){ 843632Shenry ap->a_atype |= AINDX; 844597Sbill sawindex = 0; 845597Sbill } 846632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 847597Sbill if (val != CM) break; 848597Sbill shiftover(CM); 849597Sbill } /*processing all the arguments*/ 850597Sbill 851597Sbill if (argcnt > 6){ 852597Sbill yyerror("More than 6 arguments"); 853597Sbill goto errorfix; 854597Sbill } 855597Sbill 85613274Srrh /* 85713274Srrh * See if this is a case instruction, 85813274Srrh * so we can set up tests on the following 85913274Srrh * vector of branch displacements 86013274Srrh */ 86113274Srrh if (yyopcode.Op_eopcode == CORE){ 86213274Srrh switch(yyopcode.Op_popcode){ 86313274Srrh case 0x8f: /* caseb */ 86413274Srrh case 0xaf: /* casew */ 86513274Srrh case 0xcf: /* casel */ 86613274Srrh incasetable++; 86713274Srrh break; 86813274Srrh default: 86913274Srrh incasetable = 0; 87013274Srrh break; 87113274Srrh } 87213274Srrh } 87313274Srrh 8745827Srrh insout(yyopcode, arglist, 875597Sbill auxval == INSTn ? argcnt : - argcnt); 876597Sbill break; 877597Sbill 8785827Srrh case IQUAD: toconv = TYPQ; goto bignumlist; 8795827Srrh case IOCTA: toconv = TYPO; goto bignumlist; 8805827Srrh 8815827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist; 8825827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist; 8835827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist; 8845827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist; 8855827Srrh bignumlist: 886597Sbill /* 8875827Srrh * eat a list of non 32 bit numbers. 8885827Srrh * IQUAD and IOCTA can, possibly, return 8895827Srrh * INT's, if the numbers are "small". 8905827Srrh * 8915827Srrh * The value of the numbers is coming back 8925827Srrh * as an expression, NOT in yybignum. 893597Sbill */ 8945827Srrh shift; /* over the opener */ 8955827Srrh if ((val == BIGNUM) || (val == INT)){ 896597Sbill do{ 8975827Srrh if ((val != BIGNUM) && (val != INT)){ 8985827Srrh ERROR(ty_float[toconv] 8995827Srrh ? "floating number expected" 9005827Srrh : "integer number expected" ); 901597Sbill } 9025827Srrh dotp->e_xvalue += ty_nbyte[toconv]; 9035827Srrh if (passno == 2){ 9045827Srrh bignumwrite( 9055827Srrh ((struct exp *)yylval)->e_number, 9065827Srrh toconv); 907597Sbill } 908597Sbill xp = explist; 9095827Srrh shift; /* over this number */ 9105827Srrh if (auxval = (val == CM)) 9115827Srrh shift; /* over the comma */ 9125827Srrh } while (auxval); /* as long as there are commas */ 913597Sbill } 914597Sbill break; 9155827Srrh /* end of the case for initialized big numbers */ 916597Sbill } /*end of the switch for looking at each reserved word*/ 917597Sbill 9185827Srrh continue; 919597Sbill 920597Sbill errorfix: 921597Sbill /* 922597Sbill * got here by either requesting to skip to the 923597Sbill * end of this statement, or by erroring out and 924597Sbill * wanting to apply panic mode recovery 925597Sbill */ 926597Sbill while ( (val != NL) 927597Sbill && (val != SEMI) 928597Sbill && (val != PARSEEOF) 929597Sbill ){ 930597Sbill shift; 931597Sbill } 932597Sbill if (val == NL) 933597Sbill lineno++; 934597Sbill shift; 935597Sbill 936597Sbill } /*end of the loop to read the entire file, line by line*/ 937597Sbill 938597Sbill } /*end of yyparse*/ 939597Sbill 940597Sbill /* 941597Sbill * Process a register declaration of the form 942597Sbill * % <expr> 943597Sbill * 944597Sbill * Note: 945597Sbill * The scanner has already processed funny registers of the form 946597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 947597Sbill * preceding zero digit). If there was any space between the % and 948597Sbill * the digit, the scanner wouldn't have recognized it, so we 949597Sbill * hack it out here. 950597Sbill */ 9515827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ 9525827Srrh inttoktype val; /*what the read head is sitting on*/ 953597Sbill int *regnoback; /*call by return*/ 954597Sbill { 9555827Srrh reg struct exp *locxp; 9565827Srrh struct exp *loc1xp; 9575827Srrh struct exp **ptrloc1xp = & loc1xp; 958597Sbill 959597Sbill expr(locxp, val); /*and leave the current read head with value*/ 960597Sbill if ( (passno == 2) && 9615827Srrh ( (locxp->e_xtype & XTYPE) != XABS 9625827Srrh || (locxp->e_xvalue < 0) 9635827Srrh || (locxp->e_xvalue >= 16) 964597Sbill ) 965597Sbill ){ 966597Sbill yyerror("Illegal register"); 967597Sbill return(0); 968597Sbill } 969632Shenry *regnoback = locxp->e_xvalue; 970597Sbill return(val); 971597Sbill } 97212945Srrh /* 97312945Srrh * Shift over error 97412945Srrh */ 97512945Srrh shiftoerror(token) 97612945Srrh int token; 97712945Srrh { 97812945Srrh char *tok_to_name(); 97912945Srrh yyerror("%s expected", tok_to_name(token)); 98012945Srrh } 981597Sbill 982597Sbill /*VARARGS1*/ 983597Sbill yyerror(s, a1, a2,a3,a4,a5) 984597Sbill char *s; 985597Sbill { 986597Sbill 987649Shenry #define sink stdout 988597Sbill 9895827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 990597Sbill fprintf(sink, "Assembler:\n"); 991597Sbill anyerrs++; 9925827Srrh if (silent) 9935827Srrh return; 994597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 995597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 996597Sbill fprintf(sink, "\n"); 9975827Srrh #undef sink 998597Sbill } 999676Shenry 1000676Shenry /*VARARGS1*/ 1001676Shenry yywarning(s, a1, a2,a3,a4,a5) 1002676Shenry char *s; 1003676Shenry { 1004676Shenry #define sink stdout 10055827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1006676Shenry fprintf(sink, "Assembler:\n"); 10075827Srrh anywarnings++; 10085827Srrh if (silent) 10095827Srrh return; 1010676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1011676Shenry fprintf(sink, s, a1, a2,a3,a4,a5); 1012676Shenry fprintf(sink, "\n"); 10135827Srrh #undef sink 1014676Shenry } 1015