# HG changeset patch # User lost@starbug # Date 1270176297 21600 # Node ID 105393e31f2095738a3a04623320ff1df96261fe # Parent 7d91ab7ac7d6d6cfcfc2d0121814813fbd4cda51 Generic memory mode insns diff -r 7d91ab7ac7d6 -r 105393e31f20 lwasm/Makefile.am --- a/lwasm/Makefile.am Thu Apr 01 18:39:40 2010 -0600 +++ b/lwasm/Makefile.am Thu Apr 01 20:44:57 2010 -0600 @@ -3,7 +3,7 @@ lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \ instab.c symbol.c macro.c \ insn_inh.c insn_rtor.c insn_tfm.c insn_rlist.c insn_rel.c \ - insn_bitbit.c insn_indexed.c \ + insn_bitbit.c insn_indexed.c insn_gen.c \ pseudo.c section.c os9.c lwasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -L$(top_builddir)/lwlib -L$(top_srcdir)/lwlib -lgnu -llw EXTRA_DIST = lwasm.h input.h instab.h diff -r 7d91ab7ac7d6 -r 105393e31f20 lwasm/insn_gen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/insn_gen.c Thu Apr 01 20:44:57 2010 -0600 @@ -0,0 +1,434 @@ +/* +insn_gen.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 . + +Contains code for parsing general addressing modes (IMM+DIR+EXT+IND) +*/ + +#include + +#include +#include + +#include + +#include "lwasm.h" +#include "instab.h" + +extern void insn_indexed_parse_aux(asmstate_t *as, line_t *l, char **p); +extern void insn_indexed_resolve_aux(asmstate_t *as, line_t *l, int force); +extern void insn_indexed_emit_aux(asmstate_t *as, line_t *l); + +// "extra" is required due to the way OIM, EIM, TIM, and AIM work +void insn_parse_gen_aux(asmstate_t *as, line_t *l, char **p) +{ + const char *optr2; + int v1, tv, rval; + lw_expr_t *s; + + optr2 = *p; + while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++ + /* do nothing */ ; + + if (*optr2 == ',' || **p == '[') + { + l -> lint = -1; + l -> lint2 = 1; + insn_parse_indexed_aux(as, l, p); + goto out; + } + + if (**p == '<') + { + (*p)++; + l -> lint2 = 0; + } + + // for compatibility with asxxxx + // * followed by a digit, alpha, or _, or ., or ?, or another * is "f8" + else if (**p == '*') + { + tv = *(*p + 1); + if (isdigit(tv) || isalpha(tv) || tv == '_' || tv == '.' || tv == '?' || tv == '@' || tv == '*' || tv == '+' || tv == '-') + { + l -> lint2 = 0; + (*p)++; + } + } + else if (**p == '>') + { + (*p)++; + l -> lint2 = 2; + } + else + { + l -> lint2 = -1; + } + + s = lwasm_parse_expr(as, p); + if (!s) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + + lwasm_save_expr(l, 0, s); + + if (as -> output_format == OUTPUT_OBJ && l -> lint2 == -1) + { + l -> lint2 = 2; + goto out; + } + + // if we have a constant now, figure out dp vs nondp + if (lw_expr_istype(s, lw_expr_type_int)) + { + v1 = lw_expr_intval(s); + if (((v1 >> 8) & 0xff) == (l -> dpval & 0xff)) + { + l -> lint2 = 0; + goto out; + } + l -> lint2 = 2; + } + +out: + if (l -> lint2 != -1) + { + if (l -> lint2 == 0) + { + l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; + } + else if (l -> lint2 == 2) + { + l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; + } + else if (l -> lint2 == 1 && l -> lint != -1) + { + l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; + } + } +} + +void insn_resolve_gen_aux(asmstate_t *as, line_t *l, int force) +{ + lw_expr_t *e; + + if (l -> lint2 == 1) + { + // indexed + insn_resolve_indexed_aux(as, l, force); + goto out; + } + + if (l -> lint2 != -1) + return; + + e = lwasm_fetch_expr(l, 0); + if (lw_expr_istype(e, lw_expr_type_int)) + { + int v; + + v = lw_expr_intval(e); + + if (((v >> 8) & 0xff) == (l -> dpval & 0xff)) + { + l -> lint2 = 0; + goto out; + } + l -> lint2 = 2; + goto out; + } + + if (force) + { + l -> lint2 = 2; + } + +out: + if (l -> lint2 != -1) + { + if (l -> lint2 == 0) + { + l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; + } + else if (l -> lint2 == 2) + { + l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; + } + else if (l -> lint2 == 1 && l -> lint != -1) + { + l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; + } + } +} + +void insn_emit_gen_aux(asmstate_t *as, line_t *l) +{ + lw_expr_t e; + + e = lwasm_fetch_expr(l, 0); + lwasm_emitop(l, instab[l -> insn].ops[l -> lint2]); + if (l, l -> lint2 == 1) + { + lwasm_emit(l, l -> pb); + lwasm_emitexpr(l, e, l -> lint); + return; + } + + if (l -> lint2 == 2) + lwasm_emitexpr(l, e, 2); + else + lwasm_emitexpr(l, e, 1); +} + +// the various insn_gen? functions have an immediate mode of ? bits +PARSEFUNC(insn_parse_gen0) +{ + if (**p == '#') + { + lwasm_register_error(as, l, "Immediate mode not allowed"); + return; + } + + // handle non-immediate + insn_parse_gen_aux(as, l, p); +} + +RESOLVEFUNC(insn_resolve_gen0) +{ + if (l -> len != -1) + return; + + // handle non-immediate + insn_resolve_gen_aux(as, l, force); +} + +EMITFUNC(insn_emit_gen0) +{ + insn_emit_gen_aux(as, l); +} + +PARSEFUNC(insn_parse_gen8) +{ + if (**p == '#') + { + lw_expr_t e; + + (*p)++; + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + l -> len = OPLEN(instab[l -> insn].ops[3]) + 1; + l -> lint2 = 3; + lwasm_save_expr(l, 0, e); + return; + } + + // handle non-immediate + insn_parse_gen_aux(as, l, p); + if (l -> lint2 != -1) + { + if (l -> lint2 == 0) + { + l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; + } + else if (l -> lint2 == 2) + { + l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; + } + else if (l -> lint2 == 1 && l -> lint != -1) + { + l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; + } + } +} + +RESOLVEFUNC(insn_resolve_gen8) +{ + if (l -> len != -1) + return; + + // handle non-immediate + insn_resolve_gen_aux(as, l, force); +} + +EMITFUNC(insn_emit_gen8) +{ + if (l -> lint2 == 3) + { + lw_expr_t e; + e = lwasm_fetch_expr(l, 0); + lwasm_emitop(l, instab[l -> insn].ops[3]); + lwasm_emitexpr(l, e, 1); + return; + } + + insn_emit_gen_aux(as, l); +} + +PARSEFUNC(insn_parse_gen16) +{ + if (**p == '#') + { + lw_expr_t e; + + (*p)++; + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + l -> len = OPLEN(instab[l -> insn].ops[3]) + 2; + l -> lint2 = 3; + lwasm_save_expr(l, 0, e); + return; + } + + // handle non-immediate + insn_parse_gen_aux(as, l, p); + if (l -> lint2 != -1) + { + if (l -> lint2 == 0) + { + l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; + } + else if (l -> lint2 == 2) + { + l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; + } + else if (l -> lint2 == 1 && l -> lint != -1) + { + l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; + } + } +} + +RESOLVEFUNC(insn_resolve_gen16) +{ + if (l -> len != -1) + return; + + // handle non-immediate + insn_resolve_gen_aux(as, l, force); +} + +EMITFUNC(insn_emit_gen16) +{ + if (l -> lint2 == 3) + { + lw_expr_t e; + e = lwasm_fetch_expr(l, 0); + lwasm_emitop(l, instab[l -> insn].ops[3]); + lwasm_emitexpr(l, e, 2); + return; + } + + insn_emit_gen_aux(as, l); +} + +PARSEFUNC(insn_parse_gen32) +{ + if (**p == '#') + { + lw_expr_t e; + + (*p)++; + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + l -> len = OPLEN(instab[l -> insn].ops[3]) + 4; + l -> lint2 = 3; + lwasm_save_expr(l, 0, e); + return; + } + + // handle non-immediate + insn_parse_gen_aux(as, l, p); + if (l -> lint2 != -1) + { + if (l -> lint2 == 0) + { + l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; + } + else if (l -> lint2 == 2) + { + l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; + } + else if (l -> lint2 == 1 && l -> lint != -1) + { + l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; + } + } +} + +RESOLVEFUNC(insn_resolve_gen32) +{ + if (l -> len != -1) + return; + + // handle non-immediate + insn_resolve_gen_aux(as, l, force); +} + +EMITFUNC(insn_emit_gen32) +{ + if (l -> lint2 == 3) + { + lw_expr_t e; + e = lwasm_fetch_expr(l, 0); + lwasm_emitop(l, instab[l -> insn].ops[3]); + lwasm_emitexpr(l, e, 4); + return; + } + + insn_emit_gen_aux(as, l); +} + +PARSEFUNC(insn_parse_imm8) +{ + lw_expr_t e; + + if (**p == '#') + { + (*p)++; + + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad operand"); + return; + } + l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; + lwasm_save_expr(l, 0, e); + } +} + +EMITFUNC(insn_emit_imm8) +{ + lw_expr_t e; + + lwasm_emitop(l, instab[l -> insn].ops[0]); + lwasm_emitexpr(l, e, 1); +} diff -r 7d91ab7ac7d6 -r 105393e31f20 lwasm/lwasm.h --- a/lwasm/lwasm.h Thu Apr 01 18:39:40 2010 -0600 +++ b/lwasm/lwasm.h Thu Apr 01 20:44:57 2010 -0600 @@ -140,6 +140,7 @@ char *lstr; // string passed forward int pb; // pass forward post byte int lint; // pass forward integer + int lint2; // another pass forward integer asmstate_t *as; // assembler state data ptr int pragmas; // pragmas in effect for the line };