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