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