Mercurial > hg-old > index.cgi
view src/pseudo.c @ 63:d85ba47b1e8f
Moved symbol registration so symbols that are in skipped code do not get registered and so EQU/SET can do their own registration
author | lost |
---|---|
date | Mon, 05 Jan 2009 01:17:23 +0000 |
parents | 035b95a3690f |
children | aaddd47219b4 |
line wrap: on
line source
/* pseudo.c Copyright © 2009 William Astle This file is part of LWASM. LWASM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. This file implements the various pseudo operations. */ #include <stdlib.h> #include <string.h> #include "lwasm.h" #include "instab.h" #include "expr.h" #include "util.h" extern int lwasm_read_file(asmstate_t *as, const char *filename); OPFUNC(pseudo_org) { int rval; lwasm_expr_stack_t *s; if (as -> passnum != 1) { // org is not needed to be processed on pass 2 // this will prevent phasing errors for forward references that // resolve on the second pass // we saved the org address in l -> codeaddr on pass 1 as -> addr = l -> codeaddr; return; } if (l -> sym) { register_error(as, l, 1, "No symbol allowed with ORG"); } s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); lwasm_expr_stack_free(s); return; } rval = lwasm_expr_get_value(s) & 0xffff; lwasm_expr_stack_free(s); l -> codeaddr = rval; l -> addrset = 1; as -> addr = rval; } /* The operand for include is a string optionally enclosed in " */ OPFUNC(pseudo_include) { int v1; char *fn; // only include files on pass 1 // but make sure local include context is right // for the next line... if (as -> passnum != 1) { as -> context = lwasm_next_context(as); return; } while (**p && isspace(**p)) (*p)++; if (!**p) { register_error(as, l, 1, "Bad file name"); return; } if (**p == '"') { // search for ending " (*p)++; for (v1 = 0; *((*p)+v1) && *((*p)+v1) != '"'; v1++) /* do nothing */ ; if (*((*p)+v1) != '"') { register_error(as, l, 1, "Bad file name"); return; } } else { // search for a space type character for (v1 = 0; *((*p)+v1) && !isspace(*((*p)+v1)); v1++) ; } fn = lwasm_alloc(v1 + 1); memcpy(fn, *p, v1); fn[v1] = '\0'; // end local label context on include as -> context = lwasm_next_context(as); if (lwasm_read_file(as, fn) < 0) { register_error(as, l, 1, "File include error (%s)", fn); } lwasm_free(fn); } OPFUNC(pseudo_rmb) { int rval; lwasm_expr_stack_t *s; s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); lwasm_expr_stack_free(s); return; } rval = lwasm_expr_get_value(s); lwasm_expr_stack_free(s); l -> nocodelen = rval; as -> addr += rval; } OPFUNC(pseudo_rmd) { int rval; lwasm_expr_stack_t *s; s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); lwasm_expr_stack_free(s); return; } rval = lwasm_expr_get_value(s) * 2; lwasm_expr_stack_free(s); l -> nocodelen = rval; as -> addr += rval; } OPFUNC(pseudo_rmq) { int rval; lwasm_expr_stack_t *s; s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); lwasm_expr_stack_free(s); return; } rval = lwasm_expr_get_value(s) * 4; lwasm_expr_stack_free(s); l -> nocodelen = rval; as -> addr += rval; } OPFUNC(pseudo_zmb) { int rval; lwasm_expr_stack_t *s; s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); lwasm_expr_stack_free(s); return; } rval = lwasm_expr_get_value(s); lwasm_expr_stack_free(s); while (rval-- > 0) { lwasm_emit(as, l, 0); } } OPFUNC(pseudo_zmd) { int rval; lwasm_expr_stack_t *s; s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); lwasm_expr_stack_free(s); return; } rval = lwasm_expr_get_value(s); lwasm_expr_stack_free(s); while (rval-- > 0) { lwasm_emit(as, l, 0); lwasm_emit(as, l, 0); } } OPFUNC(pseudo_zmq) { int rval; lwasm_expr_stack_t *s; s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); lwasm_expr_stack_free(s); return; } rval = lwasm_expr_get_value(s); lwasm_expr_stack_free(s); while (rval-- > 0) { lwasm_emit(as, l, 0); lwasm_emit(as, l, 0); lwasm_emit(as, l, 0); lwasm_emit(as, l, 0); } } OPFUNC(pseudo_end) { int rval; lwasm_expr_stack_t *s; as -> endseen = 1; // address only matters for DECB output if (as -> outformat != OUTPUT_DECB) return; s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 2, "Incomplete reference"); } rval = lwasm_expr_get_value(s); lwasm_expr_stack_free(s); rval = rval & 0xffff; if (as -> passnum == 2) { as -> execaddr = rval; l -> symaddr = rval; l -> addrset = 2; } } OPFUNC(pseudo_align) { int rval; lwasm_expr_stack_t *s; int cn; if (as -> passnum == 2) { while (as -> addr < l -> symaddr) lwasm_emit(as, l, 0); return; } s = lwasm_evaluate_expr(as, l, *p, NULL); if (!s) { register_error(as, l, 1, "Bad expression"); return; } if (!lwasm_expr_is_constant(s)) { register_error(as, l, 1, "Illegal incomplete reference (pass 1)"); } rval = lwasm_expr_get_value(s); lwasm_expr_stack_free(s); if (rval < 1) { register_error(as, l, 1, "Illegal alignment %d", rval); return; } cn = l -> codeaddr % rval; if (cn) cn = rval - cn; while (cn--) { lwasm_emit(as, l, 0); } l -> symaddr = as -> addr; } OPFUNC(pseudo_equ) { int rval; // equ is not needed to be processed on pass 2 if (as -> passnum != 1) return; if (l -> sym == NULL) { register_error(as, l, 1, "No symbol specified"); return; } if (lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &rval) < 0) rval = 0; l -> symaddr = rval & 0xFFFF; l -> addrset = 2; lwasm_register_symbol(as, l, l -> sym, rval); } OPFUNC(pseudo_set) { } /* void pseudo_set(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; if (cl -> hassym == 0) { errorp1(ERR_NOSYM); return; } rval = eval_expr(as, cl, optr, &v1); // eval_expr returns -1 if there was a forward ref // or -2 if the expr was invalid if (rval == -2) { // carp errorp1(ERR_FORWARD); } if (rval < 0) { // remove symbol ref cl -> hassym = 0; // mark as a "comment" so it isn't processed next time cl -> opcode = -1; return; } cl -> code_symloc = v1; cl -> isset = 1; cl -> isequ = 1; cl -> symaddr = v1 & 0xFFFF; } void pseudo_setdp(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; if (cl -> hassym) { register_error(as, cl, ERR_SYM); cl -> hassym = 0; return; } else { rval = eval_expr(as, cl, optr, &v1); if (rval == -1) { errorp1(ERR_FORWARD); } if (rval < 0) { cl -> opcode = -1; return; } } // setdp needs to resolve properly on pass 2 if (v1 > 0xff || v1 < 0) { errorp1(ERR_OVERFLOW); } as -> dpval = v1 & 0xff; cl -> dpval = v1 & 0xff; cl -> issetdp = 1; cl -> numcodebytes = 0; //printf("%s\n", "SETDP2"); } */ OPFUNC(pseudo_fcc) { int delim = 0; delim = **p; if (!delim) { register_error(as, l, 1, "Bad operand"); return; } *p += 1; while (**p && **p != delim) { lwasm_emit(as, l, **p); (*p)++; } if (**p) (*p)++; } OPFUNC(pseudo_fcs) { int delim = 0; delim = **p; if (!delim) { register_error(as, l, 1, "Bad operand"); return; } *p += 1; while (**p && **p != delim) { if (!*((*p) + 1) || *((*p) + 1) == delim) lwasm_emit(as, l, **p | 0x80); else lwasm_emit(as, l, **p); (*p)++; } if (**p) (*p)++; } OPFUNC(pseudo_fcn) { int delim = 0; delim = **p; if (!delim) { register_error(as, l, 1, "Bad operand"); return; } *p += 1; while (**p && **p != delim) { lwasm_emit(as, l, **p); (*p)++; } if (**p) (*p)++; lwasm_emit(as, l, 0); } OPFUNC(pseudo_fcb) { int v1; fcb_again: if (lwasm_expr_result(as, l, p, EXPR_PASS2CONST | EXPR_BYTE, &v1) < 0) return; lwasm_emit(as, l, v1); if (**p == ',') { (*p)++; goto fcb_again; } } OPFUNC(pseudo_fdb) { int v1; fdb_again: if (lwasm_expr_result(as, l, p, EXPR_PASS2CONST, &v1) < 0) return; lwasm_emit(as, l, v1 >> 8); lwasm_emit(as, l, v1 & 0xff); if (**p == ',') { (*p)++; goto fdb_again; } } OPFUNC(pseudo_fqb) { int v1; fqb_again: if (lwasm_expr_result(as, l, p, EXPR_PASS2CONST, &v1) < 0) return; lwasm_emit(as, l, v1 >> 24); lwasm_emit(as, l, v1 >> 16); lwasm_emit(as, l, v1 >> 8); lwasm_emit(as, l, v1 & 0xff); if (**p == ',') { (*p)++; goto fqb_again; } } // don't need to do anything if we are executing one of these OPFUNC(pseudo_endc) { if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount -= 1; if (as -> skipcount <= 0) { as -> skipcond = 0; } } return; } // if "else" executes, we must be going into an "ignore" state OPFUNC(pseudo_else) { if (as -> skipmacro) return; if (as -> skipcond) { if (as -> skipcount == 1) { as -> skipcount = 0; as -> skipcond = 0; } return; } as -> skipcond = 1; as -> skipcount = 1; } OPFUNC(pseudo_ifne) { int v1; int rval; if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; return; } rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1); if (rval < 0) return; if (!v1) { as -> skipcond = 1; as -> skipcount = 1; } } OPFUNC(pseudo_ifeq) { int v1; int rval; if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; return; } rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1); if (rval < 0) return; if (v1) { as -> skipcond = 1; as -> skipcount = 1; } } OPFUNC(pseudo_iflt) { int v1; int rval; if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; return; } rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1); if (rval < 0) return; if (v1 >= 0) { as -> skipcond = 1; as -> skipcount = 1; } } OPFUNC(pseudo_ifle) { int v1; int rval; if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; return; } rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1); if (rval < 0) return; if (v1 > 0) { as -> skipcond = 1; as -> skipcount = 1; } } OPFUNC(pseudo_ifgt) { int v1; int rval; if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; return; } rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1); if (rval < 0) return; if (v1 <= 0) { as -> skipcond = 1; as -> skipcount = 1; } } OPFUNC(pseudo_ifge) { int v1; int rval; if (as -> skipcond && !(as -> skipmacro)) { as -> skipcount++; return; } rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1); if (rval < 0) return; if (v1 < 0) { as -> skipcond = 1; as -> skipcount = 1; } } OPFUNC(pseudo_error) { register_error(as, l, 1, "User error: %s", *p); }