xref: /csrg-svn/old/as.vax/asexpr.c (revision 5823)
1*5823Srrh /*
2*5823Srrh  *	Copyright (c) 1982 Regents of the University of California
3*5823Srrh  */
4*5823Srrh #ifndef lint
5*5823Srrh static char sccsid[] = "@(#)asexpr.c 4.3 02/14/82";
6*5823Srrh 
7*5823Srrh #endif not lint
8593Sbill #include <stdio.h>
9593Sbill #include "as.h"
10*5823Srrh #include "asscan.h"
11593Sbill #include "asexpr.h"
12593Sbill 
13593Sbill /*
14593Sbill  * Tables for combination of operands.
15593Sbill  */
16593Sbill #define	XTXRN	5<<1		/* indexes last row/column when right shifted */
17593Sbill 
18593Sbill /*
19593Sbill  *	table for +
20593Sbill  */
21593Sbill readonly char pltab[6][6] = {
22593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
23593Sbill 
24593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
25593Sbill /*ABS*/		XUNDEF,	XABS,	XTEXT,	XDATA,	XBSS,	XXTRN,
26593Sbill /*TXT*/		XUNDEF,	XTEXT,	ERR,	ERR,	ERR,	ERR,
27593Sbill /*DAT*/		XUNDEF,	XDATA,	ERR,	ERR,	ERR,	ERR,
28593Sbill /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	ERR,	ERR,
29593Sbill /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
30593Sbill };
31593Sbill 
32593Sbill /*
33593Sbill  *	table for -
34593Sbill  */
35593Sbill readonly char mintab[6][6] = {
36593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
37593Sbill 
38593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
39593Sbill /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
40593Sbill /*TXT*/		XUNDEF,	XTEXT,	XABS,	ERR,	ERR,	ERR,
41593Sbill /*DAT*/		XUNDEF,	XDATA,	ERR,	XABS,	ERR,	ERR,
42593Sbill /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	XABS,	ERR,
43593Sbill /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
44593Sbill };
45593Sbill 
46593Sbill /*
47593Sbill  *	table for other operators
48593Sbill  */
49593Sbill readonly char othtab[6][6] = {
50593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
51593Sbill 
52593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
53593Sbill /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
54593Sbill /*TXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
55593Sbill /*DAT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
56593Sbill /*BSS*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
57593Sbill /*EXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
58593Sbill };
59593Sbill 
60*5823Srrh struct exp *combine(op, exp1, exp2)
61*5823Srrh 	reg struct exp *exp1, *exp2;
62593Sbill {
63*5823Srrh 	reg 	e1_type, e2_type;
64*5823Srrh 	reg	back_type;
65*5823Srrh 	char	*btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers";
66593Sbill 
67593Sbill 	lastnam=0; 			/* kludge for jxxx instructions */
68593Sbill 
69630Shenry 	e1_type = exp1->e_xtype&XTYPE;
70630Shenry 	e2_type = exp2->e_xtype&XTYPE;
71593Sbill 
72630Shenry 	if (exp1->e_xtype==XXTRN+XUNDEF)
73593Sbill 		e1_type = XTXRN;
74630Shenry 	if (exp2->e_xtype==XXTRN+XUNDEF)
75593Sbill 		e2_type = XTXRN;
76593Sbill 	if (passno==1)
77630Shenry 		if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
78593Sbill 			e1_type = e2_type = XTXRN;	/* error on != loc ctrs */
79593Sbill 	e1_type >>= 1;		/*dispose of the external (XXTRN) bit*/
80593Sbill 	e2_type >>= 1;
81593Sbill 
82*5823Srrh 	switch(exp1->e_number.num_tag){
83*5823Srrh 	case TYPB:
84*5823Srrh 	case TYPW:
85*5823Srrh 	case TYPL:
86*5823Srrh 		break;
87*5823Srrh 	default:
88*5823Srrh 		yyerror(btype);
89*5823Srrh 		return(exp1);
90*5823Srrh 	}
91*5823Srrh 	switch(exp2->e_number.num_tag){
92*5823Srrh 	case TYPB:
93*5823Srrh 	case TYPW:
94*5823Srrh 	case TYPL:
95*5823Srrh 		break;
96*5823Srrh 	default:
97*5823Srrh 		yyerror(btype);
98*5823Srrh 		return(exp1);
99*5823Srrh 	}
100*5823Srrh 	switch (op){
101593Sbill 	case PLUS:
102630Shenry 		exp1->e_xvalue += exp2->e_xvalue;
103630Shenry 		back_type = pltab[e1_type][e2_type];
104593Sbill 		break;
105593Sbill 	case MINUS:
106630Shenry 		exp1->e_xvalue -= exp2->e_xvalue;
107630Shenry 		back_type = mintab[e1_type][e2_type];
108593Sbill 		break;
109593Sbill 	case IOR:
110630Shenry 		exp1->e_xvalue |= exp2->e_xvalue;
111593Sbill 		goto comm;
112593Sbill 	case XOR:
113630Shenry 		exp1->e_xvalue ^= exp2->e_xvalue;
114593Sbill 		goto comm;
115593Sbill 	case AND:
116630Shenry 		exp1->e_xvalue &= exp2->e_xvalue;
117593Sbill 		goto comm;
118593Sbill 	case ORNOT:
119630Shenry 		exp1->e_xvalue |= ~exp2->e_xvalue;
120593Sbill 		goto comm;
121593Sbill 	case LSH:
122630Shenry 		exp1->e_xvalue <<= exp2->e_xvalue;
123593Sbill 		goto comm;
124593Sbill 	case RSH:
125630Shenry 		exp1->e_xvalue >>= exp2->e_xvalue;
126593Sbill 		goto comm;
127593Sbill 	case TILDE:
128630Shenry 		exp1->e_xvalue |= ~ exp2->e_xvalue;
129593Sbill 		goto comm;
130593Sbill 	case MUL:
131630Shenry 		exp1->e_xvalue *= exp2->e_xvalue;
132593Sbill 		goto comm;
133593Sbill 	case DIV:
134630Shenry 		if (exp2->e_xvalue == 0)
135593Sbill 			yyerror("Divide check");
136593Sbill 		else
137630Shenry 			exp1->e_xvalue /= exp2->e_xvalue;
138593Sbill 		goto comm;
139593Sbill 	case REGOP:
140630Shenry 		if (exp2->e_xvalue == 0)
141593Sbill 			yyerror("Divide check (modulo)");
142593Sbill 		else
143630Shenry 			exp1->e_xvalue %= exp2->e_xvalue;
144593Sbill 		goto comm;
145593Sbill 
146593Sbill 	comm:
147630Shenry 		back_type = othtab[e1_type][e2_type];
148593Sbill 		break;
149593Sbill 	default:
150593Sbill 		yyerror("Internal error: unknown operator");
151593Sbill 	}
152593Sbill 
153593Sbill 	if (e2_type==(XTXRN>>1))
154630Shenry 		exp1->e_xname = exp2->e_xname;
155630Shenry 	exp1->e_xtype = back_type | (
156630Shenry 			(exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
157630Shenry 	if (back_type==ERR)
158593Sbill 		yyerror("Relocation error");
159593Sbill 	return(exp1);
160593Sbill }
161593Sbill 
162593Sbill buildtokensets()
163593Sbill {
164593Sbill #define clobber(val, set) tokensets[(val)] |= (set)
165593Sbill 
166593Sbill 	clobber(SEMI,	LINSTBEGIN);
167593Sbill 	clobber(NL,	LINSTBEGIN);
168593Sbill 	clobber(INT,	LINSTBEGIN);
169593Sbill 
170593Sbill 	clobber(NAME,	YUKKYEXPRBEG + LINSTBEGIN);
171593Sbill 	clobber(INSTn,	YUKKYEXPRBEG);
172593Sbill 	clobber(INST0,	YUKKYEXPRBEG);
173593Sbill 	clobber(REG,	YUKKYEXPRBEG);
174593Sbill 	clobber(BFINT,	YUKKYEXPRBEG);
175593Sbill 
176593Sbill 	clobber(INT,	SAFEEXPRBEG);
177*5823Srrh 	clobber(BIGNUM,	SAFEEXPRBEG);
178593Sbill 
179593Sbill 	clobber(PLUS,	ADDOPS);
180593Sbill 	clobber(MINUS,	ADDOPS + EBEGOPS);
181593Sbill 
182593Sbill 	clobber(LP,	EBEGOPS);
183593Sbill 
184593Sbill 	clobber(IOR,	BOOLOPS);
185593Sbill 	clobber(XOR,	BOOLOPS);
186593Sbill 	clobber(AND,	BOOLOPS);
187593Sbill 	clobber(ORNOT,	BOOLOPS);
188593Sbill 
189593Sbill 	clobber(TILDE,	MULOPS + EBEGOPS);
190593Sbill 	clobber(LSH,	MULOPS);
191593Sbill 	clobber(RSH,	MULOPS);
192593Sbill 	clobber(MUL,	MULOPS);
193593Sbill 	clobber(DIV,	MULOPS);
194593Sbill 	clobber(REGOP,	MULOPS);	/* % */
195593Sbill 
196593Sbill }
197593Sbill 
198593Sbill /*
199593Sbill  *	We keep the current token class in this global variable, so
200593Sbill  *	the recursive descent expression analyzers can talk amongst
201593Sbill  *	themselves, and so that we may use the macros shift and shift over
202593Sbill  */
203593Sbill 
204593Sbill extern	int	yylval;		/*the value of the lexical value*/
205593Sbill extern	struct	exp	*xp;	/*the next free expression slot*/
206593Sbill 
207*5823Srrh static	inttoktype	val;
208*5823Srrh 
209*5823Srrh /*
210*5823Srrh  *	return the value the read head is sitting on
211*5823Srrh  */
212*5823Srrh inttoktype exprparse(inval, backexpr)
213*5823Srrh 	inttoktype	inval;
214593Sbill 	struct	exp **backexpr;
215593Sbill {
216*5823Srrh 	reg	struct exp *lexpr;
217*5823Srrh 	inttoktype	op;
218593Sbill 
219593Sbill 	val = inval;
220593Sbill 	lexpr = boolterm();
221593Sbill 	while (INTOKSET(val, ADDOPS)){
222593Sbill 		op = val;
223593Sbill 		shift;
224593Sbill 		lexpr = combine(op, lexpr, boolterm());
225593Sbill 	}
226593Sbill 	*backexpr = lexpr;
227593Sbill 	return(val);
228593Sbill }
229593Sbill 
230593Sbill struct exp *boolterm()
231593Sbill {
232*5823Srrh 	reg	struct exp *lexpr;
233*5823Srrh 	inttoktype	op;
234593Sbill 
235593Sbill 	lexpr = term();
236593Sbill 	while(INTOKSET(val, BOOLOPS)){
237593Sbill 		op = val;
238593Sbill 		shift;
239593Sbill 		lexpr = combine(op, lexpr, term());
240593Sbill 	}
241593Sbill 	return(lexpr);
242593Sbill }
243593Sbill 
244593Sbill struct exp *term()
245593Sbill {
246*5823Srrh 	reg	struct	exp	*lexpr;
247*5823Srrh 	inttoktype	op;
248593Sbill 
249593Sbill 	lexpr = factor();
250593Sbill 	while(INTOKSET(val, MULOPS)){
251593Sbill 		op = val;
252593Sbill 		shift;
253593Sbill 		lexpr = combine(op, lexpr, factor());
254593Sbill 	}
255593Sbill 	return(lexpr);
256593Sbill }
257593Sbill 
258593Sbill struct exp *factor()
259593Sbill {
260593Sbill 	struct	exp *lexpr;
261*5823Srrh 	inttoktype	op;
262593Sbill 	extern		int	droppedLP;	/*called exprparse after consuming an LP*/
263593Sbill 
264593Sbill 	if (val == LP || droppedLP){
265593Sbill 		if (droppedLP)
266593Sbill 			droppedLP = 0;
267593Sbill 		else
268593Sbill 			shift;		/*the LP*/
269593Sbill 		val = exprparse(val, &lexpr);
270593Sbill 		if (val != RP)
271593Sbill 			yyerror("right parenthesis expected");
272593Sbill 		else
273593Sbill 			shift;
274593Sbill 	} else
275593Sbill 	if (INTOKSET(val, YUKKYEXPRBEG)){
276593Sbill 		lexpr = yukkyexpr(val, yylval);
277593Sbill 		shift;
278593Sbill 	}
279593Sbill 	else if (INTOKSET(val, SAFEEXPRBEG)){
280593Sbill 		lexpr = (struct exp *)yylval;
281593Sbill 		shift;
282593Sbill 	}
283593Sbill 	else if ( (val == TILDE) || (val == MINUS) ){
284593Sbill 		op = val;
285593Sbill 		shift;
286593Sbill 		lexpr = xp++;
287630Shenry 		lexpr->e_xtype = XABS;
288*5823Srrh 		lexpr->e_number = Znumber;
289*5823Srrh 		lexpr->e_number.num_tag = TYPL;
290593Sbill 		lexpr = combine(op, lexpr, factor());
291*5823Srrh 	} else {
292593Sbill 		yyerror("Bad expression syntax");
293593Sbill 		lexpr = xp++;
294630Shenry 		lexpr->e_xtype = XABS;
295*5823Srrh 		lexpr->e_number = Znumber;
296*5823Srrh 		lexpr->e_number.num_tag = TYPL;
297593Sbill 	}
298593Sbill 	return(lexpr);
299593Sbill }
300593Sbill 
301593Sbill struct exp *yukkyexpr(val, np)
302593Sbill 	int	val;
303*5823Srrh 	reg	np;
304593Sbill {
305*5823Srrh 	reg	struct exp *locxp;
306*5823Srrh 	extern	int	exprisname;	/*last factor is a name*/
307*5823Srrh 		int	off = 0;
308593Sbill 
309593Sbill 	exprisname = 0;
310593Sbill 	locxp = xp++;
311*5823Srrh 	locxp->e_number = Znumber;
312*5823Srrh 	locxp->e_number.num_tag = TYPL;
313*5823Srrh 
314*5823Srrh 	switch(val){
315*5823Srrh 	case BFINT:
316*5823Srrh 		yylval = ((struct exp *)np)->e_xvalue;
317*5823Srrh 		if (yylval < 0) {
318*5823Srrh 			yylval = -yylval;
319*5823Srrh 			yylval--;
320*5823Srrh 			off = -1;
321*5823Srrh 			if (lgensym[yylval] == 1)
322*5823Srrh 				yyerror("Reference to undefined local label %db", yylval);
323*5823Srrh 		} else {
324*5823Srrh 			yylval--;
325*5823Srrh 			genref[yylval] = 1;
326593Sbill 		}
327*5823Srrh 		(void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
328*5823Srrh 		yylval = np = (int)*lookup(passno == 1);
329*5823Srrh 		lastnam = (struct symtab *)np;
330*5823Srrh 		/* FALLTHROUGH */
331*5823Srrh 	case NAME:
332593Sbill 		exprisname++;
333630Shenry 		locxp->e_xtype = ((struct symtab *)np)->s_type;
334630Shenry 		if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
335630Shenry 			locxp->e_xname = (struct symtab *)np;
336630Shenry 			locxp->e_xvalue = 0;
337593Sbill 			if (passno==1)
338630Shenry 				((struct symtab *)np)->s_type |= XFORW;
339593Sbill 		} else {	/*otherwise, just get the value*/
340630Shenry 			locxp->e_xvalue = ((struct symtab *)np)->s_value;
341630Shenry 			locxp->e_xname = NULL;
342593Sbill 		}
343*5823Srrh 		break;
344*5823Srrh 	default:
345*5823Srrh 		yyerror("Internal Error in yukkyexpr");
346*5823Srrh 		/* FALLTHROUGH */
347*5823Srrh 
348*5823Srrh 	case INSTn:
349*5823Srrh 	case INST0:
350*5823Srrh 	case REG:
351630Shenry 		locxp->e_xtype = XABS;
352630Shenry 		locxp->e_xvalue = ( (int)np) & 0xFF;
353630Shenry 		locxp->e_xloc = 0;
354630Shenry 		locxp->e_xname = NULL;
355*5823Srrh 		break;
356593Sbill 	}
357593Sbill 
358593Sbill 	return(locxp);
359593Sbill }
360593Sbill 
361593Sbill 
362593Sbill #ifdef DEBUG
363593Sbill char	*tok_name[LASTTOKEN - FIRSTTOKEN + 1];
364593Sbill struct Tok_Desc{
365593Sbill 	int		tok_which;
366593Sbill 	char		*tok_name;
367593Sbill } tok_desc[] = {
368*5823Srrh 	FIRSTTOKEN,	"firsttoken",
369*5823Srrh 	ISPACE,		"ispace",
370*5823Srrh 	IBYTE,		"ibyte",
371*5823Srrh 	IWORD,		"iword",
372*5823Srrh 	IINT,		"iint",
373*5823Srrh 	ILONG,		"ilong",
374*5823Srrh 	IQUAD,		"quad",
375*5823Srrh 	IOCTA,		"octa",
376*5823Srrh 	IDATA,		"idata",
377*5823Srrh 	IGLOBAL,	"iglobal",
378*5823Srrh 	ISET,		"iset",
379*5823Srrh 	ITEXT,		"itext",
380*5823Srrh 	ICOMM,		"icomm",
381*5823Srrh 	ILCOMM,		"ilcomm",
382*5823Srrh 	IFFLOAT,	"iffloat",
383*5823Srrh 	IDFLOAT,	"idfloat",
384*5823Srrh 	IGFLOAT,	"igfloat",
385*5823Srrh 	IHFLOAT,	"ihfloat",
386*5823Srrh 	IORG,		"iorg",
387*5823Srrh 	IASCII,		"iascii",
388*5823Srrh 	IASCIZ,		"iasciz",
389*5823Srrh 	ILSYM,		"ilsym",
390*5823Srrh 	IFILE,		"ifile",
391*5823Srrh 	ILINENO,	"ilineno",
392*5823Srrh 	IABORT,		"iabort",
393*5823Srrh 	ISTAB,		"istab",
394*5823Srrh 	ISTABSTR,	"istabstr",
395*5823Srrh 	ISTABNONE,	"istabnone",
396*5823Srrh 	ISTABDOT,	"istabdot",
397*5823Srrh 	IJXXX,		"ijxxx",
398*5823Srrh 	IALIGN,		"ialign",
399*5823Srrh 	INST0,		"inst0",
400*5823Srrh 	INSTn,		"instn",
401*5823Srrh 	BFINT,		"bfint",
402*5823Srrh 	PARSEEOF,	"parseeof",
403*5823Srrh 	ILINESKIP,	"ilineskip",
404*5823Srrh 	VOID,		"void",
405*5823Srrh 	SKIP,		"skip",
406*5823Srrh 	INT,		"int",
407*5823Srrh 	BIGNUM,		"bignum",
408*5823Srrh 	NAME,		"name",
409*5823Srrh 	STRING,		"string",
410*5823Srrh 	SIZESPEC,	"sizespec",
411*5823Srrh 	REG,		"reg",
412*5823Srrh 	MUL,		"mul",
413*5823Srrh 	LITOP,		"litop",
414*5823Srrh 	LP,		"lp",
415*5823Srrh 	MP,		"mp",
416*5823Srrh 	NEEDSBUF,	"needsbuf",
417*5823Srrh 	REGOP,		"regop",
418*5823Srrh 	NL,		"nl",
419*5823Srrh 	SCANEOF,	"scaneof",
420*5823Srrh 	BADCHAR,	"badchar",
421*5823Srrh 	SP,		"sp",
422*5823Srrh 	ALPH,		"alph",
423*5823Srrh 	DIG,		"dig",
424*5823Srrh 	SQ,		"sq",
425*5823Srrh 	DQ,		"dq",
426*5823Srrh 	SH,		"sh",
427*5823Srrh 	LSH,		"lsh",
428*5823Srrh 	RSH,		"rsh",
429*5823Srrh 	MINUS,		"minus",
430*5823Srrh 	SIZEQUOTE,	"sizequote",
431*5823Srrh 	XOR,		"xor",
432*5823Srrh 	DIV,		"div",
433*5823Srrh 	SEMI,		"semi",
434*5823Srrh 	COLON,		"colon",
435*5823Srrh 	PLUS,		"plus",
436*5823Srrh 	IOR,		"ior",
437*5823Srrh 	AND,		"and",
438*5823Srrh 	TILDE,		"tilde",
439*5823Srrh 	ORNOT,		"ornot",
440*5823Srrh 	CM,		"cm",
441*5823Srrh 	LB,		"lb",
442*5823Srrh 	RB,		"rb",
443*5823Srrh 	RP,		"rp",
444*5823Srrh 	LASTTOKEN,	"lasttoken"
445593Sbill };
446593Sbill /*
447593Sbill  *	turn a token type into a string
448593Sbill  */
449593Sbill char *tok_to_name(token)
450593Sbill {
451*5823Srrh 	static	int	fixed = 0;
452*5823Srrh 
453593Sbill 	if (!fixed){
454593Sbill 		int	i;
455593Sbill 		for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
456593Sbill 			tok_name[i] = "NOT ASSIGNED";
457593Sbill 		for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
458593Sbill 			tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name;
459593Sbill 		}
460593Sbill 		fixed = 1;
461593Sbill 	}
462593Sbill 	if (FIRSTTOKEN <= token && token <= LASTTOKEN)
463593Sbill 		return(tok_name[token]);
464593Sbill 	else
465593Sbill 		panic("Unknown token number, %d\n", token);
466593Sbill 	/*NOTREACHED*/
467593Sbill }
468593Sbill #endif DEBUG
469