changeset 236:a58f49a77441

Added os9 target, pragma to control whether $ localizes a symbol, and fixed some condition nesting bugs
author lost
date Fri, 14 Aug 2009 03:22:26 +0000
parents aa0056ca7319
children dca5938a64aa
files ChangeLog lwasm/Makefile.am lwasm/instab.c lwasm/lwasm.c lwasm/lwasm.h lwasm/main.c lwasm/os9.c lwasm/output.c lwasm/parse.c lwasm/pass1.c lwasm/pass2.c lwasm/pragma.c lwasm/pseudo.c lwasm/symbol.c
diffstat 14 files changed, 335 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Jun 12 05:25:41 2009 +0000
+++ b/ChangeLog	Fri Aug 14 03:22:26 2009 +0000
@@ -16,6 +16,7 @@
 [!] Fixed error in the fix for invalid operands included in 2.4 [LWASM]
 [b] Fixed bug with "include" directive operand parsing [LWASM]
 [b] Fixed additional parsing errors with pseudo ops [LWASM]
+[b] Fixed parsing error with various conditional nesting situations [LWASM]
 [+] Added includebin directive to include the literal contents of a binary
     file at the current assembly address. [LWASM]
 [+] Added || and && as boolean or and boolean and respectively [LWASM]
@@ -27,6 +28,10 @@
     [LWASM]
 [+] ALIGN now takes an optional padding value (ALIGN align,pad) to specify
     the byte value that will be used for padding if needed [LWASM]
+[+] Added OS9 module target along with the OS9, MOD, and EMOD pseudo ops
+    to allow building OS9 modules [LWASM]
+[+] Added pragma "dollarlocal"/"nodollarlocal" and "dollarnotlocal"/
+    "nodollarnotlocal" to control whether $ localizes a symbol [LWASM]
 [ ] Fixed a few cosmetic issues with error reporting
 
 Version 2.4
--- a/lwasm/Makefile.am	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/Makefile.am	Fri Aug 14 03:22:26 2009 +0000
@@ -1,5 +1,5 @@
 AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib
 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 macro.c pragma.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 pragma.c os9.c
 lwasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -lgnu
 EXTRA_DIST = instab.h lwasm.h expr.h util.h
--- a/lwasm/instab.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/instab.c	Fri Aug 14 03:22:26 2009 +0000
@@ -66,6 +66,8 @@
 extern OPFUNC(pseudo_ifge);
 extern OPFUNC(pseudo_iflt);
 extern OPFUNC(pseudo_ifle);
+extern OPFUNC(pseudo_ifp1);
+extern OPFUNC(pseudo_ifp2);
 extern OPFUNC(pseudo_else);
 extern OPFUNC(pseudo_endc);
 extern OPFUNC(pseudo_macro);
@@ -83,6 +85,10 @@
 extern OPFUNC(pseudo_noop);
 extern OPFUNC(pseudo_includebin);
 
+extern OPFUNC(pseudo_os9);
+extern OPFUNC(pseudo_mod);
+extern OPFUNC(pseudo_emod);
+
 instab_t instab[] =
 {
 	{ "abx",	{	0x3a,	-0x1,	-0x1,	-0x1	},	insn_inh },
@@ -371,11 +377,16 @@
 
 	{ "includebin", { -1, -1, -1, -1}, pseudo_includebin },
 	{ "include", { -1, -1, -1, -1 }, pseudo_include },
+	{ "use",	{ -1, -1, -1, -1 },	pseudo_include },
 	
 	{ "align", { -1, -1, -1, -1 },	pseudo_align },
 
 	{ "error",	{ -1, -1, -1, -1},	pseudo_error },
 
+	// these are *dangerous*
+	{ "ifp1",	{ -1, -1, -1, -1},	pseudo_ifp1, 1 },
+	{ "ifp2",	{ -1, -1, -1, -1},	pseudo_ifp2, 1 },
+
 	{ "ifeq",	{ -1, -1, -1, -1}, 	pseudo_ifeq, 1 },
 	{ "ifne",	{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
 	{ "if",		{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
@@ -402,6 +413,11 @@
 	
 	{ "pragma",	{ -1, -1, -1, -1},	pseudo_pragma },
 	{ "*pragma",	{ -1, -1, -1, -1},	pseudo_starpragma },
+	
+	// for os9 target
+	{ "os9",	{ -1, -1, -1, -1 }, pseudo_os9 },
+	{ "mod",	{ -1, -1, -1, -1 },	pseudo_mod },
+	{ "emod",	{ -1, -1, -1, -1 },	pseudo_emod },
 
 	/* for compatibility with gcc6809 output... */
 	{ ".area",	{ -1, -1, -1, -1},	pseudo_section },
@@ -435,6 +451,12 @@
 
 	// for compatibility
 	{ ".end", 	{ -1, -1, -1, -1 }, pseudo_end },
+	
+	// extra ops that are ignored because they are generally only for
+	// pretty printing the listing
+	{ "nam",	{ -1, -1, -1, -1 }, pseudo_noop },
+	{ "pag",	{ -1, -1, -1, -1 }, pseudo_noop },
+	{ "ttl",	{ -1, -1, -1, -1 }, pseudo_noop },
 
 	/* flag end of table */	
 	{ NULL,		{ -0x1, -0x1, -0x1, -0x1 }, insn_inh }
--- a/lwasm/lwasm.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/lwasm.c	Fri Aug 14 03:22:26 2009 +0000
@@ -79,6 +79,13 @@
 		register_error(as, l, 1, "Output not allowed inside BSS sections");
 		return;
 	}
+	
+	if (as -> outformat == OUTPUT_OS9 && as -> inmod == 0)
+	{
+		register_error(as, l, 1, "Output not allowed outside of module in OS9 mode");
+		return;
+	}
+	
 	if (as -> passnum == 1)
 		return;
 
@@ -90,6 +97,23 @@
 	}
 	l -> bytes[l -> codelen] = b & 0xff;
 	l -> codelen += 1;
+	
+	if (as -> outformat == OUTPUT_OS9 && as -> inmod)
+	{
+		// calc the CRC
+		b &= 0xff;
+		
+		b ^= (as -> crc) >> 16;
+		as -> crc <<= 8;
+		as -> crc ^= b << 1;
+		as -> crc ^= b << 6;
+		b ^= b << 1;
+		b ^= b << 2;
+		b ^= b << 4;
+		if (b & 0x80)
+			as -> crc ^= 0x800021;
+		as -> crc &= 0xffffff;
+	}
 }
 
 void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o)
--- a/lwasm/lwasm.h	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/lwasm.h	Fri Aug 14 03:22:26 2009 +0000
@@ -31,6 +31,7 @@
 #define OUTPUT_RAW		1	// raw sequence of bytes
 #define OUTPUT_OBJ		2	// proprietary object file format
 #define OUTPUT_RAWREL	3	// raw bytes where ORG causes a SEEK in the file
+#define OUTPUT_OS9		4	// os9 module target
 
 // structure for tracking sections
 typedef struct section_reloc_list_s section_reloc_list_t;
@@ -118,6 +119,7 @@
 	lwasm_expr_stack_t *exprs[4];	// non-constant expression values
 	int exprvals[4];	// constant expression values
 	char *exprends[4];	// pointer to character after end of expression
+	int inmod;			// in an os9 module
 	
 	sectiontab_t *sect;	// which section is the line in?
 };
@@ -182,7 +184,11 @@
 	sectiontab_t *csect;		// current section - NULL if not in one
 	
 	// only 6809 ops?
-	int no6309;					
+	int no6309;	
+	
+	// for os9 mode
+	int inmod;					// in a module?
+	unsigned long crc;			// running crc count
 } asmstate_t;
 
 // do not rewrite XXX,r to ,r if XXX evaluates to 0
@@ -191,9 +197,10 @@
 #define PRAGMA_UNDEFEXTERN		2
 // allow C-style escapes in fcc, fcs, and fcn directives
 #define PRAGMA_CESCAPES			4
-
 // allow "export <undefsym>" to import the symbol
 #define PRAGMA_IMPORTUNDEFEXPORT	8
+// don't have $ as a local symbol
+#define PRAGMA_DOLLARNOTLOCAL	16
 
 #ifndef __lwasm_c_seen__
 #define __lwasm_E__ extern
--- a/lwasm/main.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/main.c	Fri Aug 14 03:22:26 2009 +0000
@@ -94,6 +94,11 @@
 			as -> outformat = OUTPUT_RAW;
 		else if (!strcasecmp(arg, "obj"))
 			as -> outformat = OUTPUT_OBJ;
+		else if (!strcasecmp(arg, "os9"))
+		{
+			as -> pragmas |= PRAGMA_DOLLARNOTLOCAL;
+			as -> outformat = OUTPUT_OS9;
+		}
 		else
 		{
 			fprintf(stderr, "Invalid output format: %s\n", arg);
@@ -146,7 +151,7 @@
 	{ "debug",		'd',	0,		0,
 				"Set debug mode"},
 	{ "format",		'f',	"TYPE",	0,
-				"Select output format: decb, raw, obj"},
+				"Select output format: decb, raw, obj, os9"},
 	{ "list",		'l',	"FILE",	OPTION_ARG_OPTIONAL,
 				"Generate list [to FILE]"},
 	{ "decb",		'b',	0,		0,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/os9.c	Fri Aug 14 03:22:26 2009 +0000
@@ -0,0 +1,177 @@
+/*
+os9.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 <http://www.gnu.org/licenses/>.
+
+
+This file implements the various pseudo operations related to OS9 target
+*/
+#include <config.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+#include "util.h"
+
+OPFUNC(pseudo_os9)
+{
+	int r, rval;
+	
+	if (as -> outformat != OUTPUT_OS9)
+	{
+		register_error(as, l, 1, "os9 directive only valid for OS9 target");
+		return;
+	}
+	
+	// fetch immediate value
+	r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
+	if (r != 0)
+		rval = 0;
+	if (r == 1 && as -> passnum == 2)
+		register_error(as, l, 2, "Illegal external or intersegment reference");
+
+	// SWI2; FCB ...
+	lwasm_emit(as, l, 0x10);
+	lwasm_emit(as, l, 0x3f);
+	lwasm_emit(as, l, rval);
+}
+
+OPFUNC(pseudo_mod)
+{
+	int modvals[6];
+	int r, v, i;
+	
+	if (as -> outformat != OUTPUT_OS9)
+	{
+		register_error(as, l, 1, "mod directive only valid for OS9 target");
+		return;
+	}
+	
+	if (as -> inmod)
+	{
+		register_error(as, l, 1, "Already in a module!");
+		return;
+	}
+
+	// parse 6 expressions...
+	for (i = 0; i < 5; i++)
+	{
+		r = lwasm_expr_result2(as, l, p, 0, &v, -1);
+		if (r < 0)
+			return;
+		if (r > 0)
+		{
+			register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)");
+			v = 0;
+		}
+		else
+		{
+			modvals[i] = v;
+		}
+		if (**p != ',')
+		{
+			register_error(as, l, 1, "Bad operand");
+			return;
+		}
+		(*p)++;
+	}
+	r = lwasm_expr_result2(as, l, p, 0, &v, -1);
+	if (r < 0)
+		return;
+	if (r > 0)
+	{
+		register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)");
+		v = 0;
+	}
+	else
+	{
+		modvals[5] = v;
+	}
+
+	l -> inmod = 1;
+	
+	// we have an implicit ORG 0 with "mod"
+	l -> codeaddr = 0;
+	l -> addrset = 1;
+	as -> addr = 0;
+
+	// init crc
+	as -> crc = 0xffffff;
+	as -> inmod = 1;
+
+	// sync bytes
+	lwasm_emit(as, l, 0x87);
+	lwasm_emit(as, l, 0xcd);
+	
+	// mod length
+	lwasm_emit(as, l, modvals[0] >> 8);
+	lwasm_emit(as, l, modvals[0] & 0xff);
+	
+	// name offset
+	lwasm_emit(as, l, modvals[1] >> 8);
+	lwasm_emit(as, l, modvals[1] & 0xff);
+	
+	// type
+	lwasm_emit(as, l, modvals[2]);
+	
+	// flags/rev
+	lwasm_emit(as, l, modvals[3]);
+	
+	// header check
+	lwasm_emit(as, l, ~(0x87 ^ 0xCD ^ (modvals[0] >> 8) ^ (modvals[0] & 0xff)
+		^ (modvals[1] >> 8) ^ (modvals[1] & 0xff)
+		^ modvals[2] ^ modvals[3]));
+	
+	// module type specific output
+	// note that these are handled the same for all so
+	// there need not be any special casing
+	
+	// exec offset or fmgr name offset
+	lwasm_emit(as, l, modvals[4] >> 8);
+	lwasm_emit(as, l, modvals[4] & 0xff);
+	
+	// data size or drvr name offset
+	lwasm_emit(as, l, modvals[5] >> 8);
+	lwasm_emit(as, l, modvals[5] & 0xff);
+}
+
+OPFUNC(pseudo_emod)
+{
+	unsigned long tcrc;
+	
+	if (as -> outformat != OUTPUT_OS9)
+	{
+		register_error(as, l, 1, "emod directive only valid for OS9 target");
+		return;
+	}
+	
+	if (!(as -> inmod))
+	{
+		register_error(as, l, 1, "not in a module!");
+		return;
+	}
+	
+	// don't mess with CRC!
+	tcrc = as -> crc;
+	lwasm_emit(as, l, tcrc >> 16);
+	lwasm_emit(as, l, tcrc >> 8);
+	lwasm_emit(as, l, tcrc);
+	as -> inmod = 0;
+}
--- a/lwasm/output.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/output.c	Fri Aug 14 03:22:26 2009 +0000
@@ -36,6 +36,7 @@
 void write_code_decb(asmstate_t *as, FILE *of);
 void write_code_rawrel(asmstate_t *as, FILE *of);
 void write_code_obj(asmstate_t *as, FILE *of);
+void write_code_os9(asmstate_t *as, FILE *of);
 
 // this prevents warnings about not using the return value of fwrite()
 #define writebytes(s, l, c, f)	do { int r; r = fwrite((s), (l), (c), (f)); } while (0)
@@ -76,6 +77,10 @@
 		write_code_obj(as, of);
 		break;
 
+	case OUTPUT_OS9:
+		write_code_os9(as, of);
+		break;
+
 	default:
 		fprintf(stderr, "BUG: unrecognized output format when generating output file\n");
 		fclose(of);
@@ -131,6 +136,30 @@
 	}
 }
 
+
+/*
+OS9 target also just writes all the bytes in order. No need for anything
+else.
+*/
+void write_code_os9(asmstate_t *as, FILE *of)
+{
+	lwasm_line_t *cl;
+	
+	for (cl = as -> lineshead; cl; cl = cl -> next)
+	{
+		if (cl -> inmod == 0)
+			continue;
+		if (cl -> nocodelen)
+		{
+			int i;
+			for (i = 0; i < cl -> nocodelen; i++)
+				writebytes("\0", 1, 1, of);
+			continue;
+		}
+		writebytes(cl -> bytes, cl -> codelen, 1, of);
+	}
+}
+
 void write_code_decb(asmstate_t *as, FILE *of)
 {
 	long preambloc;
--- a/lwasm/parse.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/parse.c	Fri Aug 14 03:22:26 2009 +0000
@@ -47,6 +47,7 @@
 	
 	p = l -> text;
 	l -> sect = as -> csect;
+	l -> inmod = as -> inmod;
 
 	// blank lines are a no brainer
 	if (!*p)
@@ -186,8 +187,8 @@
 			(instab[opnum].fn)(as, l, &p2, opnum);
 			
 			// if we didn't end on a "space" character or EOL, throw error
-			if (*p2 && !isspace(*p2) && !(l -> err))
-				register_error(as, l, 1, "Bad operand");
+			if (*p2 && !isspace(*p2) && !(l -> err) && as -> passnum == 1)
+				register_error(as, l, 1, "Bad operand: %s (%d)", p2, as -> passnum);
 		}
 		else
 		{
--- a/lwasm/pass1.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/pass1.c	Fri Aug 14 03:22:26 2009 +0000
@@ -164,6 +164,8 @@
 	as -> passnum = 1;
 	as -> addr = 0;
 	as -> nextcontext = 1;
+
+	as -> inmod = 0;
 	
 	debug_message(1, "Entering pass 1");
 	if (lwasm_read_file(as, as -> infile) < 0)
--- a/lwasm/pass2.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/pass2.c	Fri Aug 14 03:22:26 2009 +0000
@@ -43,6 +43,7 @@
 	as -> nextcontext = 1;
 	as -> skiplines = 0;
 	as -> dpval = 0;
+	as -> inmod = 0;
 	
 	for (st = as -> sections; st; st = st -> next)
 		st -> offset = 0;
--- a/lwasm/pragma.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/pragma.c	Fri Aug 14 03:22:26 2009 +0000
@@ -117,6 +117,14 @@
 	{
 		as -> pragmas &= ~PRAGMA_IMPORTUNDEFEXPORT;
 	}
+	else if (!strcasecmp(pragma, "dollarnotlocal") || !strcasecmp(pragma, "nodollarlocal"))
+	{
+		as -> pragmas |= PRAGMA_DOLLARNOTLOCAL;
+	}
+	else if (!strcasecmp(pragma, "dollarlocal") || !strcasecmp(pragma, "nodollarnotlocal"))
+	{
+		as -> pragmas &= ~PRAGMA_DOLLARNOTLOCAL;
+	}
 	else
 	{
 		if (error)
--- a/lwasm/pseudo.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/pseudo.c	Fri Aug 14 03:22:26 2009 +0000
@@ -757,6 +757,7 @@
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
@@ -779,6 +780,7 @@
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
@@ -799,15 +801,14 @@
 		return;
 	}
 	
-	for (p2 = *p; *p2 && !isspace(*p2); p2++)
+	for (p2 = *p; **p && !isspace(**p); (*p)++)
 		/* do nothing */ ;
 	
-	sym = lwasm_alloc(p2 - *p + 1);
-	memcpy(sym, *p, p2 - *p);
-	sym[p2 - *p] = '\0';
-	
-	*p = p2;
+	sym = lwasm_alloc(*p - p2 + 1);
+	memcpy(sym, p2, *p - p2);
+	sym[*p - p2] = '\0';
 
+//	fprintf(stderr, "STUFF: %s; '%s'; '%s' (%d)\n", p2, *p, sym, as -> passnum);
 	se = lwasm_find_symbol(as, sym, l -> context);
 	if (!se)
 		se = lwasm_find_symbol(as, sym, -1);
@@ -831,10 +832,11 @@
 	lwasm_symbol_ent_t *se;
 	char *sym;
 	char *p2;
-	
+
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
@@ -864,6 +866,7 @@
 	
 	*p = p2;
 
+//	fprintf(stderr, "STUFF2: %s; '%s'; '%s' (%d)\n", *p, p2, sym, as -> passnum);
 	se = lwasm_find_symbol(as, sym, l -> context);
 	if (!se)
 		se = lwasm_find_symbol(as, sym, -1);
@@ -882,6 +885,38 @@
 	}
 }
 
+OPFUNC(pseudo_ifp1)
+{
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	if (as -> passnum != 1)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+	
+OPFUNC(pseudo_ifp2)
+{
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		skip_operand(p);
+		return;
+	}
+
+	if (as -> passnum != 2)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+	
 OPFUNC(pseudo_ifeq)
 {
 	int v1;
@@ -890,6 +925,7 @@
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
@@ -911,6 +947,7 @@
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
@@ -932,6 +969,7 @@
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
@@ -953,6 +991,7 @@
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
@@ -974,6 +1013,7 @@
 	if (as -> skipcond && !(as -> skipmacro))
 	{
 		as -> skipcount++;
+		skip_operand(p);
 		return;
 	}
 
--- a/lwasm/symbol.c	Fri Jun 12 05:25:41 2009 +0000
+++ b/lwasm/symbol.c	Fri Aug 14 03:22:26 2009 +0000
@@ -85,7 +85,7 @@
 			return -1;
 		}
 		// flag local symbols while we're at it...
-		if (*p == '?' || *p == '@' || *p == '$')
+		if (*p == '?' || *p == '@' || (*p == '$' && !(as -> pragmas & PRAGMA_DOLLARNOTLOCAL)))
 			scontext = as -> context;
 	}