changeset 351:4dba8c7e242c

conditional pseudo ops added
author lost@starbug
date Sat, 27 Mar 2010 23:37:30 -0600
parents f5666775d76f
children f5b77989f675
files lwasm/instab.c lwasm/lwasm.c lwasm/lwasm.h lwasm/pass1.c lwasm/pseudo.c
diffstat 5 files changed, 458 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/instab.c	Sat Mar 27 22:59:15 2010 -0600
+++ b/lwasm/instab.c	Sat Mar 27 23:37:30 2010 -0600
@@ -105,6 +105,62 @@
 #define pseudo_resolve_equ NULL
 #define pseudo_emit_equ NULL
 
+extern PARSEFUNC(pseudo_parse_set);
+#define pseudo_resolve_set NULL
+#define pseudo_emit_set NULL
+
+extern PARSEFUNC(pseudo_parse_setdp);
+#define pseudo_resolve_setdp NULL
+#define pseudo_emit_setdp NULL
+
+extern PARSEFUNC(pseudo_parse_ifp1);
+#define pseudo_resolve_ifp1 NULL
+#define pseudo_emit_ifp1 NULL
+
+extern PARSEFUNC(pseudo_parse_ifp2);
+#define pseudo_resolve_ifp2 NULL
+#define pseudo_emit_ifp2 NULL
+
+extern PARSEFUNC(pseudo_parse_ifne);
+#define pseudo_resolve_ifne NULL
+#define pseudo_emit_ifne NULL
+
+extern PARSEFUNC(pseudo_parse_ifeq);
+#define pseudo_resolve_ifeq NULL
+#define pseudo_emit_ifeq NULL
+
+extern PARSEFUNC(pseudo_parse_iflt);
+#define pseudo_resolve_iflt NULL
+#define pseudo_emit_iflt NULL
+
+extern PARSEFUNC(pseudo_parse_ifle);
+#define pseudo_resolve_ifle NULL
+#define pseudo_emit_ifle NULL
+
+extern PARSEFUNC(pseudo_parse_ifgt);
+#define pseudo_resolve_ifgt NULL
+#define pseudo_emit_ifgt NULL
+
+extern PARSEFUNC(pseudo_parse_ifge);
+#define pseudo_resolve_ifge NULL
+#define pseudo_emit_ifge NULL
+
+extern PARSEFUNC(pseudo_parse_ifdef);
+#define pseudo_resolve_ifdef NULL
+#define pseudo_emit_ifdef NULL
+
+extern PARSEFUNC(pseudo_parse_ifndef);
+#define pseudo_resolve_ifndef NULL
+#define pseudo_emit_ifndef NULL
+
+extern PARSEFUNC(pseudo_parse_endc);
+#define pseudo_resolve_endc NULL
+#define pseudo_emit_endc NULL
+
+extern PARSEFUNC(pseudo_parse_else);
+#define pseudo_resolve_else NULL
+#define pseudo_emit_else NULL
+
 instab_t instab[] =
 {
 /*
@@ -400,6 +456,7 @@
 
 	{ "error",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_error,		pseudo_resolve_error,			pseudo_emit_error,			lwasm_insn_normal},
 
+*/
 	// these are *dangerous*
 	{ "ifp1",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_ifp1,		pseudo_resolve_ifp1,			pseudo_emit_ifp1,			lwasm_insn_cond},
 	{ "ifp2",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_ifp2,		pseudo_resolve_ifp2,			pseudo_emit_ifp2,			lwasm_insn_cond},
@@ -416,12 +473,12 @@
 	{ "ifdef",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_ifdef,		pseudo_resolve_ifdef,			pseudo_emit_ifdef,			lwasm_insn_cond},
 	{ "ifndef",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_ifndef,	pseudo_resolve_ifndef,			pseudo_emit_ifndef,			lwasm_insn_cond},
 
-*/
 	{ "macro",		{	-1, 	-1, 	-1, 	-1}, 	pseudo_parse_macro,		pseudo_resolve_macro,			pseudo_emit_macro,			lwasm_insn_cond | lwasm_insn_setsym},
 	{ "endm",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_endm,		pseudo_resolve_endm,			pseudo_emit_endm,			lwasm_insn_cond | lwasm_insn_setsym | lwasm_insn_endm},
-/*
+
 	{ "setdp", 		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_setdp,		pseudo_resolve_setdp,			pseudo_emit_setdp,			lwasm_insn_normal},
 	{ "set",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_set,		pseudo_resolve_set,				pseudo_emit_set,			lwasm_insn_setsym},
+/*
 
 	{ "section",	{	-1, 	-1, 	-1, 	-1},	pseudo_parse_section,	pseudo_resolve_section,			pseudo_emit_section,		lwasm_insn_normal},
 	{ "sect",		{	-1, 	-1, 	-1, 	-1},	pseudo_parse_section,	pseudo_resolve_section,			pseudo_emit_section,		lwasm_insn_normal},
--- a/lwasm/lwasm.c	Sat Mar 27 22:59:15 2010 -0600
+++ b/lwasm/lwasm.c	Sat Mar 27 23:37:30 2010 -0600
@@ -88,6 +88,31 @@
 	va_end(args);
 }
 
+void lwasm_register_warning(asmstate_t *as, line_t *l, const char *msg, ...)
+{
+	lwasm_error_t *e;
+	va_list args;
+	char errbuff[1024];
+	int r;
+	
+	if (!l)
+		return;
+
+	va_start(args, msg);
+	
+	e = lw_alloc(sizeof(lwasm_error_t));
+	
+	e -> next = l -> err;
+	l -> err = e;
+	
+	as -> errorcount++;
+	
+	r = vsnprintf(errbuff, 1024, msg, args);
+	e -> mess = lw_strdup(errbuff);
+	
+	va_end(args);
+}
+
 int lwasm_next_context(asmstate_t *as)
 {
 	int r;
--- a/lwasm/lwasm.h	Sat Mar 27 22:59:15 2010 -0600
+++ b/lwasm/lwasm.h	Sat Mar 27 23:37:30 2010 -0600
@@ -99,7 +99,9 @@
 	unsigned char *output;				// output bytes
 	int outputl;						// size of output
 	int outputbl;						// size of output buffer
+	int dpval;							// direct page value
 	lwasm_error_t *err;					// list of errors
+	lwasm_error_t *warn;				// list of errors
 	line_t *prev;						// previous line
 	line_t *next;						// next line
 	
@@ -148,6 +150,7 @@
 	int errorcount;						// number of errors encountered
 	int inmacro;						// are we in a macro?
 	int skipcond;						// skipping a condition?
+	int skipcount;						// depth of "skipping"
 	int skipmacro;						// are we skipping in a macro?	
 	int endseen;						// have we seen an "end" pseudo?
 	int execaddr;						// address from "end"
@@ -181,6 +184,7 @@
 #ifndef ___lwasm_c_seen___
 
 extern void lwasm_register_error(asmstate_t *as, line_t *cl, const char *msg, ...);
+extern void lwasm_register_warning(asmstate_t *as, line_t *cl, const char *msg, ...);
 extern int lwasm_next_context(asmstate_t *as);
 extern void lwasm_emit(line_t *cl, int byte);
 extern void lwasm_emitop(line_t *cl, int opc);
--- a/lwasm/pass1.c	Sat Mar 27 22:59:15 2010 -0600
+++ b/lwasm/pass1.c	Sat Mar 27 23:37:30 2010 -0600
@@ -91,15 +91,20 @@
 		else
 		{
 			lw_expr_t te;
+
 			as -> line_tail -> next = cl;
+
+			// set the line address
 			te = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, cl -> prev);
 			cl -> addr = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, cl -> prev -> addr, te);
 			lw_expr_destroy(te);
 			lw_expr_simplify(cl -> addr, as);
+
+			// carry DP value forward
+			cl -> dpval = cl -> prev -> dpval;
 		}
 		as -> line_tail = cl;
 		as -> cl = cl;
-
 		// blank lines don't count for anything
 		// except a local symbol context break
 		if (!*line)
--- a/lwasm/pseudo.c	Sat Mar 27 22:59:15 2010 -0600
+++ b/lwasm/pseudo.c	Sat Mar 27 23:37:30 2010 -0600
@@ -511,6 +511,8 @@
 {
 	lw_expr_t e;
 	
+	l -> len = 0;
+	
 	e = lwasm_parse_expr(as, p);
 	if (!e)
 	{
@@ -527,6 +529,8 @@
 {
 	lw_expr_t e;
 	
+	l -> len = 0;
+	
 	if (!(l -> sym))
 	{
 		lwasm_register_error(as, l, "Missing symbol");
@@ -543,3 +547,363 @@
 	register_symbol(as, l, l -> sym, e, symbol_flag_none);
 	l -> symset = 1;
 }
+
+PARSEFUNC(pseudo_parse_set)
+{
+	lw_expr_t e;
+	
+	l -> len = 0;
+	
+	if (!(l -> sym))
+	{
+		lwasm_register_error(as, l, "Missing symbol");
+		return;
+	}
+	
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	
+	register_symbol(as, l, l -> sym, e, symbol_flag_set);
+	l -> symset = 1;
+}
+
+PARSEFUNC(pseudo_parse_setdp)
+{
+	lw_expr_t e;
+
+	l -> len = 0;
+	
+	if (as -> output_format == OUTPUT_OBJ)
+	{
+		lwasm_register_error(as, l, "SETDP not permitted for object target");
+		return;
+	}
+	
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "SETDP must be constant on pass 1");
+		return;
+	}
+	l -> dpval = lw_expr_intval(e) & 0xff;
+}
+
+PARSEFUNC(pseudo_parse_ifp1)
+{
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+	
+	lwasm_register_warning(as, l, "IFP1 if is not supported; ignoring");
+	
+}
+
+PARSEFUNC(pseudo_parse_ifp2)
+{
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+	
+	lwasm_register_warning(as, l, "IFP2 if is not supported; ignoring");
+}
+
+PARSEFUNC(pseudo_parse_ifeq)
+{
+	lw_expr_t e;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad expression");
+		return;
+	}
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "Conditions must be constant on pass 1");
+		return;
+	}
+	if (lw_expr_intval(e) != 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+PARSEFUNC(pseudo_parse_ifne)
+{
+	lw_expr_t e;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad expression");
+		return;
+	}
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "Conditions must be constant on pass 1");
+		return;
+	}
+	if (lw_expr_intval(e) == 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+
+PARSEFUNC(pseudo_parse_ifgt)
+{
+	lw_expr_t e;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad expression");
+		return;
+	}
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "Conditions must be constant on pass 1");
+		return;
+	}
+	if (lw_expr_intval(e) <= 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+PARSEFUNC(pseudo_parse_ifge)
+{
+	lw_expr_t e;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad expression");
+		return;
+	}
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "Conditions must be constant on pass 1");
+		return;
+	}
+	if (lw_expr_intval(e) < 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+PARSEFUNC(pseudo_parse_iflt)
+{
+	lw_expr_t e;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad expression");
+		return;
+	}
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "Conditions must be constant on pass 1");
+		return;
+	}
+	if (lw_expr_intval(e) >= 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+PARSEFUNC(pseudo_parse_ifle)
+{
+	lw_expr_t e;
+
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad expression");
+		return;
+	}
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "Conditions must be constant on pass 1");
+		return;
+	}
+	if (lw_expr_intval(e) > 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+PARSEFUNC(pseudo_parse_endc)
+{
+	l -> len = 0;
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount--;
+		if (as -> skipcount < 0)
+			as -> skipcond = 0;
+	}
+}
+
+PARSEFUNC(pseudo_parse_else)
+{
+	l -> len = 0;
+	
+	if (as -> skipmacro)
+		return;
+	
+	if (as -> skipcond)
+	{
+		if (as -> skipcount == 1)
+		{
+			as -> skipcount = 0;
+			as -> skipcond = 0;
+		}
+		return;
+	}
+	as -> skipcond = 1;
+	as -> skipcount = 1;
+}
+
+PARSEFUNC(pseudo_parse_ifdef)
+{
+	char *sym;
+	int i;
+	struct symtabe *s;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
+		/* do nothing */ ;
+	
+	sym = lw_strndup(*p, i);
+	
+	s = lookup_symbol(as, l, sym, -1, -1);
+	
+	lw_free(sym);
+	
+	if (!s)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+PARSEFUNC(pseudo_parse_ifndef)
+{
+	char *sym;
+	int i;
+	struct symtabe *s;
+	
+	l -> len = 0;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
+		/* do nothing */ ;
+	
+	sym = lw_strndup(*p, i);
+	
+	s = lookup_symbol(as, l, sym, -1, -1);
+	
+	lw_free(sym);
+
+	if (s)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+