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