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