# HG changeset patch # User lost@starbug # Date 1269742584 21600 # Node ID 1649bc7bda5a0ea965f9276fbee6dc5f9525be59 # Parent a82c55070624e451346f0a46121e592718861160 Some data oriented pseudo ops added diff -r a82c55070624 -r 1649bc7bda5a lwasm/Makefile.am --- a/lwasm/Makefile.am Sat Mar 27 19:04:03 2010 -0600 +++ b/lwasm/Makefile.am Sat Mar 27 20:16:24 2010 -0600 @@ -1,5 +1,8 @@ AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib -I$(top_builddir)/lwlib -I$(top_srcdir)/lwlib bin_PROGRAMS = lwasm -lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c instab.c symbol.c macro.c insn_inh.c +lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \ + instab.c symbol.c macro.c \ + insn_inh.c \ + pseudo.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 a82c55070624 -r 1649bc7bda5a lwasm/instab.c --- a/lwasm/instab.c Sat Mar 27 19:04:03 2010 -0600 +++ b/lwasm/instab.c Sat Mar 27 20:16:24 2010 -0600 @@ -38,6 +38,11 @@ extern PARSEFUNC(pseudo_parse_endm); #define pseudo_resolve_endm NULL +extern PARSEFUNC(pseudo_parse_noop); +extern RESOLVEFUNC(pseudo_resolve_noop); + +extern PARSEFUNC(pseudo_parse_end); +extern RESOLVEFUNC(pseudo_resolve_end); extern PARSEFUNC(insn_parse_gen8); extern RESOLVEFUNC(insn_resolve_gen8); @@ -86,8 +91,6 @@ extern RESOLVEFUNC(pseudo_resolve_zmq); extern PARSEFUNC(pseudo_parse_include); extern RESOLVEFUNC(pseudo_resolve_include); -extern PARSEFUNC(pseudo_parse_end); -extern RESOLVEFUNC(pseudo_resolve_end); extern PARSEFUNC(pseudo_parse_align); extern RESOLVEFUNC(pseudo_resolve_align); extern PARSEFUNC(pseudo_parse_error); @@ -144,8 +147,6 @@ extern RESOLVEFUNC(pseudo_resolve_ifdef); extern PARSEFUNC(pseudo_parse_ifndef); extern RESOLVEFUNC(pseudo_resolve_ifndef); -extern PARSEFUNC(pseudo_parse_noop); -extern RESOLVEFUNC(pseudo_resolve_noop); extern PARSEFUNC(pseudo_parse_includebin); extern RESOLVEFUNC(pseudo_resolve_includebin); @@ -437,13 +438,12 @@ { "fcc", { -1, -1, -1, -1 }, pseudo_parse_fcc, pseudo_resolve_fcc, lwasm_insn_normal}, { "fcn", { -1, -1, -1, -1 }, pseudo_parse_fcn, pseudo_resolve_fcn, lwasm_insn_normal}, { "fcs", { -1, -1, -1, -1 }, pseudo_parse_fcs, pseudo_resolve_fcs, lwasm_insn_normal}, - +*/ { "fcb", { -1, -1, -1, -1 }, pseudo_parse_fcb, pseudo_resolve_fcb, lwasm_insn_normal}, { "fdb", { -1, -1, -1, -1 }, pseudo_parse_fdb, pseudo_resolve_fdb, lwasm_insn_normal}, { "fqb", { -1, -1, -1, -1 }, pseudo_parse_fqb, pseudo_resolve_fqb, lwasm_insn_normal}, - { "end", { -1, -1, -1, -1 }, pseudo_parse_end, pseudo_resolve_end, lwasm_insn_normal}, - +/* { "includebin", { -1, -1, -1, -1}, pseudo_parse_includebin,pseudo_resolve_includebin, lwasm_insn_normal}, { "include", { -1, -1, -1, -1 }, pseudo_parse_include, pseudo_resolve_include, lwasm_insn_normal}, { "use", { -1, -1, -1, -1 }, pseudo_parse_include, pseudo_resolve_include, lwasm_insn_normal}, @@ -493,6 +493,7 @@ { ".area", { -1, -1, -1, -1}, pseudo_parse_section, pseudo_resolve_section, lwasm_insn_normal}, { ".globl", { -1, -1, -1, -1}, pseudo_parse_export, pseudo_resolve_export, lwasm_insn_normal}, +*/ { ".module", { -1, -1, -1, -1}, pseudo_parse_noop, pseudo_resolve_noop, lwasm_insn_normal}, { ".4byte", { -1, -1, -1, -1}, pseudo_parse_fqb, pseudo_resolve_fqb, lwasm_insn_normal}, @@ -503,7 +504,7 @@ { ".byte", { -1, -1, -1, -1}, pseudo_parse_fcb, pseudo_resolve_fcb, lwasm_insn_normal}, { ".db", { -1, -1, -1, -1}, pseudo_parse_fcb, pseudo_resolve_fcb, lwasm_insn_normal}, - +/* { ".ascii", { -1, -1, -1, -1}, pseudo_parse_fcc, pseudo_resolve_fcc, lwasm_insn_normal}, { ".str", { -1, -1, -1, -1}, pseudo_parse_fcc, pseudo_resolve_fcc, lwasm_insn_normal}, @@ -519,10 +520,11 @@ // needs to handle C escapes maybe? // { ".ascii", { -1, -1, -1, -1}, pseudo_parse_ascii, pseudo_resolve_ascii, lwasm_insn_normal}, +*/ // for compatibility { ".end", { -1, -1, -1, -1 }, pseudo_parse_end, pseudo_resolve_end, lwasm_insn_normal}, - + // extra ops that are ignored because they are generally only for // pretty printing the listing { "nam", { -1, -1, -1, -1 }, pseudo_parse_noop, pseudo_resolve_noop, lwasm_insn_normal}, @@ -530,6 +532,5 @@ { "ttl", { -1, -1, -1, -1 }, pseudo_parse_noop, pseudo_resolve_noop, lwasm_insn_normal}, // flag end of table -*/ { NULL, { -1, -1, -1, -1 }, NULL, NULL, lwasm_insn_normal} }; diff -r a82c55070624 -r 1649bc7bda5a lwasm/lwasm.c --- a/lwasm/lwasm.c Sat Mar 27 19:04:03 2010 -0600 +++ b/lwasm/lwasm.c Sat Mar 27 20:16:24 2010 -0600 @@ -431,3 +431,76 @@ return e; } + +void lwasm_save_expr(line_t *cl, int id, lw_expr_t expr) +{ + struct line_expr_s *e; + + for (e = cl -> exprs; e; e = e -> next) + { + if (e -> id == id) + { + lw_expr_destroy(e -> expr); + e -> expr = expr; + return; + } + } + + e = lw_alloc(sizeof(struct line_expr_s)); + e -> expr = expr; + e -> id = id; + e -> next = cl -> exprs; + cl -> exprs = e; +} + +lw_expr_t lwasm_fetch_expr(line_t *cl, int id) +{ + struct line_expr_s *e; + + for (e = cl -> exprs; e; e = e -> next) + { + if (e -> id == id) + { + return e -> expr; + } + } + return NULL; +} + +void skip_operand(char **p) +{ + for (; **p && !isspace(**p); (*p)++) + /* do nothing */ ; +} + +int lwasm_emitexpr(line_t *l, lw_expr_t expr, int size) +{ + int v; + + if (lw_expr_istype(expr, lw_expr_type_int)) + { + v = lw_expr_intval(expr); + } + else + { + lwasm_register_error(l -> as, l, "Expression not fully resolved"); + return -1; + } + + switch (size) + { + case 4: + lwasm_emit(l, v >> 24); + lwasm_emit(l, v >> 16); + /* fallthrough intended */ + + case 2: + lwasm_emit(l, v >> 8); + /* fallthrough intended */ + + case 1: + lwasm_emit(l, v); + } + + return 0; +} diff -r a82c55070624 -r 1649bc7bda5a lwasm/lwasm.h --- a/lwasm/lwasm.h Sat Mar 27 19:04:03 2010 -0600 +++ b/lwasm/lwasm.h Sat Mar 27 20:16:24 2010 -0600 @@ -81,6 +81,13 @@ lwasm_error_t *next; // ptr to next error }; +struct line_expr_s +{ + lw_expr_t expr; + int id; + struct line_expr_s *next; +}; + typedef struct line_s line_t; struct line_s { @@ -95,6 +102,8 @@ lwasm_error_t *err; // list of errors line_t *prev; // previous line line_t *next; // next line + + struct line_expr_s *exprs; // expressions used during parsing asmstate_t *as; // assembler state data ptr }; @@ -139,6 +148,8 @@ int inmacro; // are we in a macro? int skipcond; // skipping a condition? int skipmacro; // are we skipping in a macro? + int endseen; // have we seen an "end" pseudo? + int execaddr; // address from "end" line_t *line_head; // start of lines list line_t *line_tail; // tail of lines list @@ -173,6 +184,13 @@ extern void lwasm_emit(line_t *cl, int byte); extern void lwasm_emitop(line_t *cl, int opc); +extern void lwasm_save_expr(line_t *cl, int id, lw_expr_t expr); +extern lw_expr_t lwasm_fetch_expr(line_t *cl, int id); +extern lw_expr_t lwasm_parse_expr(asmstate_t *as, char **p); +extern int lwasm_emitexpr(line_t *cl, lw_expr_t expr, int s); + +extern void skip_operand(char **p); + #endif #define OPLEN(op) (((op)>0xFF)?2:1) diff -r a82c55070624 -r 1649bc7bda5a lwasm/pass1.c --- a/lwasm/pass1.c Sat Mar 27 19:04:03 2010 -0600 +++ b/lwasm/pass1.c Sat Mar 27 20:16:24 2010 -0600 @@ -261,5 +261,9 @@ nextline: lw_free(line); + + // if we've hit the "end" bit, finish out + if (as -> endseen) + return; } } diff -r a82c55070624 -r 1649bc7bda5a lwasm/pseudo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/pseudo.c Sat Mar 27 20:16:24 2010 -0600 @@ -0,0 +1,171 @@ +/* +pseudo.c +Copyright © 2010 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 . + +*/ + +#include + +#include "lwasm.h" +#include "instab.h" + +// for no-op pseudos +PARSEFUNC(pseudo_parse_noop) +{ +} + +RESOLVEFUNC(pseudo_resolve_noop) +{ +} + +// for "end" +PARSEFUNC(pseudo_parse_end) +{ + lw_expr_t addr; + + as -> endseen = 1; + + if (as -> output_format != OUTPUT_DECB) + { + skip_operand(p); + return; + } + + addr = lwasm_parse_expr(as, p); + if (!addr) + { + lwasm_register_error(as, l, "Bad expression"); + addr = lw_expr_build(lw_expr_type_int, 0); + } + lwasm_save_expr(l, 0, addr); +} + +RESOLVEFUNC(pseudo_resolve_end) +{ + lw_expr_t addr; + + addr = lwasm_fetch_expr(l, 0); + + if (addr) + { + if (!lw_expr_istype(addr, lw_expr_type_int)) + lwasm_register_error(as, l, "Exec address not constant!"); + else + as -> execaddr = lw_expr_intval(addr); + } + as -> endseen = 1; +} + +PARSEFUNC(pseudo_parse_fcb) +{ + int i = 0; + lw_expr_t e; + + for (;;) + { + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad expression (#%s)", i); + break; + } + lwasm_save_expr(l, i, e); + i++; + } + + l -> len = i; +} + +RESOLVEFUNC(pseudo_resolve_fcb) +{ + int i; + lw_expr_t e; + int v; + + for (i = 0; i < l -> len; i++) + { + e = lwasm_fetch_expr(l, i); + lwasm_emitexpr(l, e, 1); + } +} + +PARSEFUNC(pseudo_parse_fdb) +{ + int i = 0; + lw_expr_t e; + + for (;;) + { + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad expression (#%s)", i); + break; + } + lwasm_save_expr(l, i, e); + i++; + } + + l -> len = i * 2; +} + +RESOLVEFUNC(pseudo_resolve_fdb) +{ + int i; + lw_expr_t e; + int v; + + for (i = 0; i < (l -> len)/2; i++) + { + e = lwasm_fetch_expr(l, i); + lwasm_emitexpr(l, e, 2); + } +} + +PARSEFUNC(pseudo_parse_fqb) +{ + int i = 0; + lw_expr_t e; + + for (;;) + { + e = lwasm_parse_expr(as, p); + if (!e) + { + lwasm_register_error(as, l, "Bad expression (#%s)", i); + break; + } + lwasm_save_expr(l, i, e); + i++; + } + + l -> len = i * 4; +} + +RESOLVEFUNC(pseudo_resolve_fqb) +{ + int i; + lw_expr_t e; + int v; + + for (i = 0; i < (l -> len)/4; i++) + { + e = lwasm_fetch_expr(l, i); + lwasm_emitexpr(l, e, 4); + } +} diff -r a82c55070624 -r 1649bc7bda5a lwlib/lw_expr.c --- a/lwlib/lw_expr.c Sat Mar 27 19:04:03 2010 -0600 +++ b/lwlib/lw_expr.c Sat Mar 27 20:16:24 2010 -0600 @@ -35,6 +35,20 @@ static lw_expr_fn2_t *evaluate_var = NULL; static lw_expr_fn3_t *parse_term = NULL; +int lw_expr_istype(lw_expr_t e, int t) +{ + if (e -> type == t) + return 1; + return 0; +} + +int lw_expr_intval(lw_expr_t e) +{ + if (e -> type == lw_expr_type_int) + return e -> value; + return -1; +} + void lw_expr_set_term_parser(lw_expr_fn3_t *fn) { parse_term = fn; diff -r a82c55070624 -r 1649bc7bda5a lwlib/lw_expr.h --- a/lwlib/lw_expr.h Sat Mar 27 19:04:03 2010 -0600 +++ b/lwlib/lw_expr.h Sat Mar 27 20:16:24 2010 -0600 @@ -93,6 +93,8 @@ extern void lw_expr_set_term_parser(lw_expr_fn3_t *fn); extern lw_expr_t lw_expr_parse(char **p, void *priv); +extern int lw_expr_istype(lw_expr_t e, int t); +extern int lw_expr_intval(lw_expr_t e); #endif /* def ___lw_expr_c_seen___ */