assembly language source file reading now does end of buffer
[unix-history] / usr / src / old / as.vax / asexpr.c
CommitLineData
f70ab843
RH
1/*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4#ifndef lint
12044a7d 5static char sccsid[] = "@(#)asexpr.c 4.5 %G%";
f70ab843
RH
6
7#endif not lint
1a42d599 8#include <stdio.h>
1a42d599 9#include "as.h"
f70ab843 10#include "asscan.h"
1a42d599
BJ
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
f70ab843
RH
60struct exp *combine(op, exp1, exp2)
61 reg struct exp *exp1, *exp2;
1a42d599 62{
f70ab843
RH
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";
1a42d599
BJ
66
67 lastnam=0; /* kludge for jxxx instructions */
68
451260e7
RH
69 e1_type = exp1->e_xtype&XTYPE;
70 e2_type = exp2->e_xtype&XTYPE;
1a42d599 71
451260e7 72 if (exp1->e_xtype==XXTRN+XUNDEF)
1a42d599 73 e1_type = XTXRN;
451260e7 74 if (exp2->e_xtype==XXTRN+XUNDEF)
1a42d599
BJ
75 e2_type = XTXRN;
76 if (passno==1)
451260e7 77 if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
1a42d599
BJ
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
f70ab843
RH
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){
1a42d599 101 case PLUS:
451260e7
RH
102 exp1->e_xvalue += exp2->e_xvalue;
103 back_type = pltab[e1_type][e2_type];
1a42d599
BJ
104 break;
105 case MINUS:
451260e7
RH
106 exp1->e_xvalue -= exp2->e_xvalue;
107 back_type = mintab[e1_type][e2_type];
1a42d599
BJ
108 break;
109 case IOR:
451260e7 110 exp1->e_xvalue |= exp2->e_xvalue;
1a42d599
BJ
111 goto comm;
112 case XOR:
451260e7 113 exp1->e_xvalue ^= exp2->e_xvalue;
1a42d599
BJ
114 goto comm;
115 case AND:
451260e7 116 exp1->e_xvalue &= exp2->e_xvalue;
1a42d599
BJ
117 goto comm;
118 case ORNOT:
451260e7 119 exp1->e_xvalue |= ~exp2->e_xvalue;
1a42d599
BJ
120 goto comm;
121 case LSH:
451260e7 122 exp1->e_xvalue <<= exp2->e_xvalue;
1a42d599
BJ
123 goto comm;
124 case RSH:
451260e7 125 exp1->e_xvalue >>= exp2->e_xvalue;
1a42d599
BJ
126 goto comm;
127 case TILDE:
451260e7 128 exp1->e_xvalue |= ~ exp2->e_xvalue;
1a42d599
BJ
129 goto comm;
130 case MUL:
451260e7 131 exp1->e_xvalue *= exp2->e_xvalue;
1a42d599
BJ
132 goto comm;
133 case DIV:
451260e7 134 if (exp2->e_xvalue == 0)
1a42d599
BJ
135 yyerror("Divide check");
136 else
451260e7 137 exp1->e_xvalue /= exp2->e_xvalue;
1a42d599
BJ
138 goto comm;
139 case REGOP:
451260e7 140 if (exp2->e_xvalue == 0)
1a42d599
BJ
141 yyerror("Divide check (modulo)");
142 else
451260e7 143 exp1->e_xvalue %= exp2->e_xvalue;
1a42d599
BJ
144 goto comm;
145
146 comm:
451260e7 147 back_type = othtab[e1_type][e2_type];
1a42d599
BJ
148 break;
149 default:
150 yyerror("Internal error: unknown operator");
151 }
152
153 if (e2_type==(XTXRN>>1))
451260e7
RH
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)
1a42d599
BJ
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);
f70ab843 177 clobber(BIGNUM, SAFEEXPRBEG);
1a42d599
BJ
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
f70ab843
RH
207static inttoktype val;
208
209/*
210 * return the value the read head is sitting on
211 */
212inttoktype exprparse(inval, backexpr)
213 inttoktype inval;
1a42d599
BJ
214 struct exp **backexpr;
215{
f70ab843
RH
216 reg struct exp *lexpr;
217 inttoktype op;
1a42d599
BJ
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{
f70ab843
RH
232 reg struct exp *lexpr;
233 inttoktype op;
1a42d599
BJ
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{
f70ab843
RH
246 reg struct exp *lexpr;
247 inttoktype op;
1a42d599
BJ
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;
f70ab843 261 inttoktype op;
1a42d599
BJ
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++;
451260e7 287 lexpr->e_xtype = XABS;
f70ab843
RH
288 lexpr->e_number = Znumber;
289 lexpr->e_number.num_tag = TYPL;
1a42d599 290 lexpr = combine(op, lexpr, factor());
f70ab843 291 } else {
1a42d599
BJ
292 yyerror("Bad expression syntax");
293 lexpr = xp++;
451260e7 294 lexpr->e_xtype = XABS;
f70ab843
RH
295 lexpr->e_number = Znumber;
296 lexpr->e_number.num_tag = TYPL;
1a42d599
BJ
297 }
298 return(lexpr);
299}
300
301struct exp *yukkyexpr(val, np)
302 int val;
f70ab843 303 reg np;
1a42d599 304{
f70ab843
RH
305 reg struct exp *locxp;
306 extern int exprisname; /*last factor is a name*/
307 int off = 0;
1a42d599
BJ
308
309 exprisname = 0;
310 locxp = xp++;
f70ab843
RH
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;
1a42d599 326 }
f70ab843
RH
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:
1a42d599 332 exprisname++;
451260e7
RH
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;
1a42d599 337 if (passno==1)
451260e7 338 ((struct symtab *)np)->s_type |= XFORW;
1a42d599 339 } else { /*otherwise, just get the value*/
451260e7
RH
340 locxp->e_xvalue = ((struct symtab *)np)->s_value;
341 locxp->e_xname = NULL;
1a42d599 342 }
f70ab843
RH
343 break;
344 default:
345 yyerror("Internal Error in yukkyexpr");
346 /* FALLTHROUGH */
347
348 case INSTn:
349 case INST0:
350 case REG:
451260e7
RH
351 locxp->e_xtype = XABS;
352 locxp->e_xvalue = ( (int)np) & 0xFF;
353 locxp->e_xloc = 0;
354 locxp->e_xname = NULL;
f70ab843 355 break;
1a42d599
BJ
356 }
357
358 return(locxp);
359}
360
310f8c15
RH
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
1a42d599 375
1a42d599
BJ
376struct Tok_Desc{
377 int tok_which;
310f8c15 378 char *tok_kind;
1a42d599 379 char *tok_name;
310f8c15
RH
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",
310f8c15
RH
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",
1a42d599
BJ
478};
479/*
480 * turn a token type into a string
481 */
1a42d599
BJ
482char *tok_to_name(token)
483{
f70ab843 484 static int fixed = 0;
310f8c15
RH
485 static char buf[64];
486 static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"};
487 int i;
488 char *cp;
f70ab843 489
1a42d599 490 if (!fixed){
1a42d599 491 for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
310f8c15
RH
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];
1a42d599
BJ
495 }
496 fixed = 1;
497 }
310f8c15
RH
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 {
1a42d599 503 panic("Unknown token number, %d\n", token);
310f8c15
RH
504 /*NOTREACHED*/
505 }
1a42d599 506}