changeset 57:035b95a3690f

Added conditional assembly and macros
author lost
date Mon, 05 Jan 2009 00:01:21 +0000
parents 55260a178667
children b1d81800bc91
files src/Makefile.am src/instab.c src/instab.h src/lwasm.c src/lwasm.h src/macro.c src/parse.c src/pass2.c src/pseudo.c
diffstat 9 files changed, 405 insertions(+), 208 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile.am	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/Makefile.am	Mon Jan 05 00:01:21 2009 +0000
@@ -1,3 +1,3 @@
 bin_PROGRAMS = lwasm
-lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c symbol.c output.c pseudo.c
+lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c symbol.c output.c pseudo.c macro.c
 EXTRA_DIST = instab.h lwasm.h expr.h util.h
--- a/src/instab.c	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/instab.c	Mon Jan 05 00:01:21 2009 +0000
@@ -59,6 +59,16 @@
 extern OPFUNC(pseudo_fcb);
 extern OPFUNC(pseudo_fdb);
 extern OPFUNC(pseudo_fqb);
+extern OPFUNC(pseudo_ifne);
+extern OPFUNC(pseudo_ifeq);
+extern OPFUNC(pseudo_ifgt);
+extern OPFUNC(pseudo_ifge);
+extern OPFUNC(pseudo_iflt);
+extern OPFUNC(pseudo_ifle);
+extern OPFUNC(pseudo_else);
+extern OPFUNC(pseudo_endc);
+extern OPFUNC(pseudo_macro);
+extern OPFUNC(pseudo_endm);
 
 instab_t instab[] =
 {
@@ -331,6 +341,19 @@
 
 	{ "error",	{ -1, -1, -1, -1},	pseudo_error },
 
+	{ "ifeq",	{ -1, -1, -1, -1}, 	pseudo_ifeq, 1 },
+	{ "ifne",	{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
+	{ "if",		{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
+	{ "ifgt",	{ -1, -1, -1, -1}, 	pseudo_ifgt, 1 },
+	{ "ifge",	{ -1, -1, -1, -1}, 	pseudo_ifge, 1 },
+	{ "iflt",	{ -1, -1, -1, -1}, 	pseudo_iflt, 1 },
+	{ "ifle",	{ -1, -1, -1, -1}, 	pseudo_ifle, 1 },
+	{ "endc",	{ -1, -1, -1, -1}, 	pseudo_endc, 1 },
+	{ "else",	{ -1, -1, -1, -1}, 	pseudo_else, 1 },
+
+	{ "macro",	{ -1, -1, -1, -1}, 	pseudo_macro,	1,	0 },
+	{ "endm",	{ -1, -1, -1, -1},	pseudo_endm,	1,	1 },	
+
 	/* flag end of table */	
 	{ NULL,		{ -0x1, -0x1, -0x1, -0x1 }, insn_inh }
 };
--- a/src/instab.h	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/instab.h	Mon Jan 05 00:01:21 2009 +0000
@@ -31,6 +31,8 @@
 	char *opcode;				/* the mneumonic */
 	int ops[4];					/* opcode values for up to four addr modes */
 	void (*fn)(asmstate_t *as, lwasm_line_t *l, char **optr, int opnum);
+	int iscond;					/* set if this should be dispatched even if skipping a condition/macro */
+	int endm;					/* end of macro? */
 } instab_t;
 
 #define OPFUNC(fn)	void (fn)(asmstate_t *as, lwasm_line_t *l, char **p, int opnum)
--- a/src/lwasm.c	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/lwasm.c	Mon Jan 05 00:01:21 2009 +0000
@@ -255,3 +255,9 @@
 	}
 	va_end(args);
 }
+
+int lwasm_next_context(asmstate_t *as)
+{
+	return (as -> nextcontext++);
+}
+
--- a/src/lwasm.h	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/lwasm.h	Mon Jan 05 00:01:21 2009 +0000
@@ -31,6 +31,16 @@
 #define OUTPUT_OBJ		2	// proprietary object file format
 #define OUTPUT_RAWREL	3	// raw bytes where ORG causes a SEEK in the file
 
+// structure for tracking macros
+typedef struct macrotab_s macrotab_t;
+struct macrotab_s
+{
+	char *name;
+	char **lines;
+	int numlines;
+	macrotab_t *next;
+};
+
 // structure for tracking errors
 typedef struct lwasm_error_s lwasm_error_t;
 struct lwasm_error_s
@@ -85,6 +95,8 @@
 	
 	lwasm_symbol_ent_t *symhead;	// first entry in symbol table
 	lwasm_symbol_ent_t *symtail;	// last entry in symbol table
+	
+	macrotab_t *macros;			// macro table
 
 	const char *infile;			// input file
 	const char *outfile;		// output file
@@ -94,6 +106,13 @@
 	int filelistlen;			// number of files in the list
 	
 	int endseen;				// set to true if "end" has been seen
+	int skipcond;				// skipping a condition?
+	int skipcount;				// how many?
+	int skipmacro;				// skipping a macro?
+	int inmacro;				// are we currently in a macro?
+	int macroex;				// current depth of macro expansion
+	int nextcontext;			// next context number
+	int skiplines;				// number of lines to skip
 } asmstate_t;
 
 #define PRAGMA_NOINDEX0TONONE	1
@@ -117,6 +136,9 @@
 __lwasm_E__ lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp);
 
 
+// return next context number and update it
+__lwasm_E__ int lwasm_next_context(asmstate_t *as);
+
 // also throw an error on expression eval failure
 // return 0 on ok, -1 on error
 #define EXPR_NOFLAG			0
--- a/src/macro.c	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/macro.c	Mon Jan 05 00:01:21 2009 +0000
@@ -24,71 +24,95 @@
 #include <stdlib.h>
 #include <string.h>
 #include "lwasm.h"
+#include "instab.h"
+#include "util.h"
 
-extern void resolve_insn(asmstate_t *as, sourceline_t *cl);
-
-void pseudo_macro(asmstate_t *as, sourceline_t *cl, char **optr)
+OPFUNC(pseudo_macro)
 {
 	macrotab_t *m;
 
+	// if skipping a condition, flag in a macro
+	if (as -> skipcond)
+	{
+		as -> skipmacro = 1;
+		return;
+	}
+
+	// actually define a macro
 	if (as -> inmacro)
 	{
-		errorp1(ERR_MACRO);
+		register_error(as, l, 1, "Attempt to define a macro inside a macro");
 		return;
 	}
+
 	as -> inmacro = 1;
+
+	// don't actually do anything if not pass 1
 	if (as -> passnum != 1)
 		return;
+
+
+	if (!l -> sym)
+	{
+		register_error(as, l, 1, "Macro definition with no effect - no symbol");
+		return;
+	}
 	
+	// search for macro by same name...
 	for (m = as -> macros; m; m = m -> next)
 	{
-		if (!strcmp(m -> name, cl -> symstr))
+		if (!strcmp(m -> name, l -> sym))
 			break;
 	}
 	if (m)
 	{
-		errorp1(ERR_DUPSYM);
+		register_error(as, l, 1, "Duplicate macro definition");
 		return;
 	}
-	m = calloc(sizeof(macrotab_t), 1);
-	m -> name = strdup(cl -> symstr);
+	
+	m = lwasm_alloc(sizeof(macrotab_t));
+	m -> name = lwasm_strdup(l -> sym);
 	m -> next = as -> macros;
+	m -> lines = NULL;
+	m -> numlines = 0;
 	as -> macros = m;
-	cl -> hassym = 0;
-	while (**optr && !isspace(**optr))
-		(*optr)++;
-	cl -> macrodef = 1;
+
+	while (**p && !isspace(**p))
+		(*p)++;
 }
 
-void pseudo_endm(asmstate_t *as, sourceline_t *cl, char **optr)
+OPFUNC(pseudo_endm)
 {
+	if (as -> skipcond)
+	{
+		as -> skipmacro = 0;
+		return;
+	}
+	
 	if (!as -> inmacro)
 	{
-		errorp1(ERR_ENDM);
+		register_error(as, l, 1, "ENDM without MACRO");
 		return;
 	}
 	
 	as -> inmacro = 0;
-	cl -> macrodef = 1;
+	
+	// a macro definition counts as a context break for local symbols
+	as -> context = lwasm_next_context(as);
 }
 
-int add_macro_line(asmstate_t *as, sourceline_t *cl, char *optr)
+// the current macro will ALWAYS be the first one in the table
+int add_macro_line(asmstate_t *as, char *optr)
 {
-	macroline_t *l;
-	
 	if (!as -> inmacro)
 		return 0;
 	
 	if (as -> passnum == 2)
 		return 1;
 
-	l = calloc(sizeof(macroline_t), 1);
-	l -> linetext = strdup(optr);
-	if (as -> macros -> linetail)
-		as -> macros -> linetail -> next = l;
-	as -> macros -> linetail = l;
-	if (!(as -> macros -> linehead))
-		as -> macros -> linehead = l;
+	as -> macros -> lines = lwasm_realloc(as -> macros -> lines, sizeof(char *) * as -> macros -> numlines + 1);
+	as -> macros -> lines[as -> macros -> numlines] = lwasm_strdup(optr);
+	as -> macros -> numlines += 1;
 	return 1;
 }
 
@@ -104,128 +128,196 @@
 
 // this is just like a regular operation function
 /*
-macro args are references by "\n" where 1 <= n <= 9
+macro args are referenced by "\n" where 1 <= n <= 9
 or by "\{n}"; a \ can be included by writing \\
+a comma separates argument but one can be included with "\,"
+whitespace ends argument list but can be included with "\ " or the like
+
+In pass 1, actually add the lines to the system, in pass 2, do not
+In pass 2, track the number of lines to skip because they already will be
+processed by this function - this will be in as -> skiplines
+
 */
-void expand_macro(asmstate_t *as, sourceline_t *cl, char **optr)
+int expand_macro(asmstate_t *as, lwasm_line_t *l, char **p, char *opc)
 {
-	char **args = NULL;
-	int nargs = 0;
-	int c;
-	sourceline_t *nl;
-	int nline = 1;
+	int lc;
+	lwasm_line_t *cl, *nl;
+	int oldcontext;
 	macrotab_t *m;
-	macroline_t *ml;
-	char *buff = NULL;
-	int bufflen = 0, buffloc;
+
+	char **args = NULL;		// macro arguments
+	int nargs;				// number of arguments
+
+	char *p2, *p3;
 	
-	m = cl -> macro;
+	int bloc, blen;
+	char *linebuff;
+
+	for (m = as -> macros; m; m = m -> next)
+	{
+		if (!strcmp(opc, m -> name))
+			break;
+	}
+	// signal no macro expansion
+	if (!m)
+		return -1;
 	
-	// step the first: parse arguments
-	while (**optr && !isspace(**optr))
+
+	// save current symbol context for after macro expansion
+	oldcontext = as -> context;
+
+	cl = l;
+
+	as -> context = lwasm_next_context(as);
+
+	// step 1: parse arguments (pass 1 only)
+	if (as -> passnum == 1)
 	{
-		c = 0;
-		while ((*optr)[c] && !isspace((*optr)[c]) && (*optr)[c] != ',')
+		while (**p && !isspace(**p) && **p != ',')
 		{
-			c++;
+			p2 = *p;
+			while (*p2 && !isspace(*p2) && *p2 != ',')
+			{
+				if (*p2 == '\\')
+				{
+					if (p2[1])
+						p2++;
+				}
+			}
+			
+			// have arg here
+			args = lwasm_realloc(args, nargs + 1);
+			args[nargs] = lwasm_alloc(p2 - *p + 1);
+			args[nargs][p2 - *p] = '\0';
+			memcpy(args[nargs], *p, p2 - *p);
+			*p = p2;
+			
+			// now collapse out "\" characters
+			for (p3 = p2 = args[nargs]; *p2; p2++, p3++)
+			{
+				if (*p2 == '\\' && p2[1])
+				{
+					p2++;
+				}
+				*p3 = *p2;
+			}
+			*p3 = '\0';
+			
+			nargs++;
 		}
-		args = realloc(args, sizeof(char *) * (nargs + 1));
-		args[nargs] = malloc(c + 1);
-		strncpy(args[nargs], *optr, c);
-		args[nargs][c] = '\0';
-		nargs++;
-		*optr += c;
-		if (**optr == ',')
-			(*optr)++;
 	}
 	
-	// step the second: iterate over the lines and expand arguments and add
-	// them after "cl"
-	for (ml = m -> linehead; ml; ml = ml -> next)
+	// step 2: iterate over the lines
+	if (as -> passnum == 2)
+	{
+		// pass 2 only - parse the lines and count them
+		for (lc = 0; lc < m -> numlines; lc++)
+		{
+			cl = cl -> next;
+			as -> skiplines++;
+			lwasm_parse_line(as, cl);
+		}
+	}
+	else
 	{
-		nl = calloc(sizeof(sourceline_t), 1);
-		
-		nl -> lineno = nline++;
-		nl -> sourcefile = m -> name;
-		nl -> opcode = -1;
-		nl -> addrmode = -1;
-		nl -> addr = as -> addr;
-		nl -> dpval = as -> dpval;
-		nl -> prev = cl;
-		if (!(cl -> next))
-			as -> source_tail = nl;
-		nl -> next = cl -> next;
-		cl -> next = nl;
+		// pass 1 only - construct the lines and parse them
+		for (lc = 0; lc < m -> numlines; lc++)
+		{
+			nl = lwasm_alloc(sizeof(lwasm_line_t));
+			nl -> text = lwasm_strdup(linebuff);
+			nl -> lineno = lc + 1;
+			nl -> filename = m -> name;
+			nl -> next = NULL;
+			nl -> prev = as -> linestail;
+			nl -> err = NULL;
+			nl -> fsize = 0;
+			nl -> sym = NULL;
+			nl -> bytes = NULL;
+			nl -> codelen = 0;
+			nl -> codesize = 0;
+			nl -> nocodelen = 0;
+			nl -> addrset = 0;
+			nl -> symaddr = -1;
+			if (as -> linestail)
+				as -> linestail -> next = nl;
+			as -> linestail = nl;
+			if (!(as -> lineshead))
+				as -> lineshead = nl;
 
-		buffloc = 0;
-		c = 0;
-		while (ml -> linetext[c])
-		{
-			int ch;
-			ch = ml -> linetext[c++];
-			if (ch == '{')
+			bloc = blen = 0;
+			linebuff = NULL;
+			for (p2 = m -> lines[lc]; *p2; p2++)
 			{
-				int v = 0;
-			again:
-				ch = ml -> linetext[c++];
-				if (!ch)
+				if (*p2 == '\\' && isdigit(p2[1]))
 				{
-					c--;
+					int n;
+					
+					p2++;
+					n = *p2 - '0';
+					if (n == 0)
+					{
+						for (p3 = m -> name; p3; p3++)
+							macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
+						continue;
+					}
+					if (n < 1 || n > nargs)
+						continue;
+					for (p3 = args[n]; p3; p3++)
+						macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
 					continue;
 				}
-				if (ch >= '0' && ch <= '9')
-				{
-					v = v * 10 + (ch - '0');
-					goto again;
-				}
-				if (ch == '}')
+				else if (*p2 == '{')
 				{
-					v--;
-					if (v < nargs)
+					int n = 0, n2;
+					p2++;
+					while (*p2 && isdigit(*p2))
 					{
-						char *t;
-						for (t = args[v]; *t; t++)
-						{
-							macro_add_to_buff(&buff, &buffloc, &bufflen, *t);
-						}
+						n2 = *p2 - '0';
+						if (n2 < 0 || n2 > 9)
+							n2 = 0;
+						n = n * 10 + n2;
+						p2++;
 					}
+					if (*p2 == '}')
+						p2++;
+					 
+					if (n == 0)
+					{
+						for (p3 = m -> name; p3; p3++)
+							macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
+						continue;
+					}
+					if (n < 1 || n > nargs)
+						continue;
+					for (p3 = args[n]; p3; p3++)
+						macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
 					continue;
 				}
 				else
-					continue;
-			}
-			else if (ch == '\\' && ml -> linetext[c])
-			{
-				ch = ml -> linetext[c++];
-				if (ch >= '1' && ch <= '9')
 				{
-					ch -= '1';
-					if (ch < nargs)
-					{
-						char *t;
-						for (t = args[ch]; *t; t++)
-						{
-							macro_add_to_buff(&buff, &buffloc, &bufflen, *t);
-						}
-					}
-				}
-				else
-				{
-					c--;
-					macro_add_to_buff(&buff, &buffloc, &bufflen, '\\');
+					macro_add_to_buff(&linebuff, &bloc, &blen, *p2);
 				}
 			}
-			else
-			{
-				macro_add_to_buff(&buff, &buffloc, &bufflen, ch);
-			}
+
+			nl -> text = linebuff;
+
+			lwasm_parse_line(as, nl);
+			if (as -> endseen)
+				break;
+
 		}
-		macro_add_to_buff(&buff, &buffloc, &bufflen, 0);
-		nl -> line = strdup(buff);
+	}
+	
+	// restore context from before the macro was called
+	as -> context = oldcontext;
 
-		resolve_insn(as, nl);
-		cl = nl;
+	// clean up
+	while (nargs)
+	{
+		lwasm_free(args[--nargs]);
 	}
-	if (buff)
-		free(buff);
+	lwasm_free(args);
+
+	// indicate a macro was expanded
+	return 0;	
 }
--- a/src/parse.c	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/parse.c	Mon Jan 05 00:01:21 2009 +0000
@@ -43,7 +43,8 @@
 	
 	if (!*p)
 	{
-		as -> context += 1;
+		if (as -> inmacro == 0)
+			as -> context = lwasm_next_context(as);
 		return 0;
 	}
 	
@@ -81,7 +82,8 @@
 			p++;
 		if (!*p)
 		{
-			as -> context += 1;
+			if (as -> inmacro == 0)
+				as -> context = lwasm_next_context(as);
 			return 0;
 		}
 	}
@@ -112,8 +114,6 @@
 	while (*p2 && isspace(*p2))
 		p2++;
 
-	// check for macro (pass 1)
-	
 	// look up instruction in insn table
 	for (opnum = 0; instab[opnum].opcode; opnum++)
 	{
@@ -121,7 +121,18 @@
 			break;
 	}
 	
-	if (!(instab[opnum].opcode) || !(instab[opnum].fn))
+	if (as -> inmacro && instab[opnum].endm == 0)
+	{
+		add_macro_line(as, l -> text);
+	}
+
+	if (as -> inmacro == 0 && as -> skipcond == 0)
+	{
+		if (expand_macro(as, l, &p2, opc) == 0)
+			goto done_line;
+	}
+	
+	if (!(instab[opnum].opcode) || !(instab[opnum].fn) && !(as -> skipcond || as -> inmacro))
 	{
 		// invalid operation code, throw error
 		register_error(as, l, 1, "Invalid operation code '%s'", opc);
@@ -131,9 +142,11 @@
 		return -1;
 	}
 
-	// dispatch handler
-	(instab[opnum].fn)(as, l, &p2, opnum);
-	
+	// dispatch handler if we're not ignoring items
+	if (as -> skipcond == 0 && as -> inmacro == 0 && !(instab[opnum].iscond))
+		(instab[opnum].fn)(as, l, &p2, opnum);
+
+done_line:
 	lwasm_free(opc);
 	if (sym)
 		lwasm_free(sym);
--- a/src/pass2.c	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/pass2.c	Mon Jan 05 00:01:21 2009 +0000
@@ -37,8 +37,19 @@
 	as -> addr = 0;
 	as -> context = 0;
 	as -> endseen = 0;
-	
+	as -> skipcond = 0;
+	as -> skipcount = 0;
+	as -> skipmacro = 0;
+	as -> inmacro = 0;
+	as -> nextcontext = 1;
+	as -> skiplines = 0;
+			
 	// iterate over all the lines and re-parse them
 	for (l = as -> lineshead; l && !(as -> endseen); l = l -> next)
-		lwasm_parse_line(as, l);
+	{
+		if (as -> skiplines)
+			as -> skiplines--;
+		else
+			lwasm_parse_line(as, l);
+	}
 }
--- a/src/pseudo.c	Sun Jan 04 21:43:05 2009 +0000
+++ b/src/pseudo.c	Mon Jan 05 00:01:21 2009 +0000
@@ -75,13 +75,13 @@
 {
 	int v1;
 	char *fn;
-
+	
 	// only include files on pass 1
 	// but make sure local include context is right
 	// for the next line...
 	if (as -> passnum != 1)
 	{
-		as -> context += 1;
+		as -> context = lwasm_next_context(as);
 		return;
 	}
 
@@ -118,7 +118,7 @@
 	fn[v1] = '\0';
 
 	// end local label context on include	
-	as -> context += 1;
+	as -> context = lwasm_next_context(as);
 	if (lwasm_read_file(as, fn) < 0)
 	{
 		register_error(as, l, 1, "File include error (%s)", fn);
@@ -573,137 +573,165 @@
 	}
 }
 
-/*
 // don't need to do anything if we are executing one of these
-void pseudo_endc(asmstate_t *as, sourceline_t *cl, char **optr)
+OPFUNC(pseudo_endc)
 {
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount -= 1;
+		if (as -> skipcount <= 0)
+		{
+			as -> skipcond = 0;
+		}
+	}
 	return;
 }
 
 // if "else" executes, we must be going into an "ignore" state
-void pseudo_else(asmstate_t *as, sourceline_t *cl, char **optr)
+OPFUNC(pseudo_else)
 {
+	if (as -> skipmacro)
+		return;
+	
+	if (as -> skipcond)
+	{
+		if (as -> skipcount == 1)
+		{
+			as -> skipcount = 0;
+			as -> skipcond = 0;
+		}
+		return;
+	}
+	
 	as -> skipcond = 1;
 	as -> skipcount = 1;
 }
 
-void pseudo_ifne(asmstate_t *as, sourceline_t *cl, char **optr)
+OPFUNC(pseudo_ifne)
 {
 	int v1;
 	int rval;
-//	printf("ifne %s\n", *optr);
-	rval = eval_expr(as, cl, optr, &v1);
-	if (rval < 0)
-	{
-		errorp1(ERR_BADCOND);
-	}
-	else
+
+	if (as -> skipcond && !(as -> skipmacro))
 	{
-//	printf("Condition value: %d\n", v1);
-		if (!v1)
-		{
-//		printf("condition no match\n");
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
+		as -> skipcount++;
+		return;
+	}
+
+	rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1);
+	if (rval < 0)
+		return;
+	if (!v1)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
 	}
 }
-void pseudo_ifeq(asmstate_t *as, sourceline_t *cl, char **optr)
+
+OPFUNC(pseudo_ifeq)
 {
 	int v1;
 	int rval;
-	
-	rval = eval_expr(as, cl, optr, &v1);
-	if (rval < 0)
+
+	if (as -> skipcond && !(as -> skipmacro))
 	{
-		errorp1(ERR_BADCOND);
+		as -> skipcount++;
+		return;
 	}
-	else
+
+	rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1);
+	if (rval < 0)
+		return;
+	if (v1)
 	{
-		if (v1)
-		{
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
+		as -> skipcond = 1;
+		as -> skipcount = 1;
 	}
 }
-void pseudo_iflt(asmstate_t *as, sourceline_t *cl, char **optr)
+
+OPFUNC(pseudo_iflt)
 {
 	int v1;
 	int rval;
-	
-	rval = eval_expr(as, cl, optr, &v1);
-	if (rval < 0)
+
+	if (as -> skipcond && !(as -> skipmacro))
 	{
-		errorp1(ERR_BADCOND);
+		as -> skipcount++;
+		return;
 	}
-	else
+
+	rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1);
+	if (rval < 0)
+		return;
+	if (v1 >= 0)
 	{
-		if (v1 >= 0)
-		{
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
+		as -> skipcond = 1;
+		as -> skipcount = 1;
 	}
 }
-void pseudo_ifle(asmstate_t *as, sourceline_t *cl, char **optr)
+
+OPFUNC(pseudo_ifle)
 {
 	int v1;
 	int rval;
-	
-	rval = eval_expr(as, cl, optr, &v1);
-	if (rval < 0)
+
+	if (as -> skipcond && !(as -> skipmacro))
 	{
-		errorp1(ERR_BADCOND);
+		as -> skipcount++;
+		return;
 	}
-	else
+
+	rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1);
+	if (rval < 0)
+		return;
+	if (v1 > 0)
 	{
-		if (v1 > 0)
-		{
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
+		as -> skipcond = 1;
+		as -> skipcount = 1;
 	}
 }
-void pseudo_ifgt(asmstate_t *as, sourceline_t *cl, char **optr)
+
+OPFUNC(pseudo_ifgt)
 {
 	int v1;
 	int rval;
-	
-	rval = eval_expr(as, cl, optr, &v1);
-	if (rval < 0)
+
+	if (as -> skipcond && !(as -> skipmacro))
 	{
-		errorp1(ERR_BADCOND);
+		as -> skipcount++;
+		return;
 	}
-	else
+
+	rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1);
+	if (rval < 0)
+		return;
+	if (v1 <= 0)
 	{
-		if (v1 <= 0)
-		{
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
+		as -> skipcond = 1;
+		as -> skipcount = 1;
 	}
 }
-void pseudo_ifge(asmstate_t *as, sourceline_t *cl, char **optr)
+
+OPFUNC(pseudo_ifge)
 {
 	int v1;
 	int rval;
-	
-	rval = eval_expr(as, cl, optr, &v1);
-	if (rval < 0)
+
+	if (as -> skipcond && !(as -> skipmacro))
 	{
-		errorp1(ERR_BADCOND);
+		as -> skipcount++;
+		return;
 	}
-	else
+
+	rval = lwasm_expr_result(as, l, p, EXPR_PASS1CONST, &v1);
+	if (rval < 0)
+		return;
+	if (v1 < 0)
 	{
-		if (v1 < 0)
-		{
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
+		as -> skipcond = 1;
+		as -> skipcount = 1;
 	}
 }
-*/
 
 OPFUNC(pseudo_error)
 {