Mercurial > hg-old > index.cgi
comparison old-trunk/lwasm/old/lwasm.c @ 339:eb230fa7d28e
Prepare for migration to hg
author | lost |
---|---|
date | Fri, 19 Mar 2010 02:54:14 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
338:e7885b3ee266 | 339:eb230fa7d28e |
---|---|
1 /* | |
2 lwasm.c | |
3 Copyright © 2009 William Astle | |
4 | |
5 This file is part of LWASM. | |
6 | |
7 LWASM is free software: you can redistribute it and/or modify it under the | |
8 terms of the GNU General Public License as published by the Free Software | |
9 Foundation, either version 3 of the License, or (at your option) any later | |
10 version. | |
11 | |
12 This program is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 more details. | |
16 | |
17 You should have received a copy of the GNU General Public License along with | |
18 this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 Contains random functions used by the assembler | |
22 */ | |
23 | |
24 #define __lwasm_c_seen__ | |
25 #include <config.h> | |
26 | |
27 #include <stdarg.h> | |
28 #include <stdlib.h> | |
29 #include <stdio.h> | |
30 | |
31 #include "lwasm.h" | |
32 #include "util.h" | |
33 #include "expr.h" | |
34 | |
35 int debug_level = 0; | |
36 | |
37 int register_error(asmstate_t *as, lwasm_line_t *l, int pass, const char *fmt, ...) | |
38 { | |
39 lwasm_error_t *e; | |
40 va_list args; | |
41 char errbuff[1024]; | |
42 int r; | |
43 | |
44 if (!l) | |
45 return; | |
46 | |
47 if (as -> passnum != pass) | |
48 return; | |
49 | |
50 va_start(args, fmt); | |
51 | |
52 e = lwasm_alloc(sizeof(lwasm_error_t)); | |
53 | |
54 e -> next = l -> err; | |
55 l -> err = e; | |
56 | |
57 as -> errorcount++; | |
58 | |
59 r = vsnprintf(errbuff, 1024, fmt, args); | |
60 e -> mess = lwasm_strdup(errbuff); | |
61 | |
62 va_end(args); | |
63 | |
64 return r; | |
65 } | |
66 | |
67 void lwasm_emit(asmstate_t *as, lwasm_line_t *l, int b) | |
68 { | |
69 as -> addr += 1; | |
70 as -> addr &= 0xffff; | |
71 | |
72 if (as -> outformat == OUTPUT_OBJ && !(as -> csect)) | |
73 { | |
74 register_error(as, l, 1, "Output not allowed outside sections with obj target"); | |
75 return; | |
76 } | |
77 if (as -> outformat == OUTPUT_OBJ && as -> csect -> flags & SECTION_BSS) | |
78 { | |
79 register_error(as, l, 1, "Output not allowed inside BSS sections"); | |
80 return; | |
81 } | |
82 | |
83 if (as -> outformat == OUTPUT_OS9 && as -> inmod == 0) | |
84 { | |
85 register_error(as, l, 1, "Output not allowed outside of module in OS9 mode"); | |
86 return; | |
87 } | |
88 | |
89 if (as -> passnum == 1) | |
90 return; | |
91 | |
92 | |
93 if (l -> codelen >= l -> codesize) | |
94 { | |
95 l -> bytes = realloc(l -> bytes, l -> codesize + 16); | |
96 l -> codesize += 16; | |
97 } | |
98 l -> bytes[l -> codelen] = b & 0xff; | |
99 l -> codelen += 1; | |
100 | |
101 if (as -> outformat == OUTPUT_OS9 && as -> inmod) | |
102 { | |
103 // calc the CRC | |
104 // this is a direct transliteration from the nitros9 asm source | |
105 // to C; it can, no doubt, be optimized for 32 bit processing | |
106 b &= 0xff; | |
107 | |
108 b ^= (as -> crc)[0]; | |
109 (as -> crc)[0] = (as -> crc)[1]; | |
110 (as -> crc)[1] = (as -> crc)[2]; | |
111 (as -> crc)[1] ^= (b >> 7); | |
112 (as -> crc)[2] = (b << 1); | |
113 (as -> crc)[1] ^= (b >> 2); | |
114 (as -> crc)[2] ^= (b << 6); | |
115 b ^= (b << 1); | |
116 b ^= (b << 2); | |
117 b ^= (b << 4); | |
118 if (b & 0x80) | |
119 { | |
120 (as -> crc)[0] ^= 0x80; | |
121 (as -> crc)[2] ^= 0x21; | |
122 } | |
123 } | |
124 } | |
125 | |
126 void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o) | |
127 { | |
128 if (o >= 0x100) | |
129 lwasm_emit(as, l, o >> 8); | |
130 lwasm_emit(as, l, o & 0xff); | |
131 } | |
132 | |
133 int lwasm_lookupreg2(const char *reglist, char **str) | |
134 { | |
135 int rval = 0; | |
136 | |
137 while (*reglist) | |
138 { | |
139 if (toupper(**str) == *reglist) | |
140 { | |
141 // first char matches | |
142 if (reglist[1] == ' ' && !isalpha(*(*str + 1))) | |
143 break; | |
144 if (toupper(*(*str + 1)) == reglist[1]) | |
145 break; | |
146 } | |
147 reglist += 2; | |
148 rval++; | |
149 } | |
150 if (!*reglist) | |
151 return -1; | |
152 if (reglist[1] == ' ') | |
153 (*str)++; | |
154 else | |
155 (*str) += 2; | |
156 return rval; | |
157 } | |
158 | |
159 int lwasm_lookupreg3(const char *rlist, const char **str) | |
160 { | |
161 int rval = 0; | |
162 int f = 0; | |
163 const char *reglist = rlist; | |
164 | |
165 while (*reglist) | |
166 { | |
167 if (toupper(**str) == *reglist) | |
168 { | |
169 // first char matches | |
170 if (reglist[1] == ' ') | |
171 { | |
172 f = 1; | |
173 break; | |
174 } | |
175 if (toupper(*(*str + 1)) == reglist[1]) | |
176 { | |
177 // second char matches | |
178 if (reglist[2] == ' ') | |
179 { | |
180 f = 1; | |
181 break; | |
182 } | |
183 if (toupper(*(*str + 2)) == reglist[2]) | |
184 { | |
185 f = 1; | |
186 break; | |
187 } | |
188 } | |
189 } | |
190 reglist += 3; | |
191 rval++; | |
192 } | |
193 if (f == 0) | |
194 return -1; | |
195 | |
196 | |
197 reglist = rval * 3 + rlist; | |
198 if (reglist[1] == ' ') | |
199 (*str) += 1; | |
200 else if (reglist[2] == ' ') | |
201 (*str) += 2; | |
202 else | |
203 (*str)+=3; | |
204 return rval; | |
205 } | |
206 | |
207 struct symstateinfo | |
208 { | |
209 asmstate_t *as; | |
210 lwasm_line_t *l; | |
211 int flags; | |
212 }; | |
213 | |
214 lwasm_expr_stack_t *lwasm_expr_lookup_symbol(char *sym, void *state) | |
215 { | |
216 lwasm_symbol_ent_t *se; | |
217 struct symstateinfo *st; | |
218 lwasm_expr_stack_t *rs; | |
219 lwasm_expr_term_t *t; | |
220 lwasm_expr_stack_node_t *n; | |
221 | |
222 int val; | |
223 | |
224 st = state; | |
225 debug_message(3, "lwasm_expr_lookup_symbol(): find '%s' (context=%d)", sym, st -> as -> context); | |
226 | |
227 // check for special symbols first... | |
228 if (sym[1] == '\0') | |
229 { | |
230 switch (sym[0]) | |
231 { | |
232 // current line address | |
233 case '*': | |
234 case '.': | |
235 val = st -> l -> codeaddr; | |
236 goto retconst; | |
237 | |
238 case '<': | |
239 // previous branch point | |
240 // not implemented | |
241 break; | |
242 case '>': | |
243 // next branch point | |
244 // not implemented | |
245 break; | |
246 } | |
247 } | |
248 | |
249 // look for local symbol first then global symbol | |
250 se = lwasm_find_symbol(st -> as, sym, st -> as -> context); | |
251 if (!se) | |
252 se = lwasm_find_symbol(st -> as, sym, -1); | |
253 debug_message(3, "lwasm_expr_lookup_symbol(): got '%p'", se); | |
254 if (!se) | |
255 { | |
256 register_error(st -> as, st -> l, 2, "Undefined symbol '%s'", sym); | |
257 return NULL; | |
258 } | |
259 // external reference - can not resolve it | |
260 if (se -> flags & SYMBOL_EXTERN) | |
261 { | |
262 return NULL; | |
263 } | |
264 if (st -> flags & EXPR_SECTCONST) | |
265 { | |
266 if (se -> sect == st -> l -> sect) | |
267 { | |
268 if (se -> expr) | |
269 goto retsym; | |
270 val = se -> value; | |
271 goto retconst; | |
272 } | |
273 } | |
274 if (st -> as -> outformat == OUTPUT_OBJ && se -> sect != NULL) | |
275 { | |
276 return NULL; | |
277 } | |
278 if (st -> as -> outformat != OUTPUT_OBJ || se -> sect == NULL) | |
279 { | |
280 // global symbol, intrasegment reference, or not an object target | |
281 val = se -> value; | |
282 goto retconst; | |
283 } | |
284 | |
285 // an intersegment reference will return as NULL (to be resolved at output/link time) | |
286 // if se -> expr is NULL, it has to be an intersegment reference here | |
287 if (se -> expr == NULL) | |
288 { | |
289 return NULL; | |
290 } | |
291 | |
292 retsym: | |
293 // duplicate the expression for return | |
294 rs = lwasm_expr_stack_create(); | |
295 for (n = se -> expr -> head; n; n = n -> next) | |
296 { | |
297 lwasm_expr_stack_push(rs, n -> term); | |
298 } | |
299 return rs; | |
300 | |
301 retconst: | |
302 rs = lwasm_expr_stack_create(); | |
303 t = lwasm_expr_term_create_int(val); | |
304 lwasm_expr_stack_push(rs, t); | |
305 lwasm_expr_term_free(t); | |
306 return rs; | |
307 } | |
308 | |
309 lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp, int flags) | |
310 { | |
311 struct symstateinfo st; | |
312 | |
313 st.as = as; | |
314 st.l = l; | |
315 st.flags = flags; | |
316 | |
317 debug_message(2, "Evaluate expression: %s", inp); | |
318 | |
319 return(lwasm_expr_eval(inp, outp, lwasm_expr_lookup_symbol, &st)); | |
320 } | |
321 | |
322 | |
323 int lwasm_reevaluate_expr(asmstate_t *as, lwasm_line_t *l, lwasm_expr_stack_t *s, int flags) | |
324 { | |
325 struct symstateinfo st; | |
326 | |
327 st.as = as; | |
328 st.l = l; | |
329 st.flags = flags; | |
330 return(lwasm_expr_reval(s, lwasm_expr_lookup_symbol, &st)); | |
331 } | |
332 | |
333 // return 1 if no undefined symbols (externals and incompletes are okay) | |
334 // return 0 if there are undefined symbols | |
335 int lwasm_expr_result_ckconst(asmstate_t *as, lwasm_expr_stack_t *s) | |
336 { | |
337 lwasm_expr_stack_node_t *n; | |
338 lwasm_symbol_ent_t *se; | |
339 | |
340 if (as -> outformat != OUTPUT_OBJ) | |
341 { | |
342 if (lwasm_expr_is_constant(s)) | |
343 return 1; | |
344 else | |
345 return 0; | |
346 } | |
347 | |
348 for (n = s -> head; n; n = n -> next) | |
349 { | |
350 if (n -> term -> term_type == LWASM_TERM_SYM) | |
351 { | |
352 se = lwasm_find_symbol(as, n -> term -> symbol, as -> context); | |
353 if (!se) | |
354 se = lwasm_find_symbol(as, n -> term -> symbol, -1); | |
355 if (!se) | |
356 return 0; | |
357 } | |
358 } | |
359 return 1; | |
360 } | |
361 | |
362 /* | |
363 Evaluate an expression according to the flag value. Return 0 if a constant result was | |
364 obtained, 1 if an incomplete result was obtained, and -1 if an error was flagged. | |
365 | |
366 */ | |
367 int lwasm_expr_result2(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val, int slot) | |
368 { | |
369 lwasm_expr_stack_t *s = NULL; | |
370 const char *ep; | |
371 int rval; | |
372 | |
373 if ((as -> passnum == 1 && !(flag & EXPR_REEVAL)) || slot < 0) | |
374 { | |
375 s = lwasm_evaluate_expr(as, l, *inp, &ep, flag); | |
376 if (slot >= 0) | |
377 { | |
378 l -> exprs[slot] = s; | |
379 l -> exprends[slot] = ep; | |
380 } | |
381 if (!s) | |
382 { | |
383 register_error(as, l, 1, "Bad expression"); | |
384 *val = 0; | |
385 return -1; | |
386 } | |
387 *inp = (char *)ep; | |
388 if (slot >= 0) | |
389 { | |
390 // l -> exprends[slot] = (char *)ep; | |
391 l -> exprvals[slot] = lwasm_expr_get_value(s); | |
392 } | |
393 } | |
394 else if (l -> exprs[slot]) | |
395 { | |
396 s = l -> exprs[slot]; | |
397 lwasm_reevaluate_expr(as, l, s, flag); | |
398 l -> exprvals[slot] = lwasm_expr_get_value(s); | |
399 } | |
400 if (as -> passnum == 2 && slot >= 0) | |
401 *inp = l -> exprends[slot]; | |
402 | |
403 if (s && lwasm_expr_is_constant(s)) | |
404 { | |
405 *val = lwasm_expr_get_value(s); | |
406 lwasm_expr_stack_free(s); | |
407 l -> exprs[slot] = NULL; | |
408 s = NULL; | |
409 return 0; | |
410 } | |
411 | |
412 if (!s && slot >= 0) | |
413 { | |
414 *val = l -> exprvals[slot]; | |
415 return 0; | |
416 } | |
417 else if (!s) | |
418 { | |
419 *val = 0; | |
420 return 0; | |
421 } | |
422 | |
423 // was a constant result on pass 1 requested? | |
424 // that means we must have a constant on either pass | |
425 if (flag & EXPR_PASS1CONST) | |
426 { | |
427 *val = 0; | |
428 if (slot >= 0) | |
429 l -> exprvals[slot] = 0; | |
430 register_error(as, l, 1, "Illegal forward, external, or inter-section reference"); | |
431 lwasm_expr_stack_free(s); | |
432 if (slot >= 0) | |
433 l -> exprs[slot] = NULL; | |
434 return -1; | |
435 } | |
436 | |
437 return 1; | |
438 } | |
439 | |
440 void debug_message(int level, const char *fmt, ...) | |
441 { | |
442 va_list args; | |
443 | |
444 va_start(args, fmt); | |
445 if (debug_level >= level) | |
446 { | |
447 if (level > 0) | |
448 fprintf(stderr, "DEBUG %d: ", level); | |
449 vfprintf(stderr, fmt, args); | |
450 fputc('\n', stderr); | |
451 } | |
452 va_end(args); | |
453 } | |
454 | |
455 int lwasm_next_context(asmstate_t *as) | |
456 { | |
457 int r; | |
458 r = as -> nextcontext; | |
459 as -> nextcontext += 1; | |
460 debug_message(3, "lwasm_next_context(): %d (%d) pass %d", r, as -> nextcontext, as -> passnum); | |
461 return r; | |
462 } | |
463 |