xref: /csrg-svn/old/as.vax/asparse.c (revision 30099)
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*30099Sdonn static char sccsid[] = "@(#)asparse.c	5.3 (Berkeley) 11/17/86";
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 
yyparse()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 = &regno;
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;
14323578Smckusick 			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;
28123578Smckusick 	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 	 */
29723578Smckusick    case IBYTE:	curlen = NBWD/4; goto elist;
29823578Smckusick    case IWORD:	curlen = NBWD/2; goto elist;
29923578Smckusick    case IINT:	curlen = NBWD;   goto elist;
30023578Smckusick    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){
34123578Smckusick 				case NBWD/4:	reloc_how = TYPB; break;
34223578Smckusick 				case NBWD/2:	reloc_how = TYPW; break;
34323578Smckusick 				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);
37523578Smckusick 	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:
38723578Smckusick 	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");
42023578Smckusick 	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;
43923578Smckusick 		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){
543*30099Sdonn 				case N_LCSYM:
544*30099Sdonn 					stpt->s_dest = (struct symtab *)exprisname;
545*30099Sdonn 					stpt->s_type |= STABFLAG;
546597Sbill 				case N_GSYM:
547597Sbill 				case N_FNAME:
548597Sbill 				case N_RSYM:
549597Sbill 				case N_SSYM:
550597Sbill 				case N_LSYM:
551597Sbill 				case N_PSYM:
552597Sbill 				case N_BCOMM:
553597Sbill 				case N_ECOMM:
554597Sbill 				case N_LENG:
555632Shenry 					stpt->s_tag = STABFIXED;
556597Sbill 					break;
557597Sbill 				default:
558632Shenry 					stpt->s_tag = STABFLOATING;
559597Sbill 					break;
560597Sbill 			}
561597Sbill 		} else
562632Shenry 			stpt->s_tag = STABFIXED;
563597Sbill 	}
564597Sbill 	else {		/*really have a name*/
565632Shenry 		stpt->s_dest = locxp->e_xname;
566632Shenry 		stpt->s_index = p->s_index;
567632Shenry 		stpt->s_type = p->s_type | STABFLAG;
568597Sbill 		/*
569597Sbill 		 *	We will assign a more accruate
570597Sbill 		 *	guess of locxp's location when
571597Sbill 		 *	we sort the symbol table
572597Sbill 		 *	The final value of value is
573597Sbill 		 *	given by stabfix()
574597Sbill 		 */
57512591Scsvaf /*
57612591Scsvaf  * For exprs of the form (name + value) one needs to remember locxp->e_xvalue
57712591Scsvaf  * for use in stabfix. The right place to keep this is in stpt->s_value
57812591Scsvaf  * however this gets corrupted at an unknown point.
57912591Scsvaf  * As a bandaid hack the value is preserved in s_desc and s_other (a
58012591Scsvaf  * short and a char). This destroys these two values and will
58112591Scsvaf  * be fixed. May 19 ,1983 Alastair Fyfe
58212591Scsvaf  */
58312591Scsvaf 		if(locxp->e_xvalue) {
58412591Scsvaf 			stpt->s_other = (locxp->e_xvalue >> 16);
58512591Scsvaf 			stpt->s_desc =  (locxp->e_xvalue  & 0x0000ffff);
58612591Scsvaf 			stpt->s_tag = STABFLOATING;
58712591Scsvaf 		}
588597Sbill 	}
589597Sbill 	/*
590597Sbill 	 *	tokptr now points at one token beyond
591597Sbill 	 *	the current token stored in val and yylval,
592597Sbill 	 *	which are the next tokens after the end of
593597Sbill 	 *	this .stab directive.  This next token must
594597Sbill 	 *	be either a SEMI or NL, so is of width just
595597Sbill 	 *	one.  Therefore, to point to the next token
596597Sbill 	 *	after the end of this stab, just back up one..
597597Sbill 	 */
5985827Srrh 	buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
599597Sbill 	break;	/*end of the .stab*/
600597Sbill 
601597Sbill    case ISTABDOT:
602597Sbill 	stabname = ".stabd";
603597Sbill 	stpt = (struct symtab *)yylval;
604597Sbill 	/*
605597Sbill 	 *	We clobber everything after the
606597Sbill 	 *	.stabd and its pointer... we MUST
607597Sbill 	 *	be able to get back to this .stabd
608597Sbill 	 *	so that we can resolve its final value
609597Sbill 	 */
610597Sbill 	stabstart = tokptr;
611597Sbill 	shift;		/*over the ISTABDOT*/
612597Sbill 	if (passno == 1){
613597Sbill 		expr(locxp, val);
614632Shenry 		if (! (locxp->e_xvalue & STABTYPS)){
615597Sbill 			yyerror("Invalid type in .stabd");
616597Sbill 			goto errorfix;
617597Sbill 		}
618632Shenry 		stpt->s_ptype = locxp->e_xvalue;
619597Sbill 		shiftover(CM);
620597Sbill 		expr(locxp, val);
621632Shenry 		stpt->s_other = locxp->e_xvalue;
622597Sbill 		shiftover(CM);
623597Sbill 		expr(locxp, val);
624632Shenry 		stpt->s_desc = locxp->e_xvalue;
625597Sbill 		/*
626597Sbill 		 *
627597Sbill 		 *	Now, clobber everything but the
628597Sbill 		 *	.stabd pseudo and the pointer
629597Sbill 		 *	to its symbol table entry
630597Sbill 		 *	tokptr points to the next token,
631597Sbill 		 *	build the skip up to this
632597Sbill 		 */
6335827Srrh 		buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
634597Sbill 	}
635597Sbill 	/*
636597Sbill 	 *	pass 1:	Assign a good guess for its position
637597Sbill 	 *		(ensures they are sorted into right place)/
638597Sbill 	 *	pass 2:	Fix the actual value
639597Sbill 	 */
640632Shenry 	stpt->s_value = dotp->e_xvalue;
641632Shenry 	stpt->s_index = dotp - usedot;
642632Shenry 	stpt->s_tag = STABFLOATING;	/*although it has no effect in pass 2*/
643597Sbill 	break;
644597Sbill 
645597Sbill    case ISTABNONE:	stabname = ".stabn"; goto shortstab;
646597Sbill 
647597Sbill    case ISTABSTR: 	stabname = ".stabs";
648597Sbill    shortstab:
649597Sbill 	auxval = val;
650597Sbill 	if (passno == 2) goto errorfix;
651597Sbill 	stpt = (struct symtab *)yylval;
652597Sbill 	stabstart = tokptr;
6535827Srrh 	(bytetoktype *)stabstart -= sizeof(struct symtab *);
6545827Srrh 	(bytetoktype *)stabstart -= sizeof(bytetoktype);
655597Sbill 	shift;
656597Sbill 	if (auxval == ISTABSTR){
65713513Srrh 		stringp = (struct strdesc *)yylval;
658597Sbill 		shiftover(STRING);
65913513Srrh 		stpt->s_name = (char *)stringp;
66013446Srrh 		/*
66113446Srrh 		 *	We want the trailing null included in this string.
66213446Srrh 		 *	We utilize the cheat the string scanner used,
66313446Srrh 		 *	and merely increment the string length
66413446Srrh 		 */
66513513Srrh 		stringp->sd_strlen += 1;
666597Sbill 		shiftover(CM);
667597Sbill 	} else {
66813571Srrh 		stpt->s_name = (char *)savestr("\0", 0, STR_BOTH);
669597Sbill 	}
670597Sbill 	goto tailstab;
671597Sbill 	break;
672597Sbill 
6735827Srrh    case ICOMM:		/* .comm  <name> , <expr> */
674597Sbill    case ILCOMM: 	/* .lcomm <name> , <expr> */
675597Sbill 	auxval = val;
676597Sbill 	shift;
677597Sbill 	np = (struct symtab *)yylval;
678597Sbill 	shiftover(NAME);
679597Sbill 	shiftover(CM);
680597Sbill 	expr(locxp, val);
681597Sbill 
6825827Srrh 	if ( (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
683597Sbill 		yyerror("comm size not absolute");
6845827Srrh 	if (passno == 1 && (np->s_type&XTYPE) != XUNDEF)
68513521Srrh 		yyerror("Redefinition of %s", FETCHNAME(np));
686597Sbill 	if (passno==1) {
687632Shenry 		np->s_value = locxp->e_xvalue;
688597Sbill 		if (auxval == ICOMM)
689632Shenry 			np->s_type |= XXTRN;
690597Sbill 		else {
691632Shenry 			np->s_type &= ~XTYPE;
692632Shenry 			np->s_type |= XBSS;
693597Sbill 		}
694597Sbill 	}
695597Sbill 	break;
696597Sbill 
697597Sbill    case IALIGN: 		/* .align <expr> */
698597Sbill 	stpt = (struct symtab *)yylval;
699597Sbill 	shift;
700597Sbill 	expr(locxp, val);
701597Sbill 	jalign(locxp, stpt);
702597Sbill 	break;
703597Sbill 
704597Sbill    case INST0: 		/* instructions w/o arguments*/
70513274Srrh 	incasetable = 0;
7065827Srrh 	insout(yyopcode, (struct arg *)0, 0);
707597Sbill 	shift;
708597Sbill 	break;
709597Sbill 
710597Sbill    case INSTn:		/* instructions with arguments*/
711597Sbill    case IJXXX: 		/* UNIX style jump instructions */
712597Sbill 	auxval = val;
713597Sbill 	/*
714597Sbill 	 *	Code to process an argument list
715597Sbill 	 */
716597Sbill 	ap = arglist;
717597Sbill 	xp = explist;
718597Sbill 
719597Sbill 	shift;		/* bring in the first token for the arg list*/
720597Sbill 
721597Sbill 	for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
722597Sbill 		/*
723597Sbill 		 *	code to process an argument proper
724597Sbill 		 */
725597Sbill 	    sawindex  = sawmul = sawsize = 0;
726597Sbill 	    {
727597Sbill 		switch(val) {
728597Sbill 
729597Sbill 		   default:
730597Sbill 		     disp:
731597Sbill 			if( !(INTOKSET(val,
732597Sbill 				 EBEGOPS
733597Sbill 				+YUKKYEXPRBEG
734597Sbill 				+SAFEEXPRBEG)) ) {
735597Sbill 				ERROR("expression expected");
736597Sbill 			}
737632Shenry 			expr(ap->a_xp,val);
738597Sbill 		     overdisp:
739597Sbill 			if ( val == LP || sawsize){
740597Sbill 				shiftover(LP);
741597Sbill 				findreg(regno);
742597Sbill 				shiftover(RP);
743632Shenry 				ap->a_atype = ADISP;
744632Shenry 				ap->a_areg1 = regno;
745597Sbill 			} else {
746632Shenry 				ap->a_atype = AEXP;
747632Shenry 				ap->a_areg1 = 0;
748597Sbill 			}
749597Sbill 			goto index;
750597Sbill 
751597Sbill 		   case SIZESPEC:
752597Sbill 		     sizespec:
753597Sbill 			sawsize = yylval;
754597Sbill 			shift;
755597Sbill 			goto disp;
756597Sbill 
757597Sbill 		   case REG:
758597Sbill 		   case REGOP:
759597Sbill 			findreg(regno);
760632Shenry 			ap->a_atype = AREG;
761632Shenry 			ap->a_areg1 = regno;
762597Sbill 			break;
763597Sbill 
764597Sbill 		   case MUL:
765597Sbill 			sawmul = 1;
766597Sbill 			shift;
767597Sbill 			if (val == LP) goto base;
768597Sbill 			if (val == LITOP) goto imm;
769597Sbill 			if (val == SIZESPEC) goto sizespec;
770597Sbill 			if (INTOKSET(val,
771597Sbill 				 EBEGOPS
772597Sbill 				+YUKKYEXPRBEG
773597Sbill 				+SAFEEXPRBEG)) goto disp;
774597Sbill 			ERROR("expression, '(' or '$' expected");
775597Sbill 			break;
776597Sbill 
777597Sbill 		   case LP:
778597Sbill 		     base:
779597Sbill 			shift;	/*consume the LP*/
780597Sbill 			/*
781597Sbill 			 *	hack the ambiguity of
782597Sbill 			 *	movl (expr) (rn), ...
783597Sbill 			 *	note that (expr) could also
784597Sbill 			 *	be (rn) (by special hole in the
785597Sbill 			 *	grammar), which we ensure
786597Sbill 			 *	means register indirection, instead
787597Sbill 			 *	of an expression with value n
788597Sbill 			 */
789597Sbill 			if (val != REG && val != REGOP){
790597Sbill 				droppedLP = 1;
791632Shenry 				val = exprparse(val, &(ap->a_xp));
792597Sbill 				droppedLP = 0;
793597Sbill 				goto overdisp;
794597Sbill 			}
795597Sbill 			findreg(regno);
796597Sbill 			shiftover(RP);
797597Sbill 			if (val == PLUS){
798597Sbill 				shift;
799632Shenry 				ap->a_atype = AINCR;
800597Sbill 			} else
801632Shenry 				ap->a_atype = ABASE;
802632Shenry 			ap->a_areg1 = regno;
803597Sbill 			goto index;
804597Sbill 
805597Sbill 		   case LITOP:
806597Sbill 		      imm:
807597Sbill 			shift;
808597Sbill 			expr(locxp, val);
809632Shenry 			ap->a_atype = AIMM;
810632Shenry 			ap->a_areg1 = 0;
811632Shenry 			ap->a_xp = locxp;
812597Sbill 			goto index;
813597Sbill 
814597Sbill 		   case MP:
815597Sbill 			shift;	/* -(reg) */
816597Sbill 			findreg(regno);
817597Sbill 			shiftover(RP);
818632Shenry 			ap->a_atype = ADECR;
819632Shenry 			ap->a_areg1 = regno;
820597Sbill 	  index:			/*look for [reg] */
821597Sbill 			if (val == LB){
822597Sbill 				shift;
823597Sbill 				findreg(regno);
824597Sbill 				shiftover(RB);
825597Sbill 				sawindex = 1;
826632Shenry 				ap->a_areg2 = regno;
827597Sbill 			}
828597Sbill 			break;
829597Sbill 
830597Sbill 		}	/*end of the switch to process an arg*/
831597Sbill 	    }	/*end of processing an argument*/
832597Sbill 
833597Sbill 	    if (sawmul){
834597Sbill 			/*
835597Sbill 			 * Make a concession for *(%r)
836597Sbill 			 * meaning *0(%r)
837597Sbill 			 */
838632Shenry 			if (ap->a_atype == ABASE) {
839632Shenry 				ap->a_atype = ADISP;
840632Shenry 				xp->e_xtype = XABS;
8415827Srrh 				xp->e_number = Znumber;
8425827Srrh 				xp->e_number.num_tag = TYPL;
843632Shenry 				xp->e_xloc = 0;
844632Shenry 				ap->a_xp = xp++;
845597Sbill 			}
846632Shenry 			ap->a_atype |= ASTAR;
847597Sbill 			sawmul = 0;
848597Sbill 	    }
849597Sbill 	    if (sawindex){
850632Shenry 		ap->a_atype |= AINDX;
851597Sbill 		sawindex = 0;
852597Sbill 	    }
853632Shenry 	    ap->a_dispsize = sawsize == 0 ? d124 : sawsize;
854597Sbill 		if (val != CM) break;
855597Sbill 		shiftover(CM);
856597Sbill 	}	/*processing all the arguments*/
857597Sbill 
858597Sbill 	if (argcnt > 6){
859597Sbill 		yyerror("More than 6 arguments");
860597Sbill 		goto errorfix;
861597Sbill 	}
862597Sbill 
86313274Srrh 	/*
86413274Srrh 	 *	See if this is a case instruction,
86513274Srrh 	 *	so we can set up tests on the following
86613274Srrh 	 *	vector of branch displacements
86713274Srrh 	 */
86813274Srrh 	if (yyopcode.Op_eopcode == CORE){
86913274Srrh 		switch(yyopcode.Op_popcode){
87013274Srrh 		case 0x8f:	/* caseb */
87113274Srrh 		case 0xaf:	/* casew */
87213274Srrh 		case 0xcf:	/* casel */
87313274Srrh 			incasetable++;
87413274Srrh 			break;
87513274Srrh 		default:
87613274Srrh 			incasetable = 0;
87713274Srrh 			break;
87813274Srrh 		}
87913274Srrh 	}
88013274Srrh 
8815827Srrh 	insout(yyopcode, arglist,
882597Sbill 		auxval == INSTn ? argcnt : - argcnt);
883597Sbill 	break;
884597Sbill 
8855827Srrh    case IQUAD:		toconv = TYPQ;	goto bignumlist;
8865827Srrh    case IOCTA:		toconv = TYPO;	goto bignumlist;
8875827Srrh 
8885827Srrh    case IFFLOAT:	toconv = TYPF;	goto bignumlist;
8895827Srrh    case IDFLOAT:	toconv = TYPD;	goto bignumlist;
8905827Srrh    case IGFLOAT:	toconv = TYPG;	goto bignumlist;
8915827Srrh    case IHFLOAT:	toconv = TYPH;	goto bignumlist;
8925827Srrh    bignumlist:
893597Sbill 	/*
8945827Srrh 	 *	eat a list of non 32 bit numbers.
8955827Srrh 	 *	IQUAD and IOCTA can, possibly, return
8965827Srrh 	 *	INT's, if the numbers are "small".
8975827Srrh 	 *
8985827Srrh 	 *	The value of the numbers is coming back
8995827Srrh 	 *	as an expression, NOT in yybignum.
900597Sbill 	 */
9015827Srrh 	shift;	/* over the opener */
9025827Srrh 	if ((val == BIGNUM) || (val == INT)){
903597Sbill 		do{
9045827Srrh 			if ((val != BIGNUM) && (val != INT)){
9055827Srrh 				ERROR(ty_float[toconv]
9065827Srrh 				   ? "floating number expected"
9075827Srrh 				   : "integer number expected" );
908597Sbill 			}
9095827Srrh 			dotp->e_xvalue += ty_nbyte[toconv];
9105827Srrh 			if (passno == 2){
9115827Srrh 				bignumwrite(
9125827Srrh 					((struct exp *)yylval)->e_number,
9135827Srrh 					toconv);
914597Sbill 			}
915597Sbill 			xp = explist;
9165827Srrh 			shift;		/* over this number */
9175827Srrh 			if (auxval = (val == CM))
9185827Srrh 				shift;	/* over the comma */
9195827Srrh 		} while (auxval);	/* as long as there are commas */
920597Sbill 	}
921597Sbill 	break;
9225827Srrh 	/* end of the case for initialized big numbers */
923597Sbill     }	/*end of the switch for looking at each reserved word*/
924597Sbill 
9255827Srrh 	continue;
926597Sbill 
927597Sbill    errorfix:
928597Sbill 	/*
929597Sbill 	 *	got here by either requesting to skip to the
930597Sbill 	 *	end of this statement, or by erroring out and
931597Sbill 	 *	wanting to apply panic mode recovery
932597Sbill 	 */
933597Sbill 	while (    (val != NL)
934597Sbill 		&& (val != SEMI)
935597Sbill 		&& (val != PARSEEOF)
936597Sbill 	      ){
937597Sbill 		shift;
938597Sbill 	}
939597Sbill 	if (val == NL)
940597Sbill 		lineno++;
941597Sbill 	shift;
942597Sbill 
943597Sbill     }	/*end of the loop to read the entire file, line by line*/
944597Sbill 
945597Sbill }	/*end of yyparse*/
946597Sbill 
947597Sbill /*
948597Sbill  *	Process a register declaration of the form
949597Sbill  *	% <expr>
950597Sbill  *
951597Sbill  *	Note:
952597Sbill  *		The scanner has already processed funny registers of the form
953597Sbill  *	%dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
954597Sbill  *	preceding zero digit).  If there was any space between the % and
955597Sbill  *	the digit, the scanner wouldn't have recognized it, so we
956597Sbill  *	hack it out here.
957597Sbill  */
funnyreg(val,regnoback)9585827Srrh inttoktype funnyreg(val, regnoback)	/*what the read head will sit on*/
9595827Srrh 	inttoktype	val;		/*what the read head is sitting on*/
960597Sbill 	int	*regnoback;		/*call by return*/
961597Sbill {
9625827Srrh 	reg	struct	exp *locxp;
9635827Srrh 		struct	exp *loc1xp;
9645827Srrh 		struct	exp **ptrloc1xp = & loc1xp;
965597Sbill 
966597Sbill 	expr(locxp, val);	/*and leave the current read head with value*/
967597Sbill 	if ( (passno == 2) &&
9685827Srrh 	    (   (locxp->e_xtype & XTYPE) != XABS
9695827Srrh 	     || (locxp->e_xvalue < 0)
9705827Srrh 	     || (locxp->e_xvalue >= 16)
971597Sbill 	    )
972597Sbill 	  ){
973597Sbill 		yyerror("Illegal register");
974597Sbill 		return(0);
975597Sbill 	}
976632Shenry 	*regnoback = locxp->e_xvalue;
977597Sbill 	return(val);
978597Sbill }
97912945Srrh /*
98012945Srrh  *	Shift over error
98112945Srrh  */
shiftoerror(token)98212945Srrh shiftoerror(token)
98312945Srrh 	int	token;
98412945Srrh {
98512945Srrh 	char	*tok_to_name();
98612945Srrh 	yyerror("%s expected", tok_to_name(token));
98712945Srrh }
988597Sbill 
989597Sbill /*VARARGS1*/
yyerror(s,a1,a2,a3,a4,a5)990597Sbill yyerror(s, a1, a2,a3,a4,a5)
991597Sbill 	char	*s;
992597Sbill {
993597Sbill 
994649Shenry #define	sink stdout
995597Sbill 
9965827Srrh 	if (anyerrs == 0 && anywarnings == 0 && ! silent)
997597Sbill 		fprintf(sink, "Assembler:\n");
998597Sbill 	anyerrs++;
9995827Srrh 	if (silent)
10005827Srrh 		return;
1001597Sbill 	fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
1002597Sbill 	fprintf(sink, s, a1, a2,a3,a4,a5);
1003597Sbill 	fprintf(sink, "\n");
10045827Srrh #undef sink
1005597Sbill }
1006676Shenry 
1007676Shenry /*VARARGS1*/
yywarning(s,a1,a2,a3,a4,a5)1008676Shenry yywarning(s, a1, a2,a3,a4,a5)
1009676Shenry 	char	*s;
1010676Shenry {
1011676Shenry #define	sink stdout
10125827Srrh 	if (anyerrs == 0 && anywarnings == 0 && ! silent)
1013676Shenry 		fprintf(sink, "Assembler:\n");
10145827Srrh 	anywarnings++;
10155827Srrh 	if (silent)
10165827Srrh 		return;
1017676Shenry 	fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno);
1018676Shenry 	fprintf(sink, s, a1, a2,a3,a4,a5);
1019676Shenry 	fprintf(sink, "\n");
10205827Srrh #undef sink
1021676Shenry }
1022