modern syntax for asgops & inits cause Donn's latest ccom rejects the old.
[unix-history] / usr / src / old / as.tahoe / asexpr.c
CommitLineData
60fc276f
SL
1/*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4#ifndef lint
5static 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 */
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 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
144buildtokensets()
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
186extern int yylval; /*the value of the lexical value*/
187extern struct exp *xp; /*the next free expression slot*/
188
189static inttoktype val;
190
191/*
192 * return the value the read head is sitting on
193 */
194inttoktype 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
212struct 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
226struct 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
240struct 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
283struct 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++;
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 */
346static char pdirect[] = "directive";
347static char pinstr[] = "instruction";
348static char phunk[] = "lexeme";
349static char psmall[] = "small symbol";
350static 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
358struct Tok_Desc{
359 int tok_which;
360 char *tok_kind;
361 char *tok_name;
362};
363struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1];
364
365struct 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 */
461char *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 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}