Add copyright
[unix-history] / usr / src / old / as.vax / asexpr.c
... / ...
CommitLineData
1/*
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.
5 */
6
7#ifndef lint
8static char sccsid[] = "@(#)asexpr.c 5.1 (Berkeley) %G%";
9#endif not lint
10
11#endif not lint
12#include <stdio.h>
13#include "as.h"
14#include "asscan.h"
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
64struct exp *combine(op, exp1, exp2)
65 reg struct exp *exp1, *exp2;
66{
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";
70
71 lastnam=0; /* kludge for jxxx instructions */
72
73 e1_type = exp1->e_xtype&XTYPE;
74 e2_type = exp2->e_xtype&XTYPE;
75
76 if (exp1->e_xtype==XXTRN+XUNDEF)
77 e1_type = XTXRN;
78 if (exp2->e_xtype==XXTRN+XUNDEF)
79 e2_type = XTXRN;
80 if (passno==1)
81 if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
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
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){
105 case PLUS:
106 exp1->e_xvalue += exp2->e_xvalue;
107 back_type = pltab[e1_type][e2_type];
108 break;
109 case MINUS:
110 exp1->e_xvalue -= exp2->e_xvalue;
111 back_type = mintab[e1_type][e2_type];
112 break;
113 case IOR:
114 exp1->e_xvalue |= exp2->e_xvalue;
115 goto comm;
116 case XOR:
117 exp1->e_xvalue ^= exp2->e_xvalue;
118 goto comm;
119 case AND:
120 exp1->e_xvalue &= exp2->e_xvalue;
121 goto comm;
122 case ORNOT:
123 exp1->e_xvalue |= ~exp2->e_xvalue;
124 goto comm;
125 case LSH:
126 exp1->e_xvalue <<= exp2->e_xvalue;
127 goto comm;
128 case RSH:
129 exp1->e_xvalue >>= exp2->e_xvalue;
130 goto comm;
131 case TILDE:
132 exp1->e_xvalue |= ~ exp2->e_xvalue;
133 goto comm;
134 case MUL:
135 exp1->e_xvalue *= exp2->e_xvalue;
136 goto comm;
137 case DIV:
138 if (exp2->e_xvalue == 0)
139 yyerror("Divide check");
140 else
141 exp1->e_xvalue /= exp2->e_xvalue;
142 goto comm;
143 case REGOP:
144 if (exp2->e_xvalue == 0)
145 yyerror("Divide check (modulo)");
146 else
147 exp1->e_xvalue %= exp2->e_xvalue;
148 goto comm;
149
150 comm:
151 back_type = othtab[e1_type][e2_type];
152 break;
153 default:
154 yyerror("Internal error: unknown operator");
155 }
156
157 if (e2_type==(XTXRN>>1))
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)
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);
181 clobber(BIGNUM, SAFEEXPRBEG);
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
211static inttoktype val;
212
213/*
214 * return the value the read head is sitting on
215 */
216inttoktype exprparse(inval, backexpr)
217 inttoktype inval;
218 struct exp **backexpr;
219{
220 reg struct exp *lexpr;
221 inttoktype op;
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{
236 reg struct exp *lexpr;
237 inttoktype op;
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{
250 reg struct exp *lexpr;
251 inttoktype op;
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;
265 inttoktype op;
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++;
291 lexpr->e_xtype = XABS;
292 lexpr->e_number = Znumber;
293 lexpr->e_number.num_tag = TYPL;
294 lexpr = combine(op, lexpr, factor());
295 } else {
296 yyerror("Bad expression syntax");
297 lexpr = xp++;
298 lexpr->e_xtype = XABS;
299 lexpr->e_number = Znumber;
300 lexpr->e_number.num_tag = TYPL;
301 }
302 return(lexpr);
303}
304
305struct exp *yukkyexpr(val, np)
306 int val;
307 reg np;
308{
309 reg struct exp *locxp;
310 extern int exprisname; /*last factor is a name*/
311 int off = 0;
312
313 exprisname = 0;
314 locxp = xp++;
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;
330 }
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:
336 exprisname++;
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;
341 if (passno==1)
342 ((struct symtab *)np)->s_type |= XFORW;
343 } else { /*otherwise, just get the value*/
344 locxp->e_xvalue = ((struct symtab *)np)->s_value;
345 locxp->e_xname = NULL;
346 }
347 break;
348 default:
349 yyerror("Internal Error in yukkyexpr");
350 /* FALLTHROUGH */
351
352 case INSTn:
353 case INST0:
354 case REG:
355 locxp->e_xtype = XABS;
356 locxp->e_xvalue = ( (int)np) & 0xFF;
357 locxp->e_xloc = 0;
358 locxp->e_xname = NULL;
359 break;
360 }
361
362 return(locxp);
363}
364
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
379
380struct Tok_Desc{
381 int tok_which;
382 char *tok_kind;
383 char *tok_name;
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",
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",
482};
483/*
484 * turn a token type into a string
485 */
486char *tok_to_name(token)
487{
488 static int fixed = 0;
489 static char buf[64];
490 static struct Tok_Desc NA = {0, (char *)0, "NOT ASSIGNED"};
491 int i;
492 char *cp;
493
494 if (!fixed){
495 for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
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];
499 }
500 fixed = 1;
501 }
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 {
507 panic("Unknown token number, %d\n", token);
508 /*NOTREACHED*/
509 }
510}