From 8f907237643c7ea4c1ee99d9cfcdd3e5e6cfb34a Mon Sep 17 00:00:00 2001 From: CSRG Date: Tue, 31 May 1988 05:55:07 -0800 Subject: [PATCH] BSD 4_3_Tahoe development Work on file usr/src/bin/as/as.tahoe/asparse.c Synthesized-from: CSRG/cd2/4.3tahoe --- usr/src/bin/as/as.tahoe/asparse.c | 1215 +++++++++++++++++++++++++++++ 1 file changed, 1215 insertions(+) create mode 100644 usr/src/bin/as/as.tahoe/asparse.c diff --git a/usr/src/bin/as/as.tahoe/asparse.c b/usr/src/bin/as/as.tahoe/asparse.c new file mode 100644 index 0000000000..193b842403 --- /dev/null +++ b/usr/src/bin/as/as.tahoe/asparse.c @@ -0,0 +1,1215 @@ +/* + * Copyright (c) 1982 Regents of the University of California + */ +#ifndef lint +static char sccsid[] = "$W$ (Berkeley) 5/31/88"; +#endif not lint + +#include +#include "as.h" +#include "asscan.h" +#include "assyms.h" +#include "asexpr.h" + +int lgensym[10]; +char genref[10]; + +long bitfield; +int bitoff; +int curlen; /* current length of literals */ +int printblank; + +/* + * The following three variables are communication between various + * modules to special case a number of things. They are properly + * categorized as hacks. + */ +extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/ +int exprisname; /*last factor in an expression was a name*/ +int droppedLP; /*one is analyzing an expression beginning with*/ + /*a left parenthesis, which has already been*/ + /*shifted. (Used to parse ()(rn)*/ + +char yytext[NCPName+2]; /*the lexical image*/ +int yylval; /*the lexical value; sloppy typing*/ +u_char yyopcode; /* lexical value for an opcode */ +Bignum yybignum; /* lexical value for a big number */ +int num_type; /* type of bignums */ +/* + * Expression and argument managers + */ +struct exp *xp; /*next free expression slot, used by expr.c*/ +struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/ +struct arg arglist[NARG]; /*building up operands in instructions*/ +/* + * Sets to accelerate token discrimination + */ +char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1]; + +static char UDotsname[64]; /*name of the assembly source*/ + +yyparse() +{ + reg struct exp *locxp; + /* + * loc1xp and ptrloc1xp are used in the + * expression lookahead + */ + struct exp *loc1xp; /*must be non register*/ + struct exp **ptrloc1xp = & loc1xp; + struct exp *pval; /*hacking expr:expr*/ + + reg struct symtab *np; + reg int argcnt; + + reg inttoktype val; /*what yylex gives*/ + reg inttoktype auxval; /*saves val*/ + + reg struct arg *ap; /*first free argument*/ + + reg struct symtab *p; + reg struct symtab *stpt; + + struct strdesc *stringp; /*handles string lists*/ + + int regno; /*handles arguments*/ + int *ptrregno = ®no; + int sawmul; /*saw * */ + int sawindex; /*saw [rn]*/ + int sawsize; + int seg_type; /*the kind of segment: data or text*/ + int seg_number; /*the segment number*/ + int space_value; /*how much .space needs*/ + int fill_rep; /*how many reps for .fill */ + int rep_fill; /*the same - temprary */ + int fill_size; /*how many bytes for .fill */ + + int field_width; /*how wide a field is to be*/ + int field_value; /*the value to stuff in a field*/ + char *stabname; /*name of stab dealing with*/ + ptrall stabstart; /*where the stab starts in the buffer*/ + int reloc_how; /* how to relocate expressions */ + int incasetable; /* set if in a case table */ + int j, k; + char ch; + int length; /* for printout */ + union twolong + { + long lpart[2]; + char strpart [8]; + }fillval; + + + incasetable = 0; + xp = explist; + ap = arglist; + + val = yylex(); + + while (val != PARSEEOF){ /* primary loop */ + + while (INTOKSET(val, LINSTBEGIN)){ + if (val == INT) { + int i = ((struct exp *)yylval)->e_xvalue; + shift; + if (val != COLON){ + yyerror("Local label %d is not followed by a ':' for a label definition", + i); + goto errorfix; + } + if (i < 0 || i > 9) { + yyerror("Local labels are 0-9"); + goto errorfix; + } + (void)sprintf(yytext, "L%d\001%d", i, lgensym[i]); + lgensym[i]++; + genref[i] = 0; + yylval = (int)*lookup(passno == 1); + val = NAME; + np = (struct symtab *)yylval; + goto restlab; + } + if (val == NL){ + lineno++; + if (liston && (passno == 2) && (! endofsource)) + { + /* printing previous line & layout */ + length = strlen (layout); + fprintf (listfile, "%*.*s", LHEAD, LHEAD, layout); + if (length <= LHEAD+LLEN) + j = LLEN; + else { /* break line at last blank */ + j = LHEAD+LLEN; + while(j>LHEAD && layout[j]!= ' ') + j--; + if(j == LHEAD) + j = LLEN; + else + j -= LHEAD; + } + k = LHEAD+j; + fprintf (listfile, "%-*.*s", LLEN, j, &layout[LHEAD]); + fprintf (listfile, " "); + do { + ch = getc (source); + putc (ch, listfile); + } while (ch != '\n'); + while (k < length) + { + fprintf (listfile, "%*s", LHEAD, ""); + /* break line at last blank */ + if(layout[k] == ' ') + k++; + if((j = k+LLEN) >= length) + j = length; + else + while(j>k && layout[j]!= ' ') + j--; + if(j == k) + j = LLEN; + else + j -= k; + fprintf (listfile, "%-*.*s\n", j, j, &layout[k]); + k += j; + } + k = 0; + while (layout[k] != '\0') + layout[k++] = '\0'; + ch = getc (source); + if (ch == EOF) + { + if (ind == ninfiles) + endofsource = 1; + else + { + source = fopen (innames[ind++], "r"); + lineno = 1; + } + } + else + ungetc (ch, source); + layoutpos = layout; + (void)sprintf (layoutpos, "%4ld ", lineno); + layoutpos += 6; + long_out (dotp->e_xvalue); + if (dotp->e_xvalue >= datbase) + (void)sprintf (layoutpos," * "); + else + (void)sprintf (layoutpos," "); + layoutpos += 4; + } + shift; + } else + if (val == SEMI) + shift; + else { /*its a name, so we have a label or def */ + if (val != NAME){ + ERROR("Name expected for a label"); + } + np = (struct symtab *)yylval; + shiftover(NAME); + if (val != COLON) { + yyerror("\"%s\" is not followed by a ':' for a label definition", + FETCHNAME(np)); + goto errorfix; + } +restlab: + shift; + flushfield(NBPW/4); + if ((np->s_type&XTYPE)!=XUNDEF) { + if( (np->s_type&XTYPE)!=dotp->e_xtype + || np->s_value!=dotp->e_xvalue + || ( (passno==1) + &&(np->s_index != dotp->e_xloc) + ) + ){ +#ifndef DEBUG + if (FETCHNAME(np)[0] != 'L') +#endif not DEBUG + { + if (passno == 1) + yyerror("%s redefined", + FETCHNAME(np)); + else + yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d", + FETCHNAME(np), + np->s_value, + dotp->e_xvalue); + } + } + } + np->s_type &= ~(XTYPE|XFORW); + np->s_type |= dotp->e_xtype; + np->s_value = dotp->e_xvalue; + if (passno == 1){ + np->s_index = dotp-usedot; + if (FETCHNAME(np)[0] == 'L'){ + nlabels++; + } + np->s_tag = LABELID; + } + } /*end of this being a label*/ + } /*end of to consuming all labels, NLs and SEMIS */ + + xp = explist; + ap = arglist; + + /* + * process the INSTRUCTION body + */ + switch(val){ + + default: + ERROR("Unrecognized instruction or directive"); + + case IABORT: + shift; + sawabort(); + /*NOTREACHED*/ + break; + + case PARSEEOF: + tokptr -= sizeof(bytetoktype); + *tokptr++ = VOID; + tokptr[1] = VOID; + tokptr[2] = PARSEEOF; + break; + + case IFILE: + shift; + stringp = (struct strdesc *)yylval; + shiftover(STRING); + dotsname = &UDotsname[0]; + movestr(dotsname, stringp->sd_string, + min(stringp->sd_strlen, sizeof(UDotsname))); + break; + + case ILINENO: + shift; /*over the ILINENO*/ + expr(locxp, val); + lineno = locxp->e_xvalue; + break; + + case ISET: /* .set , */ + shift; + np = (struct symtab *)yylval; + shiftover(NAME); + shiftover(CM); + expr(locxp, val); + np->s_type &= (XXTRN|XFORW); + np->s_type |= locxp->e_xtype&(XTYPE|XFORW); + np->s_value = locxp->e_xvalue; + if (passno==1) + np->s_index = locxp->e_xloc; + if ((locxp->e_xtype&XTYPE) == XUNDEF) + yyerror("Illegal set?"); + break; + + case ILSYM: /*.lsym name , expr */ + shift; + np = (struct symtab *)yylval; + shiftover(NAME); + shiftover(CM); + expr(locxp, val); + /* + * Build the unique occurance of the + * symbol. + * The character scanner will have + * already entered it into the symbol + * table, but we should remove it + */ + if (passno == 1){ + stpt = (struct symtab *)symalloc(); + stpt->s_name = np->s_name; + np->s_tag = OBSOLETE; /*invalidate original */ + nforgotten++; + np = stpt; + if ( (locxp->e_xtype & XTYPE) != XABS) + yyerror("Illegal second argument to lsym"); + np->s_value = locxp->e_xvalue; + np->s_type = XABS; + np->s_tag = ILSYM; + } + break; + + case IGLOBAL: /*.globl */ + shift; + np = (struct symtab *)yylval; + shiftover(NAME); + np->s_type |= XXTRN; + break; + + case IDATA: /*.data [ ] */ + case ITEXT: /*.text [ ] */ + incasetable = 0; + seg_type = -val; + shift; + if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ + expr(locxp, val); + seg_type = -seg_type; /*now, it is positive*/ + } + + if (seg_type < 0) { /*there wasn't an associated expr*/ + seg_number = 0; + seg_type = -seg_type; + } else { + if ( ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ + || (seg_number = locxp->e_xvalue) >= NLOC) { + yyerror("illegal location counter"); + seg_number = 0; + } + } + if (seg_type == IDATA) + seg_number += NLOC; + flushfield(NBPW/4); + dotp = &usedot[seg_number]; + if (passno==2) { /* go salt away in pass 2*/ + txtfil = usefile[seg_number]; + relfil = rusefile[seg_number]; + } + break; + + /* + * Storage filler directives: + * + * .byte [] + * + * exprlist: empty | exprlist outexpr + * outexpr: | : + */ + case IBYTE: curlen = NBPW/4; goto elist; + case IWORD: curlen = NBPW/2; goto elist; + case IINT: curlen = NBPW; goto elist; + case ILONG: curlen = NBPW; goto elist; + + elist: + seg_type = val; + shift; + + /* + * Expression List processing + */ + if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){ + do{ + /* + * expression list consists of a list of : + * + * : + * (pack expr2 into expr1 bits + */ + expr(locxp, val); + /* + * now, pointing at the next token + */ + /* if (val == COLON){ */ + /* shiftover(COLON); */ + /* expr(pval, val); */ + /* if ((locxp->e_xtype & XTYPE) != XABS) */ + /* yyerror("Width not absolute"); */ + /* field_width = locxp->e_xvalue; */ + /* locxp = pval; */ + /* if (bitoff + field_width > curlen) */ + /* flushfield(curlen); */ + /* if (field_width > curlen) */ + /* yyerror("Expression crosses field boundary"); */ + /* } else { */ + field_width = curlen; + if (bitoff == 0) printblank = 0; + else printblank = 1; + flushfield(curlen); + if (liston && (passno == 2) && printblank) + *layoutpos++ = ' '; + /* } */ + + if ((locxp->e_xtype & XTYPE) != XABS) { + if (bitoff) + yyerror("Illegal relocation in field"); + switch(curlen){ + case NBPW/4: reloc_how = TYPB; break; + case NBPW/2: reloc_how = TYPW; break; + case NBPW: reloc_how = TYPL; break; + } + if (passno == 1){ + dotp->e_xvalue += ty_nbyte[reloc_how]; + } else { + outrel(locxp, reloc_how); + if (liston) + *layoutpos++ = ' '; + } + } else { + /* + * + * See if we are doing a case instruction. + * If so, then see if the branch distance, + * stored as a word, + * is going to loose sig bits. + */ + if (passno == 2 && incasetable){ + if ( !(ISWORD(locxp->e_xvalue))) + yyerror("Case will branch too far"); + } + field_value = locxp->e_xvalue & ( (1L << field_width)-1); + bitfield |= field_value << bitoff; + bitoff += field_width; + } + xp = explist; + if (auxval = (val == CM)) + shift; + } while (auxval); + } /* there existed an expression at all */ + + flushfield(curlen); + if ( ( curlen == NBPW/4) && bitoff) + dotp->e_xvalue ++; + break; + /*end of case IBYTE, IWORD, ILONG, IINT*/ + + case ISPACE: /* .space */ + shift; + expr(locxp, val); + if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ + yyerror("Space size not absolute"); + if (locxp->e_xvalue < 0) + yyerror("Space size not positive"); + space_value = locxp->e_xvalue; + ospace: + flushfield(NBPW/4); + { + static char spacebuf[128]; + while (space_value > sizeof(spacebuf)){ + outs(spacebuf, sizeof(spacebuf)); + space_value -= sizeof(spacebuf); + } + outs(spacebuf, space_value); + } + if (liston && (passno == 2)) + (void)sprintf (layoutpos, "****"); + break; + + /* + * .fill rep, size, value + * repeat rep times: fill size bytes with (truncated) value + * size must be between 1 and 8 + */ + case IFILL: + shift; + expr(locxp, val); + if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ + yyerror("Fill repetition count not absolute"); + rep_fill = fill_rep = locxp->e_xvalue; + shiftover(CM); + expr(locxp, val); + if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ + yyerror("Fill size not absolute"); + fill_size = locxp->e_xvalue; + if (fill_size <= 0 || fill_size > 8) + yyerror("Fill count not in in 1..8"); + shiftover(CM); + expr(locxp, val); + if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ + yyerror("Fill value not absolute"); + flushfield(NBPW/4); + dotp->e_xvalue += fill_rep * fill_size; + if (passno == 1) { + locxp->e_xvalue += fill_rep * fill_size; + } else { + fillval.lpart[0] = locxp->e_yvalue; + fillval.lpart[1] = locxp->e_xvalue; + while (fill_rep-- > 0) + bwrite(&(fillval.strpart[8-fill_size]),fill_size,txtfil); + if (liston) { + while (rep_fill-- > 0) + { + switch (fill_size) + { + case 1: + byte_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + case 2: + word_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + case 3: + byte_out (locxp->e_xvalue >> 16); + byte_out (locxp->e_xvalue >> 8); + byte_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + case 4: + long_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + case 5: + byte_out (locxp->e_yvalue); + long_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + case 6: + word_out (locxp->e_yvalue); + long_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + case 7: + byte_out (locxp->e_yvalue >> 16); + byte_out (locxp->e_yvalue >> 8); + byte_out (locxp->e_yvalue); + long_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + case 8: + long_out (locxp->e_yvalue); + long_out (locxp->e_xvalue); + *layoutpos++ = ' '; + break; + } + } + } + } + break; + + case IASCII: /* .ascii [ ] */ + case IASCIZ: /* .asciz [ ] */ + auxval = val; + shift; + /* + * Code to consume a string list + * + * stringlist: empty | STRING | stringlist STRING + */ + while (val == STRING){ + int mystrlen; + flushfield(NBPW/4); + if (bitoff) + dotp->e_xvalue++; + stringp = (struct strdesc *)yylval; + /* + * utilize the string scanner cheat; + * the scanner appended a null byte on the string, + * but didn't charge it to sd_strlen + */ + mystrlen = stringp->sd_strlen; + mystrlen += (auxval == IASCIZ) ? 1 : 0; + if (passno == 2){ + if (stringp->sd_place & STR_CORE){ + outs(stringp->sd_string, mystrlen); + if (liston) + { + int i; + for (i = 0;i < mystrlen; i++) + { + (void)sprintf (layoutpos, "%02x", + stringp->sd_string[i]); + layoutpos += 2; + } + } + } else { + int i, nread; + fseek(strfile, stringp->sd_stroff, 0); + for (i = 0; i < mystrlen;/*VOID*/){ + nread = fread(yytext, 1, + min(mystrlen - i, + sizeof(yytext)), strfile); + outs(yytext, nread); + if (liston) + { + int k; + for (k = 0;k < nread; k++) + { + (void)sprintf (layoutpos, + "%02x", yytext[k]); + layoutpos += 2; + } + } + i += nread; + } + } + } else { + dotp->e_xvalue += mystrlen; + } + shift; /*over the STRING*/ + if (val == CM) /*could be a split string*/ + shift; + } + break; + + case IORG: /* .org */ + shift; + expr(locxp, val); + + if ((locxp->e_xtype & XTYPE) == XABS) /* tekmdp */ + orgwarn++; + else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype) + yyerror("Illegal expression to set origin"); + if ((unsigned)locxp->e_xvalue < (unsigned)dotp->e_xvalue) + { + ERROR("Backwards 'org'"); + } + space_value = locxp->e_xvalue - dotp->e_xvalue; + goto ospace; + break; + +/* + * + * Process stabs. Stabs are created only by the f77 + * and the C compiler with the -g flag set. + * We only look at the stab ONCE, during pass 1, and + * virtually remove the stab from the intermediate file + * so it isn't seen during pass2. This makes for some + * hairy processing to handle labels occuring in + * stab entries, but since most expressions in the + * stab are integral we save lots of time in the second + * pass by not looking at the stabs. + * A stab that is tagged floating will be bumped during + * the jxxx resolution phase. A stab tagged fixed will + * not be be bumped. + * + * .stab: Old fashioned stabs + * .stabn: For stabs without names + * .stabs: For stabs with string names + * .stabd: For stabs for line numbers or bracketing, + * without a string name, without + * a final expression. The value of the + * final expression is taken to be the current + * location counter, and is patched by the 2nd pass + * + * .stab{,}*NCPName,, , , + * .stabn , , , + * .stabs STRING, , , , + * .stabd , , # . + */ + case ISTAB: + yyerror(".stab directive no longer supported"); + goto errorfix; + + tailstab: + expr(locxp, val); + if (! (locxp->e_xvalue & STABTYPS)){ + yyerror("Invalid type in %s", stabname); + goto errorfix; + } + stpt->s_ptype = locxp->e_xvalue; + shiftover(CM); + expr(locxp, val); + stpt->s_other = locxp->e_xvalue; + shiftover(CM); + expr(locxp, val); + stpt->s_desc = locxp->e_xvalue; + shiftover(CM); + exprisname = 0; + expr(locxp, val); + p = locxp->e_xname; + if (p == NULL) { /*absolute expr to begin with*/ + stpt->s_value = locxp->e_xvalue; + stpt->s_index = dotp - usedot; + if (exprisname){ + stpt->s_type = locxp->e_xtype; + switch(stpt->s_ptype){ + case N_LCSYM: + stpt->s_dest = (struct symtab *)exprisname; + stpt->s_type |= STABFLAG; + case N_GSYM: + case N_FNAME: + case N_RSYM: + case N_SSYM: + case N_LSYM: + case N_PSYM: + case N_BCOMM: + case N_ECOMM: + case N_LENG: + stpt->s_tag = STABFIXED; + break; + default: + stpt->s_tag = STABFLOATING; + break; + } + } else + stpt->s_tag = STABFIXED; + } + else { /*really have a name*/ + stpt->s_dest = locxp->e_xname; + stpt->s_index = p->s_index; + stpt->s_type = p->s_type | STABFLAG; + /* + * We will assign a more accruate + * guess of locxp's location when + * we sort the symbol table + * The final value of value is + * given by stabfix() + */ +/* + * For exprs of the form (name + value) one needs to remember locxp->e_xvalue + * for use in stabfix. The right place to keep this is in stpt->s_value + * however this gets corrupted at an unknown point. + * As a bandaid hack the value is preserved in s_desc and s_other (a + * short and a char). This destroys these two values and will + * be fixed. May 19 ,1983 Alastair Fyfe + */ + if(locxp->e_xvalue) { + stpt->s_other = (locxp->e_xvalue >> 16); + stpt->s_desc = (locxp->e_xvalue & 0x0000ffff); + stpt->s_tag = STABFLOATING; + } + } + /* + * tokptr now points at one token beyond + * the current token stored in val and yylval, + * which are the next tokens after the end of + * this .stab directive. This next token must + * be either a SEMI or NL, so is of width just + * one. Therefore, to point to the next token + * after the end of this stab, just back up one.. + */ + buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); + break; /*end of the .stab*/ + + case ISTABDOT: + stabname = ".stabd"; + stpt = (struct symtab *)yylval; + /* + * We clobber everything after the + * .stabd and its pointer... we MUST + * be able to get back to this .stabd + * so that we can resolve its final value + */ + stabstart = tokptr; + shift; /*over the ISTABDOT*/ + if (passno == 1){ + expr(locxp, val); + if (! (locxp->e_xvalue & STABTYPS)){ + yyerror("Invalid type in .stabd"); + goto errorfix; + } + stpt->s_ptype = locxp->e_xvalue; + shiftover(CM); + expr(locxp, val); + stpt->s_other = locxp->e_xvalue; + shiftover(CM); + expr(locxp, val); + stpt->s_desc = locxp->e_xvalue; + /* + * + * Now, clobber everything but the + * .stabd pseudo and the pointer + * to its symbol table entry + * tokptr points to the next token, + * build the skip up to this + */ + buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype)); + } + /* + * pass 1: Assign a good guess for its position + * (ensures they are sorted into right place)/ + * pass 2: Fix the actual value + */ + stpt->s_value = dotp->e_xvalue; + stpt->s_index = dotp - usedot; + stpt->s_tag = STABFLOATING; /*although it has no effect in pass 2*/ + break; + + case ISTABNONE: stabname = ".stabn"; goto shortstab; + + case ISTABSTR: stabname = ".stabs"; + shortstab: + auxval = val; + if (passno == 2) goto errorfix; + stpt = (struct symtab *)yylval; + stabstart = tokptr; + (bytetoktype *)stabstart -= sizeof(struct symtab *); + (bytetoktype *)stabstart -= sizeof(bytetoktype); + shift; + if (auxval == ISTABSTR){ + stringp = (struct strdesc *)yylval; + shiftover(STRING); + stpt->s_name = (char *)stringp; + /* + * We want the trailing null included in this string. + * We utilize the cheat the string scanner used, + * and merely increment the string length + */ + stringp->sd_strlen += 1; + shiftover(CM); + } else { + stpt->s_name = (char *)savestr("\0", 0, STR_BOTH); + } + goto tailstab; + break; + + case ICOMM: /* .comm , */ + case ILCOMM: /* .lcomm , */ + auxval = val; + shift; + np = (struct symtab *)yylval; + shiftover(NAME); + shiftover(CM); + expr(locxp, val); + + if ( (locxp->e_xtype & XTYPE) != XABS) /* tekmdp */ + yyerror("comm size not absolute"); + if (passno == 1 && (np->s_type&XTYPE) != XUNDEF) + yyerror("Redefinition of %s", FETCHNAME(np)); + if (passno==1) { + np->s_value = locxp->e_xvalue; + if (auxval == ICOMM) + np->s_type |= XXTRN; + else { + np->s_type &= ~XTYPE; + np->s_type |= XBSS; + } + } + break; + + case IALIGN: /* .align */ + stpt = (struct symtab *)yylval; + shift; + expr(locxp, val); + if ((dotp->e_xtype & XTYPE) == XDATA) + djalign(locxp, stpt); + else + jalign(locxp, stpt); + break; + + case INST0: /* instructions w/o arguments*/ + incasetable = 0; + insout(yyopcode, (struct arg *)0, 0); + shift; + break; + + case INSTn: /* instructions with arguments*/ + case IJXXX: /* UNIX style jump instructions */ + auxval = val; + /* + * Code to process an argument list + */ + ap = arglist; + xp = explist; + + shift; /* bring in the first token for the arg list*/ + + for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ + /* + * code to process an argument proper + */ + sawindex = sawmul = sawsize = 0; + { + switch(val) { + + default: + disp: + if( !(INTOKSET(val, + EBEGOPS + +YUKKYEXPRBEG + +SAFEEXPRBEG)) ) { + ERROR("expression expected"); + } + expr(ap->a_xp,val); + overdisp: + if ( val == LP || sawsize){ + shiftover(LP); + findreg(regno); + shiftover(RP); + ap->a_atype = ADISP; + ap->a_areg1 = regno; + } else { + ap->a_atype = AEXP; + ap->a_areg1 = 0; + } + goto index; + + case SIZESPEC: + sizespec: + sawsize = yylval; + shift; + goto disp; + + case REG: + case REGOP: + findreg(regno); + ap->a_atype = AREG; + ap->a_areg1 = regno; + break; + + case MUL: + sawmul = 1; + shift; + if (val == LP) goto base; + if (val == LITOP) goto imm; + if (val == SIZESPEC) goto sizespec; + if (INTOKSET(val, + EBEGOPS + +YUKKYEXPRBEG + +SAFEEXPRBEG)) goto disp; + ERROR("expression, '(' or '$' expected"); + break; + + case LP: + base: + shift; /*consume the LP*/ + /* + * hack the ambiguity of + * movl (expr) (rn), ... + * note that (expr) could also + * be (rn) (by special hole in the + * grammar), which we ensure + * means register indirection, instead + * of an expression with value n + */ + if (val != REG && val != REGOP){ + droppedLP = 1; + val = exprparse(val, &(ap->a_xp)); + droppedLP = 0; + goto overdisp; + } + findreg(regno); + shiftover(RP); + if (val == PLUS){ + shift; + ap->a_atype = AINCR; + if (sawmul && regno != 0xE) + yyerror ("Autoincrement deferred register must be SP"); + if (!(sawmul || regno == 0xE)) + yyerror ("Autoincrement register must be SP"); + } else + ap->a_atype = ABASE; + ap->a_areg1 = regno; + goto index; + + case LITOP: + imm: + shift; + expr(locxp, val); + ap->a_atype = AIMM; + ap->a_areg1 = 0; + ap->a_xp = locxp; + goto index; + + case MP: + shift; /* -(reg) */ + findreg(regno); + if (regno != 0xE) + yyerror ("Autodecrement register must be SP"); + shiftover(RP); + ap->a_atype = ADECR; + ap->a_areg1 = regno; + index: /*look for [reg] */ + if (val == LB){ + shift; + findreg(regno); + shiftover(RB); + sawindex = 1; + ap->a_areg2 = regno; + } + break; + + } /*end of the switch to process an arg*/ + } /*end of processing an argument*/ + + if (sawmul){ + /* + * Make a concession for *(%r) + * meaning *0(%r) + */ + if (ap->a_atype == ABASE) { + ap->a_atype = ADISP; + xp->e_xtype = XABS; + xp->e_number = Znumber; + xp->e_number.num_tag = TYPL; + xp->e_xloc = 0; + ap->a_xp = xp++; + } + ap->a_atype |= ASTAR; + sawmul = 0; + } + if (sawindex){ + ap->a_atype |= AINDX; + sawindex = 0; + } + ap->a_dispsize = sawsize == 0 ? d124 : sawsize; + if (val != CM) break; + shiftover(CM); + } /*processing all the arguments*/ + + if (argcnt > 6){ + yyerror("More than 6 arguments"); + goto errorfix; + } + + /* + * See if this is a case instruction, + * so we can set up tests on the following + * vector of branch displacements + */ + if (yyopcode == 0xfc) /* 'casel' instruction */ + incasetable++; + else + incasetable = 0; + + insout(yyopcode, arglist, + auxval == INSTn ? argcnt : - argcnt); + break; + + case IQUAD: num_type = TYPQ; goto bignumlist; + case IFFLOAT: num_type = TYPF; goto bignumlist; + case IDFLOAT: num_type = TYPD; + bignumlist: + /* + * eat a list of non 32 bit numbers. + * IQUAD can, possibly, return + * INT's, if the numbers are "small". + * + * The value of the numbers is coming back + * as an expression, NOT in yybignum. + */ + shift; /* over the opener */ + if ((val == BIGNUM) || (val == INT)){ + do{ + if ((val != BIGNUM) && (val != INT)){ + ERROR(ty_float[num_type] + ? "floating number expected" + : "integer number expected" ); + } + dotp->e_xvalue += ty_nbyte[num_type]; + if (passno == 2){ + switch (num_type) { + case TYPF: + bwrite(((struct exp *)yylval)->e_number.num_num.numFf_float.Ff_ulong, + ty_nbyte[num_type], txtfil); + if (liston) + { + long_out(((struct exp *)yylval)->e_number.num_num.numFf_float.Ff_ulong[0]); + *layoutpos++ = ' '; + } + break; + case TYPD: + bwrite(&((struct exp *)yylval)->e_number.num_num.numFd_float.Fd_ulong[0], + sizeof (long), txtfil); + bwrite(&((struct exp *)yylval)->e_number.num_num.numFd_float.Fd_ulong[1], + sizeof (long), txtfil); + if (liston) + { + long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0]); + long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1]); + *layoutpos++ = ' '; + } + break; + case TYPQ: + bwrite(&((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1], + sizeof (long), txtfil); + bwrite(&((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0], + sizeof (long), txtfil); + if (liston) + { + long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1]); + long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0]); + *layoutpos++ = ' '; + } + break; + } + } + xp = explist; + shift; /* over this number */ + if (auxval = (val == CM)) + shift; /* over the comma */ + } while (auxval); /* as long as there are commas */ + } + break; + /* end of the case for initialized big numbers */ + } /*end of the switch for looking at each reserved word*/ + + continue; + + errorfix: + /* + * got here by either requesting to skip to the + * end of this statement, or by erroring out and + * wanting to apply panic mode recovery + */ + while ( (val != NL) + && (val != SEMI) + && (val != PARSEEOF) + ){ + shift; + } + if (val == NL) + lineno++; + shift; + + } /*end of the loop to read the entire file, line by line*/ + +} /*end of yyparse*/ + +/* + * Process a register declaration of the form + * % + * + * Note: + * The scanner has already processed funny registers of the form + * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional + * preceding zero digit). If there was any space between the % and + * the digit, the scanner wouldn't have recognized it, so we + * hack it out here. + */ +inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ + inttoktype val; /*what the read head is sitting on*/ + int *regnoback; /*call by return*/ +{ + reg struct exp *locxp; + struct exp *loc1xp; + struct exp **ptrloc1xp = & loc1xp; + + expr(locxp, val); /*and leave the current read head with value*/ + if ( (passno == 2) && + ( (locxp->e_xtype & XTYPE) != XABS + || (locxp->e_xvalue < 0) + || (locxp->e_xvalue >= 16) + ) + ){ + yyerror("Illegal register"); + return(0); + } + *regnoback = locxp->e_xvalue; + return(val); +} +/* + * Shift over error + */ +shiftoerror(token) + int token; +{ + char *tok_to_name(); + yyerror("%s expected", tok_to_name(token)); +} + +/*VARARGS1*/ +yyerror(s, a1, a2,a3,a4,a5) + char *s; +{ + +#define sink stdout + + if (anyerrs == 0 && anywarnings == 0 && ! silent) + fprintf(sink, "Assembler:\n"); + anyerrs++; + if (silent) + return; + fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); + fprintf(sink, s, a1, a2,a3,a4,a5); + fprintf(sink, "\n"); +#undef sink +} + +/*VARARGS1*/ +yywarning(s, a1, a2,a3,a4,a5) + char *s; +{ +#define sink stdout + if (anyerrs == 0 && anywarnings == 0 && ! silent) + fprintf(sink, "Assembler:\n"); + anywarnings++; + if (silent) + return; + fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); + fprintf(sink, s, a1, a2,a3,a4,a5); + fprintf(sink, "\n"); +#undef sink +} -- 2.20.1