Commit | Line | Data |
---|---|---|
1a42d599 | 1 | /* Copyright (c) 1980 Regents of the University of California */ |
451260e7 | 2 | static char sccsid[] = "@(#)asexpr.c 4.2 %G%"; |
1a42d599 | 3 | #include <stdio.h> |
1a42d599 BJ |
4 | #include "as.h" |
5 | #include "asexpr.h" | |
6 | ||
7 | /* | |
8 | * Tables for combination of operands. | |
9 | */ | |
10 | #define XTXRN 5<<1 /* indexes last row/column when right shifted */ | |
11 | ||
12 | /* | |
13 | * table for + | |
14 | */ | |
15 | readonly char pltab[6][6] = { | |
16 | /* UND ABS TXT DAT BSS EXT */ | |
17 | ||
18 | /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, | |
19 | /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN, | |
20 | /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR, | |
21 | /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR, | |
22 | /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR, | |
23 | /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, | |
24 | }; | |
25 | ||
26 | /* | |
27 | * table for - | |
28 | */ | |
29 | readonly char mintab[6][6] = { | |
30 | /* UND ABS TXT DAT BSS EXT */ | |
31 | ||
32 | /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, | |
33 | /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, | |
34 | /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR, | |
35 | /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR, | |
36 | /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR, | |
37 | /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, | |
38 | }; | |
39 | ||
40 | /* | |
41 | * table for other operators | |
42 | */ | |
43 | readonly char othtab[6][6] = { | |
44 | /* UND ABS TXT DAT BSS EXT */ | |
45 | ||
46 | /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, | |
47 | /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, | |
48 | /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
49 | /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
50 | /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
51 | /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
52 | }; | |
53 | ||
54 | struct exp * | |
55 | combine(op, exp1, exp2) | |
56 | register struct exp *exp1, *exp2; | |
57 | { | |
58 | register e1_type, e2_type; | |
451260e7 | 59 | register back_type; |
1a42d599 BJ |
60 | |
61 | lastnam=0; /* kludge for jxxx instructions */ | |
62 | ||
451260e7 RH |
63 | e1_type = exp1->e_xtype&XTYPE; |
64 | e2_type = exp2->e_xtype&XTYPE; | |
1a42d599 | 65 | |
451260e7 | 66 | if (exp1->e_xtype==XXTRN+XUNDEF) |
1a42d599 | 67 | e1_type = XTXRN; |
451260e7 | 68 | if (exp2->e_xtype==XXTRN+XUNDEF) |
1a42d599 BJ |
69 | e2_type = XTXRN; |
70 | if (passno==1) | |
451260e7 | 71 | if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type) |
1a42d599 BJ |
72 | e1_type = e2_type = XTXRN; /* error on != loc ctrs */ |
73 | e1_type >>= 1; /*dispose of the external (XXTRN) bit*/ | |
74 | e2_type >>= 1; | |
75 | ||
76 | switch (op) { | |
77 | case PLUS: | |
451260e7 RH |
78 | exp1->e_xvalue += exp2->e_xvalue; |
79 | back_type = pltab[e1_type][e2_type]; | |
1a42d599 BJ |
80 | break; |
81 | case MINUS: | |
451260e7 RH |
82 | exp1->e_xvalue -= exp2->e_xvalue; |
83 | back_type = mintab[e1_type][e2_type]; | |
1a42d599 BJ |
84 | break; |
85 | case IOR: | |
451260e7 | 86 | exp1->e_xvalue |= exp2->e_xvalue; |
1a42d599 BJ |
87 | goto comm; |
88 | case XOR: | |
451260e7 | 89 | exp1->e_xvalue ^= exp2->e_xvalue; |
1a42d599 BJ |
90 | goto comm; |
91 | case AND: | |
451260e7 | 92 | exp1->e_xvalue &= exp2->e_xvalue; |
1a42d599 BJ |
93 | goto comm; |
94 | case ORNOT: | |
451260e7 | 95 | exp1->e_xvalue |= ~exp2->e_xvalue; |
1a42d599 BJ |
96 | goto comm; |
97 | case LSH: | |
451260e7 | 98 | exp1->e_xvalue <<= exp2->e_xvalue; |
1a42d599 BJ |
99 | goto comm; |
100 | case RSH: | |
451260e7 | 101 | exp1->e_xvalue >>= exp2->e_xvalue; |
1a42d599 BJ |
102 | goto comm; |
103 | case TILDE: | |
451260e7 | 104 | exp1->e_xvalue |= ~ exp2->e_xvalue; |
1a42d599 BJ |
105 | goto comm; |
106 | case MUL: | |
451260e7 | 107 | exp1->e_xvalue *= exp2->e_xvalue; |
1a42d599 BJ |
108 | goto comm; |
109 | case DIV: | |
451260e7 | 110 | if (exp2->e_xvalue == 0) |
1a42d599 BJ |
111 | yyerror("Divide check"); |
112 | else | |
451260e7 | 113 | exp1->e_xvalue /= exp2->e_xvalue; |
1a42d599 BJ |
114 | goto comm; |
115 | case REGOP: | |
451260e7 | 116 | if (exp2->e_xvalue == 0) |
1a42d599 BJ |
117 | yyerror("Divide check (modulo)"); |
118 | else | |
451260e7 | 119 | exp1->e_xvalue %= exp2->e_xvalue; |
1a42d599 BJ |
120 | goto comm; |
121 | ||
122 | comm: | |
451260e7 | 123 | back_type = othtab[e1_type][e2_type]; |
1a42d599 BJ |
124 | break; |
125 | default: | |
126 | yyerror("Internal error: unknown operator"); | |
127 | } | |
128 | ||
129 | if (e2_type==(XTXRN>>1)) | |
451260e7 RH |
130 | exp1->e_xname = exp2->e_xname; |
131 | exp1->e_xtype = back_type | ( | |
132 | (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) ); | |
133 | if (back_type==ERR) | |
1a42d599 BJ |
134 | yyerror("Relocation error"); |
135 | return(exp1); | |
136 | } | |
137 | ||
138 | buildtokensets() | |
139 | { | |
140 | #define clobber(val, set) tokensets[(val)] |= (set) | |
141 | ||
142 | clobber(SEMI, LINSTBEGIN); | |
143 | clobber(NL, LINSTBEGIN); | |
144 | clobber(INT, LINSTBEGIN); | |
145 | ||
146 | clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); | |
147 | clobber(INSTn, YUKKYEXPRBEG); | |
148 | clobber(INST0, YUKKYEXPRBEG); | |
149 | clobber(REG, YUKKYEXPRBEG); | |
150 | clobber(BFINT, YUKKYEXPRBEG); | |
151 | ||
152 | clobber(INT, SAFEEXPRBEG); | |
153 | clobber(FLTNUM, SAFEEXPRBEG); | |
154 | ||
155 | clobber(PLUS, ADDOPS); | |
156 | clobber(MINUS, ADDOPS + EBEGOPS); | |
157 | ||
158 | clobber(LP, EBEGOPS); | |
159 | ||
160 | clobber(IOR, BOOLOPS); | |
161 | clobber(XOR, BOOLOPS); | |
162 | clobber(AND, BOOLOPS); | |
163 | clobber(ORNOT, BOOLOPS); | |
164 | ||
165 | clobber(TILDE, MULOPS + EBEGOPS); | |
166 | clobber(LSH, MULOPS); | |
167 | clobber(RSH, MULOPS); | |
168 | clobber(MUL, MULOPS); | |
169 | clobber(DIV, MULOPS); | |
170 | clobber(REGOP, MULOPS); /* % */ | |
171 | ||
172 | } | |
173 | ||
174 | /* | |
175 | * We keep the current token class in this global variable, so | |
176 | * the recursive descent expression analyzers can talk amongst | |
177 | * themselves, and so that we may use the macros shift and shift over | |
178 | */ | |
179 | ||
180 | extern int yylval; /*the value of the lexical value*/ | |
181 | extern struct exp *xp; /*the next free expression slot*/ | |
182 | ||
183 | static int val; | |
184 | int exprparse(inval, backexpr) /*return the value the read head is sitting on*/ | |
185 | int inval; | |
186 | struct exp **backexpr; | |
187 | { | |
188 | register struct exp *lexpr; | |
189 | int op; | |
190 | ||
191 | val = inval; | |
192 | lexpr = boolterm(); | |
193 | while (INTOKSET(val, ADDOPS)){ | |
194 | op = val; | |
195 | shift; | |
196 | lexpr = combine(op, lexpr, boolterm()); | |
197 | } | |
198 | *backexpr = lexpr; | |
199 | return(val); | |
200 | } | |
201 | ||
202 | struct exp *boolterm() | |
203 | { | |
204 | register struct exp *lexpr; | |
205 | int op; | |
206 | ||
207 | lexpr = term(); | |
208 | while(INTOKSET(val, BOOLOPS)){ | |
209 | op = val; | |
210 | shift; | |
211 | lexpr = combine(op, lexpr, term()); | |
212 | } | |
213 | return(lexpr); | |
214 | } | |
215 | ||
216 | struct exp *term() | |
217 | { | |
218 | register struct exp *lexpr; | |
219 | int op; | |
220 | ||
221 | lexpr = factor(); | |
222 | while(INTOKSET(val, MULOPS)){ | |
223 | op = val; | |
224 | shift; | |
225 | lexpr = combine(op, lexpr, factor()); | |
226 | } | |
227 | return(lexpr); | |
228 | } | |
229 | ||
230 | struct exp *factor() | |
231 | { | |
232 | struct exp *lexpr; | |
233 | int op; | |
234 | extern int droppedLP; /*called exprparse after consuming an LP*/ | |
235 | ||
236 | if (val == LP || droppedLP){ | |
237 | if (droppedLP) | |
238 | droppedLP = 0; | |
239 | else | |
240 | shift; /*the LP*/ | |
241 | val = exprparse(val, &lexpr); | |
242 | if (val != RP) | |
243 | yyerror("right parenthesis expected"); | |
244 | else | |
245 | shift; | |
246 | } else | |
247 | if (INTOKSET(val, YUKKYEXPRBEG)){ | |
248 | lexpr = yukkyexpr(val, yylval); | |
249 | shift; | |
250 | } | |
251 | else if (INTOKSET(val, SAFEEXPRBEG)){ | |
252 | lexpr = (struct exp *)yylval; | |
253 | shift; | |
254 | } | |
255 | else if ( (val == TILDE) || (val == MINUS) ){ | |
256 | op = val; | |
257 | shift; | |
258 | lexpr = xp++; | |
451260e7 RH |
259 | lexpr->e_xtype = XABS; |
260 | lexpr->e_xvalue = 0; | |
1a42d599 BJ |
261 | lexpr = combine(op, lexpr, factor()); |
262 | } | |
263 | else { | |
264 | yyerror("Bad expression syntax"); | |
265 | lexpr = xp++; | |
451260e7 RH |
266 | lexpr->e_xtype = XABS; |
267 | lexpr->e_xvalue = 0; | |
1a42d599 BJ |
268 | } |
269 | return(lexpr); | |
270 | } | |
271 | ||
272 | struct exp *yukkyexpr(val, np) | |
273 | int val; | |
274 | register np; | |
275 | { | |
276 | register struct exp *locxp; | |
277 | extern int exprisname; /*last factor is a name*/ | |
278 | ||
279 | exprisname = 0; | |
280 | locxp = xp++; | |
281 | if (val == NAME || val == BFINT){ | |
282 | if (val == BFINT) { | |
283 | int off = 0; | |
451260e7 | 284 | yylval = ((struct exp *)np)->e_xvalue; |
1a42d599 BJ |
285 | if (yylval < 0) { |
286 | yylval = -yylval; | |
287 | yylval--; | |
288 | off = -1; | |
289 | if (lgensym[yylval] == 1) | |
290 | yyerror("Reference to undefined local label %db", yylval); | |
291 | } else { | |
292 | yylval--; | |
293 | genref[yylval] = 1; | |
294 | } | |
295 | sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off); | |
296 | yylval = np = (int)*lookup(passno == 1); | |
297 | lastnam = (struct symtab *)np; | |
298 | } | |
299 | exprisname++; | |
451260e7 RH |
300 | locxp->e_xtype = ((struct symtab *)np)->s_type; |
301 | if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/ | |
302 | locxp->e_xname = (struct symtab *)np; | |
303 | locxp->e_xvalue = 0; | |
1a42d599 | 304 | if (passno==1) |
451260e7 | 305 | ((struct symtab *)np)->s_type |= XFORW; |
1a42d599 | 306 | } else { /*otherwise, just get the value*/ |
451260e7 RH |
307 | locxp->e_xvalue = ((struct symtab *)np)->s_value; |
308 | locxp->e_xname = NULL; | |
1a42d599 BJ |
309 | } |
310 | } else { /*INSTn or INST0 or REG*/ | |
451260e7 RH |
311 | locxp->e_xtype = XABS; |
312 | locxp->e_xvalue = ( (int)np) & 0xFF; | |
313 | locxp->e_xloc = 0; | |
314 | locxp->e_xname = NULL; | |
1a42d599 BJ |
315 | } |
316 | ||
317 | return(locxp); | |
318 | } | |
319 | ||
320 | ||
321 | #ifdef DEBUG | |
322 | char *tok_name[LASTTOKEN - FIRSTTOKEN + 1]; | |
323 | struct Tok_Desc{ | |
324 | int tok_which; | |
325 | char *tok_name; | |
326 | } tok_desc[] = { | |
327 | FIRSTTOKEN, "firsttoken", /* 0 */ | |
328 | ISPACE, "ispace", /* 1 */ | |
329 | IBYTE, "ibyte", /* 2 */ | |
330 | IWORD, "iword", /* 3 */ | |
331 | IINT, "iint", /* 4 */ | |
332 | ILONG, "ilong", /* 5 */ | |
333 | IDATA, "idata", /* 6 */ | |
334 | IGLOBAL, "iglobal", /* 7 */ | |
335 | ISET, "iset", /* 8 */ | |
336 | ITEXT, "itext", /* 9 */ | |
337 | ICOMM, "icomm", /* 10 */ | |
338 | ILCOMM, "ilcomm", /* 11 */ | |
339 | IFLOAT, "ifloat", /* 12 */ | |
340 | IDOUBLE, "idouble", /* 13 */ | |
341 | IORG, "iorg", /* 14 */ | |
342 | IASCII, "iascii", /* 15 */ | |
343 | IASCIZ, "iasciz", /* 16 */ | |
344 | ILSYM, "ilsym", /* 17 */ | |
345 | IFILE, "ifile", /* 18 */ | |
346 | ILINENO, "ilineno", /* 19 */ | |
347 | IABORT, "iabort", /* 20 */ | |
348 | ISTAB, "istab", /* 23 */ | |
349 | ISTABSTR, "istabstr", /* 24 */ | |
350 | ISTABNONE, "istabnone", /* 25 */ | |
351 | ISTABDOT, "istabdot", /* 26 */ | |
352 | IJXXX, "ijxxx", /* 27 */ | |
353 | IALIGN, "ialign", /* 28 */ | |
354 | INST0, "inst0", /* 29 */ | |
355 | INSTn, "instn", /* 30 */ | |
356 | BFINT, "bfint", /* 31 */ | |
357 | PARSEEOF, "parseeof", /* 32 */ | |
358 | ILINESKIP, "ilineskip", /* 33 */ | |
359 | VOID, "void", /* 34 */ | |
360 | SKIP, "skip", /* 35 */ | |
361 | INT, "int", /* 36 */ | |
362 | FLTNUM, "fltnum", /* 37 */ | |
363 | NAME, "name", /* 38 */ | |
364 | STRING, "string", /* 39 */ | |
365 | QUAD, "quad", /* 40 */ | |
366 | SIZESPEC, "sizespec", /* 41 */ | |
367 | REG, "reg", /* 42 */ | |
368 | MUL, "mul", /* 43 */ | |
369 | LITOP, "litop", /* 44 */ | |
370 | LP, "lp", /* 45 */ | |
371 | MP, "mp", /* 46 */ | |
372 | NEEDSBUF, "needsbuf", /* 48 */ | |
373 | REGOP, "regop", /* 49 */ | |
374 | NL, "nl", /* 50 */ | |
375 | SCANEOF, "scaneof", /* 51 */ | |
376 | BADCHAR, "badchar", /* 52 */ | |
377 | SP, "sp", /* 53 */ | |
378 | ALPH, "alph", /* 54 */ | |
379 | DIG, "dig", /* 55 */ | |
380 | SQ, "sq", /* 56 */ | |
381 | DQ, "dq", /* 57 */ | |
382 | SH, "sh", /* 58 */ | |
383 | LSH, "lsh", /* 59 */ | |
384 | RSH, "rsh", /* 60 */ | |
385 | MINUS, "minus", /* 61 */ | |
386 | SIZEQUOTE, "sizequote", /* 62 */ | |
387 | XOR, "xor", /* 64 */ | |
388 | DIV, "div", /* 65 */ | |
389 | SEMI, "semi", /* 66 */ | |
390 | COLON, "colon", /* 67 */ | |
391 | PLUS, "plus", /* 68 */ | |
392 | IOR, "ior", /* 69 */ | |
393 | AND, "and", /* 70 */ | |
394 | TILDE, "tilde", /* 71 */ | |
395 | ORNOT, "ornot", /* 72 */ | |
396 | CM, "cm", /* 73 */ | |
397 | LB, "lb", /* 74 */ | |
398 | RB, "rb", /* 75 */ | |
399 | RP, "rp", /* 76 */ | |
400 | LASTTOKEN, "lasttoken" /* 80 */ | |
401 | }; | |
402 | /* | |
403 | * turn a token type into a string | |
404 | */ | |
405 | static int fixed = 0; | |
406 | char *tok_to_name(token) | |
407 | { | |
408 | if (!fixed){ | |
409 | int i; | |
410 | for (i = FIRSTTOKEN; i <= LASTTOKEN; i++) | |
411 | tok_name[i] = "NOT ASSIGNED"; | |
412 | for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){ | |
413 | tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name; | |
414 | } | |
415 | fixed = 1; | |
416 | } | |
417 | if (FIRSTTOKEN <= token && token <= LASTTOKEN) | |
418 | return(tok_name[token]); | |
419 | else | |
420 | panic("Unknown token number, %d\n", token); | |
421 | /*NOTREACHED*/ | |
422 | } | |
423 | #endif DEBUG |