Mercurial > hg-old > index.cgi
annotate src/pseudo.c @ 47:804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
author | lost |
---|---|
date | Sun, 04 Jan 2009 07:25:03 +0000 |
parents | 34568fab6058 |
children | 21ae0fab469b |
rev | line source |
---|---|
0 | 1 /* |
4
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
2 pseudo.c |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
3 Copyright © 2009 William Astle |
4
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
4 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
5 This file is part of LWASM. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
6 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
7 LWASM is free software: you can redistribute it and/or modify it under the |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
8 terms of the GNU General Public License as published by the Free Software |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
9 Foundation, either version 3 of the License, or (at your option) any later |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
10 version. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
11 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
12 This program is distributed in the hope that it will be useful, but WITHOUT |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
15 more details. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
16 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
17 You should have received a copy of the GNU General Public License along with |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
18 this program. If not, see <http://www.gnu.org/licenses/>. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
19 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
20 |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
21 This file implements the various pseudo operations. |
34568fab6058
Fixed package to include all required files; also added copyright preamble to all source files
lost
parents:
0
diff
changeset
|
22 */ |
0 | 23 |
24 #include <stdlib.h> | |
25 #include "lwasm.h" | |
26 #include "instab.h" | |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
27 #include "expr.h" |
0 | 28 |
29 | |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
30 OPFUNC(pseudo_org) |
0 | 31 { |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
32 int rval; |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
33 lwasm_expr_stack_t *s; |
0 | 34 |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
35 if (l -> sym) |
0 | 36 { |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
37 register_error(as, l, 1, "No symbol allowed with ORG"); |
0 | 38 } |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
39 s = lwasm_evaluate_expr(as, l, *p, NULL); |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
40 if (!s) |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
41 { |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
42 register_error(as, l, 1, "Bad expression"); |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
43 return; |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
44 } |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
45 if (!lwasm_expr_is_constant(s)) |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
46 { |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
47 register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
48 return; |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
49 } |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
50 rval = lwasm_expr_get_value(s); |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
51 l -> codeaddr = rval; |
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
52 as -> addr = rval; |
0 | 53 } |
54 | |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
55 /* |
0 | 56 void pseudo_include(asmstate_t *as, sourceline_t *cl, char **optr) |
57 { | |
58 int v1; | |
59 | |
60 if (as -> passnum != 1) | |
61 return; | |
62 while (**optr && isspace(**optr)) | |
63 (*optr)++; | |
64 if (!**optr) | |
65 { | |
66 register_error(as, cl, ERR_BADFN); | |
67 return; | |
68 } | |
69 for (v1 = 0; *((*optr)+v1) && !isspace(*((*optr)+v1)); v1++) | |
70 ; | |
71 { | |
72 char *fn = malloc(v1 + 1); | |
73 strncpy(fn, *optr, v1); | |
74 fn[v1] = '\0'; | |
75 lwasm_read_file(as, fn); | |
76 } | |
77 } | |
78 | |
79 | |
80 void pseudo_rmb(asmstate_t *as, sourceline_t *cl, char **optr) | |
81 { | |
82 int rval, v1; | |
83 | |
84 rval = eval_expr(as, cl, optr, &v1); | |
85 if (rval < 0) | |
86 { | |
87 errorp1(ERR_FORWARD); | |
88 return; | |
89 } | |
90 if (v1 < 0) | |
91 { | |
92 errorp1(ERR_BADOPER); | |
93 return; | |
94 } | |
95 cl -> len = v1; | |
96 cl -> nocode = 1; | |
97 } | |
98 | |
99 void pseudo_rmd(asmstate_t *as, sourceline_t *cl, char **optr) | |
100 { | |
101 int rval, v1; | |
102 | |
103 rval = eval_expr(as, cl, optr, &v1); | |
104 if (rval < 0) | |
105 { | |
106 errorp1(ERR_FORWARD); | |
107 return; | |
108 } | |
109 if (v1 < 0) | |
110 { | |
111 errorp1(ERR_BADOPER); | |
112 return; | |
113 } | |
114 cl -> len = v1 * 2; | |
115 cl -> nocode = 1; | |
116 } | |
117 | |
118 void pseudo_rmq(asmstate_t *as, sourceline_t *cl, char **optr) | |
119 { | |
120 int rval, v1; | |
121 | |
122 rval = eval_expr(as, cl, optr, &v1); | |
123 if (rval < 0) | |
124 { | |
125 errorp1(ERR_FORWARD); | |
126 return; | |
127 } | |
128 if (v1 < 0) | |
129 { | |
130 errorp1(ERR_BADOPER); | |
131 return; | |
132 } | |
133 cl -> len = v1 * 4; | |
134 cl -> nocode = 1; | |
135 } | |
136 | |
137 void pseudo_zmb(asmstate_t *as, sourceline_t *cl, char **optr) | |
138 { | |
139 int rval, v1; | |
140 | |
141 rval = eval_expr(as, cl, optr, &v1); | |
142 if (rval < 0) | |
143 { | |
144 errorp1(ERR_FORWARD); | |
145 return; | |
146 } | |
147 if (v1 < 0) | |
148 { | |
149 errorp1(ERR_BADOPER); | |
150 return; | |
151 } | |
152 while (v1--) | |
153 emit(0); | |
154 } | |
155 | |
156 void pseudo_zmd(asmstate_t *as, sourceline_t *cl, char **optr) | |
157 { | |
158 int rval, v1; | |
159 | |
160 rval = eval_expr(as, cl, optr, &v1); | |
161 if (rval < 0) | |
162 { | |
163 errorp1(ERR_FORWARD); | |
164 return; | |
165 } | |
166 if (v1 < 0) | |
167 { | |
168 errorp1(ERR_BADOPER); | |
169 return; | |
170 } | |
171 while (v1--) | |
172 { | |
173 emit(0); | |
174 emit(0); | |
175 } | |
176 } | |
177 | |
178 void pseudo_zmq(asmstate_t *as, sourceline_t *cl, char **optr) | |
179 { | |
180 int rval, v1; | |
181 | |
182 rval = eval_expr(as, cl, optr, &v1); | |
183 if (rval < 0) | |
184 { | |
185 errorp1(ERR_FORWARD); | |
186 return; | |
187 } | |
188 if (v1 < 0) | |
189 { | |
190 errorp1(ERR_BADOPER); | |
191 return; | |
192 } | |
193 while (v1--) | |
194 { | |
195 emit(0); | |
196 emit(0); | |
197 emit(0); | |
198 emit(0); | |
199 } | |
200 } | |
201 | |
202 void pseudo_end(asmstate_t *as, sourceline_t *cl, char **optr) | |
203 { | |
204 int rval, v1; | |
205 | |
206 while (**optr && isspace(**optr)) | |
207 ; | |
208 if (**optr && **optr != '*' && **optr != ';') | |
209 { | |
210 rval = eval_expr(as, cl, optr, &v1); | |
211 if (rval < 0) | |
212 { | |
213 errorp1(ERR_FORWARD); | |
214 return; | |
215 } | |
216 } | |
217 else | |
218 { | |
219 v1 = 0; | |
220 } | |
221 if (as -> passnum == 2) | |
222 as -> execaddr = v1; | |
223 } | |
224 | |
225 void pseudo_align(asmstate_t *as, sourceline_t *cl, char **optr) | |
226 { | |
227 int rval, v1; | |
228 int cn; | |
229 | |
230 rval = eval_expr(as, cl, optr, &v1); | |
231 if (rval < 0) | |
232 { | |
233 errorp1(ERR_FORWARD); | |
234 return; | |
235 } | |
236 cn = cl -> addr % v1; | |
237 if (cn) | |
238 cn = v1 - cn; | |
239 | |
240 while (cn) | |
241 { | |
242 emit(0); | |
243 cn--; | |
244 } | |
245 } | |
246 | |
247 void pseudo_equ(asmstate_t *as, sourceline_t *cl, char **optr) | |
248 { | |
249 int rval, v1; | |
250 | |
251 if (cl -> hassym == 0) | |
252 { | |
253 errorp1(ERR_NOSYM); | |
254 return; | |
255 } | |
256 rval = eval_expr(as, cl, optr, &v1); | |
257 // eval_expr returns -1 if there was a forward ref | |
258 // or -2 if the expr was invalid | |
259 if (rval == -2) | |
260 { | |
261 // carp | |
262 errorp1(ERR_FORWARD); | |
263 } | |
264 if (rval < 0) | |
265 { | |
266 // remove symbol ref | |
267 cl -> hassym = 0; | |
268 // mark as a "comment" so it isn't processed next time | |
269 cl -> opcode = -1; | |
270 return; | |
271 } | |
272 cl -> code_symloc = v1; | |
273 cl -> isequ = 1; | |
274 cl -> symaddr = v1 & 0xFFFF; | |
275 } | |
276 | |
277 void pseudo_set(asmstate_t *as, sourceline_t *cl, char **optr) | |
278 { | |
279 int rval, v1; | |
280 | |
281 if (cl -> hassym == 0) | |
282 { | |
283 errorp1(ERR_NOSYM); | |
284 return; | |
285 } | |
286 rval = eval_expr(as, cl, optr, &v1); | |
287 // eval_expr returns -1 if there was a forward ref | |
288 // or -2 if the expr was invalid | |
289 if (rval == -2) | |
290 { | |
291 // carp | |
292 errorp1(ERR_FORWARD); | |
293 } | |
294 if (rval < 0) | |
295 { | |
296 // remove symbol ref | |
297 cl -> hassym = 0; | |
298 // mark as a "comment" so it isn't processed next time | |
299 cl -> opcode = -1; | |
300 return; | |
301 } | |
302 cl -> code_symloc = v1; | |
303 cl -> isset = 1; | |
304 cl -> isequ = 1; | |
305 cl -> symaddr = v1 & 0xFFFF; | |
306 } | |
307 | |
308 void pseudo_setdp(asmstate_t *as, sourceline_t *cl, char **optr) | |
309 { | |
310 int rval, v1; | |
311 | |
312 if (cl -> hassym) | |
313 { | |
314 register_error(as, cl, ERR_SYM); | |
315 cl -> hassym = 0; | |
316 return; | |
317 } | |
318 else | |
319 { | |
320 rval = eval_expr(as, cl, optr, &v1); | |
321 if (rval == -1) | |
322 { | |
323 errorp1(ERR_FORWARD); | |
324 } | |
325 if (rval < 0) | |
326 { | |
327 cl -> opcode = -1; | |
328 return; | |
329 } | |
330 } | |
331 // setdp needs to resolve properly on pass 2 | |
332 if (v1 > 0xff || v1 < 0) | |
333 { | |
334 errorp1(ERR_OVERFLOW); | |
335 } | |
336 as -> dpval = v1 & 0xff; | |
337 cl -> dpval = v1 & 0xff; | |
338 cl -> issetdp = 1; | |
339 cl -> numcodebytes = 0; | |
340 //printf("%s\n", "SETDP2"); | |
341 } | |
342 | |
343 void pseudo_fcc(asmstate_t *as, sourceline_t *cl, char **optr) | |
344 { | |
345 int cn = 0; | |
346 int delim = 0; | |
347 | |
348 delim = *(*optr)++; | |
349 if (!delim) | |
350 { | |
351 errorp1(ERR_BADOPER); | |
352 } | |
353 else | |
354 { | |
355 while (**optr && **optr != delim) | |
356 { | |
357 emit(**optr); | |
358 (*optr)++; | |
359 cn += 1; | |
360 } | |
361 } | |
362 cl -> len = cn; | |
363 } | |
364 | |
365 void pseudo_fcs(asmstate_t *as, sourceline_t *cl, char **optr) | |
366 { | |
367 int cn = 0; | |
368 int delim = 0; | |
369 | |
370 delim = *(*optr)++; | |
371 if (!delim) | |
372 { | |
373 errorp1(ERR_BADOPER); | |
374 } | |
375 else | |
376 { | |
377 while (**optr && **optr != delim) | |
378 { | |
379 if (!*((*optr) + 1) || *((*optr) + 1) == delim) | |
380 emit((**optr) | 0x80); | |
381 else | |
382 emit(**optr); | |
383 (*optr)++; | |
384 cn += 1; | |
385 } | |
386 } | |
387 cl -> len = cn; | |
388 } | |
389 | |
390 void pseudo_fcn(asmstate_t *as, sourceline_t *cl, char **optr) | |
391 { | |
392 int cn = 0; | |
393 int delim = 0; | |
394 | |
395 delim = *(*optr)++; | |
396 if (!delim) | |
397 { | |
398 errorp1(ERR_BADOPER); | |
399 } | |
400 else | |
401 { | |
402 while (**optr && **optr != delim) | |
403 { | |
404 emit(**optr); | |
405 (*optr)++; | |
406 cn += 1; | |
407 } | |
408 } | |
409 emit(0); | |
410 cl -> len = cn + 1; | |
411 } | |
412 | |
413 void pseudo_fcb(asmstate_t *as, sourceline_t *cl, char **optr) | |
414 { | |
415 int rval, v1; | |
416 | |
417 fcb_again: | |
418 rval = eval_expr(as, cl, optr, &v1); | |
419 if (v1 < -127 || v1 > 0xff) | |
420 errorp2(ERR_OVERFLOW); | |
421 emit(v1 & 0xff); | |
422 if (**optr == ',') | |
423 { | |
424 (*optr)++; | |
425 goto fcb_again; | |
426 } | |
427 } | |
428 | |
429 void pseudo_fdb(asmstate_t *as, sourceline_t *cl, char **optr) | |
430 { | |
431 int rval, v1; | |
432 | |
433 fdb_again: | |
434 rval = eval_expr(as, cl, optr, &v1); | |
435 emit((v1 >> 8) & 0xff); | |
436 emit(v1 & 0xff); | |
437 if (**optr == ',') | |
438 { | |
439 (*optr)++; | |
440 goto fdb_again; | |
441 } | |
442 } | |
443 | |
444 void pseudo_fqb(asmstate_t *as, sourceline_t *cl, char **optr) | |
445 { | |
446 int rval, v1; | |
447 | |
448 fqb_again: | |
449 rval = eval_expr(as, cl, optr, &v1); | |
450 emit((v1 >> 24) & 0xff); | |
451 emit((v1 >> 16) & 0xff); | |
452 emit((v1 >> 8) & 0xff); | |
453 emit(v1 & 0xff); | |
454 if (**optr == ',') | |
455 { | |
456 (*optr)++; | |
457 goto fqb_again; | |
458 } | |
459 } | |
460 | |
461 // don't need to do anything if we are executing one of these | |
462 void pseudo_endc(asmstate_t *as, sourceline_t *cl, char **optr) | |
463 { | |
464 return; | |
465 } | |
466 | |
467 // if "else" executes, we must be going into an "ignore" state | |
468 void pseudo_else(asmstate_t *as, sourceline_t *cl, char **optr) | |
469 { | |
470 as -> skipcond = 1; | |
471 as -> skipcount = 1; | |
472 } | |
473 | |
474 void pseudo_ifne(asmstate_t *as, sourceline_t *cl, char **optr) | |
475 { | |
476 int v1; | |
477 int rval; | |
478 // printf("ifne %s\n", *optr); | |
479 rval = eval_expr(as, cl, optr, &v1); | |
480 if (rval < 0) | |
481 { | |
482 errorp1(ERR_BADCOND); | |
483 } | |
484 else | |
485 { | |
486 // printf("Condition value: %d\n", v1); | |
487 if (!v1) | |
488 { | |
489 // printf("condition no match\n"); | |
490 as -> skipcond = 1; | |
491 as -> skipcount = 1; | |
492 } | |
493 } | |
494 } | |
495 void pseudo_ifeq(asmstate_t *as, sourceline_t *cl, char **optr) | |
496 { | |
497 int v1; | |
498 int rval; | |
499 | |
500 rval = eval_expr(as, cl, optr, &v1); | |
501 if (rval < 0) | |
502 { | |
503 errorp1(ERR_BADCOND); | |
504 } | |
505 else | |
506 { | |
507 if (v1) | |
508 { | |
509 as -> skipcond = 1; | |
510 as -> skipcount = 1; | |
511 } | |
512 } | |
513 } | |
514 void pseudo_iflt(asmstate_t *as, sourceline_t *cl, char **optr) | |
515 { | |
516 int v1; | |
517 int rval; | |
518 | |
519 rval = eval_expr(as, cl, optr, &v1); | |
520 if (rval < 0) | |
521 { | |
522 errorp1(ERR_BADCOND); | |
523 } | |
524 else | |
525 { | |
526 if (v1 >= 0) | |
527 { | |
528 as -> skipcond = 1; | |
529 as -> skipcount = 1; | |
530 } | |
531 } | |
532 } | |
533 void pseudo_ifle(asmstate_t *as, sourceline_t *cl, char **optr) | |
534 { | |
535 int v1; | |
536 int rval; | |
537 | |
538 rval = eval_expr(as, cl, optr, &v1); | |
539 if (rval < 0) | |
540 { | |
541 errorp1(ERR_BADCOND); | |
542 } | |
543 else | |
544 { | |
545 if (v1 > 0) | |
546 { | |
547 as -> skipcond = 1; | |
548 as -> skipcount = 1; | |
549 } | |
550 } | |
551 } | |
552 void pseudo_ifgt(asmstate_t *as, sourceline_t *cl, char **optr) | |
553 { | |
554 int v1; | |
555 int rval; | |
556 | |
557 rval = eval_expr(as, cl, optr, &v1); | |
558 if (rval < 0) | |
559 { | |
560 errorp1(ERR_BADCOND); | |
561 } | |
562 else | |
563 { | |
564 if (v1 <= 0) | |
565 { | |
566 as -> skipcond = 1; | |
567 as -> skipcount = 1; | |
568 } | |
569 } | |
570 } | |
571 void pseudo_ifge(asmstate_t *as, sourceline_t *cl, char **optr) | |
572 { | |
573 int v1; | |
574 int rval; | |
575 | |
576 rval = eval_expr(as, cl, optr, &v1); | |
577 if (rval < 0) | |
578 { | |
579 errorp1(ERR_BADCOND); | |
580 } | |
581 else | |
582 { | |
583 if (v1 < 0) | |
584 { | |
585 as -> skipcond = 1; | |
586 as -> skipcount = 1; | |
587 } | |
588 } | |
589 } | |
590 | |
591 void pseudo_error(asmstate_t *as, sourceline_t *cl, char **optr) | |
592 { | |
593 cl -> user_error = strdup(*optr); | |
594 errorp1(ERR_USER); | |
595 } | |
47
804d7465e0f9
Implemented ORG and fixed problems with constants using $, &, or @ to specify base
lost
parents:
4
diff
changeset
|
596 */ |