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