xref: /original-bsd/old/as.vax/asparse.c (revision 1a56dd2c)
1 /*
2  * Copyright (c) 1982 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)asparse.c	5.3 (Berkeley) 11/17/86";
9 #endif not lint
10 
11 #include <stdio.h>
12 #include "as.h"
13 #include "asscan.h"
14 #include "assyms.h"
15 #include "asexpr.h"
16 
17 int	lgensym[10];
18 char	genref[10];
19 
20 long	bitfield;
21 int	bitoff;
22 int	curlen;			/* current length of literals */
23 
24 /*
25  *	The following three variables are communication between various
26  *	modules to special case a number of things.  They are properly
27  *	categorized as hacks.
28  */
29 extern	struct	symtab *lastnam;/*last name seen by the lexical analyzer*/
30 int	exprisname;		/*last factor in an expression was a name*/
31 int	droppedLP;		/*one is analyzing an expression beginning with*/
32 				/*a left parenthesis, which has already been*/
33 				/*shifted. (Used to parse (<expr>)(rn)*/
34 
35 char	yytext[NCPName+2];	/*the lexical image*/
36 int	yylval;			/*the lexical value; sloppy typing*/
37 struct	Opcode		yyopcode;	/* lexical value for an opcode */
38 Bignum	yybignum;		/* lexical value for a big number */
39 /*
40  *	Expression and argument managers
41  */
42 struct	exp	*xp;		/*next free expression slot, used by expr.c*/
43 struct	exp	explist[NEXP];	/*max of 20 expressions in one opcode*/
44 struct	arg	arglist[NARG];	/*building up operands in instructions*/
45 /*
46  *	Sets to accelerate token discrimination
47  */
48 char	tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
49 
50 static	char	UDotsname[64];	/*name of the assembly source*/
51 
52 yyparse()
53 {
54 	reg	struct	exp	*locxp;
55 		/*
56 		 *	loc1xp and ptrloc1xp are used in the
57 		 * 	expression lookahead
58 		 */
59 		struct	exp	*loc1xp;	/*must be non register*/
60 		struct	exp	**ptrloc1xp = & loc1xp;
61 		struct	exp	*pval;		/*hacking expr:expr*/
62 
63 	reg	struct	symtab	*np;
64 	reg	int		argcnt;
65 
66 	reg	inttoktype	val;		/*what yylex gives*/
67 	reg	inttoktype	auxval;		/*saves val*/
68 
69 	reg	struct 	arg	*ap;		/*first free argument*/
70 
71 	reg	struct	symtab	*p;
72 	reg	struct	symtab	*stpt;
73 
74 		struct	strdesc *stringp;	/*handles string lists*/
75 
76 		int	regno;		/*handles arguments*/
77 		int	*ptrregno = &regno;
78 		int	sawmul;		/*saw * */
79 		int	sawindex;	/*saw [rn]*/
80 		int	sawsize;
81 		int	seg_type; 	/*the kind of segment: data or text*/
82 		int	seg_number;	/*the segment number*/
83 		int	space_value;	/*how much .space needs*/
84 		int	fill_rep;	/*how many reps for .fill */
85 		int	fill_size;	/*how many bytes for .fill */
86 
87 		int	field_width;	/*how wide a field is to be*/
88 		int	field_value;	/*the value to stuff in a field*/
89 		char	*stabname;	/*name of stab dealing with*/
90 		ptrall	stabstart;	/*where the stab starts in the buffer*/
91 		int	reloc_how;	/* how to relocate expressions */
92 		int	toconv;		/* how to convert bignums */
93 		int	incasetable;	/* set if in a case table */
94 
95 	incasetable = 0;
96 	xp = explist;
97 	ap = arglist;
98 
99 	val = yylex();
100 
101     while (val != PARSEEOF){	/* primary loop */
102 
103 	while (INTOKSET(val, LINSTBEGIN)){
104 		if (val == INT) {
105 			int i = ((struct exp *)yylval)->e_xvalue;
106 			shift;
107 			if (val != COLON){
108 				yyerror("Local label %d is not followed by a ':' for a label definition",
109 					i);
110 				goto  errorfix;
111 			}
112 			if (i < 0 || i > 9) {
113 				yyerror("Local labels are 0-9");
114 				goto errorfix;
115 			}
116 			(void)sprintf(yytext, "L%d\001%d", i, lgensym[i]);
117 			lgensym[i]++;
118 			genref[i] = 0;
119 			yylval = (int)*lookup(passno == 1);
120 			val = NAME;
121 			np = (struct symtab *)yylval;
122 			goto restlab;
123 		}
124 		if (val == NL){
125 			lineno++;
126 			shift;
127 		} else
128 		if (val == SEMI)
129 			shift;
130 		else {	/*its a name, so we have a label or def */
131 			if (val != NAME){
132 				ERROR("Name expected for a label");
133 			}
134 			np = (struct symtab *)yylval;
135 			shiftover(NAME);
136 			if (val != COLON) {
137 				yyerror("\"%s\" is not followed by a ':' for a label definition",
138 					FETCHNAME(np));
139 				goto  errorfix;
140 			}
141 restlab:
142 			shift;
143 			flushfield(NBWD/4);
144 			if ((np->s_type&XTYPE)!=XUNDEF) {
145 				if (  (np->s_type&XTYPE) != dotp->e_xtype
146 				   || np->s_value != dotp->e_xvalue
147 				   || (   passno == 1
148 				       && np->s_index != dotp->e_xloc) ) {
149 					if (passno == 1)
150 						yyerror("%s redefined",
151 							FETCHNAME(np));
152 					else
153 						yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
154 							FETCHNAME(np),
155 							np->s_value,
156 							dotp->e_xvalue);
157 				}
158 			}
159 			np->s_type &= ~(XTYPE|XFORW);
160 			np->s_type |= dotp->e_xtype;
161 			np->s_value = dotp->e_xvalue;
162 			if (passno == 1){
163 				np->s_index = dotp-usedot;
164 				if (FETCHNAME(np)[0] == 'L'){
165 					nlabels++;
166 				}
167 				np->s_tag = LABELID;
168 			}
169 		}	/*end of this being a label*/
170 	}	/*end of consuming all labels, NLs and SEMIS */
171 
172 	xp = explist;
173 	ap = arglist;
174 
175 	/*
176 	 *	process the INSTRUCTION body
177 	 */
178 	switch(val){
179 
180     default:
181 	ERROR("Unrecognized instruction or directive");
182 
183    case IABORT:
184 	shift;
185 	sawabort();
186 	/*NOTREACHED*/
187 	break;
188 
189    case PARSEEOF:
190 	tokptr -= sizeof(bytetoktype);
191 	*tokptr++ = VOID;
192 	tokptr[1] = VOID;
193 	tokptr[2] = PARSEEOF;
194 	break;
195 
196    case IFILE:
197 	shift;
198 	stringp = (struct strdesc *)yylval;
199 	shiftover(STRING);
200 	dotsname = &UDotsname[0];
201 	movestr(dotsname, stringp->sd_string,
202 		min(stringp->sd_strlen, sizeof(UDotsname)));
203 	break;
204 
205    case ILINENO:
206 	shift;		/*over the ILINENO*/
207 	expr(locxp, val);
208 	lineno = locxp->e_xvalue;
209 	break;
210 
211    case ISET: 	/* .set  <name> , <expr> */
212 	shift;
213 	np = (struct symtab *)yylval;
214 	shiftover(NAME);
215 	shiftover(CM);
216 	expr(locxp, val);
217 	np->s_type &= (XXTRN|XFORW);
218 	np->s_type |= locxp->e_xtype&(XTYPE|XFORW);
219 	np->s_value = locxp->e_xvalue;
220 	if (passno==1)
221 		np->s_index = locxp->e_xloc;
222 	if ((locxp->e_xtype&XTYPE) == XUNDEF)
223 		yyerror("Illegal set?");
224 	break;
225 
226    case ILSYM: 	/*.lsym name , expr */
227 	shift;
228 	np = (struct symtab *)yylval;
229 	shiftover(NAME);
230 	shiftover(CM);
231 	expr(locxp, val);
232 	/*
233 	 *	Build the unique occurance of the
234 	 *	symbol.
235 	 *	The character scanner will have
236 	 *	already entered it into the symbol
237 	 *	table, but we should remove it
238 	 */
239 	if (passno == 1){
240 		stpt = (struct symtab *)symalloc();
241 		stpt->s_name = np->s_name;
242 		np->s_tag = OBSOLETE;	/*invalidate original */
243 		nforgotten++;
244 		np = stpt;
245 		if ( (locxp->e_xtype & XTYPE) != XABS)
246 			yyerror("Illegal second argument to lsym");
247 		np->s_value = locxp->e_xvalue;
248 		np->s_type = XABS;
249 		np->s_tag = ILSYM;
250 	}
251 	break;
252 
253    case IGLOBAL: 	/*.globl <name> */
254 	shift;
255 	np = (struct symtab *)yylval;
256 	shiftover(NAME);
257 	np->s_type |= XXTRN;
258 	break;
259 
260    case IDATA: 	/*.data [ <expr> ] */
261    case ITEXT: 	/*.text [ <expr> ] */
262 	seg_type = -val;
263 	shift;
264 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
265 		expr(locxp, val);
266 		seg_type = -seg_type;   /*now, it is positive*/
267 	}
268 
269 	if (seg_type < 0) {	/*there wasn't an associated expr*/
270 		seg_number = 0;
271 		seg_type = -seg_type;
272 	} else {
273 		if (   ((locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
274 		    || (seg_number = locxp->e_xvalue) >= NLOC) {
275 			yyerror("illegal location counter");
276 			seg_number = 0;
277 		}
278 	}
279 	if (seg_type == IDATA)
280 		seg_number += NLOC;
281 	flushfield(NBWD/4);
282 	dotp = &usedot[seg_number];
283 	if (passno==2) {	/* go salt away in pass 2*/
284 		txtfil = usefile[seg_number];
285 		relfil = rusefile[seg_number];
286 	}
287 	break;
288 
289 	/*
290 	 *	Storage filler directives:
291 	 *
292 	 *	.byte	[<exprlist>]
293 	 *
294 	 *	exprlist:  empty | exprlist outexpr
295 	 *	outexpr:   <expr> | <expr> : <expr>
296 	 */
297    case IBYTE:	curlen = NBWD/4; goto elist;
298    case IWORD:	curlen = NBWD/2; goto elist;
299    case IINT:	curlen = NBWD;   goto elist;
300    case ILONG:	curlen = NBWD;   goto elist;
301 
302    elist:
303 	seg_type = val;
304 	shift;
305 
306 	/*
307 	 *	Expression List processing
308 	 */
309 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
310 	    do{
311 		/*
312 		 *	expression list consists of a list of :
313 		 *	<expr>
314 		 *	<expr> : <expr>
315 		 *		(pack expr2 into expr1 bits
316 		 */
317 		expr(locxp, val);
318 		/*
319 		 *	now, pointing at the next token
320 		 */
321 		if (val == COLON){
322 			shiftover(COLON);
323 			expr(pval, val);
324 			if ((locxp->e_xtype & XTYPE) != XABS) /* tekmdp */
325 				yyerror("Width not absolute");
326 			field_width = locxp->e_xvalue;
327 			locxp = pval;
328 			if (bitoff + field_width > curlen)
329 				flushfield(curlen);
330 			if (field_width > curlen)
331 				yyerror("Expression crosses field boundary");
332 		} else {
333 			field_width = curlen;
334 			flushfield(curlen);
335 		}
336 
337 		if ((locxp->e_xtype & XTYPE) != XABS) {
338 			if (bitoff)
339 				yyerror("Illegal relocation in field");
340 			switch(curlen){
341 				case NBWD/4:	reloc_how = TYPB; break;
342 				case NBWD/2:	reloc_how = TYPW; break;
343 				case NBWD:	reloc_how = TYPL; break;
344 			}
345 			if (passno == 1){
346 				dotp->e_xvalue += ty_nbyte[reloc_how];
347 			} else {
348 				outrel(locxp, reloc_how);
349 			}
350 		} else {
351 			/*
352 			 *
353 			 *	See if we are doing a case instruction.
354 			 *	If so, then see if the branch distance,
355 			 *	stored as a word,
356 			 *	is going to loose sig bits.
357 			 */
358 			if (passno == 2 && incasetable){
359 				if (  (locxp->e_xvalue < -32768)
360 				    ||(locxp->e_xvalue > 32767)){
361 					yyerror("Case will branch too far");
362 				}
363 			}
364 			field_value = locxp->e_xvalue & ( (1L << field_width)-1);
365 			bitfield |= field_value << bitoff;
366 			bitoff += field_width;
367 		}
368 		xp = explist;
369 		if (auxval = (val == CM))
370 			shift;
371 	    } while (auxval);
372 	}	/* there existed an expression at all */
373 
374 	flushfield(curlen);
375 	if ( ( curlen == NBWD/4) && bitoff)
376 		dotp->e_xvalue ++;
377 	break;
378 	/*end of case IBYTE, IWORD, ILONG, IINT*/
379 
380    case ISPACE: 	/* .space <expr> */
381 	shift;
382 	expr(locxp, val);
383 	if ((locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
384 		yyerror("Space size not absolute");
385 	space_value = locxp->e_xvalue;
386   ospace:
387 	flushfield(NBWD/4);
388 	{
389 		static char spacebuf[128];
390 		while (space_value > sizeof(spacebuf)){
391 			outs(spacebuf, sizeof(spacebuf));
392 			space_value -= sizeof(spacebuf);
393 		}
394 		outs(spacebuf, space_value);
395 	}
396 	break;
397 
398 	/*
399 	 *	.fill rep, size, value
400 	 *	repeat rep times: fill size bytes with (truncated) value
401 	 *	size must be between 1 and 8
402 	 */
403    case	IFILL:
404 	shift;
405 	expr(locxp, val);
406 	if ( (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
407 		yyerror("Fill repetition count not absolute");
408 	fill_rep = locxp->e_xvalue;
409 	shiftover(CM);
410 	expr(locxp, val);
411 	if ( (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
412 		yyerror("Fill size not absolute");
413 	fill_size = locxp->e_xvalue;
414 	if (fill_size <= 0 || fill_size > 8)
415 		yyerror("Fill count not in in 1..8");
416 	shiftover(CM);
417 	expr(locxp, val);
418 	if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
419 		yyerror("Fill value not absolute");
420 	flushfield(NBWD/4);
421 	dotp->e_xvalue += fill_rep * fill_size;
422 	if (passno == 2) {
423 		while(fill_rep-- > 0)
424 			bwrite((char *)&locxp->e_xvalue, fill_size, txtfil);
425 	}
426 	break;
427 
428    case IASCII:		/* .ascii [ <stringlist> ] */
429    case IASCIZ: 	/* .asciz [ <stringlist> ] */
430 	auxval = val;
431 	shift;
432 	/*
433 	 *	Code to consume a string list
434 	 *
435 	 *	stringlist: empty | STRING | stringlist STRING
436 	 */
437 	while (val == STRING){
438 		int	mystrlen;
439 		flushfield(NBWD/4);
440 		if (bitoff)
441 			dotp->e_xvalue++;
442 		stringp = (struct strdesc *)yylval;
443 		/*
444 		 *	utilize the string scanner cheat;
445 		 *	the scanner appended a null byte on the string,
446 		 *	but didn't charge it to sd_strlen
447 		 */
448 		mystrlen = stringp->sd_strlen;
449 		mystrlen += (auxval == IASCIZ) ? 1 : 0;
450 		if (passno == 2){
451 			if (stringp->sd_place & STR_CORE){
452 				outs(stringp->sd_string, mystrlen);
453 			} else {
454 				int	i, nread;
455 				fseek(strfile, stringp->sd_stroff, 0);
456 				for (i = 0; i < mystrlen;/*VOID*/){
457 					nread = fread(yytext, 1,
458 						min(mystrlen - i,
459 						  sizeof(yytext)), strfile);
460 					outs(yytext, nread);
461 					i += nread;
462 				}
463 			}
464 		} else {
465 			dotp->e_xvalue += mystrlen;
466 		}
467 		shift;		/*over the STRING*/
468 		if (val == CM)	/*could be a split string*/
469 			shift;
470 	}
471 	break;
472 
473    case IORG: 	/* .org <expr> */
474 	shift;
475 	expr(locxp, val);
476 
477 	if ((locxp->e_xtype & XTYPE) == XABS)	/* tekmdp */
478 		orgwarn++;
479 	else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype)
480 		yyerror("Illegal expression to set origin");
481 	space_value = locxp->e_xvalue - dotp->e_xvalue;
482 	if (space_value < 0)
483 		yyerror("Backwards 'org'");
484 	goto ospace;
485 	break;
486 
487 /*
488  *
489  *	Process stabs.  Stabs are created only by the f77
490  *	and the C compiler with the -g flag set.
491  *	We only look at the stab ONCE, during pass 1, and
492  *	virtually remove the stab from the intermediate file
493  *	so it isn't seen during pass2.  This makes for some
494  *	hairy processing to handle labels occuring in
495  *	stab entries, but since most expressions in the
496  *	stab are integral we save lots of time in the second
497  *	pass by not looking at the stabs.
498  *	A stab that is tagged floating will be bumped during
499  *	the jxxx resolution phase.  A stab tagged fixed will
500  *	not be be bumped.
501  *
502  *	.stab:	Old fashioned stabs
503  *	.stabn: For stabs without names
504  *	.stabs:	For stabs with string names
505  *	.stabd: For stabs for line numbers or bracketing,
506  *		without a string name, without
507  *		a final expression.  The value of the
508  *		final expression is taken to be  the current
509  *		location counter, and is patched by the 2nd pass
510  *
511  *	.stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr>
512  *	.stabn		 <expr>, <expr>, <expr>, <expr>
513  *	.stabs   STRING, <expr>, <expr>, <expr>, <expr>
514  *	.stabd		 <expr>, <expr>, <expr> # .
515  */
516    case ISTAB:
517 	yyerror(".stab directive no longer supported");
518 	goto errorfix;
519 
520   tailstab:
521 	expr(locxp, val);
522 	if (! (locxp->e_xvalue & STABTYPS)){
523 		yyerror("Invalid type in %s", stabname);
524 		goto errorfix;
525 	}
526 	stpt->s_ptype = locxp->e_xvalue;
527 	shiftover(CM);
528 	expr(locxp, val);
529 	stpt->s_other = locxp->e_xvalue;
530 	shiftover(CM);
531 	expr(locxp, val);
532 	stpt->s_desc = locxp->e_xvalue;
533 	shiftover(CM);
534 	exprisname = 0;
535 	expr(locxp, val);
536 	p = locxp->e_xname;
537 	if (p == NULL) {	/*absolute expr to begin with*/
538 		stpt->s_value = locxp->e_xvalue;
539 		stpt->s_index = dotp - usedot;
540 		if (exprisname){
541 			stpt->s_type = locxp->e_xtype;
542 			switch(stpt->s_ptype){
543 				case N_LCSYM:
544 					stpt->s_dest = (struct symtab *)exprisname;
545 					stpt->s_type |= STABFLAG;
546 				case N_GSYM:
547 				case N_FNAME:
548 				case N_RSYM:
549 				case N_SSYM:
550 				case N_LSYM:
551 				case N_PSYM:
552 				case N_BCOMM:
553 				case N_ECOMM:
554 				case N_LENG:
555 					stpt->s_tag = STABFIXED;
556 					break;
557 				default:
558 					stpt->s_tag = STABFLOATING;
559 					break;
560 			}
561 		} else
562 			stpt->s_tag = STABFIXED;
563 	}
564 	else {		/*really have a name*/
565 		stpt->s_dest = locxp->e_xname;
566 		stpt->s_index = p->s_index;
567 		stpt->s_type = p->s_type | STABFLAG;
568 		/*
569 		 *	We will assign a more accruate
570 		 *	guess of locxp's location when
571 		 *	we sort the symbol table
572 		 *	The final value of value is
573 		 *	given by stabfix()
574 		 */
575 /*
576  * For exprs of the form (name + value) one needs to remember locxp->e_xvalue
577  * for use in stabfix. The right place to keep this is in stpt->s_value
578  * however this gets corrupted at an unknown point.
579  * As a bandaid hack the value is preserved in s_desc and s_other (a
580  * short and a char). This destroys these two values and will
581  * be fixed. May 19 ,1983 Alastair Fyfe
582  */
583 		if(locxp->e_xvalue) {
584 			stpt->s_other = (locxp->e_xvalue >> 16);
585 			stpt->s_desc =  (locxp->e_xvalue  & 0x0000ffff);
586 			stpt->s_tag = STABFLOATING;
587 		}
588 	}
589 	/*
590 	 *	tokptr now points at one token beyond
591 	 *	the current token stored in val and yylval,
592 	 *	which are the next tokens after the end of
593 	 *	this .stab directive.  This next token must
594 	 *	be either a SEMI or NL, so is of width just
595 	 *	one.  Therefore, to point to the next token
596 	 *	after the end of this stab, just back up one..
597 	 */
598 	buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
599 	break;	/*end of the .stab*/
600 
601    case ISTABDOT:
602 	stabname = ".stabd";
603 	stpt = (struct symtab *)yylval;
604 	/*
605 	 *	We clobber everything after the
606 	 *	.stabd and its pointer... we MUST
607 	 *	be able to get back to this .stabd
608 	 *	so that we can resolve its final value
609 	 */
610 	stabstart = tokptr;
611 	shift;		/*over the ISTABDOT*/
612 	if (passno == 1){
613 		expr(locxp, val);
614 		if (! (locxp->e_xvalue & STABTYPS)){
615 			yyerror("Invalid type in .stabd");
616 			goto errorfix;
617 		}
618 		stpt->s_ptype = locxp->e_xvalue;
619 		shiftover(CM);
620 		expr(locxp, val);
621 		stpt->s_other = locxp->e_xvalue;
622 		shiftover(CM);
623 		expr(locxp, val);
624 		stpt->s_desc = locxp->e_xvalue;
625 		/*
626 		 *
627 		 *	Now, clobber everything but the
628 		 *	.stabd pseudo and the pointer
629 		 *	to its symbol table entry
630 		 *	tokptr points to the next token,
631 		 *	build the skip up to this
632 		 */
633 		buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
634 	}
635 	/*
636 	 *	pass 1:	Assign a good guess for its position
637 	 *		(ensures they are sorted into right place)/
638 	 *	pass 2:	Fix the actual value
639 	 */
640 	stpt->s_value = dotp->e_xvalue;
641 	stpt->s_index = dotp - usedot;
642 	stpt->s_tag = STABFLOATING;	/*although it has no effect in pass 2*/
643 	break;
644 
645    case ISTABNONE:	stabname = ".stabn"; goto shortstab;
646 
647    case ISTABSTR: 	stabname = ".stabs";
648    shortstab:
649 	auxval = val;
650 	if (passno == 2) goto errorfix;
651 	stpt = (struct symtab *)yylval;
652 	stabstart = tokptr;
653 	(bytetoktype *)stabstart -= sizeof(struct symtab *);
654 	(bytetoktype *)stabstart -= sizeof(bytetoktype);
655 	shift;
656 	if (auxval == ISTABSTR){
657 		stringp = (struct strdesc *)yylval;
658 		shiftover(STRING);
659 		stpt->s_name = (char *)stringp;
660 		/*
661 		 *	We want the trailing null included in this string.
662 		 *	We utilize the cheat the string scanner used,
663 		 *	and merely increment the string length
664 		 */
665 		stringp->sd_strlen += 1;
666 		shiftover(CM);
667 	} else {
668 		stpt->s_name = (char *)savestr("\0", 0, STR_BOTH);
669 	}
670 	goto tailstab;
671 	break;
672 
673    case ICOMM:		/* .comm  <name> , <expr> */
674    case ILCOMM: 	/* .lcomm <name> , <expr> */
675 	auxval = val;
676 	shift;
677 	np = (struct symtab *)yylval;
678 	shiftover(NAME);
679 	shiftover(CM);
680 	expr(locxp, val);
681 
682 	if ( (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
683 		yyerror("comm size not absolute");
684 	if (passno == 1 && (np->s_type&XTYPE) != XUNDEF)
685 		yyerror("Redefinition of %s", FETCHNAME(np));
686 	if (passno==1) {
687 		np->s_value = locxp->e_xvalue;
688 		if (auxval == ICOMM)
689 			np->s_type |= XXTRN;
690 		else {
691 			np->s_type &= ~XTYPE;
692 			np->s_type |= XBSS;
693 		}
694 	}
695 	break;
696 
697    case IALIGN: 		/* .align <expr> */
698 	stpt = (struct symtab *)yylval;
699 	shift;
700 	expr(locxp, val);
701 	jalign(locxp, stpt);
702 	break;
703 
704    case INST0: 		/* instructions w/o arguments*/
705 	incasetable = 0;
706 	insout(yyopcode, (struct arg *)0, 0);
707 	shift;
708 	break;
709 
710    case INSTn:		/* instructions with arguments*/
711    case IJXXX: 		/* UNIX style jump instructions */
712 	auxval = val;
713 	/*
714 	 *	Code to process an argument list
715 	 */
716 	ap = arglist;
717 	xp = explist;
718 
719 	shift;		/* bring in the first token for the arg list*/
720 
721 	for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
722 		/*
723 		 *	code to process an argument proper
724 		 */
725 	    sawindex  = sawmul = sawsize = 0;
726 	    {
727 		switch(val) {
728 
729 		   default:
730 		     disp:
731 			if( !(INTOKSET(val,
732 				 EBEGOPS
733 				+YUKKYEXPRBEG
734 				+SAFEEXPRBEG)) ) {
735 				ERROR("expression expected");
736 			}
737 			expr(ap->a_xp,val);
738 		     overdisp:
739 			if ( val == LP || sawsize){
740 				shiftover(LP);
741 				findreg(regno);
742 				shiftover(RP);
743 				ap->a_atype = ADISP;
744 				ap->a_areg1 = regno;
745 			} else {
746 				ap->a_atype = AEXP;
747 				ap->a_areg1 = 0;
748 			}
749 			goto index;
750 
751 		   case SIZESPEC:
752 		     sizespec:
753 			sawsize = yylval;
754 			shift;
755 			goto disp;
756 
757 		   case REG:
758 		   case REGOP:
759 			findreg(regno);
760 			ap->a_atype = AREG;
761 			ap->a_areg1 = regno;
762 			break;
763 
764 		   case MUL:
765 			sawmul = 1;
766 			shift;
767 			if (val == LP) goto base;
768 			if (val == LITOP) goto imm;
769 			if (val == SIZESPEC) goto sizespec;
770 			if (INTOKSET(val,
771 				 EBEGOPS
772 				+YUKKYEXPRBEG
773 				+SAFEEXPRBEG)) goto disp;
774 			ERROR("expression, '(' or '$' expected");
775 			break;
776 
777 		   case LP:
778 		     base:
779 			shift;	/*consume the LP*/
780 			/*
781 			 *	hack the ambiguity of
782 			 *	movl (expr) (rn), ...
783 			 *	note that (expr) could also
784 			 *	be (rn) (by special hole in the
785 			 *	grammar), which we ensure
786 			 *	means register indirection, instead
787 			 *	of an expression with value n
788 			 */
789 			if (val != REG && val != REGOP){
790 				droppedLP = 1;
791 				val = exprparse(val, &(ap->a_xp));
792 				droppedLP = 0;
793 				goto overdisp;
794 			}
795 			findreg(regno);
796 			shiftover(RP);
797 			if (val == PLUS){
798 				shift;
799 				ap->a_atype = AINCR;
800 			} else
801 				ap->a_atype = ABASE;
802 			ap->a_areg1 = regno;
803 			goto index;
804 
805 		   case LITOP:
806 		      imm:
807 			shift;
808 			expr(locxp, val);
809 			ap->a_atype = AIMM;
810 			ap->a_areg1 = 0;
811 			ap->a_xp = locxp;
812 			goto index;
813 
814 		   case MP:
815 			shift;	/* -(reg) */
816 			findreg(regno);
817 			shiftover(RP);
818 			ap->a_atype = ADECR;
819 			ap->a_areg1 = regno;
820 	  index:			/*look for [reg] */
821 			if (val == LB){
822 				shift;
823 				findreg(regno);
824 				shiftover(RB);
825 				sawindex = 1;
826 				ap->a_areg2 = regno;
827 			}
828 			break;
829 
830 		}	/*end of the switch to process an arg*/
831 	    }	/*end of processing an argument*/
832 
833 	    if (sawmul){
834 			/*
835 			 * Make a concession for *(%r)
836 			 * meaning *0(%r)
837 			 */
838 			if (ap->a_atype == ABASE) {
839 				ap->a_atype = ADISP;
840 				xp->e_xtype = XABS;
841 				xp->e_number = Znumber;
842 				xp->e_number.num_tag = TYPL;
843 				xp->e_xloc = 0;
844 				ap->a_xp = xp++;
845 			}
846 			ap->a_atype |= ASTAR;
847 			sawmul = 0;
848 	    }
849 	    if (sawindex){
850 		ap->a_atype |= AINDX;
851 		sawindex = 0;
852 	    }
853 	    ap->a_dispsize = sawsize == 0 ? d124 : sawsize;
854 		if (val != CM) break;
855 		shiftover(CM);
856 	}	/*processing all the arguments*/
857 
858 	if (argcnt > 6){
859 		yyerror("More than 6 arguments");
860 		goto errorfix;
861 	}
862 
863 	/*
864 	 *	See if this is a case instruction,
865 	 *	so we can set up tests on the following
866 	 *	vector of branch displacements
867 	 */
868 	if (yyopcode.Op_eopcode == CORE){
869 		switch(yyopcode.Op_popcode){
870 		case 0x8f:	/* caseb */
871 		case 0xaf:	/* casew */
872 		case 0xcf:	/* casel */
873 			incasetable++;
874 			break;
875 		default:
876 			incasetable = 0;
877 			break;
878 		}
879 	}
880 
881 	insout(yyopcode, arglist,
882 		auxval == INSTn ? argcnt : - argcnt);
883 	break;
884 
885    case IQUAD:		toconv = TYPQ;	goto bignumlist;
886    case IOCTA:		toconv = TYPO;	goto bignumlist;
887 
888    case IFFLOAT:	toconv = TYPF;	goto bignumlist;
889    case IDFLOAT:	toconv = TYPD;	goto bignumlist;
890    case IGFLOAT:	toconv = TYPG;	goto bignumlist;
891    case IHFLOAT:	toconv = TYPH;	goto bignumlist;
892    bignumlist:
893 	/*
894 	 *	eat a list of non 32 bit numbers.
895 	 *	IQUAD and IOCTA can, possibly, return
896 	 *	INT's, if the numbers are "small".
897 	 *
898 	 *	The value of the numbers is coming back
899 	 *	as an expression, NOT in yybignum.
900 	 */
901 	shift;	/* over the opener */
902 	if ((val == BIGNUM) || (val == INT)){
903 		do{
904 			if ((val != BIGNUM) && (val != INT)){
905 				ERROR(ty_float[toconv]
906 				   ? "floating number expected"
907 				   : "integer number expected" );
908 			}
909 			dotp->e_xvalue += ty_nbyte[toconv];
910 			if (passno == 2){
911 				bignumwrite(
912 					((struct exp *)yylval)->e_number,
913 					toconv);
914 			}
915 			xp = explist;
916 			shift;		/* over this number */
917 			if (auxval = (val == CM))
918 				shift;	/* over the comma */
919 		} while (auxval);	/* as long as there are commas */
920 	}
921 	break;
922 	/* end of the case for initialized big numbers */
923     }	/*end of the switch for looking at each reserved word*/
924 
925 	continue;
926 
927    errorfix:
928 	/*
929 	 *	got here by either requesting to skip to the
930 	 *	end of this statement, or by erroring out and
931 	 *	wanting to apply panic mode recovery
932 	 */
933 	while (    (val != NL)
934 		&& (val != SEMI)
935 		&& (val != PARSEEOF)
936 	      ){
937 		shift;
938 	}
939 	if (val == NL)
940 		lineno++;
941 	shift;
942 
943     }	/*end of the loop to read the entire file, line by line*/
944 
945 }	/*end of yyparse*/
946 
947 /*
948  *	Process a register declaration of the form
949  *	% <expr>
950  *
951  *	Note:
952  *		The scanner has already processed funny registers of the form
953  *	%dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
954  *	preceding zero digit).  If there was any space between the % and
955  *	the digit, the scanner wouldn't have recognized it, so we
956  *	hack it out here.
957  */
958 inttoktype funnyreg(val, regnoback)	/*what the read head will sit on*/
959 	inttoktype	val;		/*what the read head is sitting on*/
960 	int	*regnoback;		/*call by return*/
961 {
962 	reg	struct	exp *locxp;
963 		struct	exp *loc1xp;
964 		struct	exp **ptrloc1xp = & loc1xp;
965 
966 	expr(locxp, val);	/*and leave the current read head with value*/
967 	if ( (passno == 2) &&
968 	    (   (locxp->e_xtype & XTYPE) != XABS
969 	     || (locxp->e_xvalue < 0)
970 	     || (locxp->e_xvalue >= 16)
971 	    )
972 	  ){
973 		yyerror("Illegal register");
974 		return(0);
975 	}
976 	*regnoback = locxp->e_xvalue;
977 	return(val);
978 }
979 /*
980  *	Shift over error
981  */
982 shiftoerror(token)
983 	int	token;
984 {
985 	char	*tok_to_name();
986 	yyerror("%s expected", tok_to_name(token));
987 }
988 
989 /*VARARGS1*/
990 yyerror(s, a1, a2,a3,a4,a5)
991 	char	*s;
992 {
993 
994 #define	sink stdout
995 
996 	if (anyerrs == 0 && anywarnings == 0 && ! silent)
997 		fprintf(sink, "Assembler:\n");
998 	anyerrs++;
999 	if (silent)
1000 		return;
1001 	fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
1002 	fprintf(sink, s, a1, a2,a3,a4,a5);
1003 	fprintf(sink, "\n");
1004 #undef sink
1005 }
1006 
1007 /*VARARGS1*/
1008 yywarning(s, a1, a2,a3,a4,a5)
1009 	char	*s;
1010 {
1011 #define	sink stdout
1012 	if (anyerrs == 0 && anywarnings == 0 && ! silent)
1013 		fprintf(sink, "Assembler:\n");
1014 	anywarnings++;
1015 	if (silent)
1016 		return;
1017 	fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno);
1018 	fprintf(sink, s, a1, a2,a3,a4,a5);
1019 	fprintf(sink, "\n");
1020 #undef sink
1021 }
1022