changeset 354:60568b123281

Added os9 opcodes and ERROR
author lost@starbug
date Tue, 30 Mar 2010 23:10:01 -0600
parents faa97115952e
children 981e34165e97
files lwasm/Makefile.am lwasm/instab.c lwasm/lwasm.c lwasm/lwasm.h lwasm/os9.c lwasm/pass1.c lwasm/pseudo.c
diffstat 7 files changed, 250 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/Makefile.am	Tue Mar 30 21:48:49 2010 -0600
+++ b/lwasm/Makefile.am	Tue Mar 30 23:10:01 2010 -0600
@@ -3,6 +3,6 @@
 lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \
 	instab.c symbol.c macro.c \
 	insn_inh.c \
-	pseudo.c section.c
+	pseudo.c section.c os9.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
--- a/lwasm/instab.c	Tue Mar 30 21:48:49 2010 -0600
+++ b/lwasm/instab.c	Tue Mar 30 23:10:01 2010 -0600
@@ -177,6 +177,10 @@
 #define pseudo_resolve_endsection NULL
 #define pseudo_emit_endsection NULL
 
+extern PARSEFUNC(pseudo_parse_error);
+#define pseudo_resolve_error NULL
+#define pseudo_emit_error NULL
+
 instab_t instab[] =
 {
 /*
@@ -470,9 +474,9 @@
 	
 	{ "align", 		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_align,		pseudo_resolve_align,			pseudo_emit_align,			lwasm_insn_normal},
 
+*/
 	{ "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},
--- a/lwasm/lwasm.c	Tue Mar 30 21:48:49 2010 -0600
+++ b/lwasm/lwasm.c	Tue Mar 30 23:10:01 2010 -0600
@@ -129,6 +129,31 @@
 		cl -> outputbl += 8;
 	}
 	cl -> output[cl -> outputl++] = byte & 0xff;
+	
+	if (cl -> inmod)
+	{
+		asmstate_t *as = cl -> as;
+		// update module CRC
+		// this is a direct transliteration from the nitros9 asm source
+		// to C; it can, no doubt, be optimized for 32 bit processing  
+		byte &= 0xff;
+
+		byte ^= (as -> crc)[0];
+		(as -> crc)[0] = (as -> crc)[1];
+		(as -> crc)[1] = (as -> crc)[2];
+		(as -> crc)[1] ^= (byte >> 7);
+		(as -> crc)[2] = (byte << 1); 
+		(as -> crc)[1] ^= (byte >> 2);
+		(as -> crc)[2] ^= (byte << 6);
+		byte ^= (byte << 1);
+		byte ^= (byte << 2);
+		byte ^= (byte << 4);
+		if (byte & 0x80) 
+		{
+			(as -> crc)[0] ^= 0x80;
+		    (as -> crc)[2] ^= 0x21;
+		}
+	}
 }
 
 void lwasm_emitop(line_t *cl, int opc)
--- a/lwasm/lwasm.h	Tue Mar 30 21:48:49 2010 -0600
+++ b/lwasm/lwasm.h	Tue Mar 30 23:10:01 2010 -0600
@@ -74,6 +74,22 @@
 	PRAGMA_IMPORTUNDEFEXPORT = 0x0010	// imports symbol if undefined upon export
 };
 
+
+enum
+{
+	section_flag_bss = 1,				// BSS section
+	section_flag_none = 0				// no flags
+};
+
+typedef struct sectiontab_s sectiontab_t;
+struct sectiontab_s
+{
+	char *name;							// section name
+	int flags;							// section flags;
+	lw_expr_t offset;					// offset for next instance
+	sectiontab_t *next;
+};
+
 typedef struct lwasm_error_s lwasm_error_t;
 struct lwasm_error_s
 {
@@ -104,7 +120,8 @@
 	lwasm_error_t *warn;				// list of errors
 	line_t *prev;						// previous line
 	line_t *next;						// next line
-	
+	int inmod;							// inside a module?
+	sectiontab_t *csect;				// which section are we in?
 	struct line_expr_s *exprs;			// expressions used during parsing
 	char *lstr;							// string passed forward
 	asmstate_t *as;						// assembler state data ptr
@@ -139,22 +156,6 @@
 	int numlines;						// number lines in macro
 	macrotab_t *next;					// next macro in list
 };
-
-enum
-{
-	section_flag_bss = 1,				// BSS section
-	section_flag_none = 0				// no flags
-};
-
-typedef struct sectiontab_s sectiontab_t;
-struct sectiontab_s
-{
-	char *name;							// section name
-	int flags;							// section flags;
-	lw_expr_t offset;					// offset for next instance
-	sectiontab_t *next;
-};
-
 struct asmstate_s
 {
 	int output_format;					// output format
@@ -169,6 +170,8 @@
 	int skipmacro;						// are we skipping in a macro?	
 	int endseen;						// have we seen an "end" pseudo?
 	int execaddr;						// address from "end"
+	int inmod;							// inside an os9 module?
+	unsigned char crc[3];				// crc accumulator
 
 	line_t *line_head;					// start of lines list
 	line_t *line_tail;					// tail of lines list
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/os9.c	Tue Mar 30 23:10:01 2010 -0600
@@ -0,0 +1,192 @@
+/*
+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 <lw_expr.h>
+
+#include "lwasm.h"
+#include "instab.h"
+
+
+// OS9 syscall
+PARSEFUNC(pseudo_parse_os9)
+{
+	lw_expr_t e;
+	
+	if (as -> output_format != OUTPUT_OS9)
+	{
+		lwasm_register_error(as, l, "os9 directive only valid for OS9 target");
+		return;
+	}
+	
+	// fetch immediate value
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	lwasm_save_expr(l, 0, e);
+	l -> len = 3;
+}
+
+EMITFUNC(pseudo_emit_os9)
+{
+	lw_expr_t e;
+	
+	e = lwasm_fetch_expr(l, 0);
+
+	lwasm_emitop(l, 0x103f);
+	lwasm_emitexpr(l, e, 1);
+}
+
+PARSEFUNC(pseudo_parse_mod)
+{
+	lw_expr_t e;
+	int i;
+	
+	if (as -> output_format != OUTPUT_OS9)
+	{
+		lwasm_register_error(as, l,  "mod directive only valid for OS9 target");
+		return;
+	}
+	
+	if (as -> inmod)
+	{
+		lwasm_register_error(as, l,  "Already in a module!");
+		return;
+	}
+
+	// parse 6 expressions...
+	for (i = 0; i < 5; i++)
+	{
+		e = lwasm_parse_expr(as, p);
+		if (!e)
+		{
+			lwasm_register_error(as, l, "Bad operand");
+			return;
+		}
+
+		lwasm_save_expr(l, i, e);
+
+		if (**p != ',')
+		{
+			lwasm_register_error(as, l, "Bad operand");
+			return;
+		}
+		(*p)++;
+	}
+
+	e = lwasm_parse_expr(as, p);
+	if (!e)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	lwasm_save_expr(l, 5, e);
+
+	l -> inmod = 1;
+	
+	// we have an implicit ORG 0 with "mod"
+	lw_expr_destroy(l -> addr);
+	l -> addr = lw_expr_build(lw_expr_type_int, 0);
+
+	// init crc
+	as -> inmod = 1;
+}
+
+EMITFUNC(pseudo_emit_mod)
+{
+	lw_expr_t e1, e2, e3, e4;
+	int csum;
+	
+	as -> crc[0] = 0xff;
+	as -> crc[1] = 0xff;
+	as -> crc[2] = 0xff;
+
+	// sync bytes
+	lwasm_emit(l, 0x87);
+	lwasm_emit(l, 0xcd);
+	
+	// mod length
+	lwasm_emitexpr(l, e1 = lwasm_fetch_expr(l, 0), 2);
+	
+	// name offset
+	lwasm_emitexpr(l, e2 = lwasm_fetch_expr(l, 1), 2);
+	
+	// type
+	lwasm_emitexpr(l, e3 = lwasm_fetch_expr(l, 2), 1);
+	
+	// flags/rev
+	lwasm_emitexpr(l, e4 = lwasm_fetch_expr(l, 3), 1);
+	
+	// header check
+	csum = ~(0x87 ^ 0xCD ^(lw_expr_intval(e1) >> 8) ^ (lw_expr_intval(e1) & 0xff)
+		^ (lw_expr_intval(e2) >> 8) ^ (lw_expr_intval(e2) & 0xff)
+		^ lw_expr_intval(e3) ^ lw_expr_intval(e4));
+	lwasm_emit(l, csum);
+
+	// 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_emitexpr(l, lwasm_fetch_expr(l, 4), 2);
+	
+	// data size or drvr name offset
+	lwasm_emitexpr(l, lwasm_fetch_expr(l, 5), 2);
+}
+
+PARSEFUNC(pseudo_parse_emod)
+{
+	if (as -> output_format != OUTPUT_OS9)
+	{
+		lwasm_register_error(as, l, "emod directive only valid for OS9 target");
+		return;
+	}
+	
+	if (!(as -> inmod))
+	{
+		lwasm_register_error(as, l, "not in a module!");
+		return;
+	}
+	
+	as -> inmod = 0;
+}
+
+EMITFUNC(pseudo_emit_emod)
+{
+	unsigned char tcrc[3];
+	
+	// don't mess with CRC!
+	tcrc[0] = as -> crc[0] ^ 0xff;
+	tcrc[1] = as -> crc[1] ^ 0xff;
+	tcrc[2] = as -> crc[2] ^ 0xff;
+	lwasm_emit(l, tcrc[0]);
+	lwasm_emit(l, tcrc[1]);
+	lwasm_emit(l, tcrc[2]);
+}
--- a/lwasm/pass1.c	Tue Mar 30 21:48:49 2010 -0600
+++ b/lwasm/pass1.c	Tue Mar 30 23:10:01 2010 -0600
@@ -83,6 +83,8 @@
 		cl -> prev = as -> line_tail;
 		cl -> insn = -1;
 		cl -> as = as;
+		cl -> inmod = as -> inmod;
+		cl -> csect = as -> csect;
 		if (!as -> line_tail)
 		{
 			as -> line_head = cl;
--- a/lwasm/pseudo.c	Tue Mar 30 21:48:49 2010 -0600
+++ b/lwasm/pseudo.c	Tue Mar 30 23:10:01 2010 -0600
@@ -907,3 +907,8 @@
 	}
 }
 
+PARSEFUNC(pseudo_parse_error)
+{
+	lwasm_register_error(as, l, "User error: %s", *p);
+	skip_operand(p);
+}