diff lwasm/os9.c @ 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
children a9a14e6b4bc8
line wrap: on
line diff
--- /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;
+}