Mercurial > hg-old > index.cgi
view src/pseudo.c @ 8:f1df096aa76f 1.1
Tagged 1.1 bugfix release
author | lost |
---|---|
date | Sun, 04 Jan 2009 05:46:07 +0000 |
parents | 34568fab6058 |
children | 804d7465e0f9 |
line wrap: on
line source
/* pseudo.c Copyright © 2008 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 <ctype.h> #include <stdlib.h> #include <string.h> #include "lwasm.h" #include "instab.h" #include <stdio.h> void pseudo_org(asmstate_t *as, sourceline_t *cl, char **optr) { int v1, rval; if (cl -> hassym) { register_error(as, cl, ERR_SYM); cl -> hassym = 0; } rval = eval_expr(as, cl, optr, &v1); cl -> addr = v1; cl -> addrset = 1; as -> addr = v1; } void pseudo_include(asmstate_t *as, sourceline_t *cl, char **optr) { int v1; if (as -> passnum != 1) return; while (**optr && isspace(**optr)) (*optr)++; if (!**optr) { register_error(as, cl, ERR_BADFN); return; } for (v1 = 0; *((*optr)+v1) && !isspace(*((*optr)+v1)); v1++) ; { char *fn = malloc(v1 + 1); strncpy(fn, *optr, v1); fn[v1] = '\0'; lwasm_read_file(as, fn); } } void pseudo_rmb(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } if (v1 < 0) { errorp1(ERR_BADOPER); return; } cl -> len = v1; cl -> nocode = 1; } void pseudo_rmd(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } if (v1 < 0) { errorp1(ERR_BADOPER); return; } cl -> len = v1 * 2; cl -> nocode = 1; } void pseudo_rmq(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } if (v1 < 0) { errorp1(ERR_BADOPER); return; } cl -> len = v1 * 4; cl -> nocode = 1; } void pseudo_zmb(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } if (v1 < 0) { errorp1(ERR_BADOPER); return; } while (v1--) emit(0); } void pseudo_zmd(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } if (v1 < 0) { errorp1(ERR_BADOPER); return; } while (v1--) { emit(0); emit(0); } } void pseudo_zmq(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } if (v1 < 0) { errorp1(ERR_BADOPER); return; } while (v1--) { emit(0); emit(0); emit(0); emit(0); } } void pseudo_end(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; while (**optr && isspace(**optr)) ; if (**optr && **optr != '*' && **optr != ';') { rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } } else { v1 = 0; } if (as -> passnum == 2) as -> execaddr = v1; } void pseudo_align(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; int cn; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_FORWARD); return; } cn = cl -> addr % v1; if (cn) cn = v1 - cn; while (cn) { emit(0); cn--; } } void pseudo_equ(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 -> isequ = 1; cl -> symaddr = v1 & 0xFFFF; } 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"); } void pseudo_fcc(asmstate_t *as, sourceline_t *cl, char **optr) { int cn = 0; int delim = 0; delim = *(*optr)++; if (!delim) { errorp1(ERR_BADOPER); } else { while (**optr && **optr != delim) { emit(**optr); (*optr)++; cn += 1; } } cl -> len = cn; } void pseudo_fcs(asmstate_t *as, sourceline_t *cl, char **optr) { int cn = 0; int delim = 0; delim = *(*optr)++; if (!delim) { errorp1(ERR_BADOPER); } else { while (**optr && **optr != delim) { if (!*((*optr) + 1) || *((*optr) + 1) == delim) emit((**optr) | 0x80); else emit(**optr); (*optr)++; cn += 1; } } cl -> len = cn; } void pseudo_fcn(asmstate_t *as, sourceline_t *cl, char **optr) { int cn = 0; int delim = 0; delim = *(*optr)++; if (!delim) { errorp1(ERR_BADOPER); } else { while (**optr && **optr != delim) { emit(**optr); (*optr)++; cn += 1; } } emit(0); cl -> len = cn + 1; } void pseudo_fcb(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; fcb_again: rval = eval_expr(as, cl, optr, &v1); if (v1 < -127 || v1 > 0xff) errorp2(ERR_OVERFLOW); emit(v1 & 0xff); if (**optr == ',') { (*optr)++; goto fcb_again; } } void pseudo_fdb(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; fdb_again: rval = eval_expr(as, cl, optr, &v1); emit((v1 >> 8) & 0xff); emit(v1 & 0xff); if (**optr == ',') { (*optr)++; goto fdb_again; } } void pseudo_fqb(asmstate_t *as, sourceline_t *cl, char **optr) { int rval, v1; fqb_again: rval = eval_expr(as, cl, optr, &v1); emit((v1 >> 24) & 0xff); emit((v1 >> 16) & 0xff); emit((v1 >> 8) & 0xff); emit(v1 & 0xff); if (**optr == ',') { (*optr)++; goto fqb_again; } } // don't need to do anything if we are executing one of these void pseudo_endc(asmstate_t *as, sourceline_t *cl, char **optr) { return; } // if "else" executes, we must be going into an "ignore" state void pseudo_else(asmstate_t *as, sourceline_t *cl, char **optr) { as -> skipcond = 1; as -> skipcount = 1; } void pseudo_ifne(asmstate_t *as, sourceline_t *cl, char **optr) { int v1; int rval; // printf("ifne %s\n", *optr); rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_BADCOND); } else { // printf("Condition value: %d\n", v1); if (!v1) { // printf("condition no match\n"); as -> skipcond = 1; as -> skipcount = 1; } } } void pseudo_ifeq(asmstate_t *as, sourceline_t *cl, char **optr) { int v1; int rval; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_BADCOND); } else { if (v1) { as -> skipcond = 1; as -> skipcount = 1; } } } void pseudo_iflt(asmstate_t *as, sourceline_t *cl, char **optr) { int v1; int rval; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_BADCOND); } else { if (v1 >= 0) { as -> skipcond = 1; as -> skipcount = 1; } } } void pseudo_ifle(asmstate_t *as, sourceline_t *cl, char **optr) { int v1; int rval; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_BADCOND); } else { if (v1 > 0) { as -> skipcond = 1; as -> skipcount = 1; } } } void pseudo_ifgt(asmstate_t *as, sourceline_t *cl, char **optr) { int v1; int rval; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_BADCOND); } else { if (v1 <= 0) { as -> skipcond = 1; as -> skipcount = 1; } } } void pseudo_ifge(asmstate_t *as, sourceline_t *cl, char **optr) { int v1; int rval; rval = eval_expr(as, cl, optr, &v1); if (rval < 0) { errorp1(ERR_BADCOND); } else { if (v1 < 0) { as -> skipcond = 1; as -> skipcount = 1; } } } void pseudo_error(asmstate_t *as, sourceline_t *cl, char **optr) { cl -> user_error = strdup(*optr); errorp1(ERR_USER); }