changeset 357:0cf4948d53b4

Checkpoint - adding actual cpu instructions
author lost@starbug
date Wed, 31 Mar 2010 20:12:20 -0600
parents 7166254491ed
children be0f9f8d799f
files lwasm/Makefile.am lwasm/insn_rel.c lwasm/insn_rlist.c lwasm/insn_rtor.c lwasm/insn_tfm.c lwasm/instab.c lwasm/lwasm.c lwasm/lwasm.h
diffstat 8 files changed, 498 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/Makefile.am	Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/Makefile.am	Wed Mar 31 20:12:20 2010 -0600
@@ -2,7 +2,7 @@
 bin_PROGRAMS = lwasm
 lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \
 	instab.c symbol.c macro.c \
-	insn_inh.c \
+	insn_inh.c insn_rtor.c insn_tfm.c insn_rlist.c insn_rel.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rel.c	Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,117 @@
+/*
+insn_rel.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/>.
+*/
+
+/*
+for handling relative mode instructions
+*/
+
+#include <config.h>
+#include <stdlib.h>
+
+#include <lw_expr.h>
+
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_rel8)
+{
+	int v;
+	lw_expr_t t, e1, e2;
+	int r;
+
+	// sometimes there is a "#", ignore if there
+	if (**p == '#')
+		(*p)++;
+
+	t = lwasm_parse_expr(as, p);
+	if (!t)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+	
+	e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l);
+	e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, l -> addr);
+	lw_expr_destroy(e1);
+	e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, t, e2);
+	lw_expr_destroy(e2);
+	lwasm_save_expr(l, 0, e2);
+}
+
+EMITFUNC(insn_emit_rel8)
+{
+	lw_expr_t e;
+	int offs;
+	
+	e = lwasm_fetch_expr(l, 0);
+	if (!lw_expr_istype(e, lw_expr_type_int))
+	{
+		lwasm_register_error(as, l, "Illegal non-constant expression");
+		return;
+	}
+	
+	offs = lw_expr_intval(e);
+	if (offs < -128 || offs > 127)
+	{
+		lwasm_register_error(as, l, "Byte overflow");
+		return;
+	}
+	
+	lwasm_emitop(l, instab[l -> insn].ops[0]);
+	lwasm_emit(l, offs);
+}
+
+PARSEFUNC(insn_parse_rel16)
+{
+	int v;
+	lw_expr_t t, e1, e2;
+	int r;
+
+	// sometimes there is a "#", ignore if there
+	if (**p == '#')
+		(*p)++;
+
+	t = lwasm_parse_expr(as, p);
+	if (!t)
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+	l -> len = OPLEN(instab[l -> insn].ops[0]) + 2;
+	
+	e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l);
+	e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, l -> addr);
+	lw_expr_destroy(e1);
+	e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, t, e2);
+	lw_expr_destroy(e2);
+	lwasm_save_expr(l, 0, e2);
+}
+
+EMITFUNC(insn_emit_rel16)
+{
+	lw_expr_t e;
+	int offs;
+	
+	e = lwasm_fetch_expr(l, 0);
+	
+	lwasm_emitop(l, instab[l -> insn].ops[0]);
+	lwasm_emitexpr(l, e, 2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rlist.c	Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,65 @@
+/*
+insn_rlist.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/>.
+*/
+
+/*
+for handling inherent mode instructions
+*/
+
+#include <config.h>
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_rlist)
+{
+	int rb = 0;
+	int rn;
+	static const char *regs = "CCA B DPX Y U PCD S ";
+
+	while (**p && !isspace(**p))
+	{
+		rn = lwasm_lookupreg2(regs, p);
+		if (rn < 0)
+		{
+			lwasm_register_error(as, l, "Bad register '%s'", *p);
+			return;
+		}
+		if (**p && **p != ',' && !isspace(**p))
+		{
+			lwasm_register_error(as, l, "Bad operand");
+		}
+		if (**p == ',')
+			(*p)++;
+		if (rn == 8)
+			rn = 6;
+		else if (rn == 9)
+			rn = 0x40;
+		else
+			rn = 1 << rn;
+		rb |= rn;
+	}
+	l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+	l -> pb = rb;
+}
+
+EMITFUNC(insn_emit_rlist)
+{
+	lwasm_emitop(l, instab[l -> insn].ops[0]);
+	lwasm_emit(l, l -> pb);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rtor.c	Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,62 @@
+/*
+insn_rtor.c
+Copyright © 2010 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/>.
+
+*/
+
+#include <config.h>
+
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_rtor)
+{
+	int r0, r1;
+
+	static const char *regs = "D X Y U S PCW V A B CCDP0 0 E F ";
+	static const char *regs9 = "D X Y U S PC    A B CCDP        ";
+		
+	// register to register (r0,r1)
+	// registers are in order:
+	// D,X,Y,U,S,PC,W,V
+	// A,B,CC,DP,0,0,E,F
+
+	r0 = lwasm_lookupreg2((as -> target == TARGET_6309) ? regs9 : regs, p);
+	if (r0 < 0 || *(*p)++ != ',')
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		r0 = r1 = 0;
+	}
+	else
+	{
+		r1 = lwasm_lookupreg2((as -> target = TARGET_6309) ? regs9 : regs, p);
+		if (r1 < 0)
+		{
+			lwasm_register_error(as, l, "Bad operand");
+			r0 = r1 = 0;
+		}
+	}
+	l -> pb = (r0 << 4) | r1;
+	l -> len = OPLEN(instab[l -> insn].ops[0]) + 1;
+}
+
+EMITFUNC(insn_emit_rtor)
+{
+	lwasm_emitop(l, instab[l -> insn].ops[0]);
+	lwasm_emit(l, l -> pb);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_tfm.c	Wed Mar 31 20:12:20 2010 -0600
@@ -0,0 +1,151 @@
+/*
+insn_tfm.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/>.
+*/
+
+#include <config.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(insn_parse_tfm)
+{
+	static const char *reglist = "DXYUS   AB  00EF";
+	int r0, r1;
+	char *c;
+	int tfm = 0;
+			
+	c = strchr(reglist, toupper(*(*p)++));
+	if (!c)
+	{
+		lwasm_register_error(as, l, "Unknown operation");
+		return;
+	}
+	r0 = c - reglist;
+	if (**p == '+')
+	{
+		(*p)++;
+		tfm = 1;
+	}
+	else if (**p == '-')
+	{
+		(*p)++;
+		tfm = 2;
+	}
+	if (*(*p)++ != ',')
+	{
+		lwasm_register_error(as, l, "Unknown operation");
+		return;
+	}
+	c = strchr(reglist, toupper(*(*p)++));
+	if (!c)
+	{
+		lwasm_register_error(as, l, "Unknown operation");
+		return;
+	}
+	r1 = c - reglist;
+
+	if (**p == '+')
+	{
+		(*p)++;
+		tfm |= 4;
+	}
+	else if (**p == '-')
+	{
+		(*p)++;
+		tfm |= 8;
+	}
+	
+	if (**p && !isspace(**p))
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		return;
+	}
+			
+	// valid values of tfm here are:
+	// 1: r0+,r1 (2)
+	// 4: r0,r1+ (3)
+	// 5: r0+,r1+ (0)
+	// 10: r0-,r1- (1)
+	switch (tfm)
+	{
+	case 5: //r0+,r1+
+		l -> lint =  instab[l -> insn].ops[0];
+		break;
+
+	case 10: //r0-,r1-
+		l -> lint = instab[l -> insn].ops[1];
+		break;
+
+	case 1: // r0+,r1
+		l -> lint = instab[l -> insn].ops[2];
+		break;
+
+	case 4: // r0,r1+
+		l -> lint = instab[l -> insn].ops[3];
+		break;
+
+	default:
+		lwasm_register_error(as, l, "Unknown operation");
+		return;
+	}
+	l -> pb = (r0 << 4) | r1;
+	l -> len = OPLEN(l -> lint);
+}
+
+EMITFUNC(insn_emit_tfm)
+{
+	lwasm_emitop(l, l -> lint);
+	lwasm_emit(l, l -> pb);
+}
+
+PARSEFUNC(insn_parse_tfmrtor)
+{
+	int r0, r1;
+	static const char *regs = "D X Y U S       A B     0 0 E F ";
+	
+	// register to register (r0,r1)
+	// registers are in order:
+	// D,X,Y,U,S,PC,W,V
+	// A,B,CC,DP,0,0,E,F
+	r0 = lwasm_lookupreg2(regs, p);
+	if (r0 < 0 || *(*p)++ != ',')
+	{
+		lwasm_register_error(as, l, "Bad operand");
+		r0 = r1 = 0;
+	}
+	else
+	{
+		r1 = lwasm_lookupreg2(regs, p);
+		if (r1 < 0)
+		{
+			lwasm_register_error(as, l, "Bad operand");
+			r0 = r1 = 0;
+		}
+	}
+	l -> len = instab[l -> insn].ops[0] + 1;
+	l -> pb = (r0 << 4) | r1;
+}
+
+EMITFUNC(insn_emit_tfmrtor)
+{
+	lwasm_emitop(l, instab[l -> insn].ops[0]);
+	lwasm_emit(l, l -> pb);
+}
--- a/lwasm/instab.c	Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/instab.c	Wed Mar 31 20:12:20 2010 -0600
@@ -31,6 +31,74 @@
 #define insn_resolve_inh NULL
 extern EMITFUNC(insn_emit_inh);
 
+// register to register
+extern PARSEFUNC(insn_parse_rtor);
+#define insn_resolve_rtor NULL
+extern EMITFUNC(insn_emit_rtor);
+
+// TFM and variants
+extern PARSEFUNC(insn_parse_tfmrtor);
+#define insn_resolve_tfmrtor NULL
+extern EMITFUNC(insn_emit_tfmrtor);
+extern PARSEFUNC(insn_parse_tfm);
+#define insn_resolve_tfm NULL
+extern EMITFUNC(insn_emit_tfm);
+
+// register list
+extern PARSEFUNC(insn_parse_rlist);
+#define insn_resolve_rlist NULL
+extern EMITFUNC(insn_emit_rlist);
+
+// indexed
+extern PARSEFUNC(insn_parse_indexed);
+extern RESOLVEFUNC(insn_resolve_indexed);
+extern EMITFUNC(insn_emit_indexed);
+
+// generic 32 bit immediate
+extern PARSEFUNC(insn_parse_gen32);
+extern RESOLVEFUNC(insn_resolve_gen32);
+extern EMITFUNC(insn_emit_gen32);
+
+// generic 16 bit immediate
+extern PARSEFUNC(insn_parse_gen16);
+extern RESOLVEFUNC(insn_resolve_gen16);
+extern EMITFUNC(insn_emit_gen16);
+
+// generic 8 bit immediate
+extern PARSEFUNC(insn_parse_gen8);
+extern RESOLVEFUNC(insn_resolve_gen8);
+extern EMITFUNC(insn_emit_gen8);
+
+// generic no immediate
+extern PARSEFUNC(insn_parse_gen0);
+extern RESOLVEFUNC(insn_resolve_gen0);
+extern EMITFUNC(insn_emit_gen0);
+
+// logic memory
+extern PARSEFUNC(insn_parse_logicmem);
+extern RESOLVEFUNC(insn_resolve_logicmem);
+extern EMITFUNC(insn_emit_logicmem);
+
+// logic memory
+extern PARSEFUNC(insn_parse_imm8);
+#define insn_resolve_imm8 NULL
+extern EMITFUNC(insn_emit_imm8);
+
+// bit to bit ops
+extern PARSEFUNC(insn_parse_bitbit);
+#define insn_resolve_bitbit NULL
+extern EMITFUNC(insn_emit_bitbit);
+
+// 8 bit relative
+extern PARSEFUNC(insn_parse_rel8);
+#define insn_resolve_rel8 NULL
+extern EMITFUNC(insn_emit_rel8);
+
+// 16 bit relative
+extern PARSEFUNC(insn_parse_rel16);
+#define insn_resolve_rel16 NULL
+extern EMITFUNC(insn_emit_rel16);
+
 // MACRO pseudo op
 extern PARSEFUNC(pseudo_parse_macro);
 #define pseudo_resolve_macro	NULL
@@ -215,8 +283,8 @@
 
 instab_t instab[] =
 {
-/*
-	{ "abx",		{	0x3a,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				lwasm_emit_inh,				lwasm_insn_normal},
+
+	{ "abx",		{	0x3a,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_normal},
 	{ "adca",		{	0x99,	0xa9,	0xb9,	0x89},	insn_parse_gen8,		insn_resolve_gen8,				insn_emit_gen8,				lwasm_insn_normal},
 	{ "adcb",		{	0xd9,	0xe9,	0xf9,	0xc9},	insn_parse_gen8,		insn_resolve_gen8,				insn_emit_gen8,				lwasm_insn_normal},
 	{ "adcd",		{	0x1099,	0x10a9,	0x10b9,	0x1089},insn_parse_gen16,		insn_resolve_gen16,				insn_emit_gen16,			lwasm_insn_is6309},
@@ -382,9 +450,9 @@
 	{ "nega",		{	0x40,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_normal},
 	{ "negb",		{	0x50,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_normal},
 	{ "negd",		{	0x1040,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_is6309},
-*/
+
 	{ "nop",		{	0x12,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_normal},
-/*	
+	
 	{ "oim",		{	0x01,	0x61,	0x71,	-1	},	insn_parse_logicmem,	insn_resolve_logicmem,			insn_emit_logicmem,			lwasm_insn_is6309},
 	{ "ora",		{	0x9a,	0xaa,	0xba,	0x8a},	insn_parse_gen8,		insn_resolve_gen8,				insn_emit_gen8,				lwasm_insn_normal},
 	{ "orb",		{	0xda,	0xea,	0xfa,	0xca},	insn_parse_gen8,		insn_resolve_gen8,				insn_emit_gen8,				lwasm_insn_normal},
@@ -472,7 +540,7 @@
 	{ "tste",		{	0x114d,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_is6309},
 	{ "tstf",		{	0x115d,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_is6309},
 	{ "tstw",		{	0x105d,	-1,		-1,		-1	},	insn_parse_inh,			insn_resolve_inh,				insn_emit_inh,				lwasm_insn_is6309},
-*/
+
 	{ "org",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_org,		pseudo_resolve_org,				pseudo_emit_org,			lwasm_insn_normal},
 	{ "equ",		{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_equ,		pseudo_resolve_equ,				pseudo_emit_equ,			lwasm_insn_setsym},
 	{ "=",			{	-1, 	-1, 	-1, 	-1 },	pseudo_parse_equ,		pseudo_resolve_equ,				pseudo_emit_equ,			lwasm_insn_setsym},
--- a/lwasm/lwasm.c	Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/lwasm.c	Wed Mar 31 20:12:20 2010 -0600
@@ -555,3 +555,28 @@
 	
 	return 0;
 }
+
+int lwasm_lookupreg2(const char *regs, char **p)
+{
+	int rval = 0;
+	
+	while (*regs)
+	{
+		if (toupper(**p) == *regs)
+		{
+			if (regs[1] == ' ' && !isalpha(*(*p + 1)))
+				break;
+			if (toupper(*(*p + 1)) == regs[1])
+				break;
+		}
+		regs += 2;
+		rval++;
+	}
+	if (!*regs)
+		return -1;
+	if (regs[1] == ' ')
+		(*p)++;
+	else
+		(*p) += 2;
+	return rval;
+}
--- a/lwasm/lwasm.h	Wed Mar 31 18:46:32 2010 -0600
+++ b/lwasm/lwasm.h	Wed Mar 31 20:12:20 2010 -0600
@@ -138,6 +138,8 @@
 	sectiontab_t *csect;				// which section are we in?
 	struct line_expr_s *exprs;			// expressions used during parsing
 	char *lstr;							// string passed forward
+	int pb;								// pass forward post byte
+	int lint;							// pass forward integer
 	asmstate_t *as;						// assembler state data ptr
 };
 
@@ -232,6 +234,8 @@
 
 extern void skip_operand(char **p);
 
+extern int lwasm_lookupreg2(const char *rlist, char **p);
+
 #endif
 
 #define OPLEN(op) (((op)>0xFF)?2:1)