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