xref: /original-bsd/old/as.vax/asexpr.c (revision 23a40993)
1 /*
2  *	Copyright (c) 1982 Regents of the University of California
3  */
4 #ifndef lint
5 static char sccsid[] = "@(#)asexpr.c 4.5 06/30/83";
6 
7 #endif not lint
8 #include <stdio.h>
9 #include "as.h"
10 #include "asscan.h"
11 #include "asexpr.h"
12 
13 /*
14  * Tables for combination of operands.
15  */
16 #define	XTXRN	5<<1		/* indexes last row/column when right shifted */
17 
18 /*
19  *	table for +
20  */
21 readonly char pltab[6][6] = {
22 /*		UND	ABS	TXT	DAT	BSS	EXT */
23 
24 /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
25 /*ABS*/		XUNDEF,	XABS,	XTEXT,	XDATA,	XBSS,	XXTRN,
26 /*TXT*/		XUNDEF,	XTEXT,	ERR,	ERR,	ERR,	ERR,
27 /*DAT*/		XUNDEF,	XDATA,	ERR,	ERR,	ERR,	ERR,
28 /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	ERR,	ERR,
29 /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
30 };
31 
32 /*
33  *	table for -
34  */
35 readonly char mintab[6][6] = {
36 /*		UND	ABS	TXT	DAT	BSS	EXT */
37 
38 /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
39 /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
40 /*TXT*/		XUNDEF,	XTEXT,	XABS,	ERR,	ERR,	ERR,
41 /*DAT*/		XUNDEF,	XDATA,	ERR,	XABS,	ERR,	ERR,
42 /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	XABS,	ERR,
43 /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
44 };
45 
46 /*
47  *	table for other operators
48  */
49 readonly char othtab[6][6] = {
50 /*		UND	ABS	TXT	DAT	BSS	EXT */
51 
52 /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
53 /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
54 /*TXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
55 /*DAT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
56 /*BSS*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
57 /*EXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
58 };
59 
60 struct exp *combine(op, exp1, exp2)
61 	reg struct exp *exp1, *exp2;
62 {
63 	reg 	e1_type, e2_type;
64 	reg	back_type;
65 	char	*btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers";
66 
67 	lastnam=0; 			/* kludge for jxxx instructions */
68 
69 	e1_type = exp1->e_xtype&XTYPE;
70 	e2_type = exp2->e_xtype&XTYPE;
71 
72 	if (exp1->e_xtype==XXTRN+XUNDEF)
73 		e1_type = XTXRN;
74 	if (exp2->e_xtype==XXTRN+XUNDEF)
75 		e2_type = XTXRN;
76 	if (passno==1)
77 		if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
78 			e1_type = e2_type = XTXRN;	/* error on != loc ctrs */
79 	e1_type >>= 1;		/*dispose of the external (XXTRN) bit*/
80 	e2_type >>= 1;
81 
82 	switch(exp1->e_number.num_tag){
83 	case TYPB:
84 	case TYPW:
85 	case TYPL:
86 		break;
87 	default:
88 		yyerror(btype);
89 		return(exp1);
90 	}
91 	switch(exp2->e_number.num_tag){
92 	case TYPB:
93 	case TYPW:
94 	case TYPL:
95 		break;
96 	default:
97 		yyerror(btype);
98 		return(exp1);
99 	}
100 	switch (op){
101 	case PLUS:
102 		exp1->e_xvalue += exp2->e_xvalue;
103 		back_type = pltab[e1_type][e2_type];
104 		break;
105 	case MINUS:
106 		exp1->e_xvalue -= exp2->e_xvalue;
107 		back_type = mintab[e1_type][e2_type];
108 		break;
109 	case IOR:
110 		exp1->e_xvalue |= exp2->e_xvalue;
111 		goto comm;
112 	case XOR:
113 		exp1->e_xvalue ^= exp2->e_xvalue;
114 		goto comm;
115 	case AND:
116 		exp1->e_xvalue &= exp2->e_xvalue;
117 		goto comm;
118 	case ORNOT:
119 		exp1->e_xvalue |= ~exp2->e_xvalue;
120 		goto comm;
121 	case LSH:
122 		exp1->e_xvalue <<= exp2->e_xvalue;
123 		goto comm;
124 	case RSH:
125 		exp1->e_xvalue >>= exp2->e_xvalue;
126 		goto comm;
127 	case TILDE:
128 		exp1->e_xvalue |= ~ exp2->e_xvalue;
129 		goto comm;
130 	case MUL:
131 		exp1->e_xvalue *= exp2->e_xvalue;
132 		goto comm;
133 	case DIV:
134 		if (exp2->e_xvalue == 0)
135 			yyerror("Divide check");
136 		else
137 			exp1->e_xvalue /= exp2->e_xvalue;
138 		goto comm;
139 	case REGOP:
140 		if (exp2->e_xvalue == 0)
141 			yyerror("Divide check (modulo)");
142 		else
143 			exp1->e_xvalue %= exp2->e_xvalue;
144 		goto comm;
145 
146 	comm:
147 		back_type = othtab[e1_type][e2_type];
148 		break;
149 	default:
150 		yyerror("Internal error: unknown operator");
151 	}
152 
153 	if (e2_type==(XTXRN>>1))
154 		exp1->e_xname = exp2->e_xname;
155 	exp1->e_xtype = back_type | (
156 			(exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
157 	if (back_type==ERR)
158 		yyerror("Relocation error");
159 	return(exp1);
160 }
161 
162 buildtokensets()
163 {
164 #define clobber(val, set) tokensets[(val)] |= (set)
165 
166 	clobber(SEMI,	LINSTBEGIN);
167 	clobber(NL,	LINSTBEGIN);
168 	clobber(INT,	LINSTBEGIN);
169 
170 	clobber(NAME,	YUKKYEXPRBEG + LINSTBEGIN);
171 	clobber(INSTn,	YUKKYEXPRBEG);
172 	clobber(INST0,	YUKKYEXPRBEG);
173 	clobber(REG,	YUKKYEXPRBEG);
174 	clobber(BFINT,	YUKKYEXPRBEG);
175 
176 	clobber(INT,	SAFEEXPRBEG);
177 	clobber(BIGNUM,	SAFEEXPRBEG);
178 
179 	clobber(PLUS,	ADDOPS);
180 	clobber(MINUS,	ADDOPS + EBEGOPS);
181 
182 	clobber(LP,	EBEGOPS);
183 
184 	clobber(IOR,	BOOLOPS);
185 	clobber(XOR,	BOOLOPS);
186 	clobber(AND,	BOOLOPS);
187 	clobber(ORNOT,	BOOLOPS);
188 
189 	clobber(TILDE,	MULOPS + EBEGOPS);
190 	clobber(LSH,	MULOPS);
191 	clobber(RSH,	MULOPS);
192 	clobber(MUL,	MULOPS);
193 	clobber(DIV,	MULOPS);
194 	clobber(REGOP,	MULOPS);	/* % */
195 
196 }
197 
198 /*
199  *	We keep the current token class in this global variable, so
200  *	the recursive descent expression analyzers can talk amongst
201  *	themselves, and so that we may use the macros shift and shift over
202  */
203 
204 extern	int	yylval;		/*the value of the lexical value*/
205 extern	struct	exp	*xp;	/*the next free expression slot*/
206 
207 static	inttoktype	val;
208 
209 /*
210  *	return the value the read head is sitting on
211  */
212 inttoktype exprparse(inval, backexpr)
213 	inttoktype	inval;
214 	struct	exp **backexpr;
215 {
216 	reg	struct exp *lexpr;
217 	inttoktype	op;
218 
219 	val = inval;
220 	lexpr = boolterm();
221 	while (INTOKSET(val, ADDOPS)){
222 		op = val;
223 		shift;
224 		lexpr = combine(op, lexpr, boolterm());
225 	}
226 	*backexpr = lexpr;
227 	return(val);
228 }
229 
230 struct exp *boolterm()
231 {
232 	reg	struct exp *lexpr;
233 	inttoktype	op;
234 
235 	lexpr = term();
236 	while(INTOKSET(val, BOOLOPS)){
237 		op = val;
238 		shift;
239 		lexpr = combine(op, lexpr, term());
240 	}
241 	return(lexpr);
242 }
243 
244 struct exp *term()
245 {
246 	reg	struct	exp	*lexpr;
247 	inttoktype	op;
248 
249 	lexpr = factor();
250 	while(INTOKSET(val, MULOPS)){
251 		op = val;
252 		shift;
253 		lexpr = combine(op, lexpr, factor());
254 	}
255 	return(lexpr);
256 }
257 
258 struct exp *factor()
259 {
260 	struct	exp *lexpr;
261 	inttoktype	op;
262 	extern		int	droppedLP;	/*called exprparse after consuming an LP*/
263 
264 	if (val == LP || droppedLP){
265 		if (droppedLP)
266 			droppedLP = 0;
267 		else
268 			shift;		/*the LP*/
269 		val = exprparse(val, &lexpr);
270 		if (val != RP)
271 			yyerror("right parenthesis expected");
272 		else
273 			shift;
274 	} else
275 	if (INTOKSET(val, YUKKYEXPRBEG)){
276 		lexpr = yukkyexpr(val, yylval);
277 		shift;
278 	}
279 	else if (INTOKSET(val, SAFEEXPRBEG)){
280 		lexpr = (struct exp *)yylval;
281 		shift;
282 	}
283 	else if ( (val == TILDE) || (val == MINUS) ){
284 		op = val;
285 		shift;
286 		lexpr = xp++;
287 		lexpr->e_xtype = XABS;
288 		lexpr->e_number = Znumber;
289 		lexpr->e_number.num_tag = TYPL;
290 		lexpr = combine(op, lexpr, factor());
291 	} else {
292 		yyerror("Bad expression syntax");
293 		lexpr = xp++;
294 		lexpr->e_xtype = XABS;
295 		lexpr->e_number = Znumber;
296 		lexpr->e_number.num_tag = TYPL;
297 	}
298 	return(lexpr);
299 }
300 
301 struct exp *yukkyexpr(val, np)
302 	int	val;
303 	reg	np;
304 {
305 	reg	struct exp *locxp;
306 	extern	int	exprisname;	/*last factor is a name*/
307 		int	off = 0;
308 
309 	exprisname = 0;
310 	locxp = xp++;
311 	locxp->e_number = Znumber;
312 	locxp->e_number.num_tag = TYPL;
313 
314 	switch(val){
315 	case BFINT:
316 		yylval = ((struct exp *)np)->e_xvalue;
317 		if (yylval < 0) {
318 			yylval = -yylval;
319 			yylval--;
320 			off = -1;
321 			if (lgensym[yylval] == 1)
322 				yyerror("Reference to undefined local label %db", yylval);
323 		} else {
324 			yylval--;
325 			genref[yylval] = 1;
326 		}
327 		(void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
328 		yylval = np = (int)*lookup(passno == 1);
329 		lastnam = (struct symtab *)np;
330 		/* FALLTHROUGH */
331 	case NAME:
332 		exprisname++;
333 		locxp->e_xtype = ((struct symtab *)np)->s_type;
334 		if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
335 			locxp->e_xname = (struct symtab *)np;
336 			locxp->e_xvalue = 0;
337 			if (passno==1)
338 				((struct symtab *)np)->s_type |= XFORW;
339 		} else {	/*otherwise, just get the value*/
340 			locxp->e_xvalue = ((struct symtab *)np)->s_value;
341 			locxp->e_xname = NULL;
342 		}
343 		break;
344 	default:
345 		yyerror("Internal Error in yukkyexpr");
346 		/* FALLTHROUGH */
347 
348 	case INSTn:
349 	case INST0:
350 	case REG:
351 		locxp->e_xtype = XABS;
352 		locxp->e_xvalue = ( (int)np) & 0xFF;
353 		locxp->e_xloc = 0;
354 		locxp->e_xname = NULL;
355 		break;
356 	}
357 
358 	return(locxp);
359 }
360 
361 /*
362  *	Print definitions for token kinds
363  */
364 static char pdirect[]	= "directive";
365 static char pinstr[]	= "instruction";
366 static char phunk[]	= "lexeme";
367 static char psmall[]	= "small symbol";
368 static char pcntrl[]	= "control token";
369 
370 #define	DIRECT	pdirect
371 #define	INSTR	pinstr
372 #define	HUNK	phunk
373 #define	SMALL	psmall
374 #define	CNTRL	pcntrl
375 
376 struct Tok_Desc{
377 	int		tok_which;
378 	char		*tok_kind;
379 	char		*tok_name;
380 };
381 struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1];
382 
383 struct Tok_Desc tok_desc[] = {
384 	FIRSTTOKEN,	DIRECT,	"first token",
385 
386 	IBYTE,		DIRECT,	".byte",
387 	IWORD,		DIRECT,	".word",
388 	IINT,		DIRECT,	".int",
389 	ILONG,		DIRECT,	".long",
390 	IQUAD,		DIRECT,	".quad",
391 	IOCTA,		DIRECT,	".octa",
392 	IFFLOAT,	DIRECT,	".ffloat",
393 	IDFLOAT,	DIRECT,	".dfloat",
394 	IGFLOAT,	DIRECT,	".gfloat",
395 	IHFLOAT,	DIRECT,	".hfloat",
396 	IASCII,		DIRECT,	".ascii",
397 	IASCIZ,		DIRECT,	".asciz",
398 	IFILL,		DIRECT,	".fill",
399 	ISPACE,		DIRECT,	".space",
400 
401 	IDATA,		DIRECT,	".data",
402 	ITEXT,		DIRECT,	".text",
403 	IGLOBAL,	DIRECT,	".global",
404 	IALIGN,		DIRECT,	".align",
405 
406 	ISET,		DIRECT,	".set",
407 	ICOMM,		DIRECT,	".comm",
408 	ILCOMM,		DIRECT,	".lcomm",
409 	IORG,		DIRECT,	".org",
410 	ILSYM,		DIRECT,	".lsym",
411 
412 	ISTAB,		DIRECT,	".stab",
413 	ISTABSTR,	DIRECT,	".stabstr",
414 	ISTABNONE,	DIRECT,	".stabnone",
415 	ISTABDOT,	DIRECT,	".stabdot",
416 
417 	IFILE,		DIRECT,	".file",
418 	ILINENO,	DIRECT,	".lineno",
419 	IABORT,		DIRECT,	".abort",
420 
421 	IJXXX,		INSTR,	"jump pseudo",
422 	INST0,		INSTR,	"0 argument inst",
423 	INSTn,		INSTR,	"n argument inst",
424 
425 	PARSEEOF,	CNTRL,	"parse end of file",
426 	ILINESKIP,	CNTRL,	"skip lines",
427 	VOID,		CNTRL,	"void",
428 	SKIP,		CNTRL,	"skip",
429 	NL,		CNTRL,	"new line",
430 	SCANEOF,	CNTRL,	"scanner end of file",
431 	BADCHAR,	CNTRL,	"bad character",
432 	SH,		CNTRL,	"comment, #",
433 
434 	INT,		HUNK,	"int",
435 	BFINT,		HUNK,	"local label",
436 	BIGNUM,		HUNK,	"big number",
437 	NAME,		HUNK,	"name",
438 	STRING,		HUNK,	"string",
439 	REG,		HUNK,	"register specifier",
440 
441 	SIZESPEC,	SMALL,	"size specifier, [BWLbwl]",
442 	SIZEQUOTE,	SMALL,	"sizequote, [^']",
443 	LITOP,		SMALL,	"litop",
444 
445 	MP,		SMALL,	"minus parenthesis, -(",
446 	REGOP,		SMALL,	"register operator, %",
447 
448 	SP,		SMALL,	"space",
449 	ALPH,		SMALL,	"alphabetic character, [A-Za-z_]",
450 	DIG,		SMALL,	"digit character, [A-Fa-f0-9]",
451 
452 	SQ,		SMALL,	"single quote, '",
453 	DQ,		SMALL,	"double quote, \"",
454 
455 	LSH,		SMALL,	"arithmetic left shift, <",
456 	RSH,		SMALL,	"arithmetic right shift, >",
457 	XOR,		SMALL,	"exclusive or, ^",
458 
459 	PLUS,		SMALL,	"plus, +",
460 	MINUS,		SMALL,	"minus, -",
461 	MUL,		SMALL,	"multiply, *",
462 	DIV,		SMALL,	"divide, /",
463 	SEMI,		SMALL,	"semi colon, ;",
464 	COLON,		SMALL,	"colon, :",
465 	IOR,		SMALL,	"inclusive or, |",
466 	AND,		SMALL,	"and, &",
467 
468 	TILDE,		SMALL,	"one's complement, ~",
469 	ORNOT,		SMALL,	"ornot, !",
470 	CM,		SMALL,	"comma",
471 
472 	LB,		SMALL,	"left bracket, [",
473 	RB,		SMALL,	"right bracket, ]",
474 	LP,		SMALL,	"left parenthesis, (",
475 	RP,		SMALL,	"right parentheis, )",
476 
477 	LASTTOKEN,	SMALL,	"last token",
478 };
479 /*
480  *	turn a token type into a string
481  */
482 char *tok_to_name(token)
483 {
484 	static	int	fixed = 0;
485 	static	char	buf[64];
486 	static	struct	Tok_Desc 	NA = {0, (char *)0, "NOT ASSIGNED"};
487 		int	i;
488 		char	*cp;
489 
490 	if (!fixed){
491 		for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
492 			tok_name[i] = &NA;
493 		for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
494 			tok_name[tok_desc[i].tok_which] = &tok_desc[i];
495 		}
496 		fixed = 1;
497 	}
498 	if (FIRSTTOKEN <= token && token <= LASTTOKEN){
499 		sprintf(buf, "%s %s", tok_name[token]->tok_kind,
500 			tok_name[token]->tok_name);
501 		return(buf);
502 	} else {
503 		panic("Unknown token number, %d\n", token);
504 		/*NOTREACHED*/
505 	}
506 }
507