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