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