changeset 32:9bd0fbfe7405

Added basic indexed mode handling
author lost
date Fri, 02 Jan 2009 04:22:39 +0000
parents 674ee393426c
children 74a3fef7c8d0
files src/Makefile.am src/index.c src/insn_bitbit.c src/insn_indexed.c src/insn_misc.c src/insn_rel.c src/insn_rlist.c src/insn_rtor.c src/insn_tfm.c src/lwasm.c src/lwasm.h
diffstat 11 files changed, 529 insertions(+), 406 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile.am	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/Makefile.am	Fri Jan 02 04:22:39 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
+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
 EXTRA_DIST = instab.h lwasm.h expr.h util.h
--- a/src/index.c	Fri Jan 02 03:35:29 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/*
-index.c, Copyright © 2008 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/>.
-
-Contains  code for parsing indexed addressing modes
-
-*/
-
-#include <ctype.h>
-//#include <errno.h>
-//#include <stdio.h>
-//#include <stdlib.h>
-#include <string.h>
-#define __index_c_seen__
-//#include "instab.h"
-#include "lwasm.h"
-#include "instab.h"
-
-
-int parse_index_expr(asmstate_t *as, sourceline_t *cl, char **optr, int *postbyte, int *opmode, int *v1)
-{
-	static const char *regs = "X  Y  U  S  W  PCRPC ";
-	static const struct { char *opstr; int pb; } simpleindex[] =
-	{
-		{",x", 0x84},		{",y", 0xa4},		{",u", 0xc4},		{",s", 0xe4},
-		{",x+", 0x80},		{",y+", 0xa0},		{",u+", 0xc0},		{",s+", 0xe0},
-		{",x++", 0x81},		{",y++", 0xa1},		{",u++", 0xc1},		{",s++", 0xe1},
-		{",-x", 0x82},		{",-y", 0xa2},		{",-u", 0xc2},		{",-s", 0xe2},
-		{",--x", 0x83},		{",--y", 0xa3},		{",--u", 0xc3},		{",--s", 0xe3},
-		{"a,x", 0x86},		{"a,y", 0xa6},		{"a,u", 0xc6},		{"a,s", 0xe6},
-		{"b,x", 0x85},		{"b,y", 0xa5},		{"b,u", 0xc5},		{"b,s", 0xe5},
-		{"e,x", 0x87},		{"e,y", 0xa7},		{"e,u", 0xc7},		{"e,s", 0xe7},
-		{"f,x",	0x8a},		{"f,y",	0xaa},		{"f,u", 0xca},		{"f,s", 0xea},
-		{"d,x", 0x8b},		{"d,y", 0xab},		{"d,u", 0xcb},		{"d,s", 0xed},
-		{"w,x", 0x8e},		{"w,y", 0xae},		{"w,u", 0xce},		{"w,s", 0xee},
-		{",w", 0x8f},							{",w++", 0xcf},		{",--w", 0xef},
-		
-		{"[,x]", 0x94},		{"[,y]", 0xb4},		{"[,u", 0xd4},		{"[,s]", 0xf4},
-		{"[,x++]", 0x91},	{"[,y++]", 0xb1},	{"[,u++]", 0xd1},	{"[,s++]", 0xf1},
-		{"[,--x]", 0x93},	{"[,--y]", 0xb3},	{"[,--u]", 0xd3},	{"[,--s]", 0xf3},
-		{"[a,x]", 0x96},	{"[a,y]", 0xb6},	{"[a,u]", 0xd6},	{"[a,s]", 0xf6},
-		{"[b,x]", 0x95},	{"[b,y]", 0xb5},	{"[b,u]", 0xd5},	{"[b,s]", 0xf5},
-		{"[e,x]", 0x97},	{"[e,y]", 0xb7},	{"[e,u]", 0xd7},	{"[e,s]", 0xf7},
-		{"[f,x]", 0x9a},	{"[f,y]", 0xba},	{"[f,u]", 0xda},	{"[f,s]", 0xfa},
-		{"[d,x]", 0x9b},	{"[d,y]", 0xbb},	{"[d,u]", 0xdb},	{"[d,s]", 0xfd},
-		{"[w,x]", 0x9e},	{"[w,y]", 0xbe},	{"[w,u]", 0xde},	{"[w,s]", 0xfe},
-		{"[,w]", 0x90},							{"[,w++]", 0xd0},	{"[,--w]", 0xf0},
-		
-		{ "", -1 }
-	};
-	char stbuf[25];
-	int i;
-	int f8 = 0, f16 = 0;
-	int rn;
-	int indir = 0;
-	int rval;
-	int f0 = 0;
- 
-	for (i = 0; i < 24; i++)
-	{
-		if (*((*optr) + i) && !isspace(*((*optr) + i)))
-			stbuf[i] = *((*optr) + i);
-		else
-			break;
-	}
-	stbuf[i] = '\0';
-	if (!*((*optr) + i) || isspace(*((*optr) + i)))
-	{
-		int j;
-		// do simple lookup
-		for (j = 0; simpleindex[j].opstr[0]; j++)
-		{
-			if (!strcasecmp(stbuf, simpleindex[j].opstr))
-				break;
-		}
-		if (simpleindex[j].opstr[0])
-		{
-			*postbyte = simpleindex[j].pb;
-			*opmode = OPER_INDEX;
-			(*optr) += i;
-			return 0;
-		}
-	}
-	
-	// now we have the hard ones to work out here
-	
-	if (**optr == '[')
-	{
-		indir = 1;
-		(*optr)++;
-	}
-	
-	rn = 0;
-	for (i = 0; (*optr)[i] && !isspace((*optr)[i]); i++)
-	{
-		if ((*optr)[i] == ',')
-		{
-			rn = 1;
-			break;
-		}
-	}
-		
-	if (!rn && indir)
-	{
-		// extended indir
-		*postbyte = 0x9f;
-		*opmode = OPER_EXTIND;
-		rval = eval_expr(as, cl, optr, v1);
-		if (**optr != ']')
-		{
-			errorp1(ERR_BADOPER);
-		}
-		(*optr)++;
-		return 0;
-	}
-
-	if (cl -> p1f16)
-		f16 = 1;	
-	if (**optr == '<')
-	{
-		f8 = 1;
-		(*optr)++;
-	}
-	else if (**optr == '>')
-	{
-		f16 = 1;
-		(*optr)++;
-	}
-
-	if (**optr == '0' && *(*optr+1) == ',')
-	{
-		f0 = 1;
-	}
-	
-	// now we have to evaluate the expression
-	rval = eval_expr(as, cl, optr, v1);
-
-	if (cl -> undef && as -> passnum == 1)
-	{
-		cl -> p1f16 = 1;
-		f16 = 1;
-	}
-
-	// now look for a comma; if not present, explode
-	if (rval == -1 || *(*optr)++ != ',')
-	{
-		// syntax error; force 0 bit
-		*postbyte = -1;
-		*opmode = OPER_INDEX;
-		return -2;
-	}
-	
-	// now get the register
-	rn = lookupreg3(regs, optr);
-	if (rn < 0)
-		goto reterr;
-
-//	debug("Reg: %d\n", rn);
-
-	if (indir && **optr != ']')
-		goto reterr;
-	else
-		(*optr)++;
-	
-	// nnnn,W is only 16 bit
-	if (rn == 4)
-	{
-		if (f8)
-			goto reterr;
-		if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && *v1 == 0)
-		{
-			*opmode = OPER_INDEX;
-			if (indir)
-				*postbyte = 0x90;
-			else
-				*postbyte = 0x8f;
-			return 0;
-		}
-		*opmode = OPER_INDEX16;
-		if (indir)
-			*postbyte = 0xb0;
-		else
-			*postbyte = 0xcf;
-		return 0;
-	}
-	
-	if (indir) indir = 0x10;
-	
-	// forward ref; we can't figure anything
-	if (cl -> undef)
-	{
-		f16 = 1;
-	}
-
-	// PCR? redo v1, v2 relative to current address
-	if (rn == 5)
-	{
-		*v1 -= as -> addr;
-		
-		// we have a slight problem here
-		// PCR based on current insn loc is really
-		// -125 <= offset <= +130 (8 bit offset)
-		if (f8 || (!f16 && *v1 >= -125 && *v1 <= 130))
-		{
-			*opmode = OPER_INDEX8;
-			*postbyte = indir | 0x8C;
-			*v1 -= 3;
-			if (*v1 < -128 || *v1 > 127)
-				errorp2(ERR_OVERFLOW);
-			return 0;
-		}
-		
-		// anything else is 16 bit offset
-		// need 16 bit
-		*opmode = OPER_INDEX16;
-		*postbyte = indir | 0x8D;
-		*v1 -= 4;
-		return 0;
-	}
-
-	// constant offset from PC
-	if (rn == 6)
-	{
-		if (f8 || (!f16 && *v1 >= -128 && *v1 <= 127))
-		{
-			*opmode = OPER_INDEX8;
-			*postbyte = indir | 0x8C;
-			if (*v1 < -128 || *v1 > 127)
-				errorp2(ERR_OVERFLOW);
-			return 0;
-		}
-		
-		// everything else must be 16 bit
-		// need 16 bit
-		*opmode = OPER_INDEX16;
-		*postbyte = indir | 0x8D;
-		return 0;
-		
-	}
-
-	// we only have to deal with x,y,u,s here
-	if (!f8 && !f16 && *v1 >= -16 && *v1 <= 15)
-	{
-		if (*v1 == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE))
-		{
-			*postbyte = rn << 5 | indir | 0x80 | 0x04;
-			*opmode = OPER_INDEX;
-			return 0;
-		}
-		// we pick the smallest value here
-		if (indir)
-		{
-			f8 = 1;
-			goto no5bit;
-		}
-		*postbyte = rn << 5 | (*v1 & 0x1F);
-		*opmode = OPER_INDEX5;
-		return 0;
-	}
-no5bit:
-	if (f16 || (!f8 && (*v1 < -128 || *v1 > 127)))
-	{
-		// must be a 16 bit offset here
-		*postbyte = rn << 5 | indir | 0x80 | 0x09;
-		*opmode = OPER_INDEX16;
-		return 0;
-	}
-	
-	// if we're here, we have an 8 bit offset
-	*postbyte = rn << 5 | indir | 0x80 | 0x08;
-	*opmode = OPER_INDEX8;
-	if (*v1 < -128 || *v1 > 127)
-		errorp2(ERR_OVERFLOW);
-	return 0;
-reterr:
-	*postbyte = -1;
-	*opmode = OPER_INDEX;
-	return -2;
-}
-
-void insn_indexed_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3)
-{
-	int rval;
-	int v1, pb = -1;
-
-	*b1 = *b2 = *b3 = -1;
-
-	rval = parse_index_expr(as, cl, optr, &pb, &(cl -> addrmode), &v1);
-	if (rval < 0)
-		errorp1(ERR_BADOPER);
-	*b1 = pb;
-
-	if (cl -> addrmode == OPER_INDEX8)
-	{
-		*b2 = v1 & 0xff;
-	}
-	else if (cl -> addrmode == OPER_INDEX16 || cl -> addrmode == OPER_EXTIND)
-	{
-		*b2 = (v1 & 0xffff) >> 8;
-		*b3 = v1 & 0xff;
-	}
-}
-
-void insn_indexed(asmstate_t *as, sourceline_t *cl, char **optr)
-{
-	int b1, b2, b3;
-	
-	emitop(instab[cl -> opcode].ops[0]);
-	insn_indexed_aux(as, cl, optr, &b1, &b2, &b3);
-	if (b1 != -1)
-		emit(b1);
-	if (b2 != -1)
-		emit(b2);
-	if (b3 != -1)
-		emit(b3);
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/insn_bitbit.c	Fri Jan 02 04:22:39 2009 +0000
@@ -0,0 +1,136 @@
+/*
+insn_bitbit.c
+Copyright © 2008 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
+*/
+
+#define __insn_bitbit_c_seen__
+
+#include <stdlib.h>
+
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+
+OPFUNC(insn_bitbit)
+{
+	int r;
+	lwasm_expr_stack_t *s;
+	int v1;
+	int tv;
+		
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+	
+	r = toupper(*(*p)++);
+	if (r == 'A')
+		r = 1;
+	else if (r == 'B')
+		r = 2;
+	else if (r == 'C' && toupper(**p) == 'C')
+	{
+		r = 0;
+		(*p)++;
+	}
+	else
+	{
+		register_error(as, l, 1, "Bad register");
+		return;
+	}
+	if (*(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	s = lwasm_expr_eval(*p, NULL);
+	if (!s)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	if (!lwasm_expr_is_constant(s))
+	{
+		register_error(as, l, 2, "Incomplete reference");
+	}
+	v1 = lwasm_expr_get_value(s);
+	lwasm_expr_stack_free(s);
+	if (v1 < 0 || v1 > 7)
+	{
+		register_error(as, l, 2, "Invalid bit number");
+		v1 = 0;
+	}
+	if (*(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	r = (r << 6) | (v1 << 3);
+
+	s = lwasm_expr_eval(*p, NULL);
+	if (!s)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	if (!lwasm_expr_is_constant(s))
+	{
+		register_error(as, l, 1, "Incomplete reference");
+	}
+	v1 = lwasm_expr_get_value(s);
+	lwasm_expr_stack_free(s);
+	if (v1 < 0 || v1 > 7)
+	{
+		register_error(as, l, 2, "Invalid bit number");
+		v1 = 0;
+	}
+	if (*(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	r |= v1;
+	
+	lwasm_emit(as, l, r);
+			
+	// ignore base page address modifier
+	if (**p == '<')
+		(*p)++;
+			
+	s = lwasm_expr_eval(*p, NULL);
+	if (!s)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	if (!lwasm_expr_is_constant(s))
+	{
+		register_error(as, l, 1, "Incomplete reference");
+	}
+	v1 = lwasm_expr_get_value(s);
+	lwasm_expr_stack_free(s);
+	v1 &= 0xFFFF;
+
+	tv = v1 - ((as -> dpval) << 8);
+	if (tv > 0xFF || tv < 0)
+	{
+		register_error(as, l, 2, "Byte overflow");
+	}
+	lwasm_emit(as, l, tv & 0xff);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/insn_indexed.c	Fri Jan 02 04:22:39 2009 +0000
@@ -0,0 +1,339 @@
+/*
+insn_indexed.c
+Copyright © 2008 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 indexed mode instructions
+*/
+
+#define __insn_indexed_c_seen__
+
+#include <ctype.h>
+#include <string.h>
+
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+
+void insn_indexed_aux(asmstate_t *as, lwasm_line_t *l, const char **p, int *b1, int *b2, int *b3)
+{
+	static const char *regs = "X  Y  U  S  W  PCRPC ";
+	static const struct { char *opstr; int pb; } simpleindex[] =
+	{
+		{",x", 0x84},		{",y", 0xa4},		{",u", 0xc4},		{",s", 0xe4},
+		{",x+", 0x80},		{",y+", 0xa0},		{",u+", 0xc0},		{",s+", 0xe0},
+		{",x++", 0x81},		{",y++", 0xa1},		{",u++", 0xc1},		{",s++", 0xe1},
+		{",-x", 0x82},		{",-y", 0xa2},		{",-u", 0xc2},		{",-s", 0xe2},
+		{",--x", 0x83},		{",--y", 0xa3},		{",--u", 0xc3},		{",--s", 0xe3},
+		{"a,x", 0x86},		{"a,y", 0xa6},		{"a,u", 0xc6},		{"a,s", 0xe6},
+		{"b,x", 0x85},		{"b,y", 0xa5},		{"b,u", 0xc5},		{"b,s", 0xe5},
+		{"e,x", 0x87},		{"e,y", 0xa7},		{"e,u", 0xc7},		{"e,s", 0xe7},
+		{"f,x",	0x8a},		{"f,y",	0xaa},		{"f,u", 0xca},		{"f,s", 0xea},
+		{"d,x", 0x8b},		{"d,y", 0xab},		{"d,u", 0xcb},		{"d,s", 0xed},
+		{"w,x", 0x8e},		{"w,y", 0xae},		{"w,u", 0xce},		{"w,s", 0xee},
+		{",w", 0x8f},							{",w++", 0xcf},		{",--w", 0xef},
+		
+		{"[,x]", 0x94},		{"[,y]", 0xb4},		{"[,u", 0xd4},		{"[,s]", 0xf4},
+		{"[,x++]", 0x91},	{"[,y++]", 0xb1},	{"[,u++]", 0xd1},	{"[,s++]", 0xf1},
+		{"[,--x]", 0x93},	{"[,--y]", 0xb3},	{"[,--u]", 0xd3},	{"[,--s]", 0xf3},
+		{"[a,x]", 0x96},	{"[a,y]", 0xb6},	{"[a,u]", 0xd6},	{"[a,s]", 0xf6},
+		{"[b,x]", 0x95},	{"[b,y]", 0xb5},	{"[b,u]", 0xd5},	{"[b,s]", 0xf5},
+		{"[e,x]", 0x97},	{"[e,y]", 0xb7},	{"[e,u]", 0xd7},	{"[e,s]", 0xf7},
+		{"[f,x]", 0x9a},	{"[f,y]", 0xba},	{"[f,u]", 0xda},	{"[f,s]", 0xfa},
+		{"[d,x]", 0x9b},	{"[d,y]", 0xbb},	{"[d,u]", 0xdb},	{"[d,s]", 0xfd},
+		{"[w,x]", 0x9e},	{"[w,y]", 0xbe},	{"[w,u]", 0xde},	{"[w,s]", 0xfe},
+		{"[,w]", 0x90},							{"[,w++]", 0xd0},	{"[,--w]", 0xf0},
+		
+		{ "", -1 }
+	};
+	char stbuf[25];
+	int i;
+	int f8 = 0, f16 = 0;
+	int rn;
+	int indir = 0;
+	int rval;
+	int f0 = 0;
+ 	const char *p2;
+ 	lwasm_expr_stack_t *s;
+ 	
+	*b1 = *b2 = *b3 = -1;
+	
+	for (i = 0; i < 24; i++)
+	{
+		if (*((*p) + i) && !isspace(*((*p) + i)))
+			stbuf[i] = *((*p) + i);
+		else
+			break;
+	}
+	stbuf[i] = '\0';
+	if (!*((*p) + i) || isspace(*((*p) + i)))
+	{
+		int j;
+		// do simple lookup
+		for (j = 0; simpleindex[j].opstr[0]; j++)
+		{
+			if (!strcasecmp(stbuf, simpleindex[j].opstr))
+				break;
+		}
+		if (simpleindex[j].opstr[0])
+		{
+			*b1 = simpleindex[j].pb;
+			(*p) += i;
+			return;
+		}
+	}
+	
+	// now we have the hard ones to work out here
+	
+	// if we've previously forced the sizes, make a note of it
+	if (l -> fsize == 1)
+		f8 = 1;
+	else if (l -> fsize == 2)
+		f16 = 1;
+	
+	if (**p == '[')
+	{
+		indir = 1;
+		(*p)++;
+	}
+	
+	rn = 0;
+	for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
+	{
+		if ((*p)[i] == ',')
+		{
+			rn = 1;
+			break;
+		}
+	}
+		
+	if (!rn && indir)
+	{
+		// extended indir
+		*b1 = 0x9f;
+		*b2 = 0;
+		*b3 = 0;
+		s = lwasm_expr_eval(*p, &p2);
+		if (!s)
+		{
+			register_error(as, l, 1, "Bad expression");
+			return;
+		}
+		*p = p2;
+		if (**p != ']')
+		{
+			register_error(as, l, 1, "Bad operand");
+			return;
+		}
+		(*p)++;
+		if (!lwasm_expr_is_constant(s))
+		{
+			register_error(as, l, 2, "Incomplete reference");
+		}
+		rn = lwasm_expr_get_value(s);
+		lwasm_expr_stack_free(s);
+		*b2 = (rn >> 8) & 0xff;
+		*b3 = rn & 0xff;
+		return;
+	}
+
+	if (**p == '<')
+	{
+		f8 = 1;
+		(*p)++;
+	}
+	else if (**p == '>')
+	{
+		f16 = 1;
+		(*p)++;
+	}
+
+	if (**p == '0' && *(*p+1) == ',')
+	{
+		f0 = 1;
+	}
+	
+	// now we have to evaluate the expression
+	s = lwasm_expr_eval(*p, &p2);
+	*p = p2;
+	if (!s)
+	{
+		register_error(as, l, 1, "Bad expression");
+		return;
+	}
+	if (!lwasm_expr_is_constant(s))
+	{
+		register_error(as, l, 2, "Incomplete reference");
+		if (!f8 && !f0)
+		{
+			f16 = 1;
+			l -> fsize = 2;
+		}
+	}
+	rval = lwasm_expr_get_value(s);
+	lwasm_expr_stack_free(s);
+	
+	// now look for a comma; if not present, explode
+	if (*(*p)++ != ',')
+	{
+		// syntax error; force 0 bit
+		*b1 = 00;
+		return;
+	}
+	
+	// now get the register
+	rn = lwasm_lookupreg3(regs, p);
+	if (rn < 0)
+		goto reterr;
+
+	if (indir)
+	{
+		if (**p != ']')
+			goto reterr;
+		else
+			(*p)++;
+	}
+	
+	// nnnn,W is only 16 bit
+	if (rn == 4)
+	{
+		if (f8)
+			goto reterr;
+		if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && rval == 0)
+		{
+			if (indir)
+				*b1 = 0x90;
+			else
+				*b1 = 0x8f;
+			return;
+		}
+		if (indir)
+			*b1 = 0xb0;
+		else
+			*b1 = 0xcf;
+		*b2 = (rval >> 8) & 0xff;
+		*b3 = rval & 0xff;
+		return;
+	}
+	
+	if (indir) indir = 0x10;
+	
+	// PCR? redo v1, v2 relative to current address
+	if (rn == 5)
+	{
+		rval -= as -> addr;
+		
+		// we have a slight problem here
+		// PCR based on current insn loc is really
+		// -125 <= offset <= +130 (8 bit offset)
+		// NOTE: when we are called, we already have the opcode emitted
+		// so we only need to worry about the size of the operand
+		// hence the 2 and 3 magic numbers below instead of 3 and 4
+		// (and that also avoids errors with two byte opcodes, etc)
+		if (f8 || (!f16 && rval >= -125 && rval <= 130))
+		{
+			*b1 = indir | 0x8C;
+			rval -= 2;
+			if (rval < -128 || rval > 127)
+				register_error(as, l, 2, "Byte overflow");
+			*b2 = rval & 0xff;
+			return;
+		}
+		
+		// anything else is 16 bit offset
+		// need 16 bit
+		*b1 = indir | 0x8D;
+		rval -= 3;
+		*b2 = (rval >> 8) & 0xff;
+		*b3 = rval & 0xff;
+		return;
+	}
+
+	// constant offset from PC
+	if (rn == 6)
+	{
+		if (f8 || (!f16 && rval >= -128 && rval <= 127))
+		{
+			*b1 = indir | 0x8C;
+			if (rval < -128 || rval > 127)
+				register_error(as, l, 2, "Byte overflow");
+			*b2 = rval & 0xff;
+			return;
+		}
+		
+		// everything else must be 16 bit
+		// need 16 bit
+		*b1 = indir | 0x8D;
+		*b2 = (rval >> 8) & 0xff;
+		*b3 = rval & 0xff;
+		return;
+	}
+
+	// we only have to deal with x,y,u,s here
+	if (!f8 && !f16 && rval >= -16 && rval <= 15)
+	{
+		if (rval == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE))
+		{
+			*b1 = rn << 5 | indir | 0x80 | 0x04;
+			return;
+		}
+		// we pick the smallest value here
+		if (indir)
+		{
+			f8 = 1;
+			goto no5bit;
+		}
+		*b1 = rn << 5 | (rval & 0x1F);
+		return;
+	}
+no5bit:
+	if (f16 || (!f8 && (rval < -128 || rval > 127)))
+	{
+		// must be a 16 bit offset here
+		*b1 = rn << 5 | indir | 0x80 | 0x09;
+		*b2 = (rval >> 8) & 0xff;
+		*b3 = rval & 0xff;
+		return;
+	}
+	
+	// if we're here, we have an 8 bit offset
+	*b1 = rn << 5 | indir | 0x80 | 0x08;
+	if (rval < -128 || rval > 127)
+		register_error(as, l, 2, "Byte overflow");
+	*b2 = rval & 0xff;
+	return;
+reterr:
+	*b1 = 0;
+	return;
+}
+
+OPFUNC(insn_indexed)
+{
+	int b1, b2, b3;
+	
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+
+	insn_indexed_aux(as, l, (const char **)p, &b1, &b2, &b3);
+	if (b1 != -1)
+		lwasm_emit(as, l, b1);
+	if (b2 != -1)
+		lwasm_emit(as, l, b2);
+	if (b3 != -1)
+		lwasm_emit(as, l, b3);
+}
--- a/src/insn_misc.c	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/insn_misc.c	Fri Jan 02 04:22:39 2009 +0000
@@ -73,73 +73,3 @@
 		emit(b3);
 	}
 }
-
-void insn_bitbit(asmstate_t *as, sourceline_t *cl, char **optr)
-{
-	int r;
-	int rval;
-	int v1;
-	int tv;
-		
-	emitop(instab[cl -> opcode].ops[0]);
-	
-	cl -> addrmode = OPER_BITBIT;
-
-	r = toupper(*(*optr)++);
-	if (r == 'A')
-		r = 1;
-	else if (r == 'B')
-		r = 2;
-	else if (r == 'C' && toupper(**optr) == 'C')
-	{
-		r = 0;
-		(*optr)++;
-	}
-	else
-	{
-		errorp1(ERR_BADREG);
-		return;
-	}
-	if (*(*optr)++ != ',')
-	{
-		errorp1(ERR_BADOPER);
-		return;
-	}
-	rval = eval_expr(as, cl, optr, &v1);
-	if (v1 < 0 || v1 > 7)
-	{
-		errorp2(ERR_OVERFLOW3);
-		v1 = 0;
-	}
-	if (*(*optr)++ != ',')
-	{
-		errorp1(ERR_BADOPER);
-		return;
-	}
-	r = (r << 6) | (v1 << 3);
-	rval = eval_expr(as, cl, optr, &v1);
-	if (v1 < 0 || v1 > 7)
-	{
-		errorp2(ERR_OVERFLOW3);
-		v1 = 0;
-	}
-	if (*(*optr)++ != ',')
-	{
-		errorp1(ERR_BADOPER);
-		return;
-	}
-	r |= v1;
-	
-	emit(r);
-			
-	// ignore base page address modifier
-	if (**optr == '<')
-		optr++;
-			
-	rval = eval_expr(as, cl, optr, &v1);
-	v1 &= 0xFFFF;
-	tv = v1 - ((cl -> dpval) << 8);
-	if (tv > 0xFF || tv < 0)
-		errorp2(ERR_OVERFLOW);
-	emit(tv & 0xff);
-}
--- a/src/insn_rel.c	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/insn_rel.c	Fri Jan 02 04:22:39 2009 +0000
@@ -22,7 +22,7 @@
 for handling relative mode instructions
 */
 
-#define __insn_inh_c_seen__
+#define __insn_rel_c_seen__
 
 #include <stdlib.h>
 
--- a/src/insn_rlist.c	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/insn_rlist.c	Fri Jan 02 04:22:39 2009 +0000
@@ -22,7 +22,7 @@
 for handling inherent mode instructions
 */
 
-#define __insn_inh_c_seen__
+#define __insn_rlist_c_seen__
 
 #include "lwasm.h"
 #include "instab.h"
--- a/src/insn_rtor.c	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/insn_rtor.c	Fri Jan 02 04:22:39 2009 +0000
@@ -22,7 +22,7 @@
 for handling register to register mode instructions
 */
 
-#define __insn_inh_c_seen__
+#define __insn_rtor_c_seen__
 
 #include "lwasm.h"
 #include "instab.h"
--- a/src/insn_tfm.c	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/insn_tfm.c	Fri Jan 02 04:22:39 2009 +0000
@@ -22,7 +22,7 @@
 for handling inherent mode instructions
 */
 
-#define __insn_inh_c_seen__
+#define __insn_tfm_c_seen__
 
 #include <ctype.h>
 #include <string.h>
--- a/src/lwasm.c	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/lwasm.c	Fri Jan 02 04:22:39 2009 +0000
@@ -99,3 +99,51 @@
 		(*str) += 2;
 	return rval;
 }
+
+int lwasm_lookupreg3(const char *rlist, const char **str)
+{
+	int rval = 0;
+	int f = 0;
+	const char *reglist = rlist;
+		
+	while (*reglist)
+	{
+		if (toupper(**str) == *reglist)
+		{
+			// first char matches
+			if (reglist[1] == ' ')
+			{
+				f = 1;
+				break;
+			}
+			if (toupper(*(*str + 1)) == reglist[1])
+			{
+				// second char matches
+				if (reglist[2] == ' ')
+				{
+					f = 1;
+					break;
+				}
+				if (toupper(*(*str + 2)) == reglist[2])
+				{
+					f = 1;
+					break;
+				}
+			}
+		}
+		reglist += 3;
+		rval++;
+	}
+	if (f == 0)
+		return -1;
+	
+	
+	reglist = rval * 3 + rlist;
+	if (reglist[1] == ' ')
+		(*str) += 1;
+	else if (reglist[2] == ' ')
+		(*str) += 2;
+	else
+		(*str)+=3;
+	return rval;
+}
--- a/src/lwasm.h	Fri Jan 02 03:35:29 2009 +0000
+++ b/src/lwasm.h	Fri Jan 02 04:22:39 2009 +0000
@@ -82,6 +82,7 @@
 __lwasm_E__ void lwasm_emit(asmstate_t *as, lwasm_line_t *l, int b);
 __lwasm_E__ void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o);
 __lwasm_E__ int lwasm_lookupreg2(const char *reglist, char **str);
+__lwasm_E__ int lwasm_lookupreg3(const char *rlist, const char **str);
 
 #undef __lwasm_E__