# 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___ */