Commit | Line | Data |
---|---|---|
629188b5 JR |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | #include <stdio.h> | |
3 | #include "as.h" | |
4 | #include "asexpr.h" | |
5 | ||
6 | /* | |
7 | * Tables for combination of operands. | |
8 | */ | |
9 | ||
10 | /* | |
11 | * table for + | |
12 | */ | |
13 | readonly char pltab[6][6] = { | |
14 | /* UND ABS TXT DAT BSS EXT */ | |
15 | ||
16 | /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, | |
17 | /*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN, | |
18 | /*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR, | |
19 | /*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR, | |
20 | /*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR, | |
21 | /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, | |
22 | }; | |
23 | ||
24 | /* | |
25 | * table for - | |
26 | */ | |
27 | readonly char mintab[6][6] = { | |
28 | /* UND ABS TXT DAT BSS EXT */ | |
29 | ||
30 | /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, | |
31 | /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, | |
32 | /*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR, | |
33 | /*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR, | |
34 | /*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR, | |
35 | /*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR, | |
36 | }; | |
37 | ||
38 | /* | |
39 | * table for other operators | |
40 | */ | |
41 | readonly char othtab[6][6] = { | |
42 | /* UND ABS TXT DAT BSS EXT */ | |
43 | ||
44 | /*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, | |
45 | /*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR, | |
46 | /*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
47 | /*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
48 | /*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
49 | /*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR, | |
50 | }; | |
51 | ||
52 | struct exp * | |
53 | combine(op, exp1, exp2) | |
54 | register struct exp *exp1, *exp2; | |
55 | { | |
56 | register e1_type, e2_type; | |
57 | register type; | |
58 | ||
59 | lastnam=0; /* kludge for jxxx instructions */ | |
60 | ||
61 | e1_type = exp1->xtype&XTYPE; | |
62 | e2_type = exp2->xtype&XTYPE; | |
63 | ||
64 | if (exp1->xtype==XXTRN+XUNDEF) | |
65 | e1_type = XTXRN; | |
66 | if (exp2->xtype==XXTRN+XUNDEF) | |
67 | e2_type = XTXRN; | |
68 | if (passno==1) | |
69 | if (exp1->xloc!=exp2->xloc && e1_type==e2_type) | |
70 | e1_type = e2_type = XTXRN; /* error on != loc ctrs */ | |
71 | e1_type >>= 1; /*dispost of the external (XXTRN) bit*/ | |
72 | e2_type >>= 1; | |
73 | ||
74 | switch (op) { | |
75 | case PLUS: | |
76 | exp1->xvalue += exp2->xvalue; | |
77 | type = pltab[e1_type][e2_type]; | |
78 | break; | |
79 | case MINUS: | |
80 | exp1->xvalue -= exp2->xvalue; | |
81 | type = mintab[e1_type][e2_type]; | |
82 | break; | |
83 | case IOR: | |
84 | exp1->xvalue |= exp2->xvalue; | |
85 | goto comm; | |
86 | case XOR: | |
87 | exp1->xvalue ^= exp2->xvalue; | |
88 | goto comm; | |
89 | case AND: | |
90 | exp1->xvalue &= exp2->xvalue; | |
91 | goto comm; | |
92 | case ORNOT: | |
93 | exp1->xvalue |= ~exp2->xvalue; | |
94 | goto comm; | |
95 | case LSH: | |
96 | exp1->xvalue <<= exp2->xvalue; | |
97 | goto comm; | |
98 | case RSH: | |
99 | exp1->xvalue >>= exp2->xvalue; | |
100 | goto comm; | |
101 | case TILDE: | |
102 | exp1->xvalue |= ~ exp2->xvalue; | |
103 | goto comm; | |
104 | case MUL: | |
105 | exp1->xvalue *= exp2->xvalue; | |
106 | goto comm; | |
107 | case DIV: | |
108 | if (exp2->xvalue == 0) | |
109 | yyerror("Divide check"); | |
110 | else | |
111 | exp1->xvalue /= exp2->xvalue; | |
112 | goto comm; | |
113 | case REGOP: | |
114 | if (exp2->xvalue == 0) | |
115 | yyerror("Divide check (modulo)"); | |
116 | else | |
117 | exp1->xvalue %= exp2->xvalue; | |
118 | goto comm; | |
119 | ||
120 | comm: | |
121 | type = othtab[e1_type][e2_type]; | |
122 | break; | |
123 | default: | |
124 | yyerror("Internal error: unknown operator"); | |
125 | } | |
126 | ||
127 | if (e2_type==(XTXRN>>1)) | |
128 | exp1->xname = exp2->xname; | |
129 | exp1->xtype = type | ( | |
130 | (exp1->xtype|exp2->xtype) & (XFORW|XXTRN) ); | |
131 | if (type==ERR) | |
132 | yyerror("Relocation error"); | |
133 | return(exp1); | |
134 | } | |
135 | ||
136 | buildtokensets() | |
137 | { | |
138 | #define clobber(val, set) tokensets[(val)] |= (set) | |
139 | ||
140 | clobber(SEMI, LINSTBEGIN); | |
141 | clobber(NL, LINSTBEGIN); | |
142 | ||
143 | clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN); | |
144 | clobber(INSTn, YUKKYEXPRBEG); | |
145 | clobber(INST0, YUKKYEXPRBEG); | |
146 | clobber(REG, YUKKYEXPRBEG); | |
147 | ||
148 | clobber(INT, SAFEEXPRBEG); | |
149 | clobber(FLTNUM, SAFEEXPRBEG); | |
150 | ||
151 | clobber(PLUS, ADDOPS); | |
152 | clobber(MINUS, ADDOPS + EBEGOPS); | |
153 | ||
154 | clobber(LP, EBEGOPS); | |
155 | ||
156 | clobber(IOR, BOOLOPS); | |
157 | clobber(XOR, BOOLOPS); | |
158 | clobber(AND, BOOLOPS); | |
159 | clobber(ORNOT, BOOLOPS); | |
160 | ||
161 | clobber(TILDE, MULOPS + EBEGOPS); | |
162 | clobber(LSH, MULOPS); | |
163 | clobber(RSH, MULOPS); | |
164 | clobber(MUL, MULOPS); | |
165 | clobber(DIV, MULOPS); | |
166 | clobber(REGOP, MULOPS); /* % */ | |
167 | } | |
168 | ||
169 | /* | |
170 | * We keep the current token class in this global variable, so | |
171 | * the recursive descent expression analyzers can talk amongst | |
172 | * themselves, and so that we may use the macros shift and shift over | |
173 | */ | |
174 | ||
175 | extern int yylval; /*the value of the lexical value*/ | |
176 | extern struct exp *xp; /*the next free expression slot*/ | |
177 | ||
178 | static int val; | |
179 | int exprparse(inval, backexpr) /*return the value the read head is sitting on*/ | |
180 | int inval; | |
181 | struct exp **backexpr; | |
182 | { | |
183 | register struct exp *lexpr; | |
184 | int op; | |
185 | ||
186 | val = inval; | |
187 | lexpr = boolterm(); | |
188 | while (INTOKSET(val, ADDOPS)){ | |
189 | op = val; | |
190 | shift; | |
191 | lexpr = combine(op, lexpr, boolterm()); | |
192 | } | |
193 | *backexpr = lexpr; | |
194 | return(val); | |
195 | } | |
196 | ||
197 | struct exp *boolterm() | |
198 | { | |
199 | register struct exp *lexpr; | |
200 | int op; | |
201 | ||
202 | lexpr = term(); | |
203 | while(INTOKSET(val, BOOLOPS)){ | |
204 | op = val; | |
205 | shift; | |
206 | lexpr = combine(op, lexpr, term()); | |
207 | } | |
208 | return(lexpr); | |
209 | } | |
210 | ||
211 | struct exp *term() | |
212 | { | |
213 | register struct exp *lexpr; | |
214 | int op; | |
215 | ||
216 | lexpr = factor(); | |
217 | while(INTOKSET(val, MULOPS)){ | |
218 | op = val; | |
219 | shift; | |
220 | lexpr = combine(op, lexpr, factor()); | |
221 | } | |
222 | return(lexpr); | |
223 | } | |
224 | ||
225 | struct exp *factor() | |
226 | { | |
227 | struct exp *lexpr; | |
228 | int op; | |
229 | extern int droppedLP; /*called exprparse after consuming an LP*/ | |
230 | ||
231 | if (val == LP || droppedLP){ | |
232 | if (droppedLP) | |
233 | droppedLP = 0; | |
234 | else | |
235 | shift; /*the LP*/ | |
236 | val = exprparse(val, &lexpr); | |
237 | if (val != RP) | |
238 | yyerror("right parenthesis expected"); | |
239 | else | |
240 | shift; | |
241 | } else | |
242 | if (INTOKSET(val, YUKKYEXPRBEG)){ | |
243 | lexpr = yukkyexpr(val, yylval); | |
244 | shift; | |
245 | } | |
246 | else if (INTOKSET(val, SAFEEXPRBEG)){ | |
247 | lexpr = (struct exp *)yylval; | |
248 | shift; | |
249 | } | |
250 | else if ( (val == TILDE) || (val == MINUS) ){ | |
251 | op = val; | |
252 | shift; | |
253 | lexpr = xp++; | |
254 | lexpr->xtype = XABS; | |
255 | lexpr->xvalue = 0; | |
256 | lexpr = combine(op, lexpr, factor()); | |
257 | } | |
258 | else { | |
259 | yyerror("Bad expression syntax"); | |
260 | lexpr = xp++; | |
261 | lexpr->xtype = XABS; | |
262 | lexpr->xvalue = 0; | |
263 | } | |
264 | return(lexpr); | |
265 | } | |
266 | ||
267 | struct exp *yukkyexpr(val, np) | |
268 | int val; | |
269 | register np; | |
270 | { | |
271 | register struct exp *locxp; | |
272 | extern int exprisname; /*last factor is a name*/ | |
273 | ||
274 | exprisname = 0; | |
275 | locxp = xp++; | |
276 | if (val == NAME){ | |
277 | exprisname++; | |
278 | locxp->xtype = ((struct symtab *)np)->type; | |
279 | if (( ((struct symtab *)np)->type&XTYPE)==XUNDEF) { /*forward*/ | |
280 | locxp->xname = (struct symtab *)np; | |
281 | locxp->xvalue = 0; | |
282 | if (passno==1) | |
283 | ((struct symtab *)np)->type |= XFORW; | |
284 | } else { /*otherwise, just get the value*/ | |
285 | locxp->xvalue = ((struct symtab *)np)->value; | |
286 | locxp->xname = NULL; | |
287 | } | |
288 | } else { /*INSTn or INST0 or REG*/ | |
289 | locxp->xtype = XABS; | |
290 | locxp->xvalue = ( (int)np) & 0xFF; | |
291 | locxp->xloc = 0; | |
292 | locxp->xname = NULL; | |
293 | } | |
294 | ||
295 | return(locxp); | |
296 | } |