15827Srrh /* 219824Sdist * Copyright (c) 1982 Regents of the University of California. 319824Sdist * All rights reserved. The Berkeley software License Agreement 419824Sdist * specifies the terms and conditions for redistribution. 55827Srrh */ 619824Sdist 75827Srrh #ifndef lint 8*23578Smckusick static char sccsid[] = "@(#)asparse.c 5.2 (Berkeley) 06/19/85"; 95827Srrh #endif not lint 105827Srrh 11597Sbill #include <stdio.h> 12597Sbill #include "as.h" 13597Sbill #include "asscan.h" 14597Sbill #include "assyms.h" 155827Srrh #include "asexpr.h" 16597Sbill 17597Sbill int lgensym[10]; 18597Sbill char genref[10]; 19597Sbill 20597Sbill long bitfield; 21597Sbill int bitoff; 22597Sbill int curlen; /* current length of literals */ 23597Sbill 24597Sbill /* 25597Sbill * The following three variables are communication between various 26597Sbill * modules to special case a number of things. They are properly 27597Sbill * categorized as hacks. 28597Sbill */ 29597Sbill extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/ 30597Sbill int exprisname; /*last factor in an expression was a name*/ 31597Sbill int droppedLP; /*one is analyzing an expression beginning with*/ 32597Sbill /*a left parenthesis, which has already been*/ 33597Sbill /*shifted. (Used to parse (<expr>)(rn)*/ 34597Sbill 3513459Srrh char yytext[NCPName+2]; /*the lexical image*/ 36597Sbill int yylval; /*the lexical value; sloppy typing*/ 375827Srrh struct Opcode yyopcode; /* lexical value for an opcode */ 385827Srrh Bignum yybignum; /* lexical value for a big number */ 39597Sbill /* 40597Sbill * Expression and argument managers 41597Sbill */ 42597Sbill struct exp *xp; /*next free expression slot, used by expr.c*/ 43597Sbill struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/ 44597Sbill struct arg arglist[NARG]; /*building up operands in instructions*/ 45597Sbill /* 46597Sbill * Sets to accelerate token discrimination 47597Sbill */ 48597Sbill char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1]; 49597Sbill 5013513Srrh static char UDotsname[64]; /*name of the assembly source*/ 51597Sbill 525827Srrh yyparse() 53597Sbill { 545827Srrh reg struct exp *locxp; 555827Srrh /* 565827Srrh * loc1xp and ptrloc1xp are used in the 575827Srrh * expression lookahead 585827Srrh */ 595827Srrh struct exp *loc1xp; /*must be non register*/ 605827Srrh struct exp **ptrloc1xp = & loc1xp; 615827Srrh struct exp *pval; /*hacking expr:expr*/ 62597Sbill 635827Srrh reg struct symtab *np; 645827Srrh reg int argcnt; 65597Sbill 665827Srrh reg inttoktype val; /*what yylex gives*/ 675827Srrh reg inttoktype auxval; /*saves val*/ 68597Sbill 695827Srrh reg struct arg *ap; /*first free argument*/ 70597Sbill 715827Srrh reg struct symtab *p; 725827Srrh reg struct symtab *stpt; 73597Sbill 7413513Srrh struct strdesc *stringp; /*handles string lists*/ 75597Sbill 765827Srrh int regno; /*handles arguments*/ 775827Srrh int *ptrregno = ®no; 785827Srrh int sawmul; /*saw * */ 795827Srrh int sawindex; /*saw [rn]*/ 805827Srrh int sawsize; 815827Srrh int seg_type; /*the kind of segment: data or text*/ 825827Srrh int seg_number; /*the segment number*/ 835827Srrh int space_value; /*how much .space needs*/ 845827Srrh int fill_rep; /*how many reps for .fill */ 855827Srrh int fill_size; /*how many bytes for .fill */ 86597Sbill 875827Srrh int field_width; /*how wide a field is to be*/ 885827Srrh int field_value; /*the value to stuff in a field*/ 895827Srrh char *stabname; /*name of stab dealing with*/ 905827Srrh ptrall stabstart; /*where the stab starts in the buffer*/ 915827Srrh int reloc_how; /* how to relocate expressions */ 925827Srrh int toconv; /* how to convert bignums */ 9313274Srrh int incasetable; /* set if in a case table */ 94597Sbill 9513274Srrh incasetable = 0; 96597Sbill xp = explist; 97597Sbill ap = arglist; 98597Sbill 99597Sbill val = yylex(); 100597Sbill 101597Sbill while (val != PARSEEOF){ /* primary loop */ 102597Sbill 103597Sbill while (INTOKSET(val, LINSTBEGIN)){ 104597Sbill if (val == INT) { 105632Shenry int i = ((struct exp *)yylval)->e_xvalue; 106597Sbill shift; 1075827Srrh if (val != COLON){ 1085827Srrh yyerror("Local label %d is not followed by a ':' for a label definition", 1095827Srrh i); 1105827Srrh goto errorfix; 1115827Srrh } 112597Sbill if (i < 0 || i > 9) { 113597Sbill yyerror("Local labels are 0-9"); 114597Sbill goto errorfix; 115597Sbill } 1165827Srrh (void)sprintf(yytext, "L%d\001%d", i, lgensym[i]); 117597Sbill lgensym[i]++; 118597Sbill genref[i] = 0; 119597Sbill yylval = (int)*lookup(passno == 1); 120597Sbill val = NAME; 121597Sbill np = (struct symtab *)yylval; 122597Sbill goto restlab; 123597Sbill } 124597Sbill if (val == NL){ 125597Sbill lineno++; 126597Sbill shift; 127597Sbill } else 128597Sbill if (val == SEMI) 129597Sbill shift; 130597Sbill else { /*its a name, so we have a label or def */ 131597Sbill if (val != NAME){ 132597Sbill ERROR("Name expected for a label"); 133597Sbill } 134597Sbill np = (struct symtab *)yylval; 135597Sbill shiftover(NAME); 136597Sbill if (val != COLON) { 137597Sbill yyerror("\"%s\" is not followed by a ':' for a label definition", 13813513Srrh FETCHNAME(np)); 139597Sbill goto errorfix; 140597Sbill } 141597Sbill restlab: 142597Sbill shift; 143*23578Smckusick flushfield(NBWD/4); 144632Shenry if ((np->s_type&XTYPE)!=XUNDEF) { 14515235Sralph if ( (np->s_type&XTYPE) != dotp->e_xtype 14615235Sralph || np->s_value != dotp->e_xvalue 14715235Sralph || ( passno == 1 14815235Sralph && np->s_index != dotp->e_xloc) ) { 14915235Sralph if (passno == 1) 15015235Sralph yyerror("%s redefined", 15113513Srrh FETCHNAME(np)); 15215235Sralph else 15315235Sralph yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", 15413513Srrh FETCHNAME(np), 155632Shenry np->s_value, 156632Shenry dotp->e_xvalue); 157597Sbill } 158597Sbill } 159632Shenry np->s_type &= ~(XTYPE|XFORW); 160632Shenry np->s_type |= dotp->e_xtype; 161632Shenry np->s_value = dotp->e_xvalue; 162597Sbill if (passno == 1){ 163632Shenry np->s_index = dotp-usedot; 16413513Srrh if (FETCHNAME(np)[0] == 'L'){ 165597Sbill nlabels++; 166597Sbill } 167632Shenry np->s_tag = LABELID; 168597Sbill } 169597Sbill } /*end of this being a label*/ 17015235Sralph } /*end of consuming all labels, NLs and SEMIS */ 171597Sbill 172597Sbill xp = explist; 173597Sbill ap = arglist; 174597Sbill 175597Sbill /* 176597Sbill * process the INSTRUCTION body 177597Sbill */ 178597Sbill switch(val){ 179597Sbill 180597Sbill default: 181597Sbill ERROR("Unrecognized instruction or directive"); 182597Sbill 183597Sbill case IABORT: 184597Sbill shift; 185597Sbill sawabort(); 186597Sbill /*NOTREACHED*/ 187597Sbill break; 188597Sbill 189597Sbill case PARSEEOF: 1905827Srrh tokptr -= sizeof(bytetoktype); 191597Sbill *tokptr++ = VOID; 192597Sbill tokptr[1] = VOID; 193597Sbill tokptr[2] = PARSEEOF; 194597Sbill break; 195597Sbill 196597Sbill case IFILE: 197597Sbill shift; 19813513Srrh stringp = (struct strdesc *)yylval; 199597Sbill shiftover(STRING); 200597Sbill dotsname = &UDotsname[0]; 20113513Srrh movestr(dotsname, stringp->sd_string, 20213513Srrh min(stringp->sd_strlen, sizeof(UDotsname))); 203597Sbill break; 204597Sbill 205597Sbill case ILINENO: 206597Sbill shift; /*over the ILINENO*/ 207597Sbill expr(locxp, val); 208632Shenry lineno = locxp->e_xvalue; 209597Sbill break; 210597Sbill 211597Sbill case ISET: /* .set <name> , <expr> */ 212597Sbill shift; 213597Sbill np = (struct symtab *)yylval; 214597Sbill shiftover(NAME); 215597Sbill shiftover(CM); 216597Sbill expr(locxp, val); 217632Shenry np->s_type &= (XXTRN|XFORW); 218632Shenry np->s_type |= locxp->e_xtype&(XTYPE|XFORW); 219632Shenry np->s_value = locxp->e_xvalue; 220597Sbill if (passno==1) 221632Shenry np->s_index = locxp->e_xloc; 222632Shenry if ((locxp->e_xtype&XTYPE) == XUNDEF) 223597Sbill yyerror("Illegal set?"); 224597Sbill break; 225597Sbill 226597Sbill case ILSYM: /*.lsym name , expr */ 227597Sbill shift; 228597Sbill np = (struct symtab *)yylval; 229597Sbill shiftover(NAME); 230597Sbill shiftover(CM); 231597Sbill expr(locxp, val); 232597Sbill /* 233597Sbill * Build the unique occurance of the 234597Sbill * symbol. 235597Sbill * The character scanner will have 236597Sbill * already entered it into the symbol 237597Sbill * table, but we should remove it 238597Sbill */ 239597Sbill if (passno == 1){ 240597Sbill stpt = (struct symtab *)symalloc(); 241632Shenry stpt->s_name = np->s_name; 242632Shenry np->s_tag = OBSOLETE; /*invalidate original */ 243597Sbill nforgotten++; 244597Sbill np = stpt; 2455827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) 2465827Srrh yyerror("Illegal second argument to lsym"); 2475827Srrh np->s_value = locxp->e_xvalue; 2485827Srrh np->s_type = XABS; 249632Shenry np->s_tag = ILSYM; 250597Sbill } 251597Sbill break; 252597Sbill 253597Sbill case IGLOBAL: /*.globl <name> */ 254597Sbill shift; 255597Sbill np = (struct symtab *)yylval; 256597Sbill shiftover(NAME); 257632Shenry np->s_type |= XXTRN; 258597Sbill break; 259597Sbill 260597Sbill case IDATA: /*.data [ <expr> ] */ 261597Sbill case ITEXT: /*.text [ <expr> ] */ 262597Sbill seg_type = -val; 263597Sbill shift; 264597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 265597Sbill expr(locxp, val); 266597Sbill seg_type = -seg_type; /*now, it is positive*/ 267597Sbill } 268597Sbill 269597Sbill if (seg_type < 0) { /*there wasn't an associated expr*/ 270597Sbill seg_number = 0; 271597Sbill seg_type = -seg_type; 272597Sbill } else { 2735827Srrh if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 2745827Srrh || (seg_number = locxp->e_xvalue) >= NLOC) { 275597Sbill yyerror("illegal location counter"); 276597Sbill seg_number = 0; 277597Sbill } 278597Sbill } 279597Sbill if (seg_type == IDATA) 280597Sbill seg_number += NLOC; 281*23578Smckusick flushfield(NBWD/4); 282597Sbill dotp = &usedot[seg_number]; 283597Sbill if (passno==2) { /* go salt away in pass 2*/ 284597Sbill txtfil = usefile[seg_number]; 285597Sbill relfil = rusefile[seg_number]; 286597Sbill } 287597Sbill break; 288597Sbill 289597Sbill /* 290597Sbill * Storage filler directives: 291597Sbill * 292597Sbill * .byte [<exprlist>] 293597Sbill * 294597Sbill * exprlist: empty | exprlist outexpr 295597Sbill * outexpr: <expr> | <expr> : <expr> 296597Sbill */ 297*23578Smckusick case IBYTE: curlen = NBWD/4; goto elist; 298*23578Smckusick case IWORD: curlen = NBWD/2; goto elist; 299*23578Smckusick case IINT: curlen = NBWD; goto elist; 300*23578Smckusick case ILONG: curlen = NBWD; goto elist; 301597Sbill 302597Sbill elist: 303597Sbill seg_type = val; 304597Sbill shift; 305597Sbill 306597Sbill /* 307597Sbill * Expression List processing 308597Sbill */ 309597Sbill if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ 310597Sbill do{ 311597Sbill /* 312597Sbill * expression list consists of a list of : 313597Sbill * <expr> 314597Sbill * <expr> : <expr> 315597Sbill * (pack expr2 into expr1 bits 316597Sbill */ 317597Sbill expr(locxp, val); 318597Sbill /* 319597Sbill * now, pointing at the next token 320597Sbill */ 321597Sbill if (val == COLON){ 322597Sbill shiftover(COLON); 323597Sbill expr(pval, val); 3245827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 3255827Srrh yyerror("Width not absolute"); 326632Shenry field_width = locxp->e_xvalue; 327597Sbill locxp = pval; 3285827Srrh if (bitoff + field_width > curlen) 329597Sbill flushfield(curlen); 330597Sbill if (field_width > curlen) 331597Sbill yyerror("Expression crosses field boundary"); 332597Sbill } else { 333597Sbill field_width = curlen; 334597Sbill flushfield(curlen); 335597Sbill } 336597Sbill 3375827Srrh if ((locxp->e_xtype & XTYPE) != XABS) { 338597Sbill if (bitoff) 339597Sbill yyerror("Illegal relocation in field"); 340674Shenry switch(curlen){ 341*23578Smckusick case NBWD/4: reloc_how = TYPB; break; 342*23578Smckusick case NBWD/2: reloc_how = TYPW; break; 343*23578Smckusick case NBWD: reloc_how = TYPL; break; 344674Shenry } 345597Sbill if (passno == 1){ 346674Shenry dotp->e_xvalue += ty_nbyte[reloc_how]; 347597Sbill } else { 348674Shenry outrel(locxp, reloc_how); 349597Sbill } 350597Sbill } else { 35113274Srrh /* 35213274Srrh * 35313274Srrh * See if we are doing a case instruction. 35413274Srrh * If so, then see if the branch distance, 35513274Srrh * stored as a word, 35613274Srrh * is going to loose sig bits. 35713274Srrh */ 35813274Srrh if (passno == 2 && incasetable){ 35913274Srrh if ( (locxp->e_xvalue < -32768) 36013274Srrh ||(locxp->e_xvalue > 32767)){ 36113274Srrh yyerror("Case will branch too far"); 36213274Srrh } 36313274Srrh } 364632Shenry field_value = locxp->e_xvalue & ( (1L << field_width)-1); 365597Sbill bitfield |= field_value << bitoff; 366597Sbill bitoff += field_width; 367597Sbill } 368597Sbill xp = explist; 3695827Srrh if (auxval = (val == CM)) 3705827Srrh shift; 371597Sbill } while (auxval); 3725827Srrh } /* there existed an expression at all */ 373597Sbill 374597Sbill flushfield(curlen); 375*23578Smckusick if ( ( curlen == NBWD/4) && bitoff) 376632Shenry dotp->e_xvalue ++; 377597Sbill break; 378597Sbill /*end of case IBYTE, IWORD, ILONG, IINT*/ 379597Sbill 380597Sbill case ISPACE: /* .space <expr> */ 381597Sbill shift; 382597Sbill expr(locxp, val); 3835827Srrh if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 384597Sbill yyerror("Space size not absolute"); 385632Shenry space_value = locxp->e_xvalue; 386597Sbill ospace: 387*23578Smckusick flushfield(NBWD/4); 38813446Srrh { 38913446Srrh static char spacebuf[128]; 39013446Srrh while (space_value > sizeof(spacebuf)){ 39113446Srrh outs(spacebuf, sizeof(spacebuf)); 39213446Srrh space_value -= sizeof(spacebuf); 39313446Srrh } 39413446Srrh outs(spacebuf, space_value); 395597Sbill } 396597Sbill break; 397597Sbill 398647Shenry /* 399647Shenry * .fill rep, size, value 400647Shenry * repeat rep times: fill size bytes with (truncated) value 401647Shenry * size must be between 1 and 8 402647Shenry */ 403647Shenry case IFILL: 404597Sbill shift; 405597Sbill expr(locxp, val); 4065827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 407597Sbill yyerror("Fill repetition count not absolute"); 408647Shenry fill_rep = locxp->e_xvalue; 409597Sbill shiftover(CM); 410597Sbill expr(locxp, val); 4115827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 412647Shenry yyerror("Fill size not absolute"); 413647Shenry fill_size = locxp->e_xvalue; 414647Shenry if (fill_size <= 0 || fill_size > 8) 415647Shenry yyerror("Fill count not in in 1..8"); 416647Shenry shiftover(CM); 417647Shenry expr(locxp, val); 4185827Srrh if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 4195827Srrh yyerror("Fill value not absolute"); 420*23578Smckusick flushfield(NBWD/4); 42116570Srrh dotp->e_xvalue += fill_rep * fill_size; 42216570Srrh if (passno == 2) { 423647Shenry while(fill_rep-- > 0) 4245827Srrh bwrite((char *)&locxp->e_xvalue, fill_size, txtfil); 425647Shenry } 426597Sbill break; 427597Sbill 42813446Srrh case IASCII: /* .ascii [ <stringlist> ] */ 429597Sbill case IASCIZ: /* .asciz [ <stringlist> ] */ 430597Sbill auxval = val; 431597Sbill shift; 432597Sbill /* 433597Sbill * Code to consume a string list 434597Sbill * 435597Sbill * stringlist: empty | STRING | stringlist STRING 436597Sbill */ 43713446Srrh while (val == STRING){ 43813513Srrh int mystrlen; 439*23578Smckusick flushfield(NBWD/4); 440597Sbill if (bitoff) 44113446Srrh dotp->e_xvalue++; 44213513Srrh stringp = (struct strdesc *)yylval; 44313446Srrh /* 44413513Srrh * utilize the string scanner cheat; 44513513Srrh * the scanner appended a null byte on the string, 44613513Srrh * but didn't charge it to sd_strlen 44713446Srrh */ 44813513Srrh mystrlen = stringp->sd_strlen; 44913513Srrh mystrlen += (auxval == IASCIZ) ? 1 : 0; 45013513Srrh if (passno == 2){ 45113513Srrh if (stringp->sd_place & STR_CORE){ 45213513Srrh outs(stringp->sd_string, mystrlen); 45313513Srrh } else { 45413513Srrh int i, nread; 45513513Srrh fseek(strfile, stringp->sd_stroff, 0); 45613513Srrh for (i = 0; i < mystrlen;/*VOID*/){ 45713513Srrh nread = fread(yytext, 1, 45813513Srrh min(mystrlen - i, 45913513Srrh sizeof(yytext)), strfile); 46013513Srrh outs(yytext, nread); 46113513Srrh i += nread; 46213513Srrh } 46313513Srrh } 46413513Srrh } else { 46513513Srrh dotp->e_xvalue += mystrlen; 46613513Srrh } 467597Sbill shift; /*over the STRING*/ 468597Sbill if (val == CM) /*could be a split string*/ 469597Sbill shift; 470597Sbill } 471597Sbill break; 472597Sbill 473597Sbill case IORG: /* .org <expr> */ 474597Sbill shift; 475597Sbill expr(locxp, val); 476597Sbill 4775827Srrh if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */ 478597Sbill orgwarn++; 479632Shenry else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) 480597Sbill yyerror("Illegal expression to set origin"); 481632Shenry space_value = locxp->e_xvalue - dotp->e_xvalue; 482597Sbill if (space_value < 0) 483597Sbill yyerror("Backwards 'org'"); 484597Sbill goto ospace; 485597Sbill break; 486597Sbill 487597Sbill /* 488597Sbill * 489597Sbill * Process stabs. Stabs are created only by the f77 490597Sbill * and the C compiler with the -g flag set. 491597Sbill * We only look at the stab ONCE, during pass 1, and 492597Sbill * virtually remove the stab from the intermediate file 493597Sbill * so it isn't seen during pass2. This makes for some 494597Sbill * hairy processing to handle labels occuring in 495597Sbill * stab entries, but since most expressions in the 496597Sbill * stab are integral we save lots of time in the second 497597Sbill * pass by not looking at the stabs. 498597Sbill * A stab that is tagged floating will be bumped during 499597Sbill * the jxxx resolution phase. A stab tagged fixed will 500597Sbill * not be be bumped. 501597Sbill * 502597Sbill * .stab: Old fashioned stabs 503597Sbill * .stabn: For stabs without names 504597Sbill * .stabs: For stabs with string names 505597Sbill * .stabd: For stabs for line numbers or bracketing, 506597Sbill * without a string name, without 507597Sbill * a final expression. The value of the 508597Sbill * final expression is taken to be the current 509597Sbill * location counter, and is patched by the 2nd pass 510597Sbill * 51113459Srrh * .stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr> 512597Sbill * .stabn <expr>, <expr>, <expr>, <expr> 513597Sbill * .stabs STRING, <expr>, <expr>, <expr>, <expr> 514597Sbill * .stabd <expr>, <expr>, <expr> # . 515597Sbill */ 516597Sbill case ISTAB: 51713521Srrh yyerror(".stab directive no longer supported"); 518597Sbill goto errorfix; 519597Sbill 520597Sbill tailstab: 521597Sbill expr(locxp, val); 522632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 5235827Srrh yyerror("Invalid type in %s", stabname); 524597Sbill goto errorfix; 525597Sbill } 526632Shenry stpt->s_ptype = locxp->e_xvalue; 527597Sbill shiftover(CM); 528597Sbill expr(locxp, val); 529632Shenry stpt->s_other = locxp->e_xvalue; 530597Sbill shiftover(CM); 531597Sbill expr(locxp, val); 532632Shenry stpt->s_desc = locxp->e_xvalue; 533597Sbill shiftover(CM); 534597Sbill exprisname = 0; 535597Sbill expr(locxp, val); 536632Shenry p = locxp->e_xname; 537597Sbill if (p == NULL) { /*absolute expr to begin with*/ 538632Shenry stpt->s_value = locxp->e_xvalue; 539632Shenry stpt->s_index = dotp - usedot; 540597Sbill if (exprisname){ 54118554Sralph stpt->s_type = locxp->e_xtype; 542632Shenry switch(stpt->s_ptype){ 543597Sbill case N_GSYM: 544597Sbill case N_FNAME: 545597Sbill case N_RSYM: 546597Sbill case N_SSYM: 547597Sbill case N_LSYM: 548597Sbill case N_PSYM: 549597Sbill case N_BCOMM: 550597Sbill case N_ECOMM: 551597Sbill case N_LENG: 552632Shenry stpt->s_tag = STABFIXED; 553597Sbill break; 554597Sbill default: 555632Shenry stpt->s_tag = STABFLOATING; 556597Sbill break; 557597Sbill } 558597Sbill } else 559632Shenry stpt->s_tag = STABFIXED; 560597Sbill } 561597Sbill else { /*really have a name*/ 562632Shenry stpt->s_dest = locxp->e_xname; 563632Shenry stpt->s_index = p->s_index; 564632Shenry stpt->s_type = p->s_type | STABFLAG; 565597Sbill /* 566597Sbill * We will assign a more accruate 567597Sbill * guess of locxp's location when 568597Sbill * we sort the symbol table 569597Sbill * The final value of value is 570597Sbill * given by stabfix() 571597Sbill */ 57212591Scsvaf /* 57312591Scsvaf * For exprs of the form (name + value) one needs to remember locxp->e_xvalue 57412591Scsvaf * for use in stabfix. The right place to keep this is in stpt->s_value 57512591Scsvaf * however this gets corrupted at an unknown point. 57612591Scsvaf * As a bandaid hack the value is preserved in s_desc and s_other (a 57712591Scsvaf * short and a char). This destroys these two values and will 57812591Scsvaf * be fixed. May 19 ,1983 Alastair Fyfe 57912591Scsvaf */ 58012591Scsvaf if(locxp->e_xvalue) { 58112591Scsvaf stpt->s_other = (locxp->e_xvalue >> 16); 58212591Scsvaf stpt->s_desc = (locxp->e_xvalue & 0x0000ffff); 58312591Scsvaf stpt->s_tag = STABFLOATING; 58412591Scsvaf } 585597Sbill } 586597Sbill /* 587597Sbill * tokptr now points at one token beyond 588597Sbill * the current token stored in val and yylval, 589597Sbill * which are the next tokens after the end of 590597Sbill * this .stab directive. This next token must 591597Sbill * be either a SEMI or NL, so is of width just 592597Sbill * one. Therefore, to point to the next token 593597Sbill * after the end of this stab, just back up one.. 594597Sbill */ 5955827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 596597Sbill break; /*end of the .stab*/ 597597Sbill 598597Sbill case ISTABDOT: 599597Sbill stabname = ".stabd"; 600597Sbill stpt = (struct symtab *)yylval; 601597Sbill /* 602597Sbill * We clobber everything after the 603597Sbill * .stabd and its pointer... we MUST 604597Sbill * be able to get back to this .stabd 605597Sbill * so that we can resolve its final value 606597Sbill */ 607597Sbill stabstart = tokptr; 608597Sbill shift; /*over the ISTABDOT*/ 609597Sbill if (passno == 1){ 610597Sbill expr(locxp, val); 611632Shenry if (! (locxp->e_xvalue & STABTYPS)){ 612597Sbill yyerror("Invalid type in .stabd"); 613597Sbill goto errorfix; 614597Sbill } 615632Shenry stpt->s_ptype = locxp->e_xvalue; 616597Sbill shiftover(CM); 617597Sbill expr(locxp, val); 618632Shenry stpt->s_other = locxp->e_xvalue; 619597Sbill shiftover(CM); 620597Sbill expr(locxp, val); 621632Shenry stpt->s_desc = locxp->e_xvalue; 622597Sbill /* 623597Sbill * 624597Sbill * Now, clobber everything but the 625597Sbill * .stabd pseudo and the pointer 626597Sbill * to its symbol table entry 627597Sbill * tokptr points to the next token, 628597Sbill * build the skip up to this 629597Sbill */ 6305827Srrh buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); 631597Sbill } 632597Sbill /* 633597Sbill * pass 1: Assign a good guess for its position 634597Sbill * (ensures they are sorted into right place)/ 635597Sbill * pass 2: Fix the actual value 636597Sbill */ 637632Shenry stpt->s_value = dotp->e_xvalue; 638632Shenry stpt->s_index = dotp - usedot; 639632Shenry stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ 640597Sbill break; 641597Sbill 642597Sbill case ISTABNONE: stabname = ".stabn"; goto shortstab; 643597Sbill 644597Sbill case ISTABSTR: stabname = ".stabs"; 645597Sbill shortstab: 646597Sbill auxval = val; 647597Sbill if (passno == 2) goto errorfix; 648597Sbill stpt = (struct symtab *)yylval; 649597Sbill stabstart = tokptr; 6505827Srrh (bytetoktype *)stabstart -= sizeof(struct symtab *); 6515827Srrh (bytetoktype *)stabstart -= sizeof(bytetoktype); 652597Sbill shift; 653597Sbill if (auxval == ISTABSTR){ 65413513Srrh stringp = (struct strdesc *)yylval; 655597Sbill shiftover(STRING); 65613513Srrh stpt->s_name = (char *)stringp; 65713446Srrh /* 65813446Srrh * We want the trailing null included in this string. 65913446Srrh * We utilize the cheat the string scanner used, 66013446Srrh * and merely increment the string length 66113446Srrh */ 66213513Srrh stringp->sd_strlen += 1; 663597Sbill shiftover(CM); 664597Sbill } else { 66513571Srrh stpt->s_name = (char *)savestr("\0", 0, STR_BOTH); 666597Sbill } 667597Sbill goto tailstab; 668597Sbill break; 669597Sbill 6705827Srrh case ICOMM: /* .comm <name> , <expr> */ 671597Sbill case ILCOMM: /* .lcomm <name> , <expr> */ 672597Sbill auxval = val; 673597Sbill shift; 674597Sbill np = (struct symtab *)yylval; 675597Sbill shiftover(NAME); 676597Sbill shiftover(CM); 677597Sbill expr(locxp, val); 678597Sbill 6795827Srrh if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ 680597Sbill yyerror("comm size not absolute"); 6815827Srrh if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) 68213521Srrh yyerror("Redefinition of %s", FETCHNAME(np)); 683597Sbill if (passno==1) { 684632Shenry np->s_value = locxp->e_xvalue; 685597Sbill if (auxval == ICOMM) 686632Shenry np->s_type |= XXTRN; 687597Sbill else { 688632Shenry np->s_type &= ~XTYPE; 689632Shenry np->s_type |= XBSS; 690597Sbill } 691597Sbill } 692597Sbill break; 693597Sbill 694597Sbill case IALIGN: /* .align <expr> */ 695597Sbill stpt = (struct symtab *)yylval; 696597Sbill shift; 697597Sbill expr(locxp, val); 698597Sbill jalign(locxp, stpt); 699597Sbill break; 700597Sbill 701597Sbill case INST0: /* instructions w/o arguments*/ 70213274Srrh incasetable = 0; 7035827Srrh insout(yyopcode, (struct arg *)0, 0); 704597Sbill shift; 705597Sbill break; 706597Sbill 707597Sbill case INSTn: /* instructions with arguments*/ 708597Sbill case IJXXX: /* UNIX style jump instructions */ 709597Sbill auxval = val; 710597Sbill /* 711597Sbill * Code to process an argument list 712597Sbill */ 713597Sbill ap = arglist; 714597Sbill xp = explist; 715597Sbill 716597Sbill shift; /* bring in the first token for the arg list*/ 717597Sbill 718597Sbill for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ 719597Sbill /* 720597Sbill * code to process an argument proper 721597Sbill */ 722597Sbill sawindex = sawmul = sawsize = 0; 723597Sbill { 724597Sbill switch(val) { 725597Sbill 726597Sbill default: 727597Sbill disp: 728597Sbill if( !(INTOKSET(val, 729597Sbill EBEGOPS 730597Sbill +YUKKYEXPRBEG 731597Sbill +SAFEEXPRBEG)) ) { 732597Sbill ERROR("expression expected"); 733597Sbill } 734632Shenry expr(ap->a_xp,val); 735597Sbill overdisp: 736597Sbill if ( val == LP || sawsize){ 737597Sbill shiftover(LP); 738597Sbill findreg(regno); 739597Sbill shiftover(RP); 740632Shenry ap->a_atype = ADISP; 741632Shenry ap->a_areg1 = regno; 742597Sbill } else { 743632Shenry ap->a_atype = AEXP; 744632Shenry ap->a_areg1 = 0; 745597Sbill } 746597Sbill goto index; 747597Sbill 748597Sbill case SIZESPEC: 749597Sbill sizespec: 750597Sbill sawsize = yylval; 751597Sbill shift; 752597Sbill goto disp; 753597Sbill 754597Sbill case REG: 755597Sbill case REGOP: 756597Sbill findreg(regno); 757632Shenry ap->a_atype = AREG; 758632Shenry ap->a_areg1 = regno; 759597Sbill break; 760597Sbill 761597Sbill case MUL: 762597Sbill sawmul = 1; 763597Sbill shift; 764597Sbill if (val == LP) goto base; 765597Sbill if (val == LITOP) goto imm; 766597Sbill if (val == SIZESPEC) goto sizespec; 767597Sbill if (INTOKSET(val, 768597Sbill EBEGOPS 769597Sbill +YUKKYEXPRBEG 770597Sbill +SAFEEXPRBEG)) goto disp; 771597Sbill ERROR("expression, '(' or '$' expected"); 772597Sbill break; 773597Sbill 774597Sbill case LP: 775597Sbill base: 776597Sbill shift; /*consume the LP*/ 777597Sbill /* 778597Sbill * hack the ambiguity of 779597Sbill * movl (expr) (rn), ... 780597Sbill * note that (expr) could also 781597Sbill * be (rn) (by special hole in the 782597Sbill * grammar), which we ensure 783597Sbill * means register indirection, instead 784597Sbill * of an expression with value n 785597Sbill */ 786597Sbill if (val != REG && val != REGOP){ 787597Sbill droppedLP = 1; 788632Shenry val = exprparse(val, &(ap->a_xp)); 789597Sbill droppedLP = 0; 790597Sbill goto overdisp; 791597Sbill } 792597Sbill findreg(regno); 793597Sbill shiftover(RP); 794597Sbill if (val == PLUS){ 795597Sbill shift; 796632Shenry ap->a_atype = AINCR; 797597Sbill } else 798632Shenry ap->a_atype = ABASE; 799632Shenry ap->a_areg1 = regno; 800597Sbill goto index; 801597Sbill 802597Sbill case LITOP: 803597Sbill imm: 804597Sbill shift; 805597Sbill expr(locxp, val); 806632Shenry ap->a_atype = AIMM; 807632Shenry ap->a_areg1 = 0; 808632Shenry ap->a_xp = locxp; 809597Sbill goto index; 810597Sbill 811597Sbill case MP: 812597Sbill shift; /* -(reg) */ 813597Sbill findreg(regno); 814597Sbill shiftover(RP); 815632Shenry ap->a_atype = ADECR; 816632Shenry ap->a_areg1 = regno; 817597Sbill index: /*look for [reg] */ 818597Sbill if (val == LB){ 819597Sbill shift; 820597Sbill findreg(regno); 821597Sbill shiftover(RB); 822597Sbill sawindex = 1; 823632Shenry ap->a_areg2 = regno; 824597Sbill } 825597Sbill break; 826597Sbill 827597Sbill } /*end of the switch to process an arg*/ 828597Sbill } /*end of processing an argument*/ 829597Sbill 830597Sbill if (sawmul){ 831597Sbill /* 832597Sbill * Make a concession for *(%r) 833597Sbill * meaning *0(%r) 834597Sbill */ 835632Shenry if (ap->a_atype == ABASE) { 836632Shenry ap->a_atype = ADISP; 837632Shenry xp->e_xtype = XABS; 8385827Srrh xp->e_number = Znumber; 8395827Srrh xp->e_number.num_tag = TYPL; 840632Shenry xp->e_xloc = 0; 841632Shenry ap->a_xp = xp++; 842597Sbill } 843632Shenry ap->a_atype |= ASTAR; 844597Sbill sawmul = 0; 845597Sbill } 846597Sbill if (sawindex){ 847632Shenry ap->a_atype |= AINDX; 848597Sbill sawindex = 0; 849597Sbill } 850632Shenry ap->a_dispsize = sawsize == 0 ? d124 : sawsize; 851597Sbill if (val != CM) break; 852597Sbill shiftover(CM); 853597Sbill } /*processing all the arguments*/ 854597Sbill 855597Sbill if (argcnt > 6){ 856597Sbill yyerror("More than 6 arguments"); 857597Sbill goto errorfix; 858597Sbill } 859597Sbill 86013274Srrh /* 86113274Srrh * See if this is a case instruction, 86213274Srrh * so we can set up tests on the following 86313274Srrh * vector of branch displacements 86413274Srrh */ 86513274Srrh if (yyopcode.Op_eopcode == CORE){ 86613274Srrh switch(yyopcode.Op_popcode){ 86713274Srrh case 0x8f: /* caseb */ 86813274Srrh case 0xaf: /* casew */ 86913274Srrh case 0xcf: /* casel */ 87013274Srrh incasetable++; 87113274Srrh break; 87213274Srrh default: 87313274Srrh incasetable = 0; 87413274Srrh break; 87513274Srrh } 87613274Srrh } 87713274Srrh 8785827Srrh insout(yyopcode, arglist, 879597Sbill auxval == INSTn ? argcnt : - argcnt); 880597Sbill break; 881597Sbill 8825827Srrh case IQUAD: toconv = TYPQ; goto bignumlist; 8835827Srrh case IOCTA: toconv = TYPO; goto bignumlist; 8845827Srrh 8855827Srrh case IFFLOAT: toconv = TYPF; goto bignumlist; 8865827Srrh case IDFLOAT: toconv = TYPD; goto bignumlist; 8875827Srrh case IGFLOAT: toconv = TYPG; goto bignumlist; 8885827Srrh case IHFLOAT: toconv = TYPH; goto bignumlist; 8895827Srrh bignumlist: 890597Sbill /* 8915827Srrh * eat a list of non 32 bit numbers. 8925827Srrh * IQUAD and IOCTA can, possibly, return 8935827Srrh * INT's, if the numbers are "small". 8945827Srrh * 8955827Srrh * The value of the numbers is coming back 8965827Srrh * as an expression, NOT in yybignum. 897597Sbill */ 8985827Srrh shift; /* over the opener */ 8995827Srrh if ((val == BIGNUM) || (val == INT)){ 900597Sbill do{ 9015827Srrh if ((val != BIGNUM) && (val != INT)){ 9025827Srrh ERROR(ty_float[toconv] 9035827Srrh ? "floating number expected" 9045827Srrh : "integer number expected" ); 905597Sbill } 9065827Srrh dotp->e_xvalue += ty_nbyte[toconv]; 9075827Srrh if (passno == 2){ 9085827Srrh bignumwrite( 9095827Srrh ((struct exp *)yylval)->e_number, 9105827Srrh toconv); 911597Sbill } 912597Sbill xp = explist; 9135827Srrh shift; /* over this number */ 9145827Srrh if (auxval = (val == CM)) 9155827Srrh shift; /* over the comma */ 9165827Srrh } while (auxval); /* as long as there are commas */ 917597Sbill } 918597Sbill break; 9195827Srrh /* end of the case for initialized big numbers */ 920597Sbill } /*end of the switch for looking at each reserved word*/ 921597Sbill 9225827Srrh continue; 923597Sbill 924597Sbill errorfix: 925597Sbill /* 926597Sbill * got here by either requesting to skip to the 927597Sbill * end of this statement, or by erroring out and 928597Sbill * wanting to apply panic mode recovery 929597Sbill */ 930597Sbill while ( (val != NL) 931597Sbill && (val != SEMI) 932597Sbill && (val != PARSEEOF) 933597Sbill ){ 934597Sbill shift; 935597Sbill } 936597Sbill if (val == NL) 937597Sbill lineno++; 938597Sbill shift; 939597Sbill 940597Sbill } /*end of the loop to read the entire file, line by line*/ 941597Sbill 942597Sbill } /*end of yyparse*/ 943597Sbill 944597Sbill /* 945597Sbill * Process a register declaration of the form 946597Sbill * % <expr> 947597Sbill * 948597Sbill * Note: 949597Sbill * The scanner has already processed funny registers of the form 950597Sbill * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional 951597Sbill * preceding zero digit). If there was any space between the % and 952597Sbill * the digit, the scanner wouldn't have recognized it, so we 953597Sbill * hack it out here. 954597Sbill */ 9555827Srrh inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ 9565827Srrh inttoktype val; /*what the read head is sitting on*/ 957597Sbill int *regnoback; /*call by return*/ 958597Sbill { 9595827Srrh reg struct exp *locxp; 9605827Srrh struct exp *loc1xp; 9615827Srrh struct exp **ptrloc1xp = & loc1xp; 962597Sbill 963597Sbill expr(locxp, val); /*and leave the current read head with value*/ 964597Sbill if ( (passno == 2) && 9655827Srrh ( (locxp->e_xtype & XTYPE) != XABS 9665827Srrh || (locxp->e_xvalue < 0) 9675827Srrh || (locxp->e_xvalue >= 16) 968597Sbill ) 969597Sbill ){ 970597Sbill yyerror("Illegal register"); 971597Sbill return(0); 972597Sbill } 973632Shenry *regnoback = locxp->e_xvalue; 974597Sbill return(val); 975597Sbill } 97612945Srrh /* 97712945Srrh * Shift over error 97812945Srrh */ 97912945Srrh shiftoerror(token) 98012945Srrh int token; 98112945Srrh { 98212945Srrh char *tok_to_name(); 98312945Srrh yyerror("%s expected", tok_to_name(token)); 98412945Srrh } 985597Sbill 986597Sbill /*VARARGS1*/ 987597Sbill yyerror(s, a1, a2,a3,a4,a5) 988597Sbill char *s; 989597Sbill { 990597Sbill 991649Shenry #define sink stdout 992597Sbill 9935827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 994597Sbill fprintf(sink, "Assembler:\n"); 995597Sbill anyerrs++; 9965827Srrh if (silent) 9975827Srrh return; 998597Sbill fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); 999597Sbill fprintf(sink, s, a1, a2,a3,a4,a5); 1000597Sbill fprintf(sink, "\n"); 10015827Srrh #undef sink 1002597Sbill } 1003676Shenry 1004676Shenry /*VARARGS1*/ 1005676Shenry yywarning(s, a1, a2,a3,a4,a5) 1006676Shenry char *s; 1007676Shenry { 1008676Shenry #define sink stdout 10095827Srrh if (anyerrs == 0 && anywarnings == 0 && ! silent) 1010676Shenry fprintf(sink, "Assembler:\n"); 10115827Srrh anywarnings++; 10125827Srrh if (silent) 10135827Srrh return; 1014676Shenry fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); 1015676Shenry fprintf(sink, s, a1, a2,a3,a4,a5); 1016676Shenry fprintf(sink, "\n"); 10175827Srrh #undef sink 1018676Shenry } 1019