xref: /original-bsd/old/as.vax/asexpr.c (revision fbed46ce)
1 /*
2  *	Copyright (c) 1982 Regents of the University of California
3  */
4 #ifndef lint
5 static char sccsid[] = "@(#)asexpr.c 4.3 02/14/82";
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 #ifdef DEBUG
363 char	*tok_name[LASTTOKEN - FIRSTTOKEN + 1];
364 struct Tok_Desc{
365 	int		tok_which;
366 	char		*tok_name;
367 } tok_desc[] = {
368 	FIRSTTOKEN,	"firsttoken",
369 	ISPACE,		"ispace",
370 	IBYTE,		"ibyte",
371 	IWORD,		"iword",
372 	IINT,		"iint",
373 	ILONG,		"ilong",
374 	IQUAD,		"quad",
375 	IOCTA,		"octa",
376 	IDATA,		"idata",
377 	IGLOBAL,	"iglobal",
378 	ISET,		"iset",
379 	ITEXT,		"itext",
380 	ICOMM,		"icomm",
381 	ILCOMM,		"ilcomm",
382 	IFFLOAT,	"iffloat",
383 	IDFLOAT,	"idfloat",
384 	IGFLOAT,	"igfloat",
385 	IHFLOAT,	"ihfloat",
386 	IORG,		"iorg",
387 	IASCII,		"iascii",
388 	IASCIZ,		"iasciz",
389 	ILSYM,		"ilsym",
390 	IFILE,		"ifile",
391 	ILINENO,	"ilineno",
392 	IABORT,		"iabort",
393 	ISTAB,		"istab",
394 	ISTABSTR,	"istabstr",
395 	ISTABNONE,	"istabnone",
396 	ISTABDOT,	"istabdot",
397 	IJXXX,		"ijxxx",
398 	IALIGN,		"ialign",
399 	INST0,		"inst0",
400 	INSTn,		"instn",
401 	BFINT,		"bfint",
402 	PARSEEOF,	"parseeof",
403 	ILINESKIP,	"ilineskip",
404 	VOID,		"void",
405 	SKIP,		"skip",
406 	INT,		"int",
407 	BIGNUM,		"bignum",
408 	NAME,		"name",
409 	STRING,		"string",
410 	SIZESPEC,	"sizespec",
411 	REG,		"reg",
412 	MUL,		"mul",
413 	LITOP,		"litop",
414 	LP,		"lp",
415 	MP,		"mp",
416 	NEEDSBUF,	"needsbuf",
417 	REGOP,		"regop",
418 	NL,		"nl",
419 	SCANEOF,	"scaneof",
420 	BADCHAR,	"badchar",
421 	SP,		"sp",
422 	ALPH,		"alph",
423 	DIG,		"dig",
424 	SQ,		"sq",
425 	DQ,		"dq",
426 	SH,		"sh",
427 	LSH,		"lsh",
428 	RSH,		"rsh",
429 	MINUS,		"minus",
430 	SIZEQUOTE,	"sizequote",
431 	XOR,		"xor",
432 	DIV,		"div",
433 	SEMI,		"semi",
434 	COLON,		"colon",
435 	PLUS,		"plus",
436 	IOR,		"ior",
437 	AND,		"and",
438 	TILDE,		"tilde",
439 	ORNOT,		"ornot",
440 	CM,		"cm",
441 	LB,		"lb",
442 	RB,		"rb",
443 	RP,		"rp",
444 	LASTTOKEN,	"lasttoken"
445 };
446 /*
447  *	turn a token type into a string
448  */
449 char *tok_to_name(token)
450 {
451 	static	int	fixed = 0;
452 
453 	if (!fixed){
454 		int	i;
455 		for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
456 			tok_name[i] = "NOT ASSIGNED";
457 		for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
458 			tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name;
459 		}
460 		fixed = 1;
461 	}
462 	if (FIRSTTOKEN <= token && token <= LASTTOKEN)
463 		return(tok_name[token]);
464 	else
465 		panic("Unknown token number, %d\n", token);
466 	/*NOTREACHED*/
467 }
468 #endif DEBUG
469